数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream>
using namespace std;
int main() { short months[12] = {0}; cout << sizeof(months) << endl; cout << sizeof(months[0]) << endl; int i = 0; for (; i < 12; i++) { cout << months[i] << "\t"; } cout << endl; return 0; }
|
对数组进行赋值,除了使用下标逐个赋值,还可以使用大括号,在初始时赋值,提供的元素不够的话,未被提供的数组元素会被设置为0。
vector 和 array
字符串
C风格字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <iostream>
using namespace std;
int main() { char cat[] = {'c', 'a', 't', '\0'}; char dog[] = {'d', 'o', 'g'}; cout << dog << endl; cout << cat << endl; return 0; }
|
计算字符串长度函数:strlen()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include <iostream> #include <cstring>
using namespace std;
int main() { char name[] = "Sheng Wenzeng"; cout << "请输入您的姓名:" << endl; cin >> name; cout << strlen(name) << endl; name[5] = '\0'; cout << name << endl; return 0; }
|
一个经典错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <iostream>
using namespace std;
int main() { const int initSize = 20; char name[initSize] = {}; char food[initSize] = {}; cout << "请输入您的姓名:" << endl; cin >> name; cout << "-----输入完成------" << endl; cout << name << endl; cout << "请输入您喜欢的食物:" << endl; cin >> food; cout << "-----输入完成------" << endl; cout << food << endl; return 0; }
|
还没来得及输入食物,就输出了空格后的名:
1 2 3 4 5 6 7
| 请输入您的姓名: Sheng Wenzeng -----输入完成------ Sheng 请输入您喜欢的食物: -----输入完成------ Wenzeng
|
cin
使用空白(空格,制表符,换行符)来确定字符串的结束位置,所以只读取了一个单词,剩下的单词在输入队列中,并直接被下一个cin
读取了。
解决方案是使用getline()
函数,面向行的输入,它使用换行符来确定字符串的结束位置。
这样就解决了上面的问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <iostream>
using namespace std;
int main() { const int initSize = 20; char name[initSize] = {}; char food[initSize] = {}; cout << "请输入您的姓名:" << endl; cin.getline(name, initSize); cout << "-----输入完成------" << endl; cout << name << endl; cout << "请输入您喜欢的食物:" << endl; cin >> food; cout << "-----输入完成------" << endl; cout << food << endl; return 0; }
|
1 2 3 4 5 6 7 8
| 请输入您的姓名: Sheng Wenzeng -----输入完成------ Sheng Wenzeng 请输入您喜欢的食物: rice -----输入完成------ rice
|
cin.getline()
有第三个参数,这将在第17章学到。
事实上,还有另一个函数,名为cin.get()
,也可以解决这个问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream>
using namespace std;
int main() { const int initSize = 20; char name[initSize] = {}; char food[initSize] = {}; cout << "请输入您的姓名:" << endl; cin.get(name, initSize); cout << "-----输入完成------" << endl; cout << name << endl; cout << "请输入您喜欢的食物:" << endl; cin.get(food, initSize); cout << "-----输入完成------" << endl; cout << food << endl; return 0; }
|
但是随即出现了新问题:
1 2 3 4 5 6 7
| 请输入您的姓名: Sheng Wenzeng -----输入完成------ Sheng Wenzeng 请输入您喜欢的食物: -----输入完成------
|
可以看到,第二个输入没有给我们输入的机会,直接回车为空。
这也是get()
和geiline()
的区别,getline()
会读取最后的换行符并抛弃,但是get不会读取换行符,而是会将换行符留在输入队列中。
解决方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include <iostream>
using namespace std;
int main() { const int initSize = 20; char name[initSize] = {}; char food[initSize] = {}; cout << "请输入您的姓名:" << endl; cin.get(name, initSize); cin.get(); cout << "-----输入完成------" << endl; cout << name << endl; cout << "请输入您喜欢的食物:" << endl; cin.get(food, initSize); cout << "-----输入完成------" << endl; cout << food << endl; return 0; }
|
也就是加了一个get()
去读取留在输入队列中的换行符。
问题来了,既然get()
这么麻烦,还要get()
干什么?用getline()
不就好了吗?
首先,老式实现没有getline()
,其次get()
是为了解决知道停止读取的原因,是已经读取了整行,还是因为数组已经被填满了?
如果是已经读取了整行,那么此时输入队列中还有一个换行符,否则,就是数组被填满了,这将在第17章详细讨论。
空行和其他问题
当get()
或getline()
读取空行,会发生什么?
会设置失效位,导致接下来的输入被阻断,此时可以使用cin.clear()
来恢复输入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <iostream>
using namespace std;
int main() { const int initSize = 20; char name[initSize] = {}; char food[initSize] = {}; cout << "请输入您的姓名:" << endl; cin.get(name, initSize); cin.clear(); cin.get(); cout << "-----输入完成------" << endl; cout << name << endl; cout << "请输入您喜欢的食物:" << endl; cin.get(food, initSize); cout << "-----输入完成------" << endl; cout << food << endl; return 0; }
|
如果输入的长度长于给定的数组长度,会发生什么?
getline()
和get()
会把剩下的字符留在输入队列中,getline()
还会设置失效位。后面会介绍(5、6、17)
混合输入字符串和数字
混合输入数字和面向行的字符串会导致问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream>
using namespace std;
int main() { const int initSize = 20; char year[initSize] = {}; char name[initSize] = {}; cout << "请输入出生年份:" << endl; cin >> year; cout << "-----输入完成------" << endl; cout << year << endl;
cout << "请输入您的姓名:" << endl; cin.get(name, initSize); cout << "-----输入完成------" << endl; cout << name << endl; return 0; }
|
1 2 3 4 5 6 7
| 请输入出生年份: 2001 -----输入完成------ 2001 请输入您的姓名: -----输入完成------
|
这段代码不会给用户输入姓名的机会,输入出生年份回车后就会直接完成全部的输入,原因是输入数字后,换行符被留在了输入队列。(cin()
以空白(空格,制表符,换行符)来确定字符串的结束位置,所以只读取了一个单词,剩下的单词(包括这个空白)在输入队列中,并直接被下一个cin()
读取了。)
解决方法也很简单,使用cin.get()
读取掉这个空白符:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream>
using namespace std;
int main() { const int initSize = 20; char year[initSize] = {}; char name[initSize] = {}; cout << "请输入出生年份:" << endl; (cin >> year).get(); cout << "-----输入完成------" << endl; cout << year << endl;
cout << "请输入您的姓名:" << endl; cin.get(name, initSize); cout << "-----输入完成------" << endl; cout << name << endl; return 0; }
|
1 2 3 4 5 6 7 8
| 请输入出生年份: 2001 -----输入完成------ 2001 请输入您的姓名: Sheng Wenzeng -----输入完成------ Sheng Wenzeng
|
C++风格string
能够把一个string赋值给另一个string
一些方法
结构
一个结构,存储多种类型的数据,如同时存储int
和float
结构声明及初始化示例一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream>
using namespace std;
struct rightTriangle { string name; float a{}; float b{}; };
int main() { rightTriangle triangle; triangle.name = "triangle"; triangle.a = 1; triangle.b = 1;
rightTriangle rightTriangle{"rightTriangle", 1, 1}; return 0; }
|
共用体
共用体可以存储不同的数据类型,但是同一时间只能存储一种。共用体的长度是最大成员的长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include <iostream> #include <string>
using namespace std;
union rightTriangle_edge { int a_int; float a_float; };
struct rightTriangle { string name; rightTriangle_edge edge_1; rightTriangle_edge edge_2; };
int main() { rightTriangle_edge edge_1{10L}; rightTriangle_edge edge_2{10};
rightTriangle triangle_1{"triangle_1", 10, 10}; rightTriangle triangle_2{"triangle_2", 10, 10}; return 0; }
|
匿名共用体:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <iostream> #include <string>
using namespace std;
union rightTriangle_edge { int a_int; double a_double; };
struct rightTriangle { string name; rightTriangle_edge edge_1; rightTriangle_edge edge_2; };
int main() { rightTriangle_edge edge_1{}; edge_1.a_double = 10.0; rightTriangle_edge edge_2{}; edge_2.a_int = 10;
cout << edge_1.a_double << endl << edge_2.a_int << endl;
rightTriangle triangle_1; triangle_1.name = "triangle_1"; triangle_1.edge_1.a_int = 10; triangle_1.edge_2.a_int = 10; cout << triangle_1.edge_1.a_int << endl; return 0; }
|
枚举
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <iostream>
using namespace std;
enum week { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday };
int main() { week week_begin; week_begin = Sunday; cout << week_begin; return 0; }
|
指针和自由存储空间