(1) String的头文件和命名空间,必须包含string头文件,string定义在命名空间std中
#include<string> using std::string;(2) 初始化
string s1; //默认构造函数,s1是空串 string s2(s1); //将s2初始化为s1的一个副本.s1可以是有’\0‘的char数组 string s3("value"); //将s3初始化为一个字符串字面值的副本 string s4(n,'c'); //将s4初始化为字符'c'的n个副本如果提供了一个字符串字面值,该字面值中除了最后那个空字符外其他所有的字符都被拷贝到新创建的string对象中去。
(3) 直接初始化和拷贝初始化
string s8 = string(10, 'c');等同于:
string temp(10, 'c'); string s8 = temp;(4) string对象上的操作 1.string对象会自动忽略开头的空白(即空格符,换行符,制表符),并从第一个真正的字符开始读起,直到遇见下一处空白为止。 2.geline读取一整行 如果希望在最终得到的字符中保留输入时的空白符,应该用getline函数代替原来的>>运算符。
getline()原型istream& getline ( istream &is , string &str , char delim ); getline函数的参数是一个输入流和一个string对象,函数从给定的输入流读入内容,直到遇见换行符为止(换行符也被读进来了)。
string line; while(getline(cin, line)) cout << line << endl;(5) string::size_type类型 它是一个无符号类型的值,所有用于存放string类的size函数返回值的变量(size返回的是一个无符号整形数),都应该是string::size_type类型。
string line; auto len = line.size();(6) string对象相等意味着它们的长度相同而且所包含的字符也全部相同 比较原则:1.长度 2.长度相同比较大小写字母顺序大小
(7) 字面值和string对象相加 当把string对象和字符字面值及字符串字面值混在一条语句中,必须确保每个加法运算符两侧的运算对象至少有一个是string
string s5 = "hello" + ","; // 错误 string s4 = s1 + ","; //正确 string s6 = (S1 + ",") + "word"; //正确 括号内的子表达式 的结果也是一个string对象 string s7 = ("hello" + ",") + "word"; //错误 两个字符串字面值相加s6括号内的(S1 + “,”)子表达式 的结果也是一个string对象 切记,字符串字面值与string是不同的类型。
(8)处理string对象中的字符 cctype头文件中的函数(C语言标准库中的ctype.h)
isalnum(c) 如果c是字母或数字,则为true isalpha(c) 如果c是字母,则为true isdigit(c) 如果c是数字,则为true islower(c) 如果c是小写字母,则为ture isupper(c) 如果c是大写字母,则为true isspace(c) 如果c是空白字符,则为true ispunct(c) 如果c是标点符号,则为true//排除字母,数字,空格 iscntrl(c) 如果c是控制字符,则为true。控制字符见 https://baike.so.com/doc/235350-248973.html isgraph(c) 如果c不是空格,但是可打印,则为true isprint(c) 如果c是可打印的字符,则为true isxdigit(c) 如果c是十六进制数,则为true tolower(c) 如果c是大写字母,则返回其小写字母形式,否则直接返回c toupper(c) 如果c是小写字母,则返回其大写字母形式,否则直接返回c(9)处理每个字符 通过auto关键字让编译器决定变量c的类型,这里的c的类型是char
for(auto c : str) cout << c << endl;通过decltype关键字获取字符串size的类型
decltype(s.size()) cnt = 0;把字符串中的小写字符全部转换成大写字母:
for(auto c : str) c = toupper(c); cout << str << endl;(10) 处理部分字符 1.使用下标处理 2.通过迭代器 ps:string对象的下表必须大于等于0而小于等于s.size()。 从s[0] ---- s[s.size() - 1]
(1) vector初始化
v5列表初始化包含了初始值个数的元素,每个元素被赋予相应的初始值
vector<T> v1//v1是一个空的vector,此时不能直接使用下标,因为vector里还木有元素 vector<T> v2(v1)//等价于vector<T> v2=v1,将v1中所有元素拷贝给v2,注意拷贝的时候,两个vector的对象的类型必须一致 vector<T> v3(n)//初始化n个元素,每个元素的值为0 vector<T> v4(n,val)//v初始化n个元素,每个元素的初始值都为val vector<T> v5={a,b,c......}//vector初始化列表,显示的表示了每个初值两个vector的拷贝类型必须相同:
// 错误 vector<int> a(b); vector<string> c(a); vector< int >初始化 vector<int> ivec(10); // 10个元素,每个都初始化为0 vector<int> v2{10}; //v2一个元素,元素值是10 vector<int> v3{10,1}; //v3两个元素,元素值是10和1 vector< string >初始化 s4:不能使用字符串的字面值构建vector对象 vector<string> s1={"hello","world","!"}; vector<string> s2(4,"ha"); // 4个ha对象 vector<string> s3{10}; //10个字符串,初始化为""(空) vector<string> s4("hi"); //错误,不能使用字符串的字面值构建vector对象(2) vector对象中添加元素 利用push_back添加元素
#include <iostream> #include <vector> using namespace std; int main() { vector<int> My_vector; int iint; while (cin >> iint) { My_vector.push_back(iint); } return 0; }vector对象能高效增长 通过修改capcity动态添加元素。
(3) 其他vector操作
v.empty() v.push_bach() v.size() v1 = { a, b, c...} //用列表中元素的拷贝替换v1中的元素 v1 == v2 //v1和v2相等当且仅当当他们元素数量相等且对应位置元素值相同size返回vector对象中元素的个数,返回值的类型是由vector定义的size_type类型 如存放int类型的内容,则类型为vector< int >::size_type
(4)不能用下标形式添加元素
vector<int> v; for(decltype(v.size()) index = 0; index != 10; ++index) v[index] = index; // 错误,v不包含任何元素 for(decltype(v.size()) index = 0; index != 10; ++index) v.push_back(index); //正确,添加新元素,元素为index注意:vector对象以及string对象的下标可用于访问已存在的元素。而不能用于添加元素。
vector<int> v(10); cout << v[10] << endl;//v含有10个元素,下标从0-9,10超出范围(1) 我们可以通过下标运算符来访问string对象的字符或者vector对象的元素,还可以通过另一种通用的机制迭代器来实现相同的目的。
//如果v是vector则,b,e的类型为vector::itearator auto b = v.begin(), e = v.end(); // b和e的类型相同end迭代器指示的是一个本不存在的“尾后”,尾部元素的下一个位置,仅仅是个标记没有什么实际含义; 特殊情况下如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器。
(2) 因为end返回的迭代器不实际指示某个元素,所以不能对其进行递增或解引用的操作。
//处理完全部字符或者遇到空白 for(auto it = s.begin(); it != s.end() && !isspace(*it); ++it) *it = toupper(*it); //当前字符改写成大写形式泛型编程:for循环中使用 != 而非 < 进行判断
(3) 迭代器类型 迭代器的标准库类型使用iterator 和 const_iterator来表示迭代器的类型
vector<int>::iterator it; string::iterator it2; vector<int>::const_iterator it3; //只能读元素,不能写 string::const_iterator it4; //只能读字符,不能写C++11新标准中的cbegin和cend类型
vector<int> v; const vector<int> cv; auto it1 = v.begin(); // vector<int>::iterator auto it2 = cv.begin(); // vector<int>::const_iterator auto it3 = v.cbegin(); // it3的类型是vector<int>::const_iterator // C++11中的新标准中引入新函数:cbegin 和 cendC++11中的新标准中引入新函数:cbegin 和 cend不论是vector和string对象是否是常量,返回值都是const_iterator。
(4) 解引用和成员访问操作 解引用操作:
(*it).empty(); //圆括号必不可少 it->empty();(5) 但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素 在迭代器循环体内,迭代器是指向了一个容器内的元素的,如果这个时候向容器添加了元素,是很可能使当前迭代器失效的(取决于添加元素的位置和容器的类型),所以在遍历的时候都是不能做插入、删除等写操作的。
(6) 迭代器运算 it1 - it2 两个迭代器相减的结果是它们之间的距离。 只要两个迭代器指向的是同一个容器中的元素或者尾元素的下一个位置,就能将其相减; 其类型是名为difference_type的带符号整形数,这个距离可正可负,所以是带符号整形数。
数组是类似与标准库类型vector的数据结构,与vector不同的是,数组的大小确定不变,不能随意向数组中增加元素。 如果不清楚元素的确切个数,请用vector。
(1) 数组的初始化与定义 编译的时候数组的维度必须是一个常量表达式 constexpr 变量,由于复杂的系统很难分辨一个初始值到底是不是常量表达式。 constexpr 类型以便编译器来验证变量的值是否是一个常量表达式,声明为constexpr 类型的变量一定是一个常量
constexpr unsigned sz = 42; int *parr[sz] //含有42个整形指针的数组(2) 定义数组的时候必须指定数组的类型,不允许用auto关键字由初始化列表推断类型
(3) 显示初始化数组元素
int a2[] = {0, 1, 2}; //维度是3的数组 string a4[3] = { "hi", "bye"}; //等价于a4[] = { "hi", "bye", ""};(4) 数组的特殊性 字符数组有一种额外的初始化形式(字符串字面值), 一定要注意字符串字面值的结尾处还有一个空字符
const char a4[6] = "nihaoa"; //错误,还需要一个位置放'\0'空字符串 char a3[] = "nihaoa"; //自动添加字符串结束的空字串(5) 不允许拷贝和赋值 不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值。
int a[] = {0 , 1 , 2}; int a2[] = a; //错误,不能将数组的内容拷贝给其他数组作为其初始值 a2 = a; //错误,不能用数组为其他数组赋值(6) 使用数组下标的时候,通常将其定义为size_t类型(机器相关的无符号类型)
(7) 指针也是迭代器 1.可以通过自己定义一个指针来构造数组的尾迭代器
int a[] = {0,1,2,3,4,5,6,7,8,9}; int *p = arr; //p指向arr的第一个元素 ++p; // p指向arr[1] int *e = &arr[10]; //指向arr尾元素的下一个位置的指针(相当于迭代器end) for(int *b = arr; b != e ; b++) cout << *b << endl; //输出arr的元素2.使用标准库函数begin和end
int a[] = {0,1,2,3,4,5,6,7,8,9}; int *beg = begin(a); //指向a的首元素 int *last = end(a); //指向a的尾后元素 //寻找第一个负元素,如果检查完全部元素则结束循环 while(beg != last && *beg >=0) ++beg;(8) 下标和指针
标准库string和vector也能执行下表运算,但是数组与它们有所不同。 标准库类型限定使用下标必须是无符号整形,而内置的下标运算无此要求,
int *p = &a[2]; //p指向索引为2的元素,也就是数组集合中的第三个元素 int j =p[1]; //指向数组a中索引为3的元素 int k = p[-2]; // p[-2]等同于a[0]表示的那个元素(9) C++中的string转换成C风格字符串
string s("hello"); char *str = s ; //错误,不能用string对象初始化char* const char *str = s.c_str(); //正确(10) 使用数组初始化vector对象 数组 == >vector对象需要拷贝取得首元素和尾后地址,或数组的部分位置
int int_arr[] = {0,1,2,3,4,5,6}; vector<int> v( begin(int_arr), end(int_arr) ); vector<int> v( begin(int_arr + 1), end(int_arr + 4) );