重拾C++ 基础知识总结(二)

时间:2023-12-10 15:25:14

1、标准库string类型:

用户程序要使用string类型对象,必须包含相关头文件 #include <string>

字符串字面值与标准库string类型不是同一种类型,字符串字面值是字符数组,而string是对象

2、

int main(){

string s;

cin>>s;

cout<<"s="<<s<<endl;

}

string类型的输入操作符:

读取并忽略开头所有的空白字符;读取字符直至再次遇到空白字符,读取终止(即只读取一个单词)

// 读取多个字符串,直至遇到文件尾

int main(){

string s,result;

while(cin>>s)

result += s;

cout<<"result="<<result<<endl;

}

3、getline()函数读取整行文本(接受两个参数,一个输入流对象和一个string对象,getline函数并不会忽略开头的换行符但会忽略尾部的换行符)

int main(){

string line;

while(getline(cin,line))

cout<<"line="<<line<<endl;

}

string对象重载了运算符 + = == != >= <= < > []

其中 s[] 返回s中位置为n的字符,位置从0开始计数

另外还有函数 s.empty() 判断字符串是否为空串, 函数 s.size() 返回字符的个数

s.size()函数的返回值:string::size_type类型,任何存储string的size操作结果变量必须为string::size_type类型,不要把size的返回值赋给一个int变量(使用配套类库类型string::size_type可以做到与机器无关,string::size_type是unsigned的)

4、string对象重载了运算符 + = == != >= <= < > []

其中关系操作符 > < >= <= 是区分大小写的,大写字母排在小写字母前面

如果两个string对象的字符不同,则比较第一个不匹配的字符

赋值操作符 =  st1=st2

必须先把st1占用的相关内存释放掉,然后再分配st1足够存放st2副本的内存空间,最后把st2中的所有字符复制到新分配的内存空间中

两个string相加

下面把两个string对象连接起来产生第三个string对象

string s3 = s1 + s2;

string对象与字符串字面值的连接(+操作符的左右操作数必须至少有一个是string类型的):

string s1 = "hello";

string s2 = "world";

string s3 = s1 + ",";

string s4 = "hello" + ","; // 错误,因为没有string对象

string s5 = "s1 + "," + "world";

string s6 = "hello" + "," + s2; // 错误,因为前两个都是字符串字面值

从string获取字符

string类型通过下标获取字符([]运算符重载)

5、字符处理(cctype头文件):

isalnum(c) 判断字符是否是字母或数字

isalpha(c) 判断c是否是字符

iscntrl(c) 判断c是否为控制字符

isdigit(c) 判断c是否为数字

isgraph(c) 判断是否为空格,但可以打印

islower(c) 判断是否是小写

isprint(c) 判断是否可打印

ispunct(c) 判断是否是标点

isspace(c) 判断是否是空白字符

issupper(c) 判断是否是大写

isxdigit(c) 判断是否是十六进制数

tolower(c) 如果是大写转为小写

toupper(c) 如果是小写转为大写

6、c标准库头文件的c++版本

c++标准库除了定义了一些特定于c++的设施外,还包括c标准库。c++中的头文件cctype其实就是利用了c标准库函数,这些库函数就定义在c标准库的ctype.h头文件中。

c标准库头文件命名形式为name.h,而c++版本则命名为cname,少了后缀.h而在头文件名前加了c。c表示这个头文件源自c标准库。因此,cctype与ctype.h文件的内容是一样的,只是采用了更适合c++程序的形式。特别的,cname头文件中定义的名字都定义在命名空间std内,而.h版本中的名字却不是这样。

通常,c++程序中应采用cname这种头文件的版本,而不采用name.h版本,这样,标准库中的名字在命名空间std中保持一致。使用name.h版本会给程序员带来负担,因为他们必须记住哪些标准库名字是从cc继承来的,哪些是c++所持有的。

7、标准库vertor类型

