# C++基础2-复合数据类型
本文是《C++ Primer Plus》的笔记,本文中的案例均自己实践过,如需转发请在转发开头贴上原文地址,谢谢!
# 复合数据类型
# 数组
typeName arrayName[arraySize];
//example
int numArr[3];
//init way
int numArr[3]={1,2,3};
//列表初始化,C++11新特性,适用于所有类型
int numArr[3] {1,2,3};
1
2
3
4
5
6
7
2
3
4
5
6
7
# 字符串
# C++处理字符串第一种方式:
C-Style string。存储在Char数组中,以null character结尾。被写作'\0',ASCII码也为0。注意,如果这个数组不是以空字符结尾,用cout打印的话,还是会继续打印内存中后续的字符直到遇到空字符。
//这个不是字符串
char strArr[3] = {'h','i','h'}
//这个是字符串
char strArr[3] = {'h','i','\0'}
//初始化
char strArr[3] = "hi";
char strArr[] = "hi";
1
2
3
4
5
6
7
2
3
4
5
6
7
注意"h"和'h'是不一样的前者是字符串,包含'h'和'\0',后者是字符常量。在C++中字符串表示的是字符串所在的内存地址。
# 拼接字符串常量
任何两个由空格,制表符和换行符分隔的字符串常量都将自动拼接成一个字符串。
# 计算字符串长度
char calNum[10]="12345";
cout << strlen(calNum) << endl;
cout << sizeof(calNum) << endl;
1
2
3
2
3
第一个输出是5,不包含空字符。第二个输出是10。
# 字符串的输入问题
char n[20];
char m[20];
cin >> n;
cin >> m;
cout << n << endl;
cout << m << endl;
char oneline[20];
cin.getline(oneline, 20);
cout << oneline << endl;
char oneline1[20];
char oneline2[20];
cin.get(oneline1, 20);
cin.get();
cin.get(oneline2, 20);
cout << oneline1 << endl;
cout << oneline2 << endl;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
get和getline的区别是get将换行符还留在待输入队列中,第二个get再次读入还是这个换行符。但是使用get()可以跳过当前输入字符,哪怕是换行符。使用get()的好处是可以判断当前输入是超过字符还是正常输入结束。
如果遇到空行的话,或者输入的字符比指定的多,会设置失效位,接下来的输入会被阻断。如果想恢复输入,使用cin.clear()。
# C++处理字符串第二种方式:
C++98通过添加string类将字符串作为一种数据类型来处理,该类位于名称空间std中。
//初始化
string str1 = {"hello world"};
string str2 {"hi world"};
//赋值
str2 = str1;
//上面等价于
char[10] chrArr1;
char[10] chrArr2;
strcpy(chrArr2,chrArr1);
//如果后面的长度比前面的大会出问题,使用下面
strncpy(chrArr2,chrArr1);
string str3;
str3 = str1 + str2;
str2 += str1;
//上面等价于
strcat(chrArr2,chrArr1);
//如果拼接的字符串超出chrArr2的长度也会出问题,使用下面
strncat(chrArr2,chrArr1);
char charLen[20];
string strLen;
cout << strLen.size() << endl;
cout << strlen(charLen) << endl;
//上面的两种形式等价,但是输出结果却不一样。
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 字符串常量字面值
wchar_t name1[] = L"hello xie1";
char16_t name2[] = u"hello xie2";
char32_t name3[] = U"hello xie3";
cout << R"(hello "this" is a apple \n (what) do you think?)";
cout << R"+*( hello "this" is a apple \n "(what)" do you think? )+*";
wchar_t name4[] = LR"( hi,this is your name :)";
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 结构体
# 结构体声明与定义
//结构体的声明,声明的位置也很重要,外部声明和内部声明的范围不同
struct structName{
typeName variableName1;
typeName variableName2;
typeName variableName3;
};
//结构体的定义
struct structName structVariable1; //C style
structName structVariable2; //C++ style
//声明和定义同时
struct structName{
typeName variableName1;
typeName variableName2;
typeName variableName3;
}structVariable1,structVariable2;
//结构体数组
structName structArr[10];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
实例
struct student {
string name;
int age;
}stu1 = {
"stu1",
14
};
struct student stu2 = {"stu2",16};
student stu3 {"stu3",16};
student stu4[2] = {
{"stu4",18},
{"stu5",20}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 结构中的位字段
位域允许我们使用以bit为单位来存储数据,为我们节省内存。
struct student2 {
unsigned short name :3;
unsigned int : 0;
unsigned char sex : 1;
unsigned int : 10;
bool married : 1;
}stu2;
1
2
3
4
5
6
7
2
3
4
5
6
7
- 能够使用类域的是整型,字符型,布尔型。通常最好将位域设成unsigned。
- 位域字段从上往下定义在内存中是从低到高分配。
- 位域字段不能是类的静态成员,取地址符不能用在位域字段上。
- 位域的长度不能超过存储单元的长度。
- 空域(0长度位域)让数据从下一个存储单位开始。未命名位域将保留不使用。
# 共用体
union unionName{
typeName1 variableName1;
typeName2 variableName2;
typeName3 variableName3;
}
1
2
3
4
5
2
3
4
5
匿名共用体(anonymous union)
struct student {
string name;
union {
int age1;
char age2;
};
};
//如果把char换成string就会出错。
student stu ;
stu.age1 = 10;
//main函数中使用
union { int a; const char* p; };
a = 1;
p = "hello world";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 枚举
是由若干枚举常量组成的集合。
//在宏中使用#+类型名,可以将该类型转换成字符串
#define VNAME(value) (#value)
enum weekdays {
monday,
tuesday,
thursday
};
//scoped enumeration
enum class MColor {
red=1,
blue=2,
green=4
};
weekdays wd;
wd = tuesday;
MColor mcolor;
//不能直接使用red,可以避免污染全局环境
mcolor = MColor::red;
cout << wd << endl;
cout << VNAME(tuesday) << endl;
if (wd == weekdays(1)) {
cout << "hello world!" <<endl;
}
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
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