1、关键字
菜鸟教程
2、数据类型
内置数据类型:算数类型和空类型
算数类型:整形和浮点型
2.1 整型
定义超出范围会溢出; | 数据类型 | 占用空间 | 取值范围 | | --- | ---
| --- | | short(短整型) | 2 字节 | (-215~215-1) | | int(整型) | 4
字节 | (-231~231-1) | | long(长整型) | win 为 4,linux 为 4(32
位),8(64 位) | (-231~231-1) | | long long(长长整型) | 8 字节 |
(-263~263-1) |
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 #include <iostream> using namespace std ;int main () { short a = 10 ; int b = 10 ; long c = 10 ; long long d = 10 ; cout << "num1=" << a << endl ; cout << "num2=" << b << endl ; cout << "num3=" << c << endl ; cout << "num4=" << d << endl ; system("pause" ); return 0 ; }
2.2 实型
用于表示小数;
单精度 float 和双精度 double;
小数默认为双精度,定义 float 时需要加
f,如float a =3.14f;
,否则会截断;
科学计数法,float f2 = 3e2;//3*10^2
float f2 = 3e-2;//3*0.1^2
区别
数据类型
占用空间
有效数字类型
float
4 字节
7 位有效数字
double
8 字节
15-16 位有效数字
1 2 3 4 5 6 7 8 9 10 11 #include <iostream> using namespace std ;int main () { float a = 3.14f ; double b = 3.14 ; system("pause" ); return 0 ; }
2.3 字符型
表示形式char ch = 'a';
单引号里面只能写一个字符;
只占用一个字节;
字符型进行存储时以 ASCII 存储;
1 2 3 4 5 6 7 8 9 10 11 12 13 #include <iostream> using namespace std ;int main () { char ch = 'a' ; cout << "字符为" << ch << endl ; cout << "字符所占内存为" << sizeof (ch) << endl ; cout << "字符ch对应的ASCII编码为" << (int )ch << endl ; system("pause" ); return 0 ; }
2.4 转义字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 \a:蜂鸣,响铃 \b:回退:向后退一格 \f:换页 \n:换行,光标到下行行首 \r:回车,光标到本行行首 \t:水平制表 \v:垂直制表 \\:反斜杠 \':单引号 \":双引号 \?:问号 \ddd:三位八进制 \xhh:二位十六进制 \0:空字符(NULL),什么都不做
2.5 字符串型
C 语言类型:char 变量名[] = "字符串值";
C++类型:string 变量名 = "字符串值";
iostream
已经隐式地包含了 string
库,但最好还是显式一下,以免发生错误。头文件#include<string>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> #include <string> using namespace std ;int main () { char string1[] = "hello" ; string string2 = "world" ; cout << "string1=" <<string1 << endl ; cout << "string2=" <<string2 << endl ; system("pause" ); return 0 ; }
2.6 布尔类型
true 和 false;
只占用 1 字节;
实质上 true 为 1,false 为 0;
1 2 3 4 5 6 7 8 9 10 11 #include <iostream> using namespace std ;int main () { bool flag = true ; cout << "flag=" << flag << endl ; system("pause" ); return 0 ; }
2.7 输入
cin 变量名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> using namespace std ;int main () { int a = 10 ; cout << "a=" << a << endl ; cin >> a; cout << "a之后=" << a << endl ; string str = "helllo" ; cout << "str1=" << str << endl ; cin >> str; cout << "str2=" << str << endl ; system("pause" ); return 0 ; }
2.8 decltype 类型指示符
从表达式的类型推算出要定义变量的类型,而不使用该对象的初始化变量;
decltype(f()) sum = 0;
sum 的类型就是
f()函数返回值类型;
关于引用类型
1 2 3 4 5 6 7 8 9 #include <iostream> int main () { const int ci = 0 , & cj = ci; decltype(ci) x = ci; decltype(cj) y = x; }
指针解引用
解引用之后得到引用类型
1 2 3 int i = 42 , * p = &i, & r = i; decltype(r + 0 ) b;
多层括号
双层括号永远是引用
1 2 3 int i = 42 ; decltype(i) d;
3、运算符
3.1 算数运算符
两个小数不能做取模运算; | 运算符 | 描述 | 实例 | | --- | --- | ---
| | + | 把两个操作数相加 | A + B 将得到 30 | | - |
从第一个操作数中减去第二个操作数 | A - B 将得到 -10 | | _ |
把两个操作数相乘 | A _ B 将得到 200 | | / | 分子除以分母 | B / A 将得到
2 | | % | 取模运算符,整除后的余数 | B % A 将得到 0 | | ++ | 自增运算符
,整数值增加 1 | A++ 将得到 11 | | -- | 自减运算符
,整数值减少 1 | A-- 将得到 9 |
前置自增和后置自增
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 () { int a = 21 ; int c ; c = a++; cout << "Line 1 - Value of a++ is :" << c << endl ; cout << "Line 2 - Value of a is :" << a << endl ; c = ++a; cout << "Line 3 - Value of ++a is :" << c << endl ; return 0 ; }
1 2 3 Line 1 - Value of a++ is :21 Line 2 - Value of a is :22 Line 3 - Value of ++a is :23
3.2 赋值运算符
算符
描述
实例
=
简单的赋值运算符,把右边操作数的值赋给左边操作数
C = A + B 将把 A + B 的值赋给 C
+=
加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数
C += A 相当于 C = C + A
-=
减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数
C -= A 相当于 C = C - A
*=
乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数
C = A 相当于 C = C A
/=
除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数
C /= A 相当于 C = C / A
%=
求模且赋值运算符,求两个操作数的模赋值给左边操作数
C %= A 相当于 C = C % A
<<=
左移且赋值运算符
C <<= 2 等同于 C = C << 2
>>=
右移且赋值运算符
C >>= 2 等同于 C = C >> 2
&=
按位与且赋值运算符
C &= 2 等同于 C = C & 2
^=
按位异或且赋值运算符
C ^= 2 等同于 C = C ^ 2
|=
按位或且赋值运算符
C |= 2 等同于 C = C | 2
1 2 3 4 5 6 7 8 9 10 11 #include <iostream> using namespace std ;int main () { int a = 8 ; a >>= 2 ; cout << "a = " << a << endl ; system("pause" ); return 0 ; }
3.3 比较运算符
输出时加括号;(a==b);
计算时可加可不加; | 运算符 | 描述 | 实例 | | --- | --- | --- | | ==
| 检查两个操作数的值是否相等,如果相等则条件为真。 | (A == B) 不为真。 |
| != | 检查两个操作数的值是否相等,如果不相等则条件为真。 | (A != B)
为真。 | | > |
检查左操作数的值是否大于右操作数的值,如果是则条件为真。 | (A > B)
不为真。 | | < |
检查左操作数的值是否小于右操作数的值,如果是则条件为真。 | (A < B)
为真。 | | >= |
检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 | (A
>= B) 不为真。 | | <= |
检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 | (A
<= B) 为真。 |
1 2 3 4 5 6 7 8 9 10 11 12 #include <iostream> using namespace std ;int main () { int a = 8 ; int b = 10 ; cout << (a==b) << endl ; bool c = a != b; cout << c << endl ; system("pause" ); return 0 ; }
3.4 逻辑运算符
假设变量 A 的值为 1,变量 B 的值为 0,则:
运算符
描述
实例
&&
称为逻辑与运算符。如果两个操作数都 true,则条件为 true。
(A && B) 为 false。
||
称为逻辑或运算符。如果两个操作数中有任意一个 true,则条件为
true。
(A || B) 为 true。
!
称为逻辑非运算符。用来逆转操作数的逻辑状态,如果条件为 true
则逻辑非运算符将使其为 false。
!(A && B) 为 true。
3.5 按位赋值操作
按位与(&=)运算符,它是二进制的“与”操作,即两数中对应位都为 1
时为 1,其他情况都为 0。例如,3 & 5 的结果为
1。而按位与赋值操作就是将左操作数和右操作数进行按位与操作,然后将结果赋给左操作数,即
a &= b 等价于 a = a & b。
其次是按位或(|=)运算符,它是二进制的“或”操作,即两数中对应位有一个为
1 时为 1,其他情况都为 0。例如,3 | 5 的结果为
7。而按位或赋值操作就是将左操作数和右操作数进行按位或操作,然后将结果赋给左操作数,即
a |= b 等价于 a = a | b。
接下来是按位异或(^=)运算符,它是二进制的“异或”操作,即两数中对应位相同时为
0,不同时为 1。例如,3 ^ 5 的结果为
6。而按位异或赋值操作就是将左操作数和右操作数进行按位异或操作,然后将结果赋给左操作数,即
a ^= b 等价于 a = a ^ b。
第四个是左移位(<<=)运算符,它可以将一个数左移 n
位,相当于将其乘以 2 的 n 次方。例如,3 << 5 的结果为
96。而左移位赋值操作就是将左操作数左移右操作数位数个位置,然后将结果赋给左操作数,即
a <<= b 等价于 a = a << b。
第五个是右移位(>>=)运算符,它可以将一个数右移 n
位,相当于将其除以 2 的 n 次方。例如,16 >> 2 的结果为
4。而右移位赋值操作就是将左操作数右移右操作数位数个位置,然后将结果赋给左操作数,即
a >>= b 等价于 a = a >> b。
第六个是取反()运算符,它可以将一个数的二进制码按位取反,例如, 3
的结果为-4。而按位与取反(&~)赋值运算符是 a &= ~b
的简写,即先按位取反 b,然后与 a 进行按位与操作,最后将结果赋给 a
4、程序流程结构
顺序结构、选择结构、循环结构
4.1 选择结构
if
if...else
if...else if..else if...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <iostream> using namespace std ;int main () { int score = 0 ; cout << "请输入分数" << endl ; cin >> score; if (score > 600 ) { cout << "及格了" << endl ; } system("pause" ); return 0 ; }
顺序计数器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <iostream> int main () { int currVal = 0 , val = 0 ; if (std ::cin >> currVal) { int cnt = 1 ; while (std ::cin >> val) { if (val == currVal) ++cnt; else { std ::cout << currVal << " occurs " << cnt << " times" << std ::endl ; currVal = val; cnt = 1 ; } } std ::cout << currVal << " occurs " << cnt << " times" << std ::endl ; } return 0 ; }
4.2 三目运算符
做简单的判断;
a > b ? a : b ;
a 比 b 大则为 a,否则为 b;
4.3 switch
switch 选择结构;
switch 只能判断整型或者字符型,不能是区间;
switch 效率较高;
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 () { int score = 0 ; cout << "请输入分数" << endl ; cin >> score; switch (score) { case 10 : cout << "经典" << endl ; break ; case 9 : cout << "还行" << endl ; break ; default : cout << "不行" << endl ; break ; } system("pause" ); return 0 ; }
4.4 while
while(循环条件){循环结构}
while 语句
1 2 3 4 5 6 7 8 9 10 11 int main () { int sum = 0 , val = 1 ; while (val <=10 ) { sum += val; ++val; } std ::cout << "Sum of 1 to 10 inclusive is " << sum << std ::endl ; return 0 ; }
输出:um of 1 to 10 inclusive is 55
猜数字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <iostream> using namespace std ;int main () { int num = 0 ; int numRam = rand() % 100 + 1 ; cout << "请输入数字" << endl ; cin >> num; while (num != numRam) { if (num > numRam) { cout << "大了" << endl ; cin >> num; } else { cout << "小了" << endl ; cin >> num; } } cout << "猜对了" << endl ; system("pause" ); return 0 ; }
4.5 do...while
do{ 循环语句 } while { 循环条件 };
会先执行一次;
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 () { int num = 100 ; do { int a = 0 ; int b = 0 ; int c = 0 ; a = num / 100 ; b = num / 10 % 10 ; c = num % 10 ; if (a*a*a + b*b*b + c*c*c == num) { cout << "是水仙花数" << num << endl ; } num++; } while (num >= 100 && num < 1000 ); system("pause" ); return 0 ; }
4.6 for 循环
for( 起始表达式; 条件表达式;循环语句 ){ 循环语句 }
可以用来读取一组数据;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> using namespace std ;int main () { int a = 0 ; int b = 0 ; for (int num = 1 ; num < 100 ; num++) { a = num / 10 ; b = num % 10 ; if (a == 7 || b == 7 || num % 7 == 0 ) { cout << "敲桌子" << num << endl ; } } system("pause" ); return 0 ; }
读取输入不定的输入数据
1 2 3 4 5 6 7 8 9 int main () { int sum = 0 , value = 0 ; while (std ::cin >> value) { sum += value; } std ::cout << "Sum is: " << sum << std ::endl ; return 0 ; }
输入:1 2 3 4 5 6 8 da 输出:Sum is: 29
或者 ctrl+z,再按 Enter,表示输入结束
输入:1 2 3 4^z 输出:Sum is: 10
乘法口诀
1 2 3 4 5 6 7 8 9 10 11 12 13 #include <iostream> using namespace std ;int main () { for (int i = 1 ; i < 10 ; i++) { for (int j = 1 ; j <= i; j++) { cout << j <<"*" <<i <<"=" <<i*j<<"\t" ; } cout << endl ; } system("pause" ); return 0 ; }
4.7 break 和 continue
break 跳出循环体;
continue,执行到本行不往下执行,但是循环会继续,只是跳出本次执行块;
4.8 goto
需要一个表示符,标识符命名规范同变量;
标识符一般大写;
1 2 3 4 goto FLAG; FLAG:cout << "跳转执行到这" << endl ;
5、数组
存放相同类型的数据;
索引从 0 开始;
5.1 一维数组
定义
数据类型 数组名[ 数组长度 ];
数据类型 数组名[ 数组长度 ] = { 值1 ,值2 ,值3...};
数组类型 数组名[] = {值1 ,值2,值3...};
获取数组中的数据arr[i]
;
数组占居内存大小sizeof(arr)
;
元素个数sizeof(arr)/sizeof(arr[0])
;
直接打印
arr,输出为首地址;元素地址为&arr[0]
;
6、引用
6.1 基本介绍
引用是变量的别名;
本质就是一个指针常量;
应用必须初始化,初始化后不能改变;
可以使用引用进行地址传递;
基本使用
1 2 3 4 5 6 7 8 9 #include <iostream> using namespace std ;int main () { int a = 10 ; int & b = a; b = 20 ; cout << a << endl << b << endl ; }
6.2 3 种交换函数
地址传递;
引用的好处就是不需要解引用,在作为函数实参后,需要用到值时,直接使用引用名,而指针需要加*。
每次使用引用实际上是解引用的操作。
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 #include <iostream> using namespace std ;void f1 (int a, int b) { int temp = a; a = b; b = temp; }void f2 (int *a ,int *b) { int temp = *a; *a = *b; *b = temp; }void f3 (int &a, int &b) { int temp = a; a = b; b = temp; }int main () { int a = 10 ; int b = 20 ; f3(a, b); cout << "a = " << a<<endl ; cout << "b = " << b; }
6.3 引用函数函数返回值
不要返回局部变量的引用(较老的版本中);
函数的调用可以作为左值;
1 2 3 4 5 6 7 8 9 10 11 12 int & test02 () { static int a = 20 ; return a; }int main () { int & res = test02(); cout << res << endl ; test02() = 1000 ; cout << res << endl ; }
输出为
20
1000
6.4 常量引用
使用场景:用来修饰形参,防止误操作;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> using namespace std ;void f1 (const int &a) { cout << a << endl ; }int main () { const int & a = 10 ; int b = 10 ; f1(b); }
7、结构体
7.1 结构体概念
用户自定义数据类型;
7.2 结构体使用
struct 结构体名称 { 结构体成员列表 }
实例化的三种方法
struct 结构体名 变量名
struct 结构体名 变量名 = {成员 1 值,成员 2 值...}
定义结构体时顺便创建
创建结构体
1 2 3 4 5 struct Student { string name; int age; int score; }s3;
实例化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 struct Student s1 ; s1.name = "张三" ; s1.age = 18 ; s1.score = 78.5 ;cout << s1.name << "\t" << s1.age << "\t" << s1.score << endl ;struct Student s2 = { "李四" ,20 ,80.0 };cout << s2.name << "\t" << s2.age << "\t" << s2.score << endl ; s3.name = "王五" ; s3.age = 23 ; s3.score = 90.0 ;cout << s3.name << "\t" << s3.age << "\t" << s3.score << endl ;
7.3 结构体数组
struct Student stuArray[2] = {{"张三",18,60},{"李四",20,80}};
索引从第 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 #include <iostream> using namespace std ;struct Student { string name; int age; double score; };int main () { struct Student stuArray [3] = { {"张三" ,18 ,20 }, {"李四" ,18 ,20 }, {"王五" ,18 ,20 }, }; stuArray[2 ].name = "赵六" ; stuArray[2 ].age = 20 ; stuArray[2 ].score = 30 ; for (int i = 0 ; i < 3 ; i++) { cout << stuArray[i].name << "\t" << stuArray[i].age << "\t" << stuArray[i].score << endl ; } }
7.4 结构体指针
指向结构体struct Student* p = &s;
,其中struct
可以省略;
访问结构体指针访问p->name
;
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 ;struct Student { string name; int age; double score; };int main () { struct Student s = {"张三" ,18 ,80 }; struct Student * p = &s; cout << p->name <<"\t" << p->age<<"\t" << p->score << endl ; }
7.5 结构体嵌套结构体
结构体 1 作为结构体 2 的成员变量;
结构体 1 应该定义在结构体 2 前面;
结构体里结构体赋值t.stu.score = 80;
或者t.stu = { "张三",20,100 };
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 #include <iostream> using namespace std ;struct Student { string name; int age; double score; };struct Teacher { int id; string name; int age; struct Student stu ; };int main () { Teacher t; t.id = 01 ; t.name = "老师1" ; t.age = 45 ; t.stu.name = "学生1" ; t.stu.age = 18 ; t.stu.score = 80 ; t.stu = { "张三" ,20 ,100 }; cout << t.stu.name << endl ; }
7.6 结构体做函数参数
将结构体作为参数传递到函数里;
值传递,不会修改原对象值;
地址传递,会改变原对象值;
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 #include <iostream> using namespace std ;struct Student { string name; int age; double score; };void printStudent (struct Student s) { cout << "1.打印信息:" << s.name << "\t" << s.age << "\t" << s.score << endl ; };void printStudent (struct Student *p) { cout << "2.打印信息:" << p->name << "\t" << p->age << "\t" << p->score << endl ; };int main () { struct Student s = {"张三" ,18 ,90 }; printStudent(s); printStudent(&s); }
7.7 结构体 const
在某些时候我们需要将结构体变量传入到一个函数内,如果使用值传递就会占用大量的内存空间,因为每调用一次函数,计算机就会赋值出一个新的结构体变量,大小和原变量相同,所以应采用地址传递来节省空间,因为指针只占用
4
个字节。但是使用地址传递会带来一个隐患,即可以在函数体内修改原结构体变量的值,这对数据来说是不安全的,我们需要用
const 进行修饰,使结构体变量不可更改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <iostream> using namespace std ;struct Student { string name; int age; double score; };void printStu (const Student* p) { cout << p->name << "\t" << p->age << "\t" << p->score << endl ; }int main () { Student s = { "张三" ,18 ,90 }; printStu(&s); }
7.8 结构体案例 1
注意字符串字面量和字符相加,使用+=比较好;
随机数种子;
判断数据类型typeid(i).name();
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #include <iostream> using namespace std ;#include <string> #include <ctime> struct Student { string name; int score; };struct Teacher { string name; Student stuArray[5 ]; };void allocateSpace (struct Teacher teaArray[], int len) { string nameSpace = "ABCDE" ; for (int i = 0 ; i < len; i++) { string tname = "Teacher_" ; tname += nameSpace[i]; teaArray[i].name = tname; for (int j= 0 ; j < 5 ; j++) { string sname = "Student_" ; sname += +nameSpace[j]; int sscore = rand() % 61 + 40 ; teaArray[i].stuArray[j].name = sname; teaArray[i].stuArray[j].score = sscore; } } }void printFor (struct Teacher teaArray[], int len) { for (int i = 0 ; i < len; i++) { cout << teaArray[i].name << endl ; for (int j = 0 ; j < 5 ; j++) { cout << "\t" << teaArray[i].stuArray[j].name << "\t" << teaArray[i].stuArray[j].score << endl ; } } }int main () { srand((unsigned int )time(NULL )); struct Teacher teaArray [3]; int len = sizeof (teaArray) / sizeof (teaArray[0 ]); allocateSpace(teaArray, len); printFor(teaArray, len); }
7.9 结构体案例 2
冒泡排序;
临时变量 temp,类型为 hero;
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #include <iostream> #include <string> using namespace std ;struct hero { string name; int age; string sex; };void rink (struct hero heroArray[],int len) { for (int i = 0 ; i < len-1 ; i++) { for (int j = 0 ; j < len - i - 1 ; j++) { if (heroArray[j].age > heroArray[j+1 ].age) { struct hero temp = heroArray[j]; heroArray[j] = heroArray[j+1 ]; heroArray[j+1 ] = temp; } } } }void printHero (struct hero heroArray[], int len) { for (int i = 0 ; i < len; i++) { cout << heroArray[i].name << "\t" << heroArray[i].age << "\t" << heroArray[i].sex << endl ; } }int main () { struct hero heroArray [5] = { {"刘备" ,23 ,"男" }, {"关羽" ,22 ,"男" }, {"张飞" ,20 ,"男" }, {"赵云" ,21 ,"男" }, {"貂蝉" ,19 ,"男" }, }; int len = sizeof (heroArray) / sizeof (heroArray[0 ]); rink(heroArray, len); printHero(heroArray, len); system("pause" ); return 0 ; }
7.10 简单链表
链表:需要的时候就分配一块空间,内存是动态变化的。而数组长度是固定不变的。
实现
定义一个超女结构体,含有编号、姓名、下一个超女的指针;
1 2 3 4 5 6 struct SuperGril { int no; string name; struct SuperGril * next; };
初始化头号超女 header、尾部超女 tail 、临时超女
temp;SuperGril* header = nullptr, * tail = nullptr, * temp = nullptr;
使用临时节点创建超女,并给 header 和 tail 赋值
1 2 3 4 5 6 7 8 9 10 11 temp = new SuperGril ({ 1 ,"西施" ,nullptr }); header = tail = temp; temp = new SuperGril ({ 2 ,"冰冰" ,nullptr }); tail->next = temp; tail = temp; temp = new SuperGril ({ 3 ,"丽英" ,nullptr }); tail->next = temp; tail = temp;
遍历链表
1 2 3 4 5 6 7 temp = header;while (temp!=nullptr ) { cout << "编号" << temp->no << "\t姓名" <<temp->name << "\t下一个节点" << temp->next << endl; temp = temp->next; }
释放链表内存
1 2 3 4 5 6 7 while (header!=nullptr ) { temp = header; header = header->next; delete temp; }
全部代码
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include <iostream> #include <string> using std::cout;using std::string; using std::endl;int main () { struct SuperGril { int no; string name; struct SuperGril * next; }; SuperGril* header = nullptr , * tail = nullptr , * temp = nullptr ; temp = new SuperGril ({ 1 ,"西施" ,nullptr }); header = tail = temp; temp = new SuperGril ({ 2 ,"冰冰" ,nullptr }); tail->next = temp; tail = temp; temp = new SuperGril ({ 3 ,"丽英" ,nullptr }); tail->next = temp; tail = temp; temp = header; while (temp!=nullptr ) { cout << "编号" << temp->no << "\t姓名" <<temp->name << "\t下一个节点" << temp->next << endl; temp = temp->next; } while (header!=nullptr ) { temp = header; header = header->next; delete temp; } printf ("释放完毕\n" ); system ("pause" ); return 0 ; }
8、共同体
共同体占用的内存大小是成员占用内存最大的大小;(内存对齐)
全部成员使用一块内存;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <iostream> using std::string; using std::cout; using std::endl;int main () { union MyUnion { int a; double b; char c[21 ]; }; MyUnion data; cout << "内存占用大小=" << sizeof (data) << endl; cout << "内存地址data.a=" << (void *) &data.a << endl; cout << "内存地址data.b=" << (void *) &data.b << endl; cout << "内存地址data.c=" << (void *) &data.c << endl; system ("pause" ); return 0 ; }
image-20221023115211935
9、枚举
创建常量的一种方式
创建常量的方法:
宏常量,用预处理指令#define 创建
用 const 关键字创建;
枚举
注意事项:
枚举创建的变量取值只能在枚举范围之内;
枚举的作用域与变量的作用域相同;
可以设置枚举量的值
整型强制转为枚举量:Colors cc = Colors(1);
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 #include <iostream> using std::string; using std::cout; using std::endl;int main () { enum Colors { red=0 ,yellow,blue,other }; Colors color = red; switch (color) { case red: cout << "红色" << endl; break ; case yellow: cout << "黄色" << endl; break ; case blue: cout << "蓝色" << endl; break ; case other: cout << "红色" << endl; break ; default : cout << "未知" << endl; break ; } system ("pause" ); return 0 ; }
10、指针
1 2 3 4 5 6 7 8 9 10 double dval;double * pd = &dval;double * pd2 = pd; *pd2 = 2.0 ;cout << "dval是" <<dval << endl ;cout << "dval的地址是" <<&dval << endl ;cout << "*pd是" <<*pd << endl ;cout << "pd的地址是" <<&pd << endl ;cout << "pd本身是" <<pd << endl ;cout << "pd2是" <<*pd2 << endl ;
dval 是 2 dval 的地址是 0000004D63EFF808 pd 是 2 pd 的地址是
0000004D63EFF828 pd 本身是 0000004D63EFF808 pd2 是 2
11、函数
11.1 函数默认值
如果一个形参位置已经有默认值,则后面的形参都得有默认值;
如果函数声明中形参已经有默认值,在函数定义时就不能给默认值,否则会报错;
1 2 3 4 5 6 7 8 9 10 #include <iostream> using namespace std ;int f1 (int a, int b = 20 , int c = 30 ) { return a + b + c; }int main () { f1(10 ); f1(10 ,60 ); }
声明和定义
1 2 3 4 5 6 7 8 9 #include <iostream> using namespace std ;int f2 (int a = 10 , int b = 10 ) ;int f2 (int a = 10 ,int b = 10 ) { }int main () { f2(); }
报错:f2 重定义默认参数
11.2 函数占位参数
c++函数形参列表可以有站位参数,但调用函数时必须补齐该位置;
语法:数据类型int 函数名f(数据类型int)
;
占位参数也可以有默认参数;
1 2 3 4 5 6 7 8 void f (int ) { cout << "你好" << endl ; }int main () { f(10 ); }
默认参数
1 2 3 4 5 6 7 8 void f (int = 10 ) { cout << "你好" << endl ; }int main () { f(); }
11.3 函数的重载
同一个作用域内;
函数名相同;
函数参数类型不同 或者个数不同 或者顺序不同 ;
函数名可以相同,提高复用性;
返回值不可以作为重载的条件;void f()和int f()
;
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 #include <iostream> using namespace std ;void f () { cout << "f()调用了!" << endl ; }void f (int a) { cout << "f(int a)调用了!" << endl ; }void f (int a,int b) { cout << "f(int a,int b)调用了!" << endl ; }void f (double b) { cout << "f(double b)调用了!" << endl ; }int main () { f(); f(10 ); f(10.0 ); f(10 ,20 ); }
11.4 函数重载注意事项
引用作为重载的条件;
1 2 3 4 5 6 7 8 9 10 11 12 13 #include <iostream> using namespace std ;void f (int &a) { cout << "f(int &a)调用了!" << endl ; }void f (const int &a) { cout << "f(const int &a)调用了!" << endl ; }int main () { int a = 10 ; f(a); f(10 ); }
函数重载遇见默认参数
1 2 3 4 5 6 7 8 9 10 11 12 #include <iostream> using namespace std ;void f (int &a,int &b = 10 ) { cout << "f(int &a ,int &b = 10)调用了!" << endl ; }void f (int &a) { cout << "f(const int &a)调用了!" << endl ; }int main () { int a = 10 ; f(a); }
11.5 内联函数
函数声明之后定义,在主函数中被多次调用,原始写法:这样的写法会使程序在函数之间来回跳转,消耗一定的执行速度代价。使用内联函数的方法可以将
show 函数放在 main
函数里,避免来回跳转;但会占用一定的内存;使用较小的函数体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> using std::cout; using std::endl; using std::string;void show (const short num, const string message) ;int main () { show (1 , "我是啥啥鸟" ); show (2 , "我是啥啥鸟" ); show (3 , "我是啥啥鸟" ); system ("pause" ); return 0 ; }void show (const short num, const string message) { cout << "亲爱的" << num << "号," << message << 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 inline void show (const short num, const string message) ;int main () { show (1 , "我是啥啥鸟" ); show (2 , "我是啥啥鸟" ); show (3 , "我是啥啥鸟" ); system ("pause" ); return 0 ; }inline void show (const short num, const string message) { cout << "亲爱的" << num << "号," << message << endl; }