一、初识c++
1.创建项目
一个项目下面可以很多个文件,但只能有一个main
2.注释
单行注释://注释内容 快捷键:ctrl+k+c
多行注释:/** **/
3.变量
变量存在的意义,方便我们管理内存空间
变量创建的语法:数据类型 变量名=变量初始值;
int a=10;
4.常量:用于记录程序中不可修改的数据
#define宏常量: #define 常量名 常量值;
#const修饰的变量 const 类型 变量名=初始值;
#include<iostream>
using namespace std;
#define Day 7 //若修改会报错
int main()
{
const int a = 10;
cout << "Day=" << Day << endl;
cout << "a=" << a << endl;
system("pause");
return 0;
}
5.关键字
作用:关键字是c++中预先保留的单词(标识符)
在定义变量或者常量时,不要使用关键字
c++关键字:
6.标识符命名规则
作用:c++规定给标识符(变量、常量)命名时,有一套自己的规则
(1)标识符不能是关键字
(2)标识符只能由字母、数字、下划线组成
(3)第一个字符必须是字母或下划线
(4)标识符中字母区分大小写
二、数据类型:给变量分配合适的内存空间
1. 整型
作用:整型变量表示的整数类型的数据
c++中以下几种方式可以表示整型,但是占用内存空间不同
2.sizeof 关键字
作用:利用sizeof可以统计数据类型所占用的内存大小
语法:sizeof(数据类型/变量)
#include<iostream>
using namespace std;
int main()
{
short a=10;
int b = 10;
long c = 10;
long long d = 10;
cout << "short占用的内存空间:" << sizeof(short) << endl;
cout << "int占用的内存空间:" << sizeof(b) << endl;
cout << "long占用的内存空间:" << sizeof(c) << endl;
cout << "long long占用的内存空间:" << sizeof(d) << endl;
system("pause");
return 0;
}
3.实型(浮点型)
作用:用于表示小数
浮点型:
单精度float,4字节,七位有效数字
双精度double,8字节,15-16位有效数字
注意:
(1)默认的是双精度,单精度可以写 float f1=3.15f,最好加一个f
(2)显示一个小数,默认显示六位
(3)科学计数法 float f2=3e-2
4.字符型
作用:用于显示单个字符
语法:char ch=‘a’; //单引号只能放一个字符
注意:
(1)C和C++中字符型变量只占用一个字节
(2)字符型变量并不是把字符本身放在内存,而是将对应的ASCII码放入内存
(3)cout<<(int) ch<<endl; //强行把ch转换成int来显示
5.转移字符
作用:用于表示一些不能显示出来的ASCII字符
注意:
\t表示跳到一个tab位,一个tab位可以放八个字符
eg:cout<<“aaa\thelloworld”<<endl; //那么aaa和helloworld之间有5个空格,而若aaa变成5个aaa,那么中间的空格只有3个
6.字符串型
作用:表示一串字符
char a[]=“aaaa”;//比字符型多了一个[],c的风格
string str=“aaaa”;//c++的风格,需要一个头文件 #include
7.布尔类型bool,占一个字节
作用:True or False(1 or 0)
8.数据的输入
作用:从键盘获取数据
语法:cin>>变量;
三、运算符
1.算数运算符
作用:四则运算
%取余(两个小数不可以取余);++a:先+1再赋值;a++: 先赋值再+1;–a: 先-1再赋值;a–:先赋值再-1
int a1=10;
int a2=10;
a1++;//11
++a2;//11
int a3=10;
int b3=++a3*10;//100
int a4=10;
int b4=a4++*10;//100,然后才是a4+1变成了11
2.赋值运算符
作用:表达式赋值
+=、-=、/=、*=、%=
3. 比较运算符
作用:用于比较
== 相等于
!= 不等于
<小于
大于
4.逻辑运算符
作用:返回真or假
!:非,!!双重否定表肯定(无意义)
&&:与
||:或
四、程序流程结构
4.1.选择结构
4.1.1 if语句
(1)单行if
if (score>600) //不能加分号“;”
{
cout<<"gongxi"<<endl;
}
(2)多行if
if (score>600)
{
cout<<"gongxi"<<endl;
}
else
{
cout<<"fail"<<endl;
}
(3)多条件if
if (条件1){} else if (条件2){} … else {}
嵌套if语句
在if中写if
if (tiaojian1)
{
if (tiaojian2)
{
....
}
}
4.1.2 三目运算符
作用:简单判断
语法:表达式1 ? 表达式2 : 表达式3
1成立,则执行2,返回2
1不成立,则执行3,返回3
c=(a>b ?a : b) //max(a,b),返回的是变量
(a>b ? a : b)=100; //对大的数赋值100
4.1.3 switch 语句
作用:执行多条件分支语句,只能是整型或者字符型,不可以是一个区间,优点:swtich效率高于if
swtich (表达式)
{
case 结果1: 执行语句; break;
case 结构2: 执行语句; break;
default: 执行语句;break;
}
4.2.循环结构
4.2.1 while循环语句
while(循环条件){执行语句}
只要循环条件为真,就一直执行
4.2.2 do…while循环语句
do{执行语句}while(循环条件); //先执行一遍,若满足,则再执行一遍
4.2.3 for循环语句
for(起始表达式;条件表达式;末尾循环体){循环语句;}
for (int i=0; i<10; i++)
{
cout<<i <<endl;
}
4.2.4 嵌套循环
循环中套循环
4.3. 跳转语句
4.3.1 break 语句
作用:跳出选择结构或者循环结构,在嵌套循环中,跳出最近的内层循环
4.3.2 continue语句
作用:跳过本次循环中剩余语句
4.3.3 goto语句
作用:无条件跳转语句
a=10;
goto flag;
cout<<a<<endl;
cout<<a<<endl;
flag;
cout<<a<<endl;
五、数组
5.1 概述
内部每个元素都是同样的类型、
5.2 一维数组
5.2.1 定义方式
数据类型 数组名[数组长度];//不允许空中括号
数据类型 数组名[数组长度]={值1,值2…};//若初始化时没有全部赋值,用0来补齐
数据类型 数组名[]={值1,值2…};//数组的长度由初始值决定
5.2.2 数组名的作用
1.统计整个数组在内存中的长度
2.获取数组在内存中的首地址(数组名就是首地址,转换为10进制可以用 (int)arr 或者 (long long)arr)
第一个元素的地址 &arr[0], (int)&arr[0]
3.数组名是一个常量,不可以赋值
不可以使用arr=100;
5.2.3 冒泡排序
比较相邻的元素,第一个比第二个大,则交换,不断重复
#include<iostream>
using namespace std;
int main(){
int arr[9]={2,4,0,5,7,1,3,8,9];
for (int i=0; i<9-1;i++) //外层循环len-1
{
for (int j=0;j<9-i-1;j++) //内层循环 len-i-1
{
if (arr[j]>arr[j+1])
{
int tmp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=arr[j];
}
}
}
}
5.3 二维数组
数据类型 数组名[行数][列数];//不允许空中括号
数据类型 数组名[行数][列数]={值1,值2…};//根据行列数,自动区分
数据类型 数组名[行数][列数]={{值1,值2},{值1,值2}};//最直观
数据类型 数组名[][列数]={值1,值2…};//数组的长度由初始值决定
六、函数
6.1 概述
封装代码,减少重复
6.2 定义
返回值类型 函数名(参数列表)
{
函数体语句
return表达式//与返回值类型对应
}
6.3 函数的调用
6.4 值传递
将实参传递给形参时,形参改变不影响实参
若不需要返回值,可以写返回值类型 void
6.5 函数的常见样式
无参无返
void test01()
{
cout<<"test01"<<endl;
}
有参无返
void test02(int a)
{
}
无参有返,调用方法 int b = test03();
int test03()
{
int a=10;
return a;
}
有参有返
int test04(int b)
{
int b=10;
return b;
}
6.6 函数的声明
作用:告诉编译器函数名称以及如何调用,但函数主体可以单独定义
注意:可以多次声明,但只能定义一次
int max(int a, int b)
{
return a>b?a:b
}
int main()
{
调用函数
}
6.7 函数的分文件编写
四步骤:
1.创建.h的头文件
2.创建.cpp的源文件
3.在头文件中写函数的声明
4.在源文件中写函数的定义
swap.h文件
#include <iostream> //需要使用的库要在头文件中声明
using namespace std;
void swap(int a, int b);
swap.cpp 文件
#include "swap.h" //关联头文件
void swap(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
cout << 'a' << a << endl;
cout << 'b' << a << endl;
}
main.cpp 文件
#include <iostream>
using namespace std;
#include "swap.h" //关联头文件与源文件(vscode不然找不到源文件)
#include "swap.cpp"
int main()
{
int a = 10;
int b = 10;
swap(a, b);
system("pause");
return 0;
}
七、指针
7.1 概念
记录内存编号,直接用指针访问内存
7.2 定义与使用
int main()
{
int a = 10;
int *p; // 创建指针
p = &a; // 指针指向a的内存
cout << "a的地址" << p << endl;
cout << "p" << p << endl;
// 指针前加*,表示解引用,可以得到指针指向内存中的数据
cout << "*p" << *p << endl;
system("pause");
return 0;
}
7.3 指针所占的内存空间
32位系统下4字节,64位系统下8字节
7.4 空指针和野指针
空指针:指向内存中编号为0的空间,不可以访问,主要用于初始化指针
野指针:指向非法内存
int main()
{
int *p1 = NULL; // 空指针
// 不能写*p1=100;写入访问权限冲突,0~255之间的内存编号是系统占用,不可以访问
int *p2 = (int *)0x1100; // 读取访问权限冲突,避免出现野指针,一旦cout<<*p会出错
system("pause");
return 0;
}
7.5 const 修饰指针
int main()
{
int a = 10;
int b = 20;
const int *p1 = &a; // 常量指针,指针的指向可以修改,但指向的值不可以修改
//*p1=20; 错误,不能修改指向的值
p1 = &b; // 指向可以改变
int *const p2 = &a; // 指针常量,指针的指向不可以修改,指向的值可以改
*p2 = 20;
// p2=&b,错误
const int *const p3 = &a; // 值和指向都不可以修改
cout << "p1" << *p1 << endl;
cout << "p2" << *p2 << endl;
cout << "p3" << *p3 << endl;
system("pause");
return 0;
}
7.6指针和数组
int main()
{
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
cout << "第一个元素" << arr[0] << endl;
int *p = arr; // arr就是数组首地址
cout << "第一个元素" << *p << endl;
p++; // 让指针向后走4位
cout << "第二个元素" << *p << endl;
// 利用指针遍历数组
int *p2 = arr;
for (int i = 0; i < 10; i++)
{
cout << *p2 << endl;
p2++;
}
system("pause");
return 0;
}
7.7 指针和函数
指针作为函数参数
void swap(int a, int b);
void swap02(int *p1, int *p2);
int main()
{
int a = 10;
int b = 20;
// 1.值传递
// swap(a, b);
cout << 'a' << a << endl;
cout << 'b' << b << endl;
// 2.地址传递,可以修饰外部实参
swap02(&a, &b);
cout << 'a' << a << endl;
cout << 'b' << b << endl;
system("pause");
return 0;
}
void swap(int a, int b) // 值传递,形参改变,不改变外部实参的变化
{
int tmp = a;
a = b;
b = tmp;
}
void swap02(int *p1, int *p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
cout << "*p1" << *p1 << endl;
cout << "*p2" << *p2 << endl;
}
7.8 数组、函数、指针
数组名就是指针
传递数组的时候,最好传递一个len
八、结构体
8.1 概念
用户自定义的数据类型
8.2定义
语法: struct 结构体名 {结构体成员列表};
#include <iostream>
#include <string>
using namespace std;
struct Student
{
string name;
int age;
int score;
} s3; // s3可以不要,若保留,表示顺便创建的结构体变量,可以在后文字节初始化
int main()
{
// 初始化方式1,struct关键字可以省略
struct Student s1;
s1.name = "zhangsan";
s1.age = 18;
s1.score = 20;
cout << s1.name << s1.age << s1.age << endl;
// 初始化方式2
Student s2 = {"lisi", 20, 34};
cout << s2.name << s2.age << s2.age << endl;
// 初始化方式3,在结构体处顺便初始化
s3 = {"wangwu", 40, 90};
cout << s3.name << s3.age << s3.age << endl;
system("pause");
return 0;
}
8.3 结构体数组
将自定义的结构体放入数组中,便于维护
语法:struct 结构体名 数组名[元素个数]={{},{}…}
int main()
{
struct Student stuArray[3] = {// 初始化结构体数组,结构体同上
{"zhangsan", 18, 99},
{"lisi", 20, 100},
{"wangwu", 39, 90}};
// 赋值
stuArray[2].age = 30;
// 访问结构体
for (int i = 0; i < 3; i++)
{
cout << "姓名" << stuArray[i].name << "年龄" << stuArray[i].age << endl;
}
system("pause");
return 0;
}
8.4 结构体指针
通过指针来访问成员
->操作符来访问成员
int main()
{
// 创建变量
Student s = {"zhangsan", 10, 20};
// 创建指针,可以省略struct
struct Student *p = &s;
// 通过指针访问数据
cout << "name:" << p->name << "age:" << p->age << "score:" << p->score << endl;
system("pause");
return 0;
}
8.5 结构体嵌套结构体
struct Student // 定义结构体,必须定义在teacher之前
{
string name;
int age;
int score;
};
struct Teacher
{
int id;
string name;
int age;
struct Student stu;
};
int main()
{
// 创建变量
Teacher t;
t.age = 10000;
t.name = "laowang";
t.id = 100;
t.stu.age = 18;
t.stu.name = "zhangsan";
t.stu.score = 90;
cout << "teacher_name" << t.name << "t_age" << t.age << "t_id" << t.id << "t_stu_name" << t.stu.name << endl;
system("pause");
return 0;
}
8.6 结构体作为函数参数
// 打印学生信息
// 1.值传递
void printStudent(struct Student s)
{
s.age = 100;
cout << "printStudent name" << s.name << " age" << s.age << " score" << s.score << endl;
}
// 2.地址传递,指针用'->'
void printStudent02(struct Student *p)
{
p->age = 99;
cout << "printStudent02 name" << p->name << " age" << p->age << " score" << p->score << endl;
}
int main()
{
// 创建变量
Student stu = {"zhangsan", 19, 20};
// cout << "name" << stu.name << " age" << stu.age << " score" << stu.score << endl;
// 1.值传递,拷贝量较大
printStudent(stu);
cout << "main name" << stu.name << " age" << stu.age << " score" << stu.score << endl;
// 2.地址传递
printStudent02(&stu);
cout << "main name" << stu.name << " age" << stu.age << " score" << stu.score << endl;
// system("pause");
return 0;
}
8.7 结构体中使用const
void printStudent02(const Student *p) // 地址传递可以减少内存空间
{
// p->age = 99; 加了const,此时不允许修改值
cout << "printStudent02 name" << p->name << " age" << p->age << " score" << p->score << endl;
}
8.8 案例
三个老师,分别带5名学生
#include <iostream>
#include <string>
#include <Ctime>
using namespace std;
struct Student // 定义结构体,必须定义在teacher之前
{
string name;
int score;
};
struct Teacher
{
string name;
struct Student sArray[5];
};
void allocateSpace(Teacher tArray[], int len)
{
string nameSeed = "ABCDE";
for (int i = 0; i < len; i++)
{
tArray[i].name = "Teacher";
tArray[i].name += nameSeed[i];
for (int j = 0; j < 5; j++)
{
tArray[i].sArray[j].name = "Student";
tArray[i].sArray[j].name += nameSeed[j]; // 不能写“Student"+nameSeed,c++编译不了
int random = rand() % 61 + 40; // 40~100,rand随机产生一个大于0的数
tArray[i].sArray[j].score = random;
}
}
}
void printInfo(Teacher tArray[], int len)
{
for (int i = 0; i < len; i++)
{
cout << "t_name: " << tArray[i].name << endl;
for (int j = 0; j < 5; j++)
{
cout << "\ts_name: " << tArray[i].sArray[j].name << "\ts_score: " << tArray[i].sArray[j].score << endl;
}
}
}
int main()
{
// 随机数种子,保障随机性
srand((unsigned int)time(NULL)); // 注意包含头文件,unsigned int是无符号整型,不能为负数
// 创建3名老师
Teacher tArray[3];
int len = sizeof(tArray) / sizeof(tArray[0]);
allocateSpace(tArray, len);
printInfo(tArray, len);
// system("pause");
return 0;
}