⦁ C++基础 1. 数据类型 主要有五类数据类型:布尔类型,字符型,整型,浮点型和无类型。 部分数据类型及所占位数: 数据类型 C++语言表示 所占位数 范围 字符型 char 8b(1字节) -128~127或0~255 无符号字符型 unsigned char 8b(1字节) 0~255 整型 int 32b(4字节) -2147483648~2147483647 无符号整型 unsigned int 32b(4字节) 0~4294967295 有符号整型 signed int 32b(4字节) -2147483648~2147483647 短整型 short int 16b(2字节) -32768~32767 无符号短整型 unsigned short int 16b(2字节) 0~65535 长整型 long int 64b(8字节) -9223372036854775808 ~9223372036854775807 无符号长整型 unsigned long int 64b(8字节) 0~18446744073709551615 单精度浮点数 float 32b(4字节) 1.17549e-38~3.40282e+38 双精度浮点数 double 64b(8字节) 2.22507e-308~1.79769e+308 不同数据类型之间可以通过强制转换的方式进行更改,即在变量前使用“(数据类型)”的方式改变,但由精度高的数据类型向精度低的转换过程中,将会造成部分数据的丢失。 1. 语法 2.1 程序入口 main()函数是入口函数也是主函数,且main函数的返回类型必须是int类型,否则程序就会出现错误,main函数返回值也必须是整数,因此一般在main函数最后写return 0;。 2.2 注释 加入注释可以清晰地回顾编程的思路,在C++语言中,注释分为两种,一种是单行注释,另一行是多行注释。 单行注释用(//)引起,只能注释一行。 多行注释用(/*)开头,用(*/)结束,可以注释多行。 2.3 变量的定义及使用 变量实质上是程序告诉计算机内存需要开辟一块多大的地方,然后计算机把所开辟的内存地址给程序,当我们利用等号(=)给变量赋值时,该地址中存储的数据就是我们赋给它的数值。 变量的命名也是具有一定规则的,其规则如下: 由字母(包含字母大小写),数字(0~9)和下划线(_)组成。 不能以数字开头。 区分大小写。 变量不易过长。 不能使用关键字。 变量在使用之前必须声明,就是定义变量的类型。 2.4 语句结束符 标志这条语句结束的标志就是英文(;)。代表这条语句结束。 2.5语句块与缩进 为了便于逻辑的表达,我们会将同一逻辑语句形成一个逻辑语句块,一个语句块是由一对花括号“{}”括起来。同一逻辑的语句块的起始块位置的缩进(即空格数)是相同的。 2.6 作用域 根据变量的作用域不同,可以分为局部变量和全局变量。所谓作用域就是指变量在什么范围内有效。 2.7 常量与转义字符 常量在字面上与变量含义相对,是指在程序执行过程中不会改变的一些量,常量可以是任意数据类型,在自定义常量时,一般会把常量的所有字母定义为大写,变量一般为小写字母。 常量定义有两种格式: const 数据类型 常量名称=值; #define 常量名称 值 这两者的差异在于:#define是在编译前将值赋给常量名,后面编译的时候不再检查语法错误;const是一个关键字,是将变量转为常量,在编译过程中会检查该赋值是否正确。 C++中一些特殊的字符需要使用转义字符来实现,格式为: 反斜杠(\)+特殊字符。 常见的转义字符: 转义字符 输出字符 \\ \ \’ ‘ \’’ “ \? ? \n 换行符 \r 回车(不换行) \t 水平制表符 1. 运算符 3.1位运算符 位运算分为位逻辑运算与移位运算(对应二进制位): 含义 C++语言表示 规则 与运算 a&b 都为1时为1,反之为0。 或运算 a|b 两个数其中一个为1就为1,反之为0。 异或运算 a^b 两个数不同时结果为1,反之为0。 取反运算 ~a 对数值进行取反。 左移运算 a<<b 左移b位乘以2的b次幂。(二进制数向左移动b位,高位丢弃,在后面添b个0) 右移运算(带符号运算) a>>b 右移b位除以2的b次幂(取整);(二进制数右移b位,去掉末b位);对于有符号的,在右移时,符号位随之移动;为正数时,最高位补0;为负数时,符号位为1,最高位时补0或是1取决于编译系统。 注:在逻辑运算中,数学表示符于编程逻辑的对应关系为: ∧表示与 ∨表示或 ¬表示非 3.2算术运算符 算术运算符在c++中有7中:加(+)减(-)乘(*)除(/)取余(%)自增(++)自减(--)。 注意:在做除法运算时,当除数与被除数都是整数时,得到的结果也是整数,当其中一个是浮点数时,结果才为浮点型。 取余运算又叫做模运算,x%y是指x除以y后取其余数(其中x和y均为整数)。 自增和自减运算时针对某个变量的加一减一操作,而++或--放在变量前和变量后有差别。 ++变量:将计算结果先赋值给该变量再使用。 变量++:先使用该变量,再进行加1或减1操作。 结果: 算术运算符优先级:自增和自减》乘除取余》加减乘除,当遇到()先算()内的。 3.3关系运算符 关系运算符是双目运算关系,也就是再运算符左右两边都有内容。 关系运算符包括: 等于(==) 不等于(!=) 大于(>) 小于(<) 大于等于(>=) 小于等于(<=) 输出的结果为布尔类型。 3.4逻辑运算符 逻辑运算符包含3种,分别是与(&&),或(||),非(!)。 与运算:当两边都为1时,结果才为1。 或运算:当一边为1时,结果就为1。 非运算:取反。 优先级: !>&&>|| 算术运算符》关系运算符》逻辑运算符。 3.5赋值运算符 赋值运算符包含两种:简单和复合赋值运算符。 简单赋值运算符:= 复合赋值运算符:+=,-=,*=,/=... x+=y就相当于x=x+y 其他复合赋值运算符一样。 3.6三目运算符 三目运算符格式:条件?a:b; 该运算符指的是当条件成立时输出a,否则输出b。 1. 输入,输出 C++语言中并没有专门的输入输出语句,需要调用库函数来实现,在信息学奥赛中输入输出有两种基本形式,一种是在程序运行提示符下输入输出,另一种是利用文件输入输出。 在程序运行提示符下进行输入输出也有两大类,一类是输入,输出流,用到的库是iostream,另一类是通过格式化输入输出,用到的库是cstdio。除了上述两类在命令提示符下输入输出的以外,如果要输入输出字符可以使用getchar()函数和putchar()函数,其中getchar()函数只接受输入的第一字符,putchar()函数可以将十进制数,十六进制数,转义字符,字符等输出。 4.1输入,输出流 输入输出流格式: cin>>变量;(可连续输入) cout<<变量;(可连续输出) 如果想要进行换行的话,可以通过endl和“\n”的方式进行。 将十进制数输出成八进制或十六进制数,其格式如下: cout<<oct<<表达式;//oct 表示八进制数 cout<<hex<<表达式;//hex 表示十六进制数 转为二进制数,则需要引入bitset库文件,其格式如下: cout<<bitset<sizeof(变量类型)>(变量); 如将整型变量a=8,转换为二进制数: cout<<bitset<sizeof(int)>(a); 4.2格式化输入,输出 格式化输入使用的函数是scanf(),其格式如下: scanf(输入格式,内存地址); 输入格式中包含对应变量的格式符合变量之间的分隔符,例如要输入两个整型变量,且输入数值之间以“:”分割,输入格式写为“%d;%d”,其中%d为格式,代表输入的数值是十进制整数,“;”代表用户输入过程中不同数值之间的间隔符号,如果没有分隔符,用户可以使用空格来分隔不同变量值。 格式 说明 %d(%i) 十进制整数 %u 无符号十进制整数 %o 八进制整数 %x 十六进制整数 %c 字符 %s 字符串 %f(%e) 实数 若变量类型为长整型或双精度浮点型,可以在%后增加l,例如: 长整型表示为%ld,double类型表示为%lf。 在scanf()函数中,最后一部分表示的是各个变量的内存地址,用“&”号表示。 格式化输出使用的函数是printf(),其格式如下: printf(输出格式,输出量); 要求输出的实数保留两位小数时,其格式为%.2f。 要求输出整数保留四位数时,其格式为%4.2f。 当整数部分位数不足,需要补0的时候,格式表示为%04.2f。 需要输出实数在格式上左对齐,格式为%-04.2f。 4.3文件输入,输出 文件的输入,输出根据打开方式的不同分为3种形式,分别是通过输入,输出重定向(freopen函数,需要引入的库文件为cstdio)的方式,输入,输出流(输入流ifstreamfin(),输出流ofstream fout(),需要引入的库文件为fstream)的方式和FILE指针(fopen函数,需要引入的头文件为cstdio)的方式。 重点讲解输入,输出重定向的方式使用的输入和输出。 输入,输出重定向使用时需要引入库文件cstdio,因此在输入输出数据时建议使用scanf和printf的方式,当然也可以使用cin和cout。 读取文件格式为: freopen(“文件名”,“r”,stdin);r代表只读的方式,stdin表示标准输入方式。 注意这里只是表示打开文件,文件内部的数据并没有被程序读取,需要通过 scanf函数来读取。 写入文件格式为: freopen(“文件名”,“w”,stdout);w代表写入的方式,stdout表示标准输出 的方式,与读取文件相同,表示定义一个输出的文件,如果想要将数据写入文 件中需要通过printf函数来写入。 在完成数据写入后需要将定义的输入与输出做关闭处理,即通过fclose函数实现。 fclose(stdcin); fclose(stdout); 【例题】:给定一组数据,判断这一组数据分别是奇数还是偶数,奇数输出1,偶数输出-1,输出结果之间用空格间隔。 【输入格式】:从文件in.in中读取数据,共一行,数据之间以空格间隔。 【输出格式】:输出out.out文件中,输出共一行,不同结果之间以空格间隔。 【输入】 1 3 4 6 7 9 【输出】1 1 -1 -1 1 1 ⦁ 程序三大基本结构 1. 顺序结构 流程图符号表示含义: cmath库常用数学函数: 函数 说明 sin() cos() tan() 三角函数,分别求正弦,余弦,正切值 asin() acos() atan() 反三角函数,分别求反正弦,反余弦,反正切值 ceil() floor() 求整数函数,ceil(向上取整)返回不小于该数的最小整数,floor(向下取整)返回不大于该数的最大整数 exp() 求以自然数e为底的幂函数值 log() 求自然数e的对数值 log10() 求以10为底的对数值 abs() 求绝对值 1. 分支结构 2.1 if_else结构 使用格式: 单个或两个条件使用: 三个条件及其以上使用: 【例题1】:判断一个数是否能既被3整除,又被7整除。如果成立,则输出yes,否则输出no。 【例题2】:根据用户输入成绩(整数)判断该成绩的等级,等级分为5级,分别是优秀(90~100),良好(80~89),一般(70~79),及格(60~69)和不及格(60以下)。 2.2 switch case结构 语句格式: 【例题1】:根据输入的1~7的数字,输出所对应的星期。例如输入1,输出星期一。 【例题2】:在一维数组中输入5个数字,在输入n(1~4),n=1表示求该数组的从大到小进行排列输出,n=2表示该数组从小到大排列输出,n=3表示求该数组的平均值,n=4表示求该数组的总和。不在区间时,输出“你输入错误了!!!”。 【例题3】 #include<iostream> #include<bits/stdc++.h> #include<windows.h> using namespace std; int main(){ int a[5]={1,2,3,4,5}; //主界面 while(1){ cout<<"欢迎来到小功能实现程序(选项对应功能):"<<endl; cout<<"1.求出数组中的最大数。"<<endl; cout<<"2.求数组的平均数。"<<endl; cout<<"3.求数组的和。"<<endl; cout<<"4.求数组的最小数。"<<endl; cout<<"5.退出程序。"<<endl; int n; cin>>n; if(n==5){ cout<<"感谢使用"; break; } switch(n){ case 1:{ break; } case 2:{ int num=0; for(int i=0;i<5;i++){ num+=a[i]; } num=num/5; cout<<"该数组平均数为:"; cout<<num; Sleep(2000); system("cls"); break; } } } } 3循环结构 3.1 for循环 for循环语句结构如下: 在循环过程中,如果要跳出循环,通过break关键字可以强制跳出循环体的执行,与此同时,如果要跳出其中某次循环体的执行,后面继续执行循环体内容,则需要使用continue关键字。 【例题1】:将n(小于200)以内所有偶数相加,并输出所有偶数之和。 while循环语句结构如下: 3.2 while循环 while循环语句结构如下: 3.3 do-while 循环 do while循环语句结构如下: ⦁ 数组 1. 一维数组 数组与变量的使用相同,都要先定义后使用。 一维数组定义格式: 数据类型 一维数组名[数组长度]; 如果定义数组的类型是int类型,则这个数组内所有的元素都是int类型,从数组中查找该数组中某个元素,需要通过数组下标查找,下标的值是从0开始的。定义一维数组int a[6];就相当于在内存中开辟了6个int长度的空间。 1. 二维数组 二维数组格式: 数据类型 二维数据名[行数][列数]; ⦁ 自定义函数与指针 ⦁ 自定义函数 在c++语言中自定义函数有其自身的语法形式如下: 数据类型 函数名(形参){ 函数体; } 函数部分的参数分为形参和实参,这里参数是指在声明和调用函数过程中传递的数据,形参是定义函数的时候声明的需要接收的数据,实参是指调用函数时赋给的数据。定义的函数可以有一个或多个形参(中间以“,”分隔),当然也可以没有形参。值得注意的是,定义的函数中形参数量要与调用函数中实参数保持一致,否则会出现错误。 ⦁ 内联函数 C++语言中还存在一种加快函数调用的方法,即内联函数,缺点:操作非常少,且运算简单。格式为: 【例】要定义一个返回最大值的内联函数,方法如下: ⦁ 指针 指针可以理解成一种变量的形式,它的值是另一个变量的内存地址,直接指向内存,用“*”表示。 【例】: 注意内存地址都是十六进制数,以0x开头。 ⦁ 函数的参数传递 ⦁ 按值传递 按值传递的过程中实质上是将调用函数中的实参复制一份给形参,然而如果要传递数组,当数组非常庞大时,利用这种方法比较耗时,因为程序将数组中所有元素复制一份传递给形参进行计算。 【例】: ⦁ 地址传递 地址传递并不是将实参中的值复制一份传给形参,而是将实参变量所在的内存地址传给形参,当形参对变量做加一时,实参也会发生变化。 【例】: 注意:地址传递方法传递的一般为变量,常量和表达式是不能通过这种方式传递的。 4.3指针传递 在指针部分我们了解到,指针实质上是指向内存地址的,因此函数的指针传递实参是内存地址,形参是指针,意味着将某个变量的内存地址传给某个指针。 【例】: ⦁ 递归 递归实质上是一种动态规划的算法。 【例1】:给定一个正整数n,求n!(n的阶乘,其公式是n*(n-1)*(n-2)...*1),输入10,输出3628800。 ⦁ 数组传递参数 c语言中是不允许将数组作为参数进行传递的,而c++是可以的。 ⦁ 一维数组传递参数 从自定义函数的角度来看形参,一维数组传递参数主要有两种方式:一种是以“变量名[]”的方式传递,另一种是传递指向一维数组的指针,以“*变量名”的方式传递。在调用自定义函数时,所传递的一维数组不管是形参是哪种方式,实参只用填写变量名即可。 【例】:输入一个具有n个整数的数组,并通过传参的形式传给自定义函数,求出该数组的平均值与总和。 【输入格式】:第一行一个正整数n,表示共有n个整数。第二行n个整数,整数间用一个空格分隔。 【输出格式】:第一行输出该数组的平均值。第二行输出该数组的总和。 ⦁ 二维数组传递参数 二维数组传递参数要比一维数组复杂,从自定义函数角度来看,二维数组传递参数有三种形式:第一种是直接传递数组(注意,自定义函数的形参中必须标注二维数组的第二维大小,如第二维有5个元素,形参写作a[][5]);第二种是传递指针形式(此处的指针与一维数组传递相似,是定义一个指向一维数组的指针,但在二维数组的传递参数过程中需要指明二维数组的第二维的大小,如形参可写作(*a)[5]);第三种则是传递一维数组的指针,并在自定义函数中将一维数组转换二维数组(之所以这样处理,是利用一维数组内存空间连续的特点)。 在调用过程中,直接调用数组的变量名即可。 【例】#include<iostream> using namespace std; //第一维长度为t void p1(int a[][5],int t){ cout<<"第一种调用方式:"<<endl; for(int i=0;i<t;i++){ for(int j=0;j<5;j++){ cout<<a[i][j]<<" "; } cout<<endl; } } //第二种调用方式 void p2(int (*a)[5],int t){ cout<<"第二种调用方式:"<<endl; for(int i=0;i<t;i++){ for(int j=0;j<5;j++){ cout<<a[i][j]<<" "; } cout<<endl; } } //第三种调用方式 //一维数组指针,一维长度t,二维数组k void p3(int *a,int t,int k){ cout<<"第三种调用方式:"<<endl; for(int i=0;i<t;i++){ for(int j=0;j<5;j++){ cout<<*(a+i*k+j)<<" "; } cout<<endl; } } int main(){ int a1[5][5]={{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}}; p1(a1,5); p2(a1,5); int a2[]={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}; p3(a2,5,5); return 0; } 在传递参数过程中,可以传递一维数组和二维数组,但若想让自定义函数返回数组,在c++中是不允许的。 ⦁ 结构体 结构体是为了增加个性化自定义的数据类型,在结构体内可以设定多中数据类型,甚至还可以设定自定义函数,通过调用结构体及其变量便可以使用多种数据类型。 1. 结构体的定义与初始化 结构体也称为结构,其定义的一般格式如下。 【例】创建一个记录学生相关数据的结构体Student(一般结构体名首字母大写)如下: 1. 结构体的调用 当使用结构体内的成员或函数时,方法非常简单,其格式如下。 结构体变量名.成员变量/成员函数/其他结构体.成员变量/成员函数 【例】#include<iostream> using namespace std; struct Student{ char name[20];//姓名 int age;//年龄 float height;//身高 float chinese;//语文成绩 float math;//数学成绩 float english;//英语成绩 float sum(){//三门成绩总和 return chinese+math+english; } }; int main(){ Student stu1;//声明Student类型变量 stu1 //为结构体变量赋值 cin>>stu1.name>>stu1.age>>stu1.chinese>>stu1.english>>stu1.math; float sum=stu1.sum();//调用结构体函数 cout<<stu1.name<<"的总成绩="<<sum<<endl; return 0; } 【例】设计一个英雄的结构体,包括成员的姓名、年龄、性别;创建结构体数组,数组中存放5名英雄,通过冒泡排序的算法将数组中英雄按照年龄进行升序排序,最终打印排序后的结果。 #include<iostream> #include"swap.h" #include<string> #include <ctime> using namespace std; //1.设计英雄结构体 struct Hero { string name; int age; string sex; }; //冒泡排序:年龄的升序 void bubbleSort(struct Hero heroArray[], int len) { for (int i = 0; i < len - 1; i++) { for (int j = 0; j < len - i - 1; j++) { //如果j下标的元素年龄大于j+1下标的年龄就交换 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 << "name: " << heroArray[i].name << " age: " << heroArray[i].age << " sex: " << heroArray[i].sex << endl; } } int main() { //2.创建数组存放5名英雄 struct Hero heroArray[5] = { {"刘备",23,"男"}, {"关羽",22,"男"}, {"张飞",20,"男"}, {"赵云",21,"男"}, {"貂蝉",19,"女"} }; int len = sizeof(heroArray) / sizeof(heroArray[0]); cout << "排序前的结果:" << endl; for (int i = 0; i < len; i++) { cout << "name: " << heroArray[i].name << " age: " << heroArray[i].age << " sex: " << heroArray[i].sex << endl; } //3.冒泡排序:年龄的升序 bubbleSort(heroArray, len); //4.打印排序后所有英雄数据 cout << "排序后的结果:" << endl; printHero(heroArray, len); return 0; } 1. 运算符重载 在c++中是无法在结构体中进行大于,小于,不等于等运算的,当利用结构体数据进行这些运算的时候,需要重新定义函数,尤其是使用STL函数时,函数内部的运算符需要根据结构体定义的数据进行比较时,重写运算符是非常必要的。如果不在结构体中重写运算符,需要重新自定义函数。 【例】利用STL中的sort函数将学生按照年龄升序排序。 Sort函数需要使用STL的algorithm库文件,该函数中包含三个参数,比较数组(一般为数组形式)的起始地址,终止地址+1(因为sort函数不包含第二个参数地址,所以做加一处理)和比较规则(例如升序还是降序等)。 #include<iostream> #include<algorithm> using namespace std; //定义学生结构体 struct student{ int num;//学号 int age;//年龄 float chinese,math,english;//语文,数学,英语 }s[100]; //自定义比较规则 bool cmp(student s1,student s2){ return s1.age<s2.age; } int main(){ int n; cin>>n; for(int i=0;i<n;i++){ cin>>s[i].num >>s[i].age>>s[i].chinese >>s[i].math>>s[i].english; } sort(s,s+n,cmp); for(int i=0;i<n;i++){ cout<<s[i].num<<" " <<s[i].age<<" "<<s[i].chinese<<" " <<s[i].math<<" "<<s[i].english<<endl; } return 0; } 【输入输出】 5 1 12 98 99 100 2 13 90 91 99 3 8 100 100 100 4 5 99 98 97 5 7 100 99 97 4 5 99 98 97 5 7 100 99 97 3 8 100 100 100 1 12 98 99 100 2 13 90 91 99 如果使用结构体运算符重载的方式进行,则在sort函数中不需要重新定义函数。在了解运算符重载之前需要了解两个关键字--const和this。 const本意是不易改变的意思,在c++中用于修饰内置类型变量,自定义对象,成员函数,函数参数等,它会作为一种约束,当修饰变量时,表示这个变量在程序运行时保持不变,可以说const修饰谁谁就保持不变。 this实质上是一个const修饰的指针,指向的是当前对象,也就是说现在谁在使用,this就指向谁,而且this指针还可以访问该对象的所有成员,例如,声明一个结构体student,当前声明一个s的变量,它具有student结构体结构时,此时的对象就是s,通过this指针可以访问当前s的所有元素。 运算符重载是有格式的,其格式如下: 返回数据类型operator运算符(const结构体名称 变量)const{ 比较this->元素名称与变量,元素名称; return 数据; } 【例】:利用运算符重载和STL中的sort函数将学生按照年龄顺序升序排序。 #include<iostream> #include<algorithm> using namespace std; struct student{ int num;//定义学号 int age;//定义年龄 float chinese,math,english;//语文,数学,英语成绩 //运算符重载 bool operator<(const student s)const{ return this->age<s.age; } }s[100]; int main(){ int n; cin>>n; for(int i=0;i<n;i++){ cin>>s[i].num >>s[i].age>>s[i].chinese >>s[i].math>>s[i].english; } //此处不用在写调用函数,而是通过结构体的运算符重载方式比较 sort(s,s+n); for(int i=0;i<n;i++){ cout<<s[i].num<<" " <<s[i].age<<" "<<s[i].chinese<<" " <<s[i].math<<" "<<s[i].english<<endl; } return 0; } 【输入输出】和上面案例一样。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 提示词工程——AI应用必不可少的技术
· 地球OL攻略 —— 某应届生求职总结
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界