新手村——C++入门篇
C++入门篇,每天复盘下所学的知识点,写下来加深下印象。
根据b站黑马的视频学习。
一、基础
1、注释
单号注释 // 注释的内容
多行注释 /* 注释的内容*/
2、变量
给内存空间起个名字,方便对这内存操作。
规则:数据类型 变量名 = 初值;
int a = 10;
创建变量必须赋初值,不然报错。
3、常量
后续不允许修改。
宏常量 #define 一般在代码文件最上面,即最前面几行。
#define 常量名 常量值 #define num1 10 没有分号。
const修饰的变量,和定义变量语法一样,就是加个const,使其成为常量。
const int a = 10;
#include<iostream>
using namespace std;//常量定义
//宏常量 #define
#define Day 7
int main() {// Day = 14; Day是常量,修改就报错。//const修饰的变量const int month = 12;//month = 24; //const修饰的变量也是常量,修改报错cout << "一周有:"<<Day << "天" << endl;cout << "一年有:" << month << "月" << endl;system("pause");return 0;}
一些解释
1、#include用于引用位于其他文件中的代码
C++标准库文件后面就用<>,其他文件就()
2、using namespace std; 让代码更简洁。
提示编译器在此文件中使用C++标准库中内容,不然,库中的每个关键字都必须用std::开头表示范围
如 std::cout
3、cout关键字,用于打印输出。
<<运算符,提示编译器输入右侧内容。
4、endl关键字和Enter建类似,换行。
一般建议在" "里面加\n表示换行,因为endl会刷新缓冲区,影响程序的性能,endl在非常小的应用可以增加代码可读性。
5、main()必须要有,相当于程序的入口。
4、关键字
C++内置的标识符,定义常量变量时不可用这些,具体后面会慢慢了解。
asm | do | if | return | typedef |
---|---|---|---|---|
auto | double | inline | short | typeid |
bool | dynamic_cast | int | signed | typename |
break | else | long | sizeof | union |
case | enum | mutable | static | unsigned |
catch | explicit | namespace | static_cast | using |
char | export | new | struct | virtual |
class | extern | operator | switch | void |
const | false | private | template | volatile |
const_cast | float | protected | this | wchar_t |
continue | for | public | throw | while |
default | friend | register | true | |
delete | goto | reinterpret_cast | try |
5、标识符
字面意思,一个标记符号,来命名常量、变量,命名最好要做到见到就知道含义即代表什么。
规则:1,不能是关键字。
2,字母、数字、下划线组成,首字母必须是字母或者下划线。
3,标识符区分大小写。
二、数据类型
C++规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存
数据类型存在意义:给变量分配合适的内存空间
1、整型
整型可有四种,short、int、long、long long,所占字节个数不同,表示数的范围不同。
数据类型 | 占用空间 | 取值范围 |
---|---|---|
short(短整型) | 2字节 | (-215 ~ 215-1) |
int(整型) | 4字节 | (-231 ~ 231-1) |
long(长整形) | Windows为4字节,Linux为4字节(32位),8字节(64位) | (-231 ~ 231-1) |
long long(长长整形) | 8字节 | (-263 ~ 263-1) |
2、sizeof关键字
可以求出数据类型所占内存空间大小。
语法,sizeof(数据类型/变量名)
short num1 = 10;cout << "short占内存:" << sizeof(short) << endl;cout << "short占内存:" << sizeof(num1) << endl;
3、实型(浮点型)
分为float和double两种,所占内存空间不同,表示有效数字位数不同。
不过,一般默认输出6位有效数字(超过6位时)。
对于float,需要在赋值的后面加个f,告诉编译器这个是float型的数据,因为一般编译器会用double。
数据类型 | 占用空间 | 有效数字范围 |
---|---|---|
float | 4字节 | 7位有效数字 |
double | 8字节 | 15~16位有效数字 |
float f1 = 3.14159265354f; //默认为double,加个f就转为floatcout << "f1 =" << f1 << endl;double d1 = 3.14159265354;cout << "d1 =" << d1 << endl;
//输出均为3.14159
科学计数法表示浮点数
3e2 // 3*102
3e-2 //3*10-2
4、字符型
用于显示单个字符,定义时用单引号。
语法: char 变量名 = ‘字符’;
char ch = ‘a’;
字符变量占一个字节
字符变量不是将字符放在内存中存储,而是将其对应的ASCII码放在内存中。
#include<iostream>
using namespace std;int main() {//1 变量创建方式char ch = 'A';cout << ch << endl;//2 所占内存cout<<sizeof(char) << endl;//3 常见错误//char ch2 = "b";//创建字符要单引号//char ch3 = 'dswdr';//单引号只能一个字符//4 ASCII//a-97 A-65 大+32=小cout << (int)ch << endl;//转为十进制的数字system("pause");return 0;
}
ASCII 码大致由以下两部分组成:
- ASCII 非打印控制字符: ASCII 表上的数字 0-31 分配给了控制字符,用于控制像打印机等一些外围设备。
- ASCII 打印字符:数字 32-126 分配给了能在键盘上找到的字符,当查看或打印文档时就会出现。
记住 A 65 a 97 大写+32=小写
5、转义字符
用来显示不能显示出来的ASCII字符,目前主要先了解
\\ \t \n
#include<iostream>
using namespace std;int main() {//换行 \ncout << "hello \n";//返斜杠 \\cout<<"\\"<<endl;//水平制表 \t 作用,整齐输出数据。cout << "123456789\thello" << endl;// \t占8个空间,连前面的一起,比如1234\t,这样就剩下4个空格了,123 剩5个空格。//这个会先123456789,9后面跟7个空格再hellosystem("pause");return 0;
}
6、字符串型
用于输出一串字符。
有两种风格:
- C语言风格:char 变量名[] = “字符串”;
- C++风格:string 变量名 = “字符串”;
C++风格,需加一个头文件 #include < string > ,不然会报错,不过我用的vs2022没有报错,建议加上,使代码有好的可移植性。
#include<iostream>
using namespace std;
#include<string> //使用C++风格的字符串时要加此头文件int main() {//C风格 1、要加[]在字符名后, 2、等号后面双引号char str[] = "hello";cout << "str =" << str << endl;//C++风格 1、包含头文件string str2 = "hello world";cout << "str2 =" << str2 << endl; //加头文件,为可移植性system("pause");return 0;
}
7、bool类型
表示真假。bool只有两个值
- true—真 1
- false—假 0
其实除了0外的所有数都是真。
bool占一个字节内存空间。
#include<iostream>
using namespace std;int main() {//创建boolbool flag = true; //true为真 1cout << flag << endl;flag = false; //flase 为假 0cout << flag << endl;//查看内存空间cout << "bool 空间" << sizeof(bool) << endl;system("pause");return 0;}
8、数据输入
从键盘获取数据。
语法:cin << 变量
#include<iostream>
using namespace std;int main() {//cin >> 变量//整型int a = 0;cout << "a =" << a << endl;cout << "请给a赋值:" << endl;cin >> a;cout << "a =" << a << endl;//浮点float f = 3.14f;cout << "f = " << f << endl;cout << "f赋值:" << endl;cin >> f;cout << "f = " << f << endl;//字符char ch = 'a';cout << "ch =" << ch << endl;cout << "ch赋值:" << endl;cin >> ch;cout << "ch = "<< ch << endl;//字符串string str = "hello";cout << "str =" << str << endl;cout << "str赋值:" << endl;cin >> str;cout << "str =" << str << endl;//bool //赋值用0 1不是输入true或flase 0假 其他都为真bool flag = false;cout << "flag= " << flag << endl;cout << "赋值:" << endl;cin >> flag;cout << "flag= " << flag << endl;system("pause");return 0;
}
三、运算符
1、算术运算符
加减乘除。
除 / 就是取整。
整数相除,结果是整数;有一个是小数,结果为小数,能整除还为整数。
double d1 = 0.5;double d2 = 0.22;cout << d1 / d2 << endl; //运算结果可以是小数。double d3 = 1;cout << d2 / d3 << endl; //也为小数
取模运算 %
就是取余数
注意:两小数不能进行取模运算。
//两小数不可取模,会报错。double d01 = 3.14;double d02 = 1.1;cout << d01 % d02 << endl;
自增自减运算
分为前置和后置,不过都是加1,主要区别在于应用于表达式中。
//自增自减int a = 10;int b = 10; int c = 0;//前置递增a++; //a+1cout << "a = " << a << endl; //11//后置递增a = 10;++a; //a+1 //11cout << "a = " << a << endl;//两者区别,在表达式中有。a = 10;c = a++ * b; //先表达式运算,在进行++操作cout << "a = " << a << endl; //11cout << "c = " << c << endl; //100a = 10;c = ++a * b; //先进行++,在进行表达式操作cout << "a = " << a << endl; //11 cout << "c = " << c << endl; //110
减同理
2、赋值运算符
表达式的值赋值给变量。
// =int a = 10;a = 100;cout << "a = " << a << endl;// +=a = 10;a += 2; //a=a+2cout << "a = " << a << endl;// -=a = 10;a -= 2; //a=a-2cout << "a = " << a << endl;// *=a = 10;a *= 2; //a=a*2cout << "a = " << a << endl;// /=a = 10;a /= 2; //a=a/2cout << "a = " << a << endl;// %=a = 10;a %= 2; //a=a%2cout << "a = " << a << endl;
3、比较运算符
用于表达式比较,返回一个真值或者假值。
// 返回 真值或假值int a = 10;int b = 20;// == !=cout << (a == b) << endl; cout << (a != b) << endl;// < <= cout << (a <= b) << endl;cout << (a <= b) << endl;// > >=cout << (a > b) << endl;cout << (a >= b) << endl;
4、逻辑运算符
- 与 && 全真为真
- 或|| 有真就真
- 非 ! 取反
//返回真假 int a = 10;int b = 10;// !非 取反cout << !a << endl; //0cout << !!a << endl; //1// && 与cout << (a&&b) << endl; //1a = 0;cout << (a && b) << endl; //0// || 或cout << (a || b) << endl; //1b = 0;cout << (a || b) << endl; //0
四、程序流程结构
1、选择结构
1.1 if语句
满足则执行。if后面不加分号。
if(条件1){ 条件1满足执行的语句 }else if(条件2){条件2满足执行的语句}... else{ 都不满足执行的语句}
嵌套if语句。比较A、B、C大小
int a = 10;int b = 20;int c = 30;if (a > b) {if (a > c)cout << c << endl;elsecout << a << endl;}else {if (b > c)cout << b << endl;elsecout << c << endl;}
1.2 三目运算符
表达式1 ? 表达式2 : 表达式3
1为真执行2,反返回2的结果,否则执行3,返回3的结果。
1.3 switch语句
switch(表达式){case 结果1:执行语句;break;case 结果2:执行语句;break;...default:执行语句;break;}
switch表达式类型只能是整型或者字符型
case后加break,为程序不会一直执行下面的,特殊情况下除外可不加
2、循环结构
2.1 while循环
while(循环条件){循环语句}
循环条件为真就一直循环。所以程序需要跳出循环的出口,不然会死循环。
2.2 do while循环
do{循环语句}while(循环条件)
与while区别,就是不论是否满足条件,都会执行一次循环语句。
2.3 for循环
for(起始表达式;条件表达式;末尾循环体) { 循环语句; }
for循环内表达式用分号相隔。
语句执行顺序, for( 0 ; 1 ; 3 ) { 2 }
for循环内的变量是就近原则。不过为了程序代码理解,一般不会使用相同名称变量。
for (int i = 0; i < 10; i++){for (int i = 0; i < 10; i++){cout << i << " "; //这个i是指最近的那个}cout << endl;}
3、跳转语句
3.1 break语句
指跳出当前循环或选择结果。
- switch语句中,终止case并跳出switch
- 循环语句,跳出当前循环
- 嵌套循环,跳出最内层的循环
3.2 continue语句
跳过后面的语句,执行下一条循环语句。
3.3 goto语句
无条件跳转语句
goto 标记; 标记 :
如果标记存在,执行到标记位置。
int main() {cout << "1" << endl;goto FLAG;cout << "2" << endl;cout << "3" << endl;cout << "4" << endl;FLAG:cout << "5" << endl;system("pause");return 0;
}
goto 语句最好不用,当然可用少量,跳的太多代码不易阅读。
个人认为,goto语句对于分析mips代码有很大帮助,当然只是个题外话。
五、数组
数组就是相同数据类型元素的集合,在一片连续的内存位置中。
1、一维数组
1.1 定义方式
数据类型 数组名 [数组长度];
数据类型 数组名 [数据长度]={数据};
数据类型 数组名 []={数据};
1.2 数组名用途
- 统计数组在内存中的长度
- 获取数组在内存中首地址
数组名是常量,不能进行赋值操作
//一维数组定义//1、数据类型 数组名[数组长度]int arr[3];arr[0] = 0;arr[1] = 1;arr[2] = 2;for (int i = 0; i < 3; i++) {cout << arr[i] << endl;}//2、数据类型 数组名[数组长度]= {值1,值2....}int arr2[3] = { 20,21,22 };for (int i = 0; i < 3; i++) {cout << arr2[i] << endl;}//缺少的用0来代替。int arr2_1[5] = { 20,21,22 };for (int i = 0; i < 5; i++) {cout << arr2_1[i] << endl;}//3、数据类型 数据名[]={值1,值2....};int arr3[] = { 30,31,32,33,34 };for (int i = 0; i < 5; i++) {cout << arr3[i] << endl;}//注意:数组下标用0开始//数组名的作用。//1、统计整个数组在内存中的长度cout <<"arr数组长度(所占内存空间):" << sizeof(arr) << endl;cout << "arr数组每个元素所占内存空间数:" << sizeof(arr[0]) << endl;cout << "arr数组长度:" << sizeof(arr) / sizeof(arr[0]) << endl;//2、获取数组在内存中首地址cout << "数组的首地址为:" << &arr << endl;cout << "数组第一个元素的地址为:" << &arr[0] << endl;cout << "数组第二个元素地址为:" << &arr[1] << endl;//通过int强制转换,将16进制转为10进制。cout << "数组第三个元素首地址为(10进制表示):" << (int)&arr[2] << endl;//注意:数组名是常量,不能赋值//arr=10;//报错
1.3 案例——数组逆置
int arr[5] = { 1,2,3,4,5 };cout << "逆置前:" << endl;for (int i = 0; i < 5; i++) {cout << arr[i] << endl;}//1、记录起始结束下标位置int start = 0;int end = sizeof(arr) / sizeof(arr[0]) - 1;//2、起始结束元素互换,起始加1,结束减1int temp = 0;while (start < end) {temp = arr[start];arr[start] = arr[end];arr[end] = temp;start++; end--;}cout << "逆置后为:" << endl;for (int i = 0; i < 5; i++) {cout << arr[i] << endl;}
1.4 案例——冒泡排序
//排序总轮数=元素个数-1;//每轮对比次数=元素个数-当前排序轮数-1;int arr[9] = { 9,8,7,6,5,4,3,2,1 };cout << "排序前:" << endl;for (int i = 0; i < 9; i++) {cout << arr[i] << " ";}cout << endl;for (int i = 0; i < 9 - 1; i++) {for (int j = 0; j < 9 - 1 - i; j++) {if (arr[j + 1] < arr[j]) {int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}//排序后cout << "排序后:" << endl;for (int i = 0; i < 9; i++) {cout << arr[i] << " ";}cout << endl;
2、二维数组
2.1 定义
数据类型 数组名[行数][列数];
数据类型 数组名[行数][列数]={{},{},{}...};
建议使用此方法,代码更直观
数据类型 数组名[行数][列数]={数据...};
数据类型 数组名[][列数]={数据...};
2.2 数组名用途
- 查看二维数组所占内存空间。
- 获取二维数组首地址。
//二维数组定义,建议第二种。//1、数据类型 数组名[行数][列数];int arr[3][3];arr[0][0] = 1;arr[0][1] = 2;arr[0][2] = 3;arr[1][0] = 4;//后面类似。//2、数据类型 数组名[行数][列数]={{数据元素},{数据元素},{数据元素}};int arr2[3][3] = {{1,2,3},{4,5,6},{7,8,9}};for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {cout << arr2[i][j] << "\t";}cout << endl;}//3、数据类型 数组名[行数][列数]={数据,数据,数据...};int arr3[3][3] = { 1,2,3,4,5,6,7,8,9 };for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {cout << arr3[i][j] << "\t";}cout << endl;}//已经初始化,可以省略行数。//4、数据类型 数组名[][列数]={数据,数据,数据...};int arr4[][3]= { 1,2,3,4,5,6,7,8,9 };for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {cout << arr4[i][j] << "\t";}cout << endl;}//数组名作用,类一维//1、获取二维数组的内存空间cout << "二维数组的大小为:" << sizeof(arr) << endl;cout << "二维数组每行的大小为:" << sizeof(arr[0]) << endl;cout << "二维数组单个元素的大小为:" << sizeof(arr[0][0]) << endl;cout << "二维数组行数为:" << sizeof(arr) / sizeof(arr[0]) << endl;cout << "二维数组的列数为:" << sizeof(arr[0]) / sizeof(arr[0][0]) << endl;//2、得到二维数组的首地址cout << "二维数组的首地址为:" << arr << endl;cout << "二维数组的第一行首地址为:" << arr[0] << endl;//这个这为单个元素故需要用&取地址符号。cout << "二维数组的第一个元素的首地址为:" << &arr[0][0] << endl;cout << "二维数组的第二行首地址为:" << arr[1] << endl;cout << "二维数组的第三行首地址为:" <<(int) arr[2] << endl;
2.3 二维数组案例——输出每行和
int scores[3][3] = {{100,100,100},{90,50,100},{60,70,80}};string name[3] = { "张三","李四","王五" };for (int i = 0; i < 3; i++) {int sum = 0;for (int j = 0; j < 3; j++) {sum += scores[i][j];} cout << name[i] << "的总分为:" << sum << endl;}
六、函数
函数,就是将常用的代码封装起来,减少重复代码。
1、函数定义
返回值类型 函数名 (参数列表)
{函数体语句return表达式;}
- 返回值类型 :一个函数可以返回一个值。在函数定义中
- 函数名:给函数起个名称
- 参数列表:使用该函数时,传入的数据
- 函数体语句:花括号内的代码,函数内需要执行的语句
- return表达式: 和返回值类型挂钩,函数执行完后,返回相应的数据
2、调用
使用定义好的函数。
函数名(参数)
3、值传递
就是将实参的数值传递给形参,形参改变,实参不会发生改变。
#include<iostream>
using namespace std;//定义函数, 函数类型 函数名(参数列表){函数体语句 return 表达式}
//两个数相加函数
int add(int num1, int num2) {//形参int sum = num1 + num2;return sum;
}//值传递,调用函数将实参的数值传递给形参。
//值传递,形参发生改变,实参不会受到影响。//交换数字函数
void swap1(int num1, int num2) {cout << "交换前为:" << endl;cout << "num1 = " << num1 << "\t";cout << "num2 = " << num2 << "\t";cout << endl;int temp = num1;num1 = num2;num2 = temp;cout << "交换后为:" << endl;cout << "num1 = " << num1 << "\t";cout << "num2 = " << num2 << "\t";cout << endl;
}int main() {int a = 10; int b = 20;//调用add函数 函数名(参数列表)int c = add(a, b);//实参cout << "c = " << c << endl;cout << "a = " << a << "\t";cout << "b = " << b << "\t";cout << endl;swap1(a, b);cout << "a = " << a << "\t";cout << "b = " << b << "\t";cout << endl;system("pause");return 0;
}
4、函数常见形式
- 无参无返
- 有参无返
- 无参有返
- 有参有返
5、函数的声明
告诉编译器函数名称以及如何调用函数。
- 函数的声明可以多次,但是函数的定义只能有一次
一般用于定义的函数写在main函数后面,如果这样没有声明,程序会报错,因为程序是按代码一行一行执行的。或者用于分文件编写的函数中。
//声明可以多次,定义只能一次
//声明
int max(int a, int b);
int max(int a, int b);int main() {int a = 100;int b = 200;cout << max(a, b) << endl;system("pause");return 0;
}
//定义
int max(int a, int b)
{return a > b ? a : b;
}
6、函数分文件编写
为了让代码结构更加清晰。
步骤:
- 创建后缀名为.h的头文件
- 创建后缀名为.cpp的源文件
- 在头文件中写函数的声明
- 在源文件中写函数的定义
示例:
//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 temp = a;a = b;b = temp;cout << "a = " << a << endl;cout << "b = " << b << endl;
}
//main函数文件
#include<iostream>
using namespace std;
#include "swap.h" //同样使用此,联系起来
int main() {int a = 100;int b = 200;swap(a, b);system("pause");return 0;
}
七、指针
指针就是能通过其间接访问内存空间。内存编号从0开始,十六进制表示。指针变量保存地址
1、定义和使用
定义:数据类型 * 指针变量名;
此变量存的是地址,也是一个数。&也可以访问内存。
可以用* 也即是解引用操作,来操作指针指向的内存里的内容。
//指针记录变量的地址。//指针定义 数据类型 * 指针变量名;int a = 10;int* p;p = &a;cout << "a的地址为:" << &a << endl;cout << "a的地址为:" << p << endl;//指针的使用 //解引用的方式找到指针指向的内存//指针前加 * 代表解引用,找到指针指向内存中的数据。 *p = 1000;cout << "a = " << a << endl;cout << "*p = " << *p << endl;//指针所占内存空间//在32位OS下,指针占4个字节空间大小,不论数据类型.X86//63位,占8个字节空间大小。X64cout << "sizeof(int *) = " << sizeof(int*) << endl;cout << "sizeof(float *) = " << sizeof(float*) << endl;cout << "sizeof(double *) = " << sizeof(double*) << endl;cout << "sizeof(char *) = " << sizeof(char*) << endl;
所占内存空间根据OS而定。
2、空指针和野指针
空指针:指向内存编号为0的空间,用来初始化指针变量。
空指针的内存是不能够被访问的
野指针:指针变量指向非法的内存空间。这片内存空间并非自己定义,不知里面内容。
//空指针,指针变量指向地址变量为0的空间int* p = NULL;//空指针访问会报错,因为不是自己定义的空间。0~255为系统占用的内存,不允许用于访问//cout << *p << endl;//野指针,指针变量只想非法的内存空间。int* q = (int*)0x0321;//访问野指针会报错,因为野指针所指的内存空间并非自己所创建的。这块区域存了什么自己不知道。//cout << *q << endl;
3、const修饰的指针
有三种,修饰指针,修饰常量,两者都修饰。
int a = 10;int b = 10;//const修饰指针,常量指针const int* p = &a;//指针指向的值不能够修改,指向可修改//*p = 20; 错误p = &b;//const修饰常量,指针常量int* const p2 = &a;//指针指向的值可以修改,指向不能够修改//p2 = &b; 错误*p2 = 100;//const修饰指针和常量const int* const p3 = &a;//指针指向的值,和指针指向都不能修改//*p3 = 100; 错误//p3 = &b; 错误
4、指针和数组
利用指针访问数组中的元素。
对数组的数组名取指就是数组首地址
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int* p = arr;//arr就是数组的首地址//访问数组首个元素cout << "数组的第一个元素为:" << arr[0] << endl;cout << "利用指针看数组的第一个元素为:" << *p << endl;p++;cout << "利用指针看数组的第二个元素为:" << *p << endl;p = arr;for (int i = 0; i < 10; i++) {cout << *p << endl;p++;}
5、指针和函数
指针地址传递,和值传递不同,可以改变实参的数值。
void swap01(int a, int b) {int temp = a;a = b;b = temp;cout << "swap01 a = " << a << endl;cout << "swap01 b = " << b << endl;}void swap02(int* c, int* d) {int temp = *c;*c = *d;*d = temp;cout << "swap02 c = " << *c << endl;cout << "swap02 d = " << *d << endl;
}int main() {int a = 10;int b = 20;int c = 30;int d = 40;//1.值传递,swap01函数swap01(a, b);cout << "main a = " << a << endl;cout << "main b = " << b << endl;//2.地址传递,swap02函数,改变实参的值swap02(&c,&d); //地址传递cout << "main c = " << c << endl;cout << "main d = " << d << endl;
6、案例——指针函数数组
**案例描述:**封装一个函数,利用冒泡排序,实现对整型数组的升序排序
例如数组:int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
#include<iostream>
using namespace std;//冒泡排序函数
void bubbleSort(int* arr, int len) {for (int i = 0; i < len - 1; i++) {for (int j = 0; j < len - 1 - i; j++) {//如果j比j+1大则交换if (arr[j] > arr[j + 1]) {int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp; }}}
}//打印数组函数
void printArray(int* arr, int len) {for (int i = 0; i < len ; i++) {cout << arr[i] << endl;}
}
//数组名传入函数作为参数时,被退化为指向首元素的指针。
int main() {//构建数组int arr[10]= { 4,3,6,9,1,2,10,8,7,5 };int len = sizeof(arr) / sizeof(arr[0]);//cout << len << endl;bubbleSort(arr, len);//arr就是数组首地址,地址传递。printArray(arr, len);system("pause");return 0;
}
八、结构体
1、定义和使用
结构体就是用于自定义的数据类型,在一个结构体中可以有不同的数据类型。
struct 结构体名{成员变量列表};
创建结构体变量方式:
- struct 结构体名 变量名
- struct 结构体名 变量名={成员值…};
- 在定义结构体时就创建变量。
创建结构体时,struct是关键字,不能省略。
创建变量时,struct可以省略。
结构体变量通过"."访问成员。
#include<iostream>
using namespace std;
#include<string>//定义 struct 结构体名 {结构体成员列表};
struct student //定义结构体的关键字是struct,不可省去。
{//成员列表string name;int age;int score;
}s3; //3.定义结构体时顺便定义变量,不过此法一般不用。int main() {//定义结构体成员变量//1.struct 结构体名 结构体成员变量名struct student s1; //创建变量时,可以省去structs1.name = "张三";s1.age = 18;s1.score = 100;//访问结构体成员变量时,用.访问cout << "姓名:" << s1.name << " 年龄:" << s1.age << " 成绩:" << s1.score << endl;//2.struct 结构体名 变量名={成员列表};struct student s2 = {"李四",20,90};cout << "姓名:" << s2.name << " 年龄:" << s2.age << " 成绩:" << s2.score << endl;//3.定义结构体时定义变量s3.name = "王五";s3.age = 21;s3.score = 80;cout << "姓名:" << s3.name << " 年龄:" << s3.age << " 成绩:" << s3.score << endl;system("pause");return 0;
}
2、结构体数组
将结构体放入数组中方便后续维护。
struct 结构体名 数组名[元素个数]={ {} , {} , {} ...};
#include<iostream>
using namespace std;
#include<string>struct student
{string name;int age;int score;
};int main() {//结构体数组,将自定义的结构放入数组中,方便维护。//struct 结构体名 数组名[元素个数]={{},{},{}...};struct student arr[3] = {{"张三",18,100},{"李四",20,90},{"王五",22,80}};for (int i = 0; i < 3; i++) {cout << "姓名:" << arr[i].name << " 年龄:" << arr[i].age << " 成绩:" << arr[i].score << endl;}system("pause");return 0;
}
3、结构体指针
通过指针访问结构体中成员。->
操作符
//结构体指针,使用指针访问结构体成员。struct student s1 = { "张三",18,100 };struct student* p = &s1;//使用->访问成员变量p->score = 90;cout << "姓名:" << p->name << " 年龄:" << p->age << " 成绩:" << p->score << endl;
4、结构体嵌套
结构体的成员时另一个结构体。
如,每个老师一个学生,一个老师结构体中,记录一个学生的结构体
#include<iostream>
using namespace std;
#include<string>struct student
{string name;int age;int score;
};struct teacher {int id;string name;int age;struct student stu; //子结构体,学生
};int main() {struct teacher t1;t1.id = 1000;t1.age = 30;t1.name = "张三";t1.stu.name = "李四";t1.stu.age = 18;t1.stu.score = 99;cout << "教师编号:" << t1.id << " 教师年龄:" << t1.age << " 教师姓名:" << t1.name << endl;cout << "辅导学生姓名:" << t1.stu.name << " 年龄:" << t1.stu.age << " 成绩:" << t1.stu.score << endl;system("pause");return 0;
}
5、结构体做函数参数
同样有值传递和地址传递两种方式。
#include<iostream>
using namespace std;
#include<string>struct student
{//成员列表string name; int age; int score;
};//值传递
void printStudent(student stu) {stu.age = 30;cout << "子函数 姓名:" << stu.name << " 年龄:" << stu.age << " 成绩:" << stu.score << endl;}
//地址传递
void printStudent1(student * stu) {stu->score = 90;cout << "子函数 姓名:" << stu->name << " 年龄:" << stu->age << " 成绩:" << stu->score << endl;}
//修改结构体中的值就用地址传递,否则就值传递。
int main() {student s1 = { "张三",18,100 };printStudent(s1);cout << "main函数 姓名:" << s1.name << " 年龄:" << s1.age << " 成绩:" << s1.score << endl;student s2 = { "李四",20,99 };printStudent1(&s2);cout << "main函数 姓名:" << s2.name << " 年龄:" << s2.age << " 成绩:" << s2.score << endl;system("pause");return 0;
}
6、结构体中使用const
使用const就是为了在函数中防止修改了成员变量值。
//const使用场景
void printStudent(const student *stu) //加const防止函数体中的误操作
{//stu->age = 100; //操作失败,因为加了const修饰cout << "姓名:" << stu->name << " 年龄:" << stu->age << " 分数:" << stu->score << endl;}
7、结构体案例1
案例描述:
学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员
学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值
最终打印出老师数据以及老师所带的学生数据。
#include<iostream>
using namespace std;
#include<string>struct student
{string name; int score;
};
struct teacher1
{string name;student sArray[5];
};void allocateSpace(teacher1 tArray[], int len) {string tName = "教师";string sName = "学生";string nameSeed = "ABCDE";for (int i = 0; i < len; i++) {tArray[i].name = tName+nameSeed[i];for (int j = 0; j < 5; j++) {tArray[i].sArray[j].name = sName + nameSeed[j];tArray[i].sArray[j].score = rand() % 61 + 40;//40~100分}}
}void printTeachers(teacher1 tArray[], int len) {for (int i = 0; i < len; i++) {cout << tArray[i].name << endl;for (int j = 0; j < 5; j++) {cout << "姓名:" << tArray[i].sArray[j].name <<" 成绩:" << tArray[i].sArray[j].score << endl;}}}int main() {srand((unsigned int)time(NULL));//随机数种子,跟随系统时间teacher1 tArray[3];int len = sizeof(tArray) / sizeof(tArray[0]);//cout << len << endl;allocateSpace(tArray, len);printTeachers(tArray, len);system("pause");return 0;
}
8、案例2
案例描述:
设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。
通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果。
#include<iostream>
using namespace std;
#include<string>struct hero
{string name;int age;string sex;
};void bubbleSort(hero hArray[],int len) {for (int i = 0; i < len-1; i++) {for (int j = 0; j < len - 1 - i; j++) {if (hArray[j].age > hArray[j + 1].age) {hero temp = hArray[j];hArray[j] = hArray[j + 1];hArray[j + 1] = temp;}}}}void printHero(hero hArray[],int len) {for (int i = 0; i < len; i++) {cout << "姓名:" << hArray[i].name << " 年龄:" << hArray[i].age << " 性别:" << hArray[i].sex << endl;}
}int main() {struct hero hArray[5] = {{"刘备",23,"男"},{"关羽",22,"男"},{"张飞",20,"男"},{"赵云",21,"男"},{"貂蝉",19,"女"}, };int len = sizeof(hArray) / sizeof(hArray[0]);for (int i = 0; i < len; i++) {cout << "姓名:" << hArray[i].name << " 年龄:" << hArray[i].age << " 性别:" << hArray[i].sex << endl;}cout << "--------------------------------------------" << endl;bubbleSort(hArray, len);printHero(hArray, len);system("pause");return 0;
}
如果你看到这,恭喜你,马上就可以出新手村了,新手村的boss挑战请看下一节:
通讯录管理系统
新手村——C++入门篇相关推荐
- 女友问粉丝过万如何庆祝,我发万字长文《保姆级大数据入门篇》感恩粉丝们支持,学姐|学妹|学弟|小白看了就懂
2021大数据领域优质创作博客,带你从入门到精通,该博客每天更新,逐渐完善大数据各个知识体系的文章,帮助大家更高效学习. 有对大数据感兴趣的可以关注微信公众号:三帮大数据 目录 粉丝破万了 新星计划申 ...
- Farseer.net轻量级ORM开源框架 V1.x 入门篇:新版本说明
导航 目 录:Farseer.net轻量级ORM开源框架 目录 上一篇:没有了 下一篇:Farseer.net轻量级ORM开源框架 V1.x 入门篇:数据库配置 前言 V1.x版本终于到来了.本次 ...
- SQL注入漏洞全接触--入门篇
随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多.但是由于这个行业的入门门槛不高,程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,没有对用户输入数据的合法性进 ...
- Symbian开发系列 - 入门篇
要开始我的Symbian开发之旅了, 先收集一些相关资料,如Symbian概述, 开发平台搭建, 参考书籍与网络资源. [基础] 什么是Symbian 学习Symbian的基本概念 Symbian操 ...
- 《Ansible权威指南 》一 第一篇 Part 1 基础入门篇
本节书摘来自华章出版社<Ansible权威指南 >一书中的第1章,第1.1节,李松涛 魏 巍 甘 捷 著更多章节内容可以访问云栖社区"华章计算机"公众号查看. 第一篇 ...
- 【SSRS】入门篇(二) -- 建立数据源
原文:[SSRS]入门篇(二) -- 建立数据源 通过 [SSRS]入门篇(一) -- 创建SSRS项目 这篇,我们建立了一个SSRS项目: 接下来,我们以 AdventureWorks2012 示例 ...
- Python从入门到精通 - 入门篇 (下)
上一讲回顾:Python从入门到精通 - 入门篇 (上) 接着上篇继续后面两个章节,函数和解析式. 4 函数 Python 里函数太重要了 (说的好像在别的语言中函数不重要似的).函数的通用好处就不用 ...
- Python从入门到精通 - 入门篇 (上)
转载自微信公众号:王的机器 0 引言 微信公众号终于可以插代码了,Python 可以走一波了.首先我承认不是硬核搞 IT 的,太高级的玩法也玩不来,讲讲下面基本的还可以,之后带点机器学习.金融工程和量 ...
- matplotlib中文文档_python绘图库——Matplotlib及Seaborn使用(入门篇1)
在数据分析过程中,数据及模型可视化是无可避免的,同时这也是展示我们数据分析成果的最佳方式.因此,熟悉掌握绘图库的使用,对精进我们的数据分析技能起着不可替代的作用. 今天,我们就来了解一下python强 ...
最新文章
- 开发工具之Eclipse快捷键
- 对我国6G早期研究布局的几点建议
- python密码学编程pdf-Python密码学编程PDF电子书免费下载
- hdu2133: What day is it
- 2022年最值得学习的 5 种编程语言,你有在学习吗?
- log nginx 客户端请求大小_nginx log记录请求响应时间
- Microsoft Visual Studio下编译缺少头文件unistd.h解决办法
- js学习总结----简单的动画库封装tween.js
- linux lamp框架,LAMP架构协同应用的实例——phpMyAdmin
- mysql-5.5.17-win64 安装方法
- 继承求不同形状图形的周长和面积
- Java编程提高性能时需注意的地方
- html载入hta文件,浅谈HTA(HTML Application)和病毒的关系
- 国笔手机输入法MTK支持的语言
- HTML5 之 Meta 标签
- 各种三角形边长的计算公式
- IMX6 LCD 参数匹配过程分析
- [Android]自己动手做个拼图游戏
- Android MultiDex 源码分析
- MDCC王戈点爆全场:Smule乐器王是怎样炼成的
热门文章
- java mycat reload_MyCAT 1.6 使用reload @@config_all报错
- 按ASC码对字符串排序
- mac 邮箱客户端之腾讯企业邮箱设置 无法验证账号或密码
- arduino 1 读取电机编码器值
- 角度转度分秒lisp函数_自改小程序,提示错误,运行另一个lisp后就不会出错,求帮忙!...
- 苹果app商品定价_苹果将调整应用商店定价:中国区应用最低价涨至8元
- 一只小蜜蜂 C语言 函数 递归
- DNS故障的几种常见原因及解决方法
- 诗词锦集(持续更新)
- Nacos配置服务原理