C plus plus
一、数据类型
1 |
|
数据类型:
- 基本数据类型:短整型(short)、整型(int)、长整型(long)
- 构造类型:布尔型、枚举类型、数组类型、结构体类型、公用体类型、类类型
- 指针类型
- 引用类型
- 空类型
其他常量:
- 布尔常量:布尔类型只有两个,一个true(真),一个false(假)
- 枚举常量:枚举型数据中定义的成语也是常量
- 宏定义常量:通过#define宏定义的一些值也是常量。例如:define PI 3.14
字符变量:
1 |
|
允许对字符数据进行算术运算,此时就是对它们的ASCII码值进行算术运算:
1 |
|
数据的输入与输出:
控制台的屏幕
cout:cout<<表达式1<<表达式2<<…<<表达式n;
例如:cout<<“Hello,World!”;
cin: cin>>变量1>>变量2>>…变量n;
例如:cin >> x;
操作控制:在头文件iomanip.h中定义了一些控制流输出格式的函数,默认情况下整型数按十进制形式输出,也可以通过hex将其设置为十六进制输出。
sizeof运算符:
功能是返回指定的数据类型或者表达式值的数据类型在内存中占用的字节数。
- sizeof(类型说明符) eg:sizeof(int)
- sizeof (表达式) eg: sizeof(2+3)
- sizeof 表达式 eg: sizeof 66
| Sizeof(基本类型) | 字节数 |
|---|---|
| sizeof(char) | 1 |
| sizeof(bool) | 1 |
| sizeof(short) | 2 |
| sizeof(int) | 4 |
| sizeof(float) | 4 |
| sizeof(double) | 8 |
例一:
- sizeof(void):错误,无法对void类型使用sizeof运算符
- sizeof(void*):正确,返回4空指针占用4个字节
- sizeof(66):正确,返回4,整型常量占用4个字节
- sizeof(2==3):正确,返回1,等价于sizeof(bool)
例二:
sizeof(unsigned int):
1 | int func1() |
1 | typedef int INT ; |
例三:
1 | sizeof(int *) |
==任何类型指针的sizeof运算返回值都是4==
1 | char str[] = "123456789"; //字符数组 |
数组的大小都是==各维数==的乘积* 数组元素的大小。
条件运算符:
1 | C++中仅有的一个三目运算符 |
1 | int x = 5,y = 6,max; |
==条件运算符是至右向左结合的==
1 | int x = 5,y = 6,a = 1,b = 2; |
==条件运算符运算结果的返回值类型是表达式1和表达式2中较高的类型==
1 | int x = 5,y =6; |
类型转换:
隐式转换发生在不同数据类型的量混合运算时,由编译系统自动完成。
1 | int i = 5; |
其他隐式类型转换:
1 | int *p; |
1 | bool flag = true; |
- 算术类型和bool类型可以互相转换,==将算术类型转换成bool类型时,0转换成false,非0转换成true。==
- 将bool类型转换成算术类型时,false转换成0,true转换成1
循环嵌套
打印三角形
1
2
3
4
5
6
7
8
9
10
11
12
13
using namespace std;
int main(){
int i,j,k;
for(i = 1;i <= 5;i++){ //控制行数
for(j = 1;j < 5;j++) //控制空格数
cout << "";
for(k = 1; k <= 2*i - 1;k++) //控制打印*号的数量
cout << "*";
cout << endl;
return 0;
}
}输出乘法口诀表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using namespace std;
int main(void){
int i,j;
i = 1;
j = 1;
for(i = 1;i < 10;i++)
{
for(j = 1;j < i + 1;j ++)
cout << setw(2) << i << "*"<<j<<"="<<setw(2)<<i*j;
}
cout << endl;
return 0;
}
循环应用实例
- 阿姆斯壮数:形如:153 = 1^3^ + 5^3^ + 3^3^
1 |
|
巴斯卡三角形:原理是三角形两个边全输出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
using namespace std;
long combi(int n,int r)
{
int i;
long p = 1;
for(i = 1; i<= r;i++)
p = p*(n-i+1)/i;
return p;
}
int main()
{
int n,r,t;
for(n = 0; n <= 12;n++)
{
for(r = 0;r<=n;r++)
{
int i;
if(r==0)
{
for(i=0;i<(12-n);i++)
cout<<" ";
}else{
cout<<" ";
}
cout << setw(3)<<combi(n,r);
}
cout<<endl;
}
return 0;
}输出结果
1
2
3
4
5
6
7
8
9
10
11
12
131
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1
1 11 55 165 330 462 462 330 165 55 11 1
1 12 66 220 495 792 924 792 495 220 66 12 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
using namespace std;
int main()
int main()
{
int score[101] = {0};
int juni[102] = {0};
int count = 0,i;
do
{
cout << "input score:";
cin >> score[count++];
}while(score[count-1]!=-1);
count--;
for(i=0;i<count;i++)
juni[score[i]]++;
juni[101] = 1;
for(i = 100;i>=0;i--){
juni[i]=juni[i]+juni[i+1];
}
cout << "Result:"<<endl;
for(i=0;i<count;i++)
{
cout << score[i] <<"is";
cout << juni[score[i]+1] << endl;
}
return 0;
}
五、函数
5.1、函数参数以及返回值
1 | int function(int a,int b); //形参 |
形参与实参的区别
- 形参在调用函数时,才分配内存,调用结束后,释放内存。
- 实参是确定的值,在调用时,将实参的值赋值给形参。
- 实参与形参的个数应相等,类型应相同。
- 实参与形参之间是单项传递的,只能由实参传递给形参。
注意:==如果某一个形参有默认值,那么其后所有的参数都需要有默认值,否则不合格。==
1 | int GetMax(int x,int y = 10,int z){}//错误的写法 |
5.2、函数调用
1 | int Max(int x,int y); //函数声明 |
5.3、重载函数
定义:多个函数具有相同的函数标识符,而参数类型或者参数个数不同。
1 | int Max(int x,int y) |
没有重载函数时:
1 | int iAdd(int x,int y) |
有重载函数时:
1 | int Add(int x,int y) |
5.4、内联函数
通过inline关键字可以把函数定义为内联函数,编译器会在每个调用该函数的地方展开一个函数的副本。
1 |
|
5.5、变量的存储类别
auto 变量
1
auto int i,j,k;
特点:
- 自动变量的作用域仅限于定义该变量的个体内
- ==自动变量属于动态存储方式==
- 不同的个体允许使用同名的变量而不会混淆
static 变量
1
static int a,b;
特点:
- 静态变量在函数内定义,在程序退出时释放。
- 静态变量的作用域与自动变量相同,在哪个{}内定义,在哪使用。
- 编译器会为静态局部变量赋予0值。
register 变量
- 寄存器变量属于动态存储方式。凡需要采用静态存储方式的量不能定义为寄存器变量。
- 编译程序会自动决定哪个变量使用寄存器存储。Register起到程序优化的作用。
extern 变量
六、指针和引用
6.1、一维数组
在程序设计中,将同一数据类型的数据按一定形式有序的组织起来,这些有序数据的集合就称为数组。一个数组有一个统一的数组名,可以通过数组名和下标来唯一确定数组中的元素。
声明形式:数据类型 数组名[常量表达式]
例如:
1 | int a[10]; //声明一个整型数组,有10个元素 |
使用数组的说明:
- 数组名的定名规则和变量名相同
- 数组名后面的括号是方括号,方括号内是常量表达式
- 常量表达式表示元素的个数,即数组的长度。
- ==定义数组的变量表达式不能是变量,因为数组的大小不能动态定义。==
一般形式:数组名[下标]
1 | int a[10]; //声明数组,a[0]~a[9]是对数组a中10个元素的引用 |
两种方式:
单一数组元素赋值
1
2
3
4
5char a[3];
a[0] = 'a';
a[2] = 'c';
int i = 0;
cout << a[i] <<endl;聚合方法赋值
1
2
3
4
5int a[12] = {1,2,3,4,5,6,7,8,9,10,11,12};
或者:
int a[] = {1,2,3,4,5,6,7,8,9,10,11,12};
或者:
int a[12] = {1,2,3,4,5,6,7};举例:一维数组赋值
1
2
3
4
5
6
7
8
9
10
using namespace std;
int main()
{
int i,a[10];
for(i = 0;i < 10;i++)
a[i] = i;
for(i = 0;i < 10;i++)
cout << a[i] << endl;
}
6.2 、二维数组
声明形式:数据类型 数组名[常量表达式1][常量表达式2]
1 | int a[3][4]; //声明3行4列元素的整型数组 |
注意:定义数组的常量表达式不能是变量,因为数组的大小不能动态定义。
错误写法:int a[i][j];
引用形式:数组名[下标][下标]
单一数组元素赋值:
1
myArray[0][1] = 12
聚合方法赋值
1
2
3int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
或者
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
6.3、字符数组
用来存放字符数据的数组是字符数组,字符数组中的一个元素存放一个字符。字符数组具有数组的共同属性。由于字符串应用广泛,C和C++专门为它提供了许多方便的用法和函数。
1 | char pWold[11]; |
两种方式:
单一数组元素赋值
1
2
3
4
5pWold[0] = 'H';
pWold[1] = 'E';
pWold[2] = 'L';
pWold[3] = 'L';
pWold[4] = 'O';聚合方法赋值
1
char pWold[] = {'H','E','L','L','O','','W','O','R','L','D'};
聚合方式==只能在数组声明的时候使用==。
1
2
3
4char pWord[5] = {'H','E','L','L','O'}; //正确
char pWord[5];
pWod = {'H','E','L','L','O'}; //错误==字符数组不能给字符数组赋值==
1
2
3
4char a[5] = {'H','E','L','L','O'};
char b[5];
a = b; //错误写法
a[0] = b[0]; //正确写法字符数组常作字符串使用,作为字符串要有字符串结束符
‘\0’1
2
3
4
5//可以使用字符串为字符数组赋值
char a[] = "HELLO WORLD";
等价于:
char a[] = "HELLO WORLD\0";
//字符串结束符'\0'主要告知字符串处理函数字符串已经结束了,不需要再输出了。
举例:==使用字符串结束符”\0”防止出现非法字符==
情形一:未使用”\0”
1 |
|
情形二:使用”\0”
1 |
|
案例:
1 |
|
字符串处理函数
strcat函数
字符串链接函数strcat格式如下:
strcat(字符数组名1,字符数组名2)字符串连接函数strcat功能:
把字符数组2中的字符串连接到字符数组1中字符串的后面,并删去字符串1后的串结束符”\0”
情形一:使用strcat函数连接字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using namespace std;
int main(){
char str1[30],str2[20];
cout << "please input string1:" <<endl;
gets(str1);
cout << "please input string2:" <<endl;
gets(str2);
strcat(str1,str2); //连接两个字符串
cout << "Now the string1 is:" << endl;
puts(str1);
return 0;
}情形二:不使用strcat函数连接字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using namespace std;
int main()
{
int i = 0,j = 0;
char a[100],b[50];
cout << "please input string1:" <<endl;
cin >> a;
cout << "please input string2:" <<endl;
cin >> b;
while(a[i]!='\0');
a[i++] = b[j++];
a[i]='\0';
cout << a << endl;
return 0;
}strcpy函数
字符串复制函数strcpy格式如下:
strcpy(字符数组名1,字符数组名2);字符串复制函数strcpy功能:
把字符数组2中的字符串拷贝到字符数组1中。字符串结束标志”\0”也一同拷贝。
注意:字符串复制函数strcpy说明:
- 要求字符数组1应有足够的长度,否则不能全部转入所拷贝的字符串。
- “字符数组1”必须写成数组名形式,而”字符数组2“可以是字符数组名,也可以是一个字符串常量,这时相当于把一个字符串赋予一个字符数组。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using namespace std;
int main()
{
char str1[30],str2[20];
cout << "please input string1:" << endl;
gets(str1);
cout << "please input string2:" << endl;
gets(str2);
strcpy(str1,str2);
cout<<”Now the string1 is:\n“<<endl;
puts(str1);
}strcmp函数
字符串比较函数strcmp格式如下:
strcmp(字符数组名1,字符数组名2);字符串比较函数strcmp功能:
- 按照ASCII码顺序比较两个数组中的字符串,并由函数返回值返回比较结果。
- 字符串1=字符串2,返回值为0
- 字符串1>字符串2,返回值为一正数
- 字符串1<字符串2,返回值为一负数
- 可用于比较两个字符串常量,或比较数组和字符串常量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using namespace std;
int main()
{
char str1[30],str2[20];
int i = 0;
cout << "please input string1:" << endl;
gets(str1);
cout << "please input string2:" << endl;
gets(str2);
i = strcmp(str1,str2);
if(i>0)
cout<<"str1>str2"<<endl;
else
if(i<0)
cout<<”str1<str2“<<endl;
else
out<<”str1=str2“<<endl;
}strlen函数
字符串长度计算函数strlen格式如下:
strlen(字符数组名1,字符数组名2);字符串长度计算函数strlen功能:
计算字符创的实际长度(不含字符串结束符‘\0’),函数返回值为字符串的实际长度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using namespace std;
int main()
{
char str1[30],str2[20];
cout << "please input string1:" << endl;
gets(str1);
cout << "please input string2:" << endl;
gets(str2);
len1 = strlen(str1);
len2 = strlen(str2);
cout << "the length of string1 is:" << len1 <<endl;
cout << "the length of string2 is:" << len2 <<endl;
}
6.4、指针
指针是一种数据类型,通常所说的指针就是指针变量,它是一个专门用来存放地址的变量,而变量的指针主要在内存中的地址。变量的地址在编写代码时无法获取,只有在程序运行时才可以得到。
指针声明:
一般形式:数据类型标识符 *指针变量名;
1 | int *p_iPoint; //声明一个整型指针 |
指针的赋值:
指针可以在声明的时候赋值,也可以在后期赋值。
1 | //初始化时赋值: |
指针使用的说明:
指针变量名是p,而不是* p.
1
2
3int a = 100;
int *p;
p = 100;指针变量不可以直接赋值。
1
2
3
4
5int a = 100;
int *p;
p = (int*)100; //通过强制类型转换将100赋值给指针变量
printf("%d",p); //输出地址,能够输出地址
printf("%d",*p); //输出指针指向的值,出错语句不能将* p当变量使用。
1
2
3
4
5int a = 100;
int *p;
*p = 100; //指针没有获得地址
printf("%d",p); //输出地址,出错语句
printf("%d",*p); //输出指针指向的值,出错语句
指针运算符和取地址运算符
简介
- 和&是两个运算符, * 是指针运算符,&是取值运算符。
- 与&说明
1
2
3
4
5
6
7
using namespace std;
int main(){
int a = 100;
int *p = &a;
printf("%d",*p);
}&* p与 * &a的区别
&和* 的运算符优先级相同,按自右而左的方向结合,因此& * p是先进行 * 运算==, * p相当于取变量a==;再进行&运算,& * p相当于取变量a的地址。
- &a是先计算&运算符,==&a就是取变量a的地址==,然后计算 * 运算, * &a就相当于取变量a所在地址的值,实际就是变量a。
指针运算:
输出指针运算后的地址
1 |
|
输出结果
1 | address:2102634740 |
6.5、指针与数组
数组的存储
数组,作为同名,同类型元素的有序集合,被顺序存放在一块连续的内存中,而且每个元素存储的大小相同。数组第一元素的存储地址就是整个数组的存储首地址,该地址放在数组名中。
对于一维数组而言,其结构是线性的。所以数组元素按下标值由小到大的顺序依次存放在一块连续的内存中。
指针与一维数组
通过指针变量获取数组中的元素
1 |
|
指针与二维数组
使用指针变量遍历二维数组
1 |
|
指针与字符数组
连接两个字符数组
1 |
|
6.6、指向函数的指针
一般形式:类型名 * 函数名(参数表列);
1 | int *a(int x,int y); |
:ship::使用指针函数进行平均值计算的功能
1 |
|
:coffee:函数指针与指针函数
指针函数:就是返回指针的函数,其本质是一个函数,而返回值是一个指针,
1 | int *fun(int x,int y); |
函数指针:其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。
1 | int (*fun)(int x,int y); |
==指针函数本质是一个函数,其返回值为指针。==
==函数指针本质是一个指针,其指向一个函数。==
6.7、引用
引用实际上是一个隐式指针,它为对象建立一个别名,通过操作符&来实现。==&是取地址操作符,通过它可以获得地址==。
一般形式:数据类型 & 表达式;
1 | int a = 10; |
使用引用的说明:
- 一个C++引用被初始化后,无法使用它再去引用另一个对象,它不能被重新约束。
- 引用变量只是其他对象的别名,对它的操作与原来对象的操作具有相同的作用。
- 指针变量与引用有两点主要区别:一是:==指针是一种数据类型==,而引用不是一个数据类型;二是:指针变量和引用变量都用来指向其他变量,但指针变量使用的语法要复杂一些;而在定义了引用变量后,其使用方法与普通变量相同。
- 引用应该初始化,否则会报错。
使用引用传递参数:
通过引用交换数值
1 |
|
使用指针传递参数:
例如:交换数值
1 |
|
数组做函数参数
举例:输出每行数组中的最小值
1 | int mix(int (*a)[N],int m) //进行比较和交换的函数 |
6.8、指针数组
一般形式:数据类型 * 数组名[数组长度];
1 | int *p[4]; |
==指针数组中的数组名也是一个指针变量,该指针变量为指向指针的指针。==
1 | int *p[4]; |
p是一个指针数组,它的每一个元素是一个指针型数据(其值为地址),指针数组p的第一个值是变量a的地址。指针数组中的元素可以使用指向指针的指针来引用。
1 | int *(*p); //等价于 int **p; |
- 运算符表示p是一个指针变量, * ( * p)表示指向指针的指针, * 运算符的结合性是从右到左。
指向指针的指针获取指针数组中的元素和利用指针获取一维数组中的元素方法相同。
七、构造数据类型
7.1、结构体
结构体定义:
1 | struct 结构体类型名 |
:ship::定义一个简单员工信息的结构体
1 | struct PersonInfo |
结构体变量
结构体变量是一个构造类型,前面只是定义了结构体,形成一个新的数据类型,还需要使用该数据类型来定义变量。结构体变量有两种声明形式。
第一种声明形式是在定义结构体后,使用结构体类型名声明。例如:
1
2
3
4
5
6
7struct PersonInfo
{
int index;
char name[30];
short age;
};
PersonInfo pInfo;另一种是定义结构体时直接声明,例如:
1
2
3
4
5
6struct PersonInfo
{
int index;
char name[30];
short age;
}pInfo;
结构体成员及初始化
引用结构体成员有两种方式,一种是声明结构体变量后,通过成员运算符”.”引用,一种是声明结构体指针变量,使用指向”->”运算符引用。
使用成员运算符”.”引用结构体成员
形如: 结构体变量名.成员名
1
2
3
4
5
6
7
8
9struct PersonInfo
{
int index;
char name[30];
short age;
}pInfo;
pInfo.index
pInfo.name
pInfo.age在定义结构体时,可以同时声明结构体指针变量,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13struct PersonInfo
{
int index;
char name[30];
short age;
}*pPersonInfo;
//如果要引用指针结构体变量的成员,需要使用指向"->"运算符,一般形式如下:
// 结构体指针变量->成员名
pPersonInfo->index
pPersonInfo->name
pPersonInfo->age
结构体指针作函数参数
使用结构体指针变量做函数参数时传递的只是地址,减少了时间和空间上的开销,能够提高程序的运行效率。这种方式在实际应用中效果比较好。
1 |
|
对象的声明
声明的形式:类名 对象名表
1 | CPerson p; //声明一个对象 |
对象引用的方式:
成员引用方式:
一般形式:
对象名.成员名1
2
3CPerson p;
p.m_ilndex;
p.getIndex();对象指针方式:
一般形式:
对象指针名 -> 数据成员1
2
3CPerson *p;
(*p).m_iIndex; //对类中的成员进行引用
p->m_iLindex; //对类中的成员进行引用
