【C++ Primer】第3章:字符串、向量和数组
原创
©著作权归作者所有:来自51CTO博客作者zdb呀的原创作品,请联系作者获取转载授权,否则将追究法律责任
第3章 字符串、向量和数组
string表示可变长的字符序列
vector存放的是某种给定类型对象的可变长序列
使用命名空间
using namespace std;
头文件不应包含using声明
1. 标准库类型string
字符串初始化
string s1;
string s2(s1);
string s3("values"); //直接初始化
string s3 = "values"; //拷贝初始化
string s4(n, 'c'); //n个c组成字符串 直接初始化
拷贝初始化和直接初始化
使用等号初始化一个变量叫做拷贝初始化
不使用等号则是直接初始化
string s8 = string(10, 'c'); //拷贝初始化
在执行读写操作时,string对象会自动忽略开头的空白(即空格符、换行符、制表符等)并从第一个真正的字符开始读写,知道遇见下一个空白为止。
遇到第一个非空白符开始,之后再遇到空白符就结束
例如输入’ Hello World! ‘,会输出’Hello’
int main(){
string s;
cin >> s; // " Hello World "
cout << s <<endl; // "Hello"
return 0;
}
string s1, s2;
cin >> s1 >> s2; // " Hello" " World!"
cout << s1 << s2 <<endl; // "HelloWorld!"
一次读入一个单词
int main(){
string word;
while(cin >> word){
cout << word <<endl;
}
return 0;
}
一次读入一整行
getline函数的参数是一个输入流和一个string对象。
函数从给定的输入流中读入内容,直到遇到换行符为止(注意换行符也被读进来了),然后把所读的内容存入到那个string对象中去(注意不存放换行符)。
int main(){
string line;
while(getline(cin, line)){
cout << line << endl;
}
return 0;
}
string::size_type
类型,它是一个无符号类型
auto len = line.size(); //len的类型是string::size_type类型
注意:字符串字面值不能相加,string能相加
切记:字符串字面值与string是不相同的类型
范围for
C++11新标准
for(auto ch : str){
cout << ch << endl;
}
范围for还可以改变字符串中的字符
string s("Hello World!!!");
for(auto &c : s){
c = toupper(c);
}
cout << s <<endl; // "HELLO WORLD!!!"
2. 标准库类型vector
vector是一个类模板
使用模板时,需要指出编译器应把类或函数实例化
成何种类型。
不存在包含引用的vector,因为引用非对象。
列表初始化时C++11新标准
vector<string> v{10}; //10个“”
vector<string> v{10, "hi"} //10个"hi"
迭代器
auto b = v.begin(); //b表示v的第一个元素
auto e = v.end(); //e表示v尾元素的下一个位置 //b,e类型相同
尾后迭代器
是容器中不存在的位置
特殊情况下如果容器为空,则begin和end返回的是同一个迭代器
所有标准库容器都可以使用迭代器,只有少数容器支持下标运算符
vector<int>::iterator it; //能读写
string::iterator it2; //能读写
vector<int>::const_iterator it3; //只读不写
string::const_iterator it4; //只读不写
C++11新标准引入cbegin和cend
auto it3 = v.cbegin(); //it3的类型是vector<int>::const_iterator
迭代器的距离类型:difference_type
用迭代器实现二分查找
auto beg = text.begin(), end = text.end();
auto mid = text.begin + (text.end - text.begin())/2;
while(mid!=end && *mid!=target){
if(target < * mid){
end = mid;
}
else
beg = mid + 1;
mid = beg + (end - beg)/2;
}
3. 数组
数组维度编译的时候已知,是一个常量表达式
默认情况下,数组的元素被默认初始化
不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值
char a1[] = {'C', '+', '+'}; //维度是3
char a2[] = {'C', '+', '+', '\0'} //维度4
char a3[] = "C++"; //维度4
const char a4[6] = "Daniel"; //错误,没有空间可存放空字符
从右向左,从内向外
int *ptrs[10]; //ptrs是含有10个整型指针的数组
int &refs[10] = arr; //错误:不存在引用的数组
int (*Parray)[10] = &arr; //Parray指向一个含有10个整型的数组
int (&arrRef)[10] = arr; //arrRef引用一个含有10个整型的数组
int *(&array)[10] = ptrs; //array是数组的引用,该数组含有10个指针
使用数组下标的时候,通常将其定义为size_t类型,是无符号整型
指针也是迭代器
c++11新标准引入了begin和end函数
int ia[] = {0,1,2,3,4,5,6,7,8,9};
int *beg = begin(ia); //指向ia首元素的指针
int *last = end(ia); //指向arr尾元素的下一个位置的指针
auto n = end(arr) - begin(arr); //n的值是5,即arr元素个数 是ptrdiff_t类型 距离可能为负,所以是带符号类型
size_t和ptrdiff_t
都是定义在cstddef
头文件中的机器相关的类型。
C风格字符串
定义在cstring
头文件中
与旧代码的接口
不能用string对象直接初始化指向字符的指针,为了完成功能,string专门提供了一个名为c_str的成员函数
char *str = s; //错误:不能用string对象初始化char*
const char *str = s.c_str(); //正确
不允许用数组初始化数组
不允许用vector对象初始化数组
可以使用数组初始化vector对象
int int_arr[] = {0,1,2,3,4,5};
vector<int> ivec(begin(int_arr), end(int_arr));
vector<int> subVec(int_arr+1, int_arr+4); //用数组的一部分初始化vector
多维数组
int ia[3][4];
size_t cnt = 0;
for (auto& row : ia) {
for (auto& col : row) {
col = cnt;
++cnt;
}
}
for (const auto& row : ia) { //&不能少
for (auto col : row) {
cout << col << endl;
}
}
指针和多维数组
for(auto p = ia; p != ia + 3; ++p){ //p的类型是指向4个整数的数组的指针
for(auto q = *p; q != *p +4; ++q){ //q的类型是指向整数的指针
cout << *q << ' ';
}
cout << endl;
}
for(auto p = begin(ia); p != end(ia); ++p){
for(auto q = begin(*p); q != end(*p); ++q){
cout << *q << ' ';
}
cout << endl;
}
using int_array = int[4];
typedef int int_array[4]; //两句功能一样
for(int_array *p = ia; p != ia + 3; ++p){
for(int *q = *p; q != *p +4; ++q){
cout << *q << ' ';
}
cout << endl;
}