2020.12.c++基础
c++笔记
一.运算符
1.三目运算符
- c=a>b?a:b ---------->如果a大 c=a;否则c=b
- a>b?a:b =100 ---------->如果a大 a=100;否则b=100
2.求余以及除号的运用
一个三位数如(153),要求获取它的个位数、十位数、百位数
- 个位:153%10=3
- 十位:153/10=15 15%10=5
- 百位:153/100=1
二.选择语句
1.if 和switch语句的区别
- switch语句里面的判断只能是整型或者是字符型,不可以是一个区间。需要用到break
三.循环语句
1.while()与do....while()
- 格式 while(){.....}------->先执行再判断
- 格式do{.....}while();------->先判断再执行
2.break与continue
- break;跳出循环
- continue;跳出这次循环------>可以与if连用,进行筛选条件循环
四.数组
1.格式与初始化
-
数据类型 数组名[数组长度];------------>自己手动赋值
-
数据类型 数组名[数组长度]={值1,值2......};----------------->没有赋值完的,默认初始化填充为0
-
数据类型 数组名[]={值1,值2......};------------------>长度由后面的值的多少决定
-
注意:定义数组时,必须要有初始长度
2.一维数组名称的作用一:数组的内存空间
- sizof(数组名);------->整个数组在内存空间的长度---->多少字节
- sizof(数组名[0]);------->某一个元素所占的内存空间
- sizof(数组名)/sizof(数组名[0]);--------->数组中元素的个数
- sizeof------->用来统计一个数据类型的内存空间的大小
- 注意:byte--1字节,short---2字节,int 类型所占的内存空间是4字节,long---8字节,float--4字节,double--8字节,char--2字节,boolean--1位。
3.一维数组名称的作用二:查看数组首地址
- cout<<数组名;----------->打印数组的首地址
- &数组名[0];------>数组第一个元素的地址
- 注意:数组的首地址就是数组第一个元素的地址
- 注意:数组名是一个常量,不可以进行赋值操作
4.找数组的最大值
- 定义一个max=0;----->与数组中的元素依次进行比较
5.数组逆置
- 记录起始位置的下标和末位的下标
- 两个下标互换
- 起始下标++,末尾下标--
- 循环条件:Start<end
6.二维数组
-
数组名[行数] [列数];
-
数组名[行数] [列数]={{}, {}, .....};
-
数组名[行数] [列数]={1,2,3,4,5,6};
-
数组名[ ] [列数]={1,2,3,4,5,6};
注意:可以省去行数但是不能省去列数
7.二维数组名称的作用一:数组的内存空间
- sizeof(数组名)------>二维数组占用内存空间
- sizeof(数组名[0])------>二维数组第一行占用的内存
- sizeof(数组名[0] [0])---->二维数组第一个元素占用内存
- sizeof(数组名)/sizeof(数组名[0])---->二维数组的行数
- sizeof(数组名[0])/sizeof(数组名[0] [0])----->二维数组的列数
8.一维数组名称的作用二:数组的首地址
- cout<<数组名;----->数组的首地址
- cout<<数组名[0];------>二维数组第一行的首地址
- cout<<&数组名[0] [0];----->二维数组第一个元素的地址
- 注意:三种地址都一样
五.函数
1.函数的定义
返回值类型 函数名(参数列表){
//参数列表----->需要传入的东西
....
函数体语句;
....
return 表达式;
}
注意1:如果不需要返回值,则返回值类型为void,此时可以不用写return +返回值;或者只写return;
注意2:定义函数时,这里的参数列表中的参数,是没有真实数据的,是形式参数
2.函数的调用
函数名(参数);
注意:这里的参数是实参,当调用函数时 ,实参的值会传递给形参
3.值传递
所谓的值传递就是:实参的值会传递给形参
当调用函数时,实参的值传给形参,形参改变,但是原先的实参是不变的------->形参无法改变实参
4.常见的函数样式
-
无参无返------->常用来打印
-
有参无返-------->用来打印这个参数
-
无参有返---------->调用函数时得到的就是这个返回值
int test(){
....
return 1000;
}
-
有参有返,可以返回这个参数,return 参数;
5.函数的声明
- 函数的声明可以多次,但是函数的定义只能有一次
- 函数的声明的格式:返回值类型 函数名(参数列表);
- 函数声明的作用,告诉运行程序自己要调用这个函数,如果main函数写在前,防止无法识别。
6.函数的分文件编写
函数分文件编写的主要步骤
- 1)创建.h后缀名的头文件
需要加#include <iostream.h>
using namespace std;
这是框架。
-
2)创建.cpp后缀的源文件
需要加#include “头文件名”
-
3)在头文件中写函数的声明
-
4)在源文件中写函数的定义
-
5)在运用时,就include这个函数的头文件就好了
7.有特点的的函数:获取随机数
rand()函数得到0~32767之间的随机数
rand()%100得到0~99之间的随机数
rand()%100+1得到1~100之间的随机数
注意:可以添加随机数种子,利用当前系统的时间生成随机数,防止每次生成的随机数是一样的
# include <ctime>//时间系统头文件
srand((unsigned int)time(NULL));
六.指针
1.定义指针
- 指针定义的语法:
数据类型 *指针变量名
eg: int *p;
int a=10;
p=&a;
指针p就是a的地址
2.使用指针
可以通过解引用的方式找到指针所指向的内存
指针前面加*代表解引用,找到指针指向内存的数据
eg: *p=1000; //修改了指针所指的内容
3.指针所占的内存空间
-
在32位操作系统下,占用4字节
-
在64位操作系统下,占用8字节
eg: int * p=&a;
*int 是指针的数据类型
cout<<sizeof(int *);与cout<<sizeof(p);等价
-
**不管是什么数据类型的指针都遵循上述规律,float 、int 、double * 都是一样的数据空间
4.空指针
-
int *p;-------->指针变量p指向的内存空间的编号为0的空间 也可写做 int *p =NULL;
-
空指针是不能进行访问的
要是后续代码中 未给指针初始化 而出现了 *p=100;或者打印 *p 的操作,都是不行的,因为内存编号从0~255为系统占用的内存,不允许用户访问
5.野指针
-
避免使用 如 int *p=(int *)0x1100;
将数字转换成指针类型(地址)然后赋给指针,当你利用解引用*p时,是没有权限访问该内容的。
6.const 修饰指针的三张情况
- 1)const 修饰指针------->常量指针
const int * p=&a;
或者
int const * p=&a;
特点:指针的指向可以修改,但是指针的值不可以修改
原因:const修饰的是*p,是一个值
- 2)const 修饰常量------->指针常量
int* const p=&a;//指针常量
特点:指针的指向不可以修改,但是指针的值可以修改
原因:const修饰的是p,是一个指针
- 3)const 即修饰指针,也修饰常量
const int * const p=&a;
特点:指针的指向不可以修改,但是指针的值也不可以修改
怎么读:看定义式,const为常量,*为指针
7.指针和数组
数组名就是指针的首地址
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int *p=arr;//arr就是数组的首地址
cout<<*P<<endl;//打印首地址的元素
p++;//指针偏移四个字节,因为int*是4字节的内存空间
cout<<*P<<endl;//打印下一地址的元素
8.指针和函数(值传递和地址传递)
- 1)值传递(见上面五.3的内容)-------->形参不可以修饰实参
- 2)地址传递----->形参可以修饰实参
#include <iostream>;
using namespace std;
void swap(int m,int n) {
int temp = m;
m = n;
n = temp;
cout << "swap:a =" << m << endl;
cout << "swap:b =" << n << endl;
}
void swap2 (int* m, int* n) {
int temp = *m;
*m = *n;
*n = temp;
cout << "swap2:a =" << *m << endl;
cout << "swap2:b =" << *n << endl;
}
int main() {
int a = 10;
int b = 20;
//swap(a,b)
swap2(&a, &b);
cout<<"a ="<< a<<endl;
cout<<"b ="<< b<<endl;
}
/*
结果(使用swap(a,b)):
swap:a =20
swap:b =10
a =10
b =20
结果(使用swap2(&a,&b)):
swap2:a =20
swap2:b =10
a =20
b =10
*/
总结:如果不想修改实参,就用值传递;如果想修改实参,就用地址传递;
9.指针和数组和函数
#include <iostream>;
using namespace std;
void bubbleSort(int *arr,int length) {
for (int i = 0; i < length-1; i++) {
for (int j = 0; j < length - 1 - i; j++) {
if (arr[j] < arr[j + 1]) {
int temp = arr[j+1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
}
void printArray(int *arr,int length) {
for (int i = 0; i < length; i++) {
cout << arr[i]<<endl;
}
}
int main() {
int arr[10] = { 5,6,3,4,2,10,9,1,8,7};
int len = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr,len);
printArray(arr, len);
}
/*
结果:
10
9
8
7
6
5
4
3
2
1
*/
七.结构体
1.结构体的基本概念
结构体属于用户自定义的数据类型,允许用户存储不同数据类型
2.结构体的定义和使用
1)结构体定义语法:struct 结构体名{结构体成员列表};
2)创建结构体的一个变量
- struct 结构体名 变量名
- struct 结构体名 变量名=
- 定义结构体时顺便创建变量
//struct结构体的使用
#include <iostream>;
#include <String>;
using namespace std;
struct Student {
string name;
int age;
float score;
}s3;
int main() {
//通过学生类创建一个具体的学生
//方法一
struct Student s1;
s1.name = "aaa";
s1.age = 10;
s1.score = 99;
//方法二
struct Student s2{"bbb",11,89 };
//方法三:直接在构造体后创建
s3.name = "ccc";
s3.age = 9;
s3.score = 95;
cout << s1.age << s1.name << s1.score << endl;
cout << s2.age << s2.name << s2.score << endl;
cout << s3.age << s3.name << s3.score << endl;
}
/*结果:
10aaa99
11bbb89
9ccc95
*/
定义结构体时的关键字是struct,不可省略
创建结构体时的关键字是struct,可以省略
3.结构体数组
1)作用:将自定义的结构体放入到数组中方便维护
2)语法:struct 结构体名 数组名[元素个数]={{},{},......{}}
//结构体数组
#include <String>;
#include <iostream>
using namespace std;
struct Student {
string name;
int age;
float score;
};
int main() {
//创建结构体数组,并赋值
struct Student studentArray[3]
{
{ "aaa",10,99},
{ "bbb",11,89},
{ "ccc",9,95}
};
//给结构体数组中的元素赋值
studentArray[2].age = 20;
studentArray[2].name ="ddd" ;
studentArray[2].score =100;
//遍历元素
for (int i = 0; i <= 2; i++) {
cout << studentArray[i].age
<< studentArray[i].name
<< studentArray[i].score<<endl;
}
}
/*
结果:
10aaa99
11bbb89
20ddd100
*/
4.结构体指针
//结构体指针
#include <String>;
#include <iostream>
using namespace std;
struct Student {
string name;
int age;
float score;
};
int main() {
//1.创建结构体变量(struct可以省略)
struct Student s1 = { "aaa",10,99 };
//2.通过指针指向结构体变量(struct可以省略)
struct Student* p = &s1;
//3.通过指针访问结构体变量的数据
//通过结构体指针 访问的结构体的属性,需要利用“->”符号
cout << p->age << p->name << p->score << endl;
}
/*
结果:10aaa99
*/
5.结构体嵌套另外一个结构体
在结构体中可以定义另外一个结构体作为成员,(被嵌套的也就是另一个)结构体需要定义在前
//结构体嵌套结构体
#include <String>;
#include <iostream>
using namespace std;
struct Student {
string name;
int age;
float score;
};
//新定义一个结构体用来嵌套上面的结构体成员
struct Teacher {
string name;
int age;
struct Student s1;//子结构体中的学生s1
//此处的struct 可以省略(创建一个子结构体的成员)
};
int main() {
struct Teacher t1;
t1.age = 30;
t1.name = "hhh";
t1.s1.age = 10;
t1.s1.name ="aaa" ;
t1.s1.score=99;
cout << "老师姓名: " << t1.name << endl;
cout<<"老师年龄: " << t1.age << endl;
cout << "辅导学生姓名: " << t1.s1.name << endl;
cout << "辅导学生年龄: " << t1.s1.age << endl;
cout<<"辅导学生成绩: "<<t1.s1.score<< endl;
}
/*结果:
老师姓名: hhh
老师年龄: 30
辅导学生姓名: aaa
辅导学生年龄: 10
辅导学生成绩: 99
*/
6.结构体作为函数参数(值/地址传递)
结论同上:如果不想修改实参,就用值传递;如果想修改实参,就用地址传递;
//结构体作为函数参数(值传递/地址传递)
#include <String>;
#include <iostream>
using namespace std;
struct Student {
string name;
int age;
float score;
};
void printStudent1(struct Student s) {
s.age = 100;
cout <<"printStudent1值传递下形式参数:"<< s.age << s.name << s.score << endl;
}
void printStudent2(struct Student* p) {
p->age = 200;
cout << "printStudent2地址传递下形式参数:" << p->age << p->name << p->score << endl;
}
//!!!要求:结构体作为函数参数,将创建出来的成员作为函数的参数
//实现打印这个成员的属性的函数
int main() {
struct Student s1 = { "aaa",10,99 };
printStudent1(s1);
//printStudent2(&s1);
cout << "main函数下实际参数:" << s1.age << s1.name << s1.score << endl;
}
/*结果:使用printStudent1(struct Student s) 值传递
printStudent1值传递下形式参数:100aaa99
main函数下实际参数:10aaa99
结果:使用printStudent2(struct Student s)地址传递
printStudent2地址传递下形式参数:200aaa99
main函数下实际参数:200aaa99
*/
注意1:当结构体作为函数参数时,常使用的形式参数是指针。原因是指针的内存空间是4字节,可以节省内存空间,而且不会复制出全部的信息出来
注意2:但是使用指针作为形式参数,是地址传递,为了防止 误操作(修改形参的值)常运用const----> const Student * s
7.结构体例题排序
//设计一个英雄结构体,包括姓名,年龄和性别。
//创建结构体数组,数组中存放5名英雄
//通过冒泡排序算法,按照年龄进行排序,最终打印结果
#include <String>;
#include <iostream>
using namespace std;
struct Hero {
string name;
int age;
string sex;
};
void Bubblesort(struct Hero heroArray[],int length){
for (int i = 0; i < length - 1; i++) {
for(int j=0;j<length-j-1;j++)
if (heroArray[j].age> heroArray[j + 1].age) {
Hero temp = heroArray[j];
heroArray[j ] = heroArray[j+1];
heroArray[j+1] = temp;
}
}
}
void Printfarray(Hero heroArray[], int length) {
for (int i = 0; i < length; i++)
{
cout << "姓名:" << heroArray[i].name << " 年龄: " << heroArray[i].age
<< " 性别: " << heroArray[i].sex << endl;
}
}
int main() {
//创建结构体数组
struct Hero heroArray[5]{
{"aaa",15,"男"},
{"bbb",10,"女"},
{"ccc",5,"男"},
{"ddd",20,"男"},
{"eee",25,"女"},
};
int len = sizeof(heroArray) / sizeof(heroArray[0]);
Bubblesort(heroArray, len);//这里的heroArray是数组的首地址
Printfarray(heroArray, len);
}