所有程序均为Dev-C++
C++是C的扩展,所以初级部分,C和C++的知识点相同
数据类型
利用sizeof求出数据类型占用内存的大小。
sizeof(数据类型/变量)
整形
short(2个字节) < int = long(4个字节) < long long (8个字节)
浮点型
在使用单精度float(4个字节)和双精度double(8个字节)时,默认情况下,输出一个小数,会显示6为有效数字。
科学计数法
float f2 = 3e2;//表示3*10^2,就是300
float f3 = 3e-2;//表示3*0.1^2,就是0.03
字符型
char占用1个字节
char ch = 'a';//单引号里面只能有一个字符
常见错误:
创建字符型变量时误将单引号写为双引号;
创建字符型变量时单引号内只能有一个字符;
查看字符的ASCII码
char ch = 'a';
std::cout << (int)ch << std::endl;
转义字符
常用的转义字符;
1、换行符 \n
cout << "Hello World\n";//换行
2、反斜杠 \\,如果想输出一个反斜杠,必须要两个反斜杠才行
cout << "\\" << endl;//输出为一个反斜杠
3、水平制表符 \t
cout << "aaa\thelloworld" << endl;//输出为aaa helloworld
一个水平制表符有8个位置,上面a占3个位置,那么就还剩下5个空格,好处是有对齐的效果。
字符串型
1、C风格字符串
char str[] = "Hello World";
cout << str << endl;
注意事项:定义规范,char 字符串名[] = "Hello";等号后面要用双引号
2、C++风格字符串
string str2 = "hello world";//加头文件<string>
cout << str2 << endl;
注意事项:包含头文件<string>
布尔数据bool
true :真(本质是1)
false:假(本质是0)
bool flag = true;
cout << flag << endl;//输出1
flag = false;
cout << flag << endl;//输出0
占用内存为1个字节。bool只要是0就为假,其余都代表真。
运算符
算数运算符
1、+、 -、 *、 /(加减乘除)注:除数不能为0
2、%:取模,比如10%3,结果为1 (两个小数不能取模)
3、++
++a前置递增:相当于a = a+1,先加一再进行表达式运算
a++后置递增:先进行表达式运算再加一
4、--
--a前置递减与a--后置递减与++同理
赋值运算符
=、+=、-=、*=、/=、%=
a += b,相当于 a = a + b,其余同理。
比较运算符
a == b a等于b
a != b a不等于b
a < b a小于b
a > b a 大于b
a <= b a小于等于b
a >= b a大于等于b
逻辑运算符
!a 非 若a为真,则!a为假
a && b 与 a与b都为真,则为真,至少一个为假,则为假
a || b 或 a与b都为假,则为假,至少一个为真,则为真
在C++中只有0为假,其余都为真
程序流程结构
程序流程结构包括顺序结构、选择结构和循环结构,其中顺序结构是指按照顺序执行程序语句。
选择结构
if语句
执行满足条件的语句。
1、单行if语句语法:if(条件){条件满足执行的语句},条件为真则执行,为假则不执行。
2、多行if语句语法:if(条件){条件满足执行的语句} else {条件不满足执行的语句}
3、多条件if语句语法:if(条件1){条件1满足执行的语句}else if(条件2){条件2满足执行的语句}......else{条件都不满足的情况下执行的语句}
4、嵌套if语句:if(条件1){条件1满足执行的语句; if(条件2){条件2满足执行的语句} }
//比大小
#include <iostream>
using namespace std;
int main(){
int A,B,C;
cout << "请输入三个数:" << endl;
while(cin >> A >> B >> C)
{
if(A > B)
{
if(A > C)
{
cout << "A最重,为" << A << endl;
}
else
{
cout << "C最重,为" << C << endl;
}
}
else
{
if(B > C)
{
cout << "B最重,为" << B << endl;
}
else
{
cout << "C最重,为" << C << endl;
}
}
}
return 0;
}
三目运算符
作用:通过三目运算符实现简单的判断
语法:表达式1 ?表达式2 :表达式3
解释:
如果表达式1为真,执行表达式2,并返回表达式2的结果
如果表达式1为假,执行表达式3,并返回表达式3的结果
//将a与b比较,a大于b,返回a,否则返回b
int a = 10,b = 12,c = 0;
c = a > b ? a : b;
cout << c << endl;
在C++中三目运算符返回的是变量,可以继续赋值。
a > b ? a : b = 100;//a>b则返回a,并将100赋给a
switch语句
语法
switch(表达式)
{
case 结果1:执行语句;break;
case 结果2:执行语句;break;
case 结果3:执行语句;break;
....
default:执行语句;break;//当没有符合的条件时,执行这个语句
}
int main(){
int score = 0;
cout << "请给电影打分:" << endl;
while(cin >> score)
{
switch(score)
{
case 10:
cout << "经典电影" << endl;break;
case 9:
cout << "经典电影" << endl;break;
case 8:
cout << "不错的电影" << endl;break;
case 7:
cout << "不错的电影" << endl;break;
case 6:
cout << "电影一般" << endl;break;
default :
cout << "烂片" << endl;break;
}
}
return 0;
}
switch特点
缺点:switch(表达式){} 表达式中判断时只能是整形或字符型,不可以是一个区间
优点:结构清晰,执行效率高
循环结构
while循环语句
语法:while(循环条件){循环语句} //循环条件为真执行循环语句,为假不执行
//猜测数字
#include <iostream>
#include <cstdlib>
using namespace std;
int main(){
int a = rand()%100 + 1;//rand()%100 生成0~99的数字
cout << "请玩家输入1~100的数字:" << endl;
int b = 0;
while(cin >> b)
{
if(a == b)
{
cout << "输入正确!" << endl;
break;
}
else if(a < b)
{
cout << "大了,请继续输入!" << endl;
}
else if(a > b)
{
cout << "小了,请继续输入!" << endl;
}
}
return 0;
}
do...while循环语句
语法:do{循环语句} while{循环条件};
注意:与while的区别是do...while会先执行一次语句
//输出所有三位数的水仙花数
int main(){
int num = 100;
do
{
int a = num % 10;//个位
int b = num % 100 / 10;//十位
int c = num / 100;//百位
if(a*a*a + b*b*b + c*c*c == num)
{
cout << num << endl;
}
num += 1;
}
while(num < 1000);
return 0;
}
for循环语句
语法:for(起始表达式;条件表达式;末尾表达式){循环语句;}
for循环执行流程:起始表达式只执行一次。再执行条件表达式,若满足,则执行循环语句,
最后执行末尾表达式,如此往复,直至条件表达式不满足为止。
//敲桌子游戏,1~100中含7或是7的倍数则输出敲桌子,其余正常输出
int main(){
for(int i = 1;i <= 100;i ++)
{
int a = 0,b = 0,c = 0;
if(i > 0 && i < 9)
{
if(i == 7)
{
cout << "敲桌子!" << endl;
}
else
{
cout << i << endl;
}
}
else if(i >= 10 && i <= 99)
{
a = i % 10;//个位
b = i / 10;//百位
if(a == 7 || b == 7 || i % 7 == 0)
{
cout << "敲桌子!" << endl;
}
else
{
cout << i << endl;
}
}
else
cout << i << endl;
}
return 0;
}
当需要判断且没有循环次数时,while更好用;
当没有判断且有循环次数时,for更好用;
当没有循环次数时,考虑是否可以通过判断来循环。
嵌套循环
乘法口诀表
int main(){
for(int i = 1;i <= 9;i ++)//打印行数
{
for(int j = 1;j <= i;j ++) //打印列数,列数小于等于行数
{
cout << j << " * " << i << " = " << i*j << " ";
}
cout << endl;//打印完列数后换行
}}
跳转语句
break语句
作用:用于跳出选择结构和循环结构
break使用的情况:
1、出现在switch语句中,作用是终止case并跳出switch
2、出现在循环语句中,作用是跳出当前的循环语句
3、出现在嵌套循环中,跳出最近的内层循环语句
//嵌套循环中的break
int main(){
for(int i = 1;i < 10;i ++)
{
for(int j = 1;j < 10;j ++)
{
if(j == 5)
{
break;//退出内层循环
}
cout << "*";
}
cout << endl;
}
return 0;
}
代码结果:
因为到第5列时跳出循环,所以只打印出4列
continue语句
作用:在循环语句中,跳过本次循环中余下未执行的语句,继续执行下一次循环。
解释:continue一般用于循环语句中,假设循环体有5段代码。
for(.....){
代码1;
代码2;
if(....) continue;//代码3
代码4;
代码5;
}
if条件不成立时,代码1,2,4,5都正常执行,但是当if条件成立时,就会运行continue语句,则跳出本次循环,所以代码4,5就不会执行,再接着执行下一次循环。
goto语句
作用:可以无条件跳转语句
语法:goto标记
解释:如果标记的名称存在,执行到goto语句时,会跳转到标记的位置。
注:不推荐使用goto语句,会导致代码的可读性变差。
int main(){
cout << "1、******" << endl;
cout << "2、******" << endl;
goto FLAG;
cout << "3、******" << endl;
cout << "4、******" << endl;
FLAG:
cout << "5、*****" << endl;
return 0;
}
结果:
通过goto语句,直接跳过了3和4的执行。
数组
特点1:数组里面存放的都是相同类型的数据
特点2:连续内存存储
一维数组
定义方式:
1、数据类型 数组名[数组长度];
2、数据类型 数组名[数组长度] = {值1,值2,....};
3、数组类型 数组名[ ] = {值1,值2,....};
注:定义数组时,必须有初始长度,否组报错
数组名用途
1、可以统计整个数组在内存中的长度
int main(){
int arr2[] = {1,2,3,4,5,6,7,8,9,10};
cout << sizeof(arr2) << endl;
return 0;
}结果为40,因为int型,int占4个字节,有10个int型的数据,所以为4*10 = 40
2、可以获取数组在内存中的首地址
int main(){
int arr2[] = {1,2,3,4,5,6,7,8,9,10};
cout << arr2 << endl;cout << &arr2[0] << endl;//看第一个元素的首地址
return 0;
}输出的结果相同,数组首地址就是第一个元素的地址
数组名相当于指针变量,这篇文章中有关于数组与指针的讲解
指针详解与应用
https://mpbeta.csdn.net/mp_blog/creation/editor/147189700
找最大值
int main(){
int arr[5] = {470,365,420,410,440};
int max = 0;
for(int i = 0;i < sizeof(arr)/4;i ++)
{
if(max < arr[i])
{
max = arr[i];
}
}
cout << "最大值为:" << max << endl;
return 0;
}
数组元素逆置
//通用,只需要更改数组的数据就可以直接使用
int main(){
int arr[] = {34,22,13,25,16};
int start = 0;//起始下标
int end = sizeof(arr)/sizeof(arr[0])-1;//末尾下标
while(start < end)
{
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
++ start;
-- end;
}
for(int i = 0;i < sizeof(arr)/sizeof(arr[0]);i ++)
{
cout << arr[i] << endl;
}
return 0;
}
冒泡排序
规律:
排序的总轮数 = 元素个数 - 1;
每轮对比次数 = 元素个数 - 排序轮数 - 1;
int main(){
int arr[] = {1,4,2,5,3,6,8,9,7,0};
cout << "排序前的结果:" << endl;
for(int i = 0;i < sizeof(arr)/sizeof(arr[0]);i ++)
{
cout << arr[i] << " ";
}
cout << "排序后的结果:" << endl;
for(int i = 0;i < sizeof(arr)/sizeof(arr[0]) - 1;i ++)//轮数
{
for(int j = 0;j < sizeof(arr)/sizeof(arr[0]) - i - 1;j ++)//对比的次数
{
if(arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for(int i = 0;i < sizeof(arr)/sizeof(arr[0]);i ++)
{
cout << arr[i] << " ";
}
return 0;
}
二维数组
定义方式:
1、数组类型 数组名[行数][列数];
2、数组类型 数组名[行数][列数] = {{数据1,数据2},{数据3,数据4}};
3、数组类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4};
4、数组类型 数组名[ ][列数] = {数据1,数据2,数据3,数据4};
注:第二种定义方式更加直观,提高代码的可读性。
//第二种定义方式及遍历二维数组
int main(){
int arr1[2][3] =
{
{1,2,3},
{4,5,6}
};
for(int i = 0;i < 2;i ++)//行
{
for(int j = 0;j < 3;j ++)//列
{
cout << arr1[i][j] << " ";
}
cout << endl;
}
return 0;
}
二维数组数组名
1、查看二维数组所占的内存空间
int main(){
int arr1[2][3] =
{
{1,2,3},
{4,5,6}
};
cout << "二维数组占用的内存空间:" << sizeof(arr1) << endl;
cout << "第一行所占用的内存空间:" << sizeof(arr1[0])<< endl;
cout << "第一个元素占用的内存空间:" << sizeof(arr1[0][0]) << endl;
cout << "二维数组行数为:" << sizeof(arr1) / sizeof(arr1[0]) << endl;
cout << "二维数组列数为:" << sizeof(arr1[0]) / sizeof(arr1[0][0]) << endl;
return 0;
}
2、获取二维数组地址
int main(){
int arr1[2][3] =
{
{1,2,3},
{4,5,6}
};
cout << arr1 << endl; //0x6ffe00cout << &arr1[0][0] << endl;//0x6ffe00,说明首地址就是arr1[0][0]的地址
cout << arr1[0] << endl;//第一行首地址,0x6ffe00
cout << arr1[1] << endl;//第二行首地址,0x6ffe0c
return 0;
}
计算总分
英语 | 数学 | 语文 | |
张三 | 100 | 100 | 100 |
李四 | 90 | 50 | 100 |
王五 | 60 | 70 | 80 |
#include <string>
using namespace std;
int main(){
string name[] = {"张三","李四","王五"};
int score[3][3] =
{
{100,100,100},
{90,50,100},
{60,70,80}
};
for(int i = 0;i < 3;i ++)
{
int sum = 0;
for(int j = 0;j < 3;j ++)
{
sum += score[i][j];
cout << score[i][j] << " ";
}
cout << name[i] << "的总分:" << sum << endl;
sum = 0;
cout << endl;
}
return 0;
}
函数
语法:
返回值类型 函数名(参数列表)
{
函数体语句
return 表达式 //返回的表达式类型要与返回值类型一致
}
函数的调用
int add(int num1,int num2)//加法函数的定义
{
int sum = num1 + num2;
return sum;
}
int main(){
int sum = add(10,12);//函数调用
cout << sum << endl;
return 0;
}
值传递
void swap(int num1,int num2) //如果函数不需要返回值,声明的时候可以写void
{
cout << "交换前:" << endl;
cout << "num1:" << num1 << endl;
cout << "num2:" << num2 << endl;
cout << "交换后:" << endl;
int temp = num1;
num1 = num2;
num2 = temp;
cout << "num1:" << num1 << endl;
cout << "num2:" << num2 << endl;
//return 返回值不需要时,可以不写
}
int main(){
int a = 10;
int b = 20;
swap(a,b); //当我们做值传递时,函数的形参发生改变,并不会影响实参
cout << "a:" << a << endl;
cout << "b:" << b << endl;//a与b的值并没有发生改变
return 0;
}
函数常见的形式
1、无参无返
void test01() //无参无返
{
cout << "this is test01" << endl;
}
2、有参无返
void test02(int a) //有参无返
{
cout << "this is test02 = " << a << endl;
}
3、无参有返
int test03() //无参有返
{
int a = 10,b = 20;
cout << "this is test03" << endl;
return a+b;
}
4、有参有返
int test04(int a,int b) //有参有返
{
cout << "this is test04" << endl;
return a+b;
}
函数的声明
作用:常用于分文件编写。告诉函数编译器名称及如何调用函数。函数的实际主体可以单独定义。函数的声明可以多次,但是定义只能一次。一般将函数声明写在头文件下面。
分文件编写
步骤:
1、创建后缀名为.h的头文件
2、创建后缀名为.cpp的源文件
3、在头文件中写函数的声明
4、在源文件中写函数的定义
创建swap.cpp源文件并写函数的定义
#include <iostream>
using namespace std;
void swap(int a,int b)
{
cout << "a:" << a << endl;
cout << "b:" << b << endl;
int temp = a;
a = b;
b = temp;
cout << "a:" << a << endl;
cout << "b:" << b << endl;
}
创建swap.h头文件并写函数的声明
#ifndef __SWAP_H
#define __SWAP_Hvoid swap(int a,int b);
#endif
指针
指针详解与应用https://mpbeta.csdn.net/mp_blog/creation/editor/147189700
结构体
结构体属于用户自定义的数据类型,是一些数据类型集合组成的一个类型,允许用户存储不同的数据类型。
语法:struct 结构体名 { 结构体成员列表 };
结构体创建变量的方式
//自定义的数据类型
struct student{
int age;
string name;
int score;
};
1、struct 结构体名 变量名
struct student s1;
注:在C++中,这种定义方式struct可以省略,但是C中不可以省略
但是在C中如果
typedef struct student Stu;
Stu s1;//先typedef重定义类型名称就可以直接用Stu命名变量
当然C++中也可以用typedef
2、struct 结构体名 变量名 = {成员1值,成员2值}
struct student s1 = { 23,“lisi”,98};
3、定义结构体时顺便创建变量
struct student{
int age;
string name;
int score;
} s1;
注:
1、第一种和第二种用的比较多
2、通过 . 访问结构体变量中的成员并赋值
s1.age = 23;
s1.name = name;
s1.score = 98;
结构体数组
作用:将自定义的结构体放入到数组中方便维护
语法:struct 结构体名 数组名[元素个数] = { { },{ },{ },...} //C++中struct可以省略
定义结构体
struct student{
int age;
string name;
int score;
};
创建结构体数组并赋值
student stuArry[3] =
{
{22,"zhangsan",99},
{23,"lisi",98},
{21,"wangwu",100}
};
修改值
stuArry[2].name = "liliu"; //将数组中的wangwu改为liliu
stuArry[2].age = 32; //将数组中的21改为32
stuArry[2].score = 60; //将数组中的100改为60
遍历结构体数组
for(int i = 0;i < 3;i ++)
{
cout << " 年龄:" << stuArry[i].age << " "
<< "姓名:" << stuArry[i].name << " "
<< "分数:" << stuArry[i].score << endl;
}
结构体指针
作用:通过指针访问结构体的成员
定义结构体
struct student{
int age;
string name;
int score;
};
创建学生结构体变量
student s1 = {23,"zhangsan",99};
通过指针指向结构体变量
student *p = &s1; //注意指针类型要相同
通过指针访问结构体变量的数据
p->age = 22;
p->name = "niaoren";
p->score = 10;通过结构体指针访问结构体中的属性,需要利用“->”
结构体嵌套结构体
作用:结构体中的成员可以是另一个结构体
例如:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
struct student{
int age;
string name;
int score;
};
struct teacher{
int id;
string name;
int age;
student Stu; //老师的结构体中嵌套了学生的结构体
};
创建老师
初始化赋值
teacher t = {222,"laowang",43,{23,"lisi",98}};
直接赋值
teacher t;
t.age = 43;
t.id = 222;
t.name = "laowang";
t.Stu.age = 22;
t.Stu.name = "lisi";
t.Stu.score = 98;
结构体做函数参数
作用:将结构体作为参数向函数中传递
传递方式:1、值传递 2、地址传递
值传递
struct student{
int age;
string name;
int score;
};
void printStu(student s)
{
cout << " 年龄:" << s.age << " 姓名:" << s.name << " 分数:" << s.score << endl;
}
int main(){
student s = {23,"zhangsan",89};
printStu(s);
return 0;
}
地址传递
struct student{
int age;
string name;
int score;
};
void printStu(student* s)
{
cout << " 年龄:" << s->age << " 姓名:" << s->name << " 分数:" << s->score << endl;
}
int main(){
student s = {23,"zhangsan",89};
printStu(&s);
return 0;
}
区别:
值传递不改变实参值,地址传递改变实参数
值传递引用属性用 . ,地址传递引用属性用 ->
结构体案例
每名老师带3个学生,总共2名老师,需求为设计老师和学生的结构体,在老师的结构体中,有老师的姓名和一个存放3名学生的数组作为成员,学生的成员有姓名和考试分数,创建数组存放2名老师,通过函数给每个老师及所带的学生赋值,最终打印出老师数据和老师所带学生的数据
#include <iostream>
#include <string>
using namespace std;
struct student{
string sName;
int score;
};
struct teacher{
string tName;
student ArryS[3];//学生数组
};
void InitData(teacher *p, int len)
{
for(int i = 0;i < len;i ++)
{
cout << "输入老师姓名:" << endl;
cin >> p[i].tName;
cout << "学生1的姓名和分数:" << endl;
cin >> p[i].ArryS[0].sName >> p[i].ArryS[0].score;
cout << "学生2的姓名和分数:" << endl;
cin >> p[i].ArryS[1].sName >> p[i].ArryS[1].score;
cout << "学生3的姓名和分数:" << endl;
cin >> p[i].ArryS[2].sName >> p[i].ArryS[2].score;
}
}
void printData(const teacher *t,int len)
{
for(int i = 0;i < len;i ++)
{
cout << "老师姓名:" << t[i].tName;
cout << "学生1姓名:" << t[i].ArryS[0].sName << "学生1分数:" << t[i].ArryS[0].score << endl;
cout << "学生2姓名:" << t[i].ArryS[1].sName << "学生2分数:" << t[i].ArryS[1].score << endl;
cout << "学生3姓名:" << t[i].ArryS[2].sName << "学生3分数:" << t[i].ArryS[2].score << endl;
}
}
int main(){
teacher ArryT[2];//创建老师数组
int n = sizeof(ArryT) / sizeof(ArryT[0]);
InitData(ArryT,n);
printData(ArryT,n);
return 0;
}
枚举
语法:
enum 枚举名
{
成员1,
成员2,
....
}
一般与switch结合使用
enum Week
{
Mon, //值默认为0,也可以手动调节,如Mon = 1,则下面就从1开始累加
Tue, //1
Wed, //2
Thu, //以此类推
Fir,
Sat,
Sun
};
int main(){
Week today = Mon;
cout << today << endl; //输出为0
return 0;
}
在C++11以后,引入了枚举类,也称强类型枚举,关键字为enum class,它强制我们在使用枚举值时,必须带上枚举类名称,这样做有助于避免命名冲突。
int main(){
Week today = Week::Mon;//带枚举类名称
cout << int(today) << endl; //由于cout不认识枚举类,所以需要强制转换
return 0;
}
在cout时需要强制转换,但在switch时不需要强制转换
enum class Week
{
Mon,
Tue,
Wed,
Thu,
Fir,
Sat,
Sun
};
int main(){
Week today = Week::Mon;
switch(today)
{
case Week::Mon:cout << "星期一" << endl;break;
case Week::Tue:cout << "星期二" << endl;break;
case Week::Wed:cout << "星期三" << endl;break;
case Week::Thu:cout << "星期四" << endl;break;
case Week::Fir:cout << "星期五" << endl;break;
case Week::Sat:cout << "星期六" << endl;break;
case Week::Sun:cout << "星期日" << endl;break;
}
return 0;
}结果为 星期一
枚举值默认底层数据类型为int,我们也可以手动指定为unsigned int和char等
enum class Week :unsigned int //unsigned int
{
Mon,
Tue,
Wed,
Thu,
Fir,
Sat,
Sun
};
应用
定义三原色
enum class color
{
Red,
Green,
Blue
};在通过switch去进行指定的操作
游戏中的物品分类
enum class ItemType
{
Weapon, //武器
Clothing, //服装
Consumable //消耗品
};