1017
C++ Primer Plus
- 第1-3章
- 第4章 复合类型
-
- 4.1 数组
- 4.2 字符串(C语言)
- 4.3 string类(C++)
- 4.4 结构体struct
- 4.5 共用体/联合体union
- 4.6 枚举enum
- 4.7 指针
- 4.8 指针、数组和指针算术
- 4.9 类型组合---数组、指针、结构体的组合
- 4.10 数组的替代品
- 4.11 总结
- 4.12 复习题(第2、14、16、17题)
- 4.13 编程练习
- 第5章 循环和关系表达式
第1-3章
第4章 复合类型
4.1 数组
4.1.1 概念、三要素、书写格式、下标
①数组里的元素必须是同类型的,且在计算机中占用连续的内存空间。
②数组三要素:元素的类型、数组名、数组大小。
③声明数组的通用格式:
④数组通过下标或者索引来访问元素,下标从0开始。
4.1.2 数组的初始化规则:
只有在定义数组时才能使用初始化,此后就不能再初始化了,也不能将一个数组赋给另一个数组。
4.1.3 C++11中数组初始化方式
用大括号,并且等号可以省略。
此外,C++标准模板库(STL)提供了一种数组替代品—模板类vector,而C++11新增了模板类array。
4.2 字符串(C语言)
4.2.1 在数组中使用字符串
要把字符串存储到数组中,最常用的方法有两种:
1.将数组初始化为字符串常量;
2.从文件或键盘输入把字符串读入到数组中。
案例
4.2.2 区分 ①字符数组 和 字符串;②字符常量 和 字符串常量;③sizeof() 和 strlen() 。
①字符串 和 字符数组 的区别
C++笔记5:字符串 字符数组 string
字符数组不一定是字符串,但字符串一定是字符数组。
字符串以 空字符(null character) 结尾,空字符写作’\0’。
②字符常量 和 字符串常量的区别(字符串常量本质上是个地址)
举例:
字符常量’S’是数字83的另一种写法;
字符串常量"S"由 字符’S’和’\0’ 组成,而且实际上"S"表示的是字符串的内存地址。
③sizeof() 和 strlen() 的区别
注意区分sizeof()和strlen():
sizeof()统计整个字符数组所占内存的大小,单位是字节;
使用strlen()的前提是必须是字符串,只统计字符数组中可见的字符(‘\0’之后的字符就是不可见的字符),而且不会把 空字符\0 计算在内。
综合案例
主要用代码测试:
①字符数组 和 字符串 的区别;
②字符常量 和 字符串常量 的区别;
③sizeof() 和 strlen() 的区别。
//1.字符数组&字符串
char arr1[10] = {
'd','o','g','s' };//字符数组,不是字符串
char arr2[10] = {
'd','o','g','\0','s'};//字符数组,字符串(有结束符\0)
cout << sizeof(arr1) << endl;//10个字节,而不是4个字节,因为sizeof()统计的是整个数组的长度
cout << sizeof(arr2) << endl;//10个字节
cout << strlen(arr1) << endl;//4个字符 不会报错,会警告 C6054可能没有为字符串“arr1”添加字符串零终止符。
cout << strlen(arr2) << endl;//3个字符 只统计到结束符前的位置上,而且不把结束符算在内
//因为结束符后面还有内容,所以也会警告 C6054可能没有为字符串“arr2”添加字符串零终止符。
//2.字符常量&字符串常量
//用双引号括起来的字符串常量会隐式的包括结尾的空字符\0
cout << sizeof('s') << endl;//1个字节
cout << sizeof("s") << endl;//2个字节 除了字符s,还有结束符\0
//cout << strlen('s') << endl;//报错,strlen()是用于字符串的
cout << strlen("s") << endl;//1个字符
4.2.3 字符串输入–>每次读取一行字符串输入(案例见编程练习第1题
)
①用cin输入字符串的问题:只能读一个单词
问题:
cin使用空白(空格、制表符、换行符)作为字符串输入结束的标志,这意味着用cin获取字符数组的输入内容时一次只能读取到一个单词(因为有的单词之间是空格,比如New York,Marco Reus,而cin把空格做为字符串输入结束的标志之一)。
解决方法:
可以用istream类中成员函数getline()和get(),这两个函数都可以读取一整行直到遇到换行符。其中,getline()会丢弃最后的换行符,而get()将把换行符也作为输入的内容传输给电脑。
②面向行的输入:cin.getline() — 推荐☆☆
(4.3.3 string类I/O中会讲到getline();)
这节介绍的是cin.getline():
语法:
cin.getline(name1, 20);//默认是以'\n'作为输入结束符
cin.getline(name5, 20,'_');//以'_'作为输入结束符
括号里的参数分别是用来存储输入行的数组的名称,第二个参数是要读取的字符数(第二个参数是用来避免超越数组的边界),第三个参数是输入结束符,默认是换行符’\n’。
注意:cin.getline()不会保留结束符。
案例:
问题+结论:
问题:
从上面的例子能看出如果一次输入的内容有多余的,就会被当作下一次输入的内容,归根结底是因为用下划线作为结束符。
结论:
所以一般不推荐使用下划线作为结束符。
③面向行的输入:cin.get() —推荐☆
语法:
cin.get(name1, 20); //默认是以'\n'作为输入结束符
cin.get(name5, 20, '_' ); //以'_'作为输入结束符
括号里的参数分别是用来存储输入行的数组的名称,第二个参数是要读取的字符数(第二个参数是用来避免超越数组的边界),第三个参数是输入结束符,默认是换行符’\n’。
注意:cin.get()
会保留结束符,将其放到输入队列中。
案例1:
问题1+改进:
问题1:
从上面的例子可以看出,结束符和多余的内容会被当做是下一次的输入内容,这样会造成下一次的输入出错。
结论:
针对这个问题的解决办法是用cin.get()
把结束符吃掉。
案例2:
问题2+改进:
问题2:
由于一般输入结束后都会回车,如果用下划线做结束符,并且下划线后面还有多余的内容,这样就算用cin.get()把结束符吃掉,后面多余的内容依然会影响到下一次输入。
结论:
所以不推荐用下划线或者别的符号做结束符。
总结:
①首先,不论输入结束符是什么,都用.get()
(可以读取一个字符)把这个结束符给读取掉,即跨过这个换行符;
②另外,不要把下划线或者其他符合作为结束符,直接用默认的回车符作为结束符最简单,没有那么多问题。
这样就为下一次输入做好充分的准备了:
④cin、cin.getline()、cin.get()总结☆☆☆(案例见编程练习第1题
)
读取字符串char name[20];
的三种方法,推荐用第一种:(也可以看看第5章 - 5.9 编程练习 的 第7、7’、8、9题的汇总☆☆☆)
char name[20]; | cin.getline(name,20)☆☆ | cin.get(name,20)☆ | cin >> name; |
---|---|---|---|
多余的内容 | 当以下划线作为结束符时,输入时下划线后面多余的内容会影响下次输入。 | 当以下划线作为结束符时,输入时下划线后面多余的内容会影响下次输入。 | 不受多余的内容的影响 |
结束符 | 不受结束符的影响 | 因为会保留结束符,所以结束符和多余的内容会影响下次输入。 | 虽然cin只能读取一个单词,但也是以\n作为结束符,并且 \n会被存入到输入队列中 ,所以会影响到下次输入。 |
解决办法 | 对于多余的内容: 不要用下划线或者其他符号作为结束符。 |
对于结束符的影响: 用.get()来消除; 对于多余的内容: 不要用下划线或者其他符号作为结束符 |
对于结束符的影响: 用.get()来消除; |
示例: | cin.getline(name1,20); | cin.get(name2,20).get(); | cin >> name3; cin.get(); |
结论: | < |