vertor是同一类型的对象的集合,每个对象都有一个对应的整数索引值。它可以包含其他对象,一个容器中的所有对象都必须是同一类型的。(头文件 #include <vertor>)

vertor是一个类模版(不是一种数据类型),使用模版可以编写一个类定义或函数定义,而用于多个不同的数据类型

vertor<int> ivec;

vertor<Sales_item> Sales_vec;

8、vector对象的定义与初始化:

vertor构造函数

vertor<T> v1;

vertor<T> v2(v1);

vertor<T> v3(n,i); // v3包含n个值为i的元素

vertor<T> v4(n); // v4含有值初始化(默认初始化)的元素的n个副本

vertor<int> ivec(10,3) // 初始化包含10个3的vertor

vertor对象的动态增长:vertor可以在运行时高效地添加元素,有效的方法就是先初始化一个空的vertor对象,然后动态的增加元素

9、值初始化:内置类型数据有默认初始化值,对于自定义的类型,要使其可以自动初始化,就要提供一个默认的构造函数(无参构造函数)

10、vertor对象的操作:

v.empty() // 判断vertor是否为空

v.size() // 返回vertor的元素个数(返回类型应总是包括vertor的元素类型为vertor<T>::size_type,vertor::size_type是不正确的)

v.push_bach(t) // 在vertor的末尾增加一个值t的元素(动态添加元素)

v[n] // 返回vertor中位置为n的元素(元素由0开始计算)

v1 = v2; // 将v1中的元素替换为v2中的元素的副本

v1 == v2; // 比较两个vertor是否相等

!=, <, <=, >, >=

11、

for(vertor<int>::size_type ix = 0; ix != ivec.size(); ++i){

ivec[ix] = 0;

}

c++中习惯优先选用!=而不是<来编写循环判断条件

另外,for循环中没有保存ivec.size()的值,而是使用了函数表示结束的标识;在每次循环中测试size的当前值,而不是在进入循环前,存储size值的副本(vertor是可以动态的添加元素的,所以使用函数判断结束标识更安全)

12、c++中的vertor的下标操作不可以添加元素,下标只能用于获取已存在的元素(或者修改已存在的元素的值),应该使用push_back()函数向vertor中添加元素;

试图获取不存在的下标元素时会产生一个运行时错误,不能确保执行过程中可以捕捉到这类错误,运行程序的结果往往是不确定的

13、迭代器:

除了使用下标访问vertor的元素之外,还可以使用迭代器

头文件  #include <iterator>

每种容器类型都定义了自己的迭代器类型

vertor<int>::iterator iter;

每种容器都定义了一对命名为begin和end的函数,用于返回迭代器,如果有元素则begin返回的迭代器指向第一个元素

vertor<int>::iterator iter = ivec.begin();

由end操作返回的迭代器并不返回指向vertor中任何实际的元素,相反,它只起到一个哨兵的作用,表示已经处理完vertor中所有的元素

迭代器类型可通过解引用操作符(*操作符)来访问迭代器所指向的元素:

*iter = 0; // *iter 与 iter[0]指相同的元素

++iter; // 迭代器的自增操作,指向下一个元素

解引用操作符返回迭代器当前所指向的元素(不能对end迭代器进行解引用或自增操作)

迭代器的== 和 != 操作可以比较两个迭代器是否指向同一个元素

迭代器在vertor的应用

for(vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); iter++){

*iter = 0;

}

14、const_iterator(只读迭代器,只用于读取容器中的元素,不能改变其值)

const_iterator 与 const迭代器的区别,const的迭代器一旦被初始化就不能改变其指向的迭代器,而可以改变其迭代器对应的值

15、迭代器的算术运算:

iter+n iter-n 可以直接定位到元素

iter1-iter2 得到的数据为different_type的signed类型的值

获取中间元素的迭代器:vector<int>::iterator mid = vi.begin() + vi.size()/2;

任何改变vector长度的行为都会导致已存在的迭代器失效

16、bitset类型(头文件 #include <bitset>):

bitset类型对象的区别在于其长度而不是其类型,在定义bitset时,要明确bitset含有多少位,须在尖括号内给出它的长度值

bitset<32> bitvec; // 32位的0

string对象和bitset对象之间是反向转化的,string对象的最右边字符(下标最大的字符)用来初始化bitset对象的低阶位(下标为0的位)