5 数组
5.1 概述
数组是一个集合,里面存放了相同数据类型的变量
- 数组中的数据类型都一样
- 数组是由连续的内存组成的(放在一块连续的内存中)
5.2 一维数组
5.2.1 一维数组命名规则
数组由元素组成,可以通过元素的下标来访问数组中的元素(数组中的元素是从0开始的)
数组的三种定义方式:
- int arr[5];
- int arr[5] = {1,2,3,4,5};(如果没有全部填写完元素,会用’0‘来填补数据)
- int arr[] = {1,2,……0};
#include <iostream>
using namespace std;
int main()
{
int arr[5] = {1,2,3,4,5}
for (int i = 0; i < 5 ; i++)
{
cout << arr[i];
}
return 0;
}
5.2.2 一维数组名的用途(&)
- 可以统计数组所用内存的长度————sizeof(arr)
- 可以获取数组的在内存中的首地址
可以通过获取数组中单个元素的内存长度与总长度之商来获取数组中元素个数
#include <iostream>
using namspace std;
int main()
{
int arr[3] = {1,2,3};
cout << sizeof(arr);
cout << sizeof(arr[1]);
cout << sizeof(arr) / sizeof(arr[1]);
//数组的首地址
cout << arr;//通常为十六进制
cout << (int)arr;//转为十进制
cout << &arr[1];//一个元素的地址
return 0;
}
数组的首地址与第一个元素的地址重合
案例:五只小猪称体重
#include <iostream>
using namespace std;
int main()
{
int pigweight[5];
cout << "请分别输入五只小猪的重量" << endl;
for (int j = 0; j < 5; j++)
{cin >> pigweight[j];
}
int bigger = 0;
for (int i = 0; i < 5; i++)
{
if (pigweight[i] > pigweight[i + 1])
{
bigger = pigweight[i];
}
}
cout << "最重的小猪的体重是:" << endl << bigger << endl;
return 0;
}
遍历
案例:元素逆置
#include <iostream>
using namespace std;
int main()
{
int arr[5] = { 1,2,3,4,5 };
int mid = 0;//中间变量
for (int i = 0; i < 2; i++)//只需循环两次即可
{
mid = arr[i];//先将第一个元素赋值给中间变量
arr[i] = arr[4 - i];//再将第五个元素赋给第一个元素
arr[4 - i] = mid;//中间变量赋值给第五个元素
}
for (int j = 0; j < 5; j++)
{
cout << arr[j];
}
return 0;
}
5.2.3 冒泡排序
冒泡排序例题:数组排序
#include <iostream>
using namespace std;
int main()
{
//定义一个包含 10 个元素的整数数组,初始值为:{5, 2, 9, 1, 5, 6, 3, 8, 7, 4}
int arr[10] = { 5, 2, 9, 1, 5, 6, 3, 8, 7, 4 };
for (int p = 0; p < 10; p++)
{
cout << arr[p] << " " ;
}
cout << endl;
//实现冒泡排序算法对数组进行排序
int mid = 0;//中间变量,用于交换两个元素的位置
for (int i = 0; i < 10; i++)
//每两个相邻的数进行比较,找出第一个最大值
{
for (int j = 0; j < 9 - i; j++)
{
if (arr[j] > arr[j + 1])//如果前一个元素大于后一个元素,则交换位置
{
mid = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = mid;
//要进行十次比较,如果i < i+1,则二者的位置不变,下次循环继续比较
}
}
}
for (int p = 0; p < 10; p++)
{
cout << arr[p] << " ";
}
//分别输出排序前和排序后的数组元素
return 0;
}
我个人对冒泡排序的理解:
- 冒泡排序实则要进行两次循环。
- 第一次循环是外部循环,每轮循环减少一个元素(最大值),因此理论上要不断减少元素,直到只剩一个元素。
for(int i = 0 ; i < n ; i++)
//n为实际需比较的数+1,实际上可以改成 i <= n (此时n为需比较的数)
- 第二次循环时内部循环(实现元素的减少),通过比较相邻元素的大小,将大或小的数向左或右移动,当实现该次循环中的最后一次比较时,最大值或最小值便已确定,于是下一轮比较无需比较这一确定的元素
for(int j = 0 ; j < n - i ; j++)
//j < n - i 的目的是由于前一轮已经确定了某一最大值,
//于是在此次循环中,无需比较该元素,减少比较次数
5.3 二维数组
5.3.1 定义
矩阵
int arr[1] [2] = {{1},{1,2}}
5.3.2 二维数组名的用途
- 可以查看占用的内存空间大小
- 可以查看数组的首地址
案例:考试成绩
#include <iostream>
using namespace std;
int main()
{
int scores[3][3] = { 0 };//将二维数组中的所有元素都初始化为0
//让用户分别输入三个学生的语文数学英语成绩
for (int i = 0; i < 3; i++)
{
int sum = 0;
cout << "请输入第" << i + 1 << "位同学的,语文,数学,英语成绩:" << endl;
for (int j = 0; j < 3; j++)
{
cin >> scores[i][j];
}
cout << "这是第" << i + 1 << "位同学的三科成绩";
for (int k = 0; k < 3; k++)
{
cout << scores[i][k] << " ";
}
cout << endl;
cout << "这是第" << i + 1 << "位同学的总成绩";
for (int o = 0; o < 3; o++)
{
sum = scores[i][o] + sum;
}
cout << sum << endl;
}
return 0;
}
6 函数
将某些常用的的代码封装成函数
6.1 函数的定义
函数有五个部分组成
- 返回值类型
- 函数名
- 参数列表
- 函数体语句
- return 语句
int add (num1, num2)
{
int sum = num1+num2;
return sum;
}
6.2 函数的调用
#include <iostream>
using namespace std;
int add (int num1,int num2)//此处参数为形参,调用函数时将实参的值传递给形参
{
int sum = num1+num2;
return sum;//函数返回值
}
int main()
{
int a = 10;
int b = 10;
int c = add (a,b);//小括号里的参数为实际的参数,实参
//函数的调用:函数名 ()。被调用的函数会返回一个值
return 0;
}
6.3 值传递
在进行函数实参值传递给形参时,实参不受影响,只是把的数值传递
#include <iostream>
using namespace std;
void swap(int num1,int num2)//返回值类型为void时,不需要return语句(没有返回值)
{
int temp = num1
num1 = num2;
num2 = temp;
cout << num1 << endl;
cout << num2 << endl;
//进行了变量值的调换
}
int main()
{
int a = 10 ;
int b = 20 ;
swap(a,b);//函数被调用,执行函数体语句,无返回值
//当我们在进行函数的值传递时,形参的值发生改变,实参的值不受影响
//此时输出a , b 依然是10 20
}
6.4 函数的样式
#include <iostream>
#include <cmath>
using namespace std;
//函数的样式共有四种
//1.无参无返---即进行函数的调用后,主函数无返回值,仅执行函数体里的语句
void noprm_noret ()//无形参
{
cout << "this is a noparam_noreturnvalue function." <<endl;
//仅执行函数体
}
//2.无参有返---即进行函数的调用后,主函数有返回值
int noprm ()//无形参,但函数返回值不为void(空)
{
cout << "this is a noparam function."<<endl;
return 666;
}
//3.有参无返---即进行函数的调用后,主函数无返回值,需实参与形参进行值传递
void noret (int a ,int b)
{
cout << "there is not a return value , the fuction value is : " << a << b << endl;
}
//4.有参有返---既需要实参的值传递,又需要给主函数返回值
double prm_ret(int a)
{
double e_value = a * exp(1);
return e_value;
}
int main ()
{
//函数的调用,进行函数调用时,直接调用其函数名
//无参无返的函数调用
noprm_noret ();//直接调用
//无参有返函数的调用
int result = noprm();
//如果不需要该函数的返回值,可以仅执行函数语句,不用变量来承载函数返回值
//有参无返函数的调用
int num1 = 1;
int num2 = 2;
noret(num1,num2);//定义实参进行值传递
//有参有返函数的调用
int e_plus_value = 2;
double final_value =prm_ret(e_plus_value);
return 0;
}
6.5 函数的声明
在C++中,计算机编译的顺序是由上至下
如果函数的定义在主函数之后,计算机在编译主函数(调用函数)时会报错
此时便可以在主函数前先声明函数的存在,让计算机可以利用函数的声明,
告诉编译器函数的名称以及如何调用函数
值得注意的一点是,函数的定义只能有一次,可函数的声明不受限,但在日常工作中,常常仅进行一次函数的声明。
#include <iostream>
using namespace std;
//先进行函数的声明
int max(int a,int b);
int main()
{
int num1 = 10;
int num2 = 20;
max(num1,num2);
return 0;
}
//这是一个有参有返函数,函数的内容是比较两个参数的大小
int max (int a ,int b )
{
cout << a>b?a:b;
}
6.6 函数的分文件编写
1.在头文件中创建一个.h后缀的文件
我们创建头文件中需包含函数中所需的头文件,以及进行函数的声明
#include <iostream>
using namespace std;
//在头文件中进行函数的声明
int max (int a ,int b);
2.在源文件中创建一个后缀为.cpp的文件
我们创建源文件中,需包含我们自己创建的头文件的引用,以及函数的内容
#include "max.h"
//自己创建的头文件需用 ""
int max (int a ; int b)
{
return a>b ?a:b;
}
3.在主函数中如何调用函数
#include <iostream>
#include "max.h"
using namespace std;
int main()
{
int num1 = 10;
int num2 = 20;
cout << max(num1,num2);
return 0;
}
函数例题
案例:打印helloworld 无参无返类型
#include <iostream>
using namespace std;
void print_welcome()
{
cout << "hello world" << endl;
}
int main ()
{
print_welcome();
return 0 ;
}
案例:打印两个整数之和 有参无返类型
#include <iostream>
using namespace std;
void sum (int a , int b)
{
cout << a + b << endl;
}
int main ()
{
int num1 = 10;
int num2 = 20;
sum(num1,num2);
return 0 ;
}
案例:计算两数之积 有参有返类型
#include <iostream>
using namespace std;
int plus (int a , int b)
{
return a*b;
}
int main ()
{
int num1 = 10;
int num2 = 20;
cout << plus(num1,num2);
return 0;
}
案例:判断一个数是否为偶数
#include <iostream>
using namespace std;
bool even (int a)
{
return a%2==0;//非零即真
}
int main()
{
int n = 0;
cin >> n;
cout << even(n);
return 0;
}
7 指针
7.1指针的基本概念
指针是一个存储变量地址的变量,我们可以通过指针解引用这个操作,对所存储的变量间接的进行读写操作
7.2指针的定义和使用
#include <iostream>
using namespace std;
int main()
{ //指针的定义
int a = 0;
int *p ;//数据类型 * 指针变量名
p = &a;//指针获取变量地址时需要使用取地址符 '&'
//此时&a(a的地址存储在p中)==p
//指针的使用
*p = 1;
//此时变量a的值被我们解引用的操作修改为 '1'
//我们可以通过解引用的方法对指针所存储的变量进行读写操作(间接)
return 0;
}
7.3 指针所占内存空间
#include <iostream>
using namespace std;
int main()
{
int a= 0;
int * p = &a;//这是另一种指针定义方式,定义的同时规定它的指向
cout << sizeof(int *) << endl;//此时也可以sizeof p
cout << sizeof(double *) << endl;
cout << sizeof(float *) << endl;
cout << sizeof(char *) << endl;
//在32位系统中,所有指针数据类型大小都为4个字节,无论数据类型是什么
//在64位操作系统中都为8字节
return 0;
}
7.4 空指针和野指针
7.4.1 空指针
空指针指向内存空间为零
一般用于指针的初始化
int *p = NULL;
//其中的NULL为#define 0 NULL
cout << *p << endl;
//由于空指针指向的是内存地址0,而0~255为系统所占内存,无法访问
空指针的内存空间无法访问
7.4.2 野指针
野指针指的是指向非法内存的指针
在代码中避免出现野指针
int *p = (int *) 0x1100;//对0x1100强行定义
*p = 1000;//强行对0x1100进行解引用操作,系统报错
7.5 const修饰指针
#include <iostream>
using namespace std;
int main ()
{
int a = 10;
int b = 10;
int * p = &a;//p取a的地址
//1.const修饰指针
const int * o = &a;
//const修饰指针,此时o为常量指针
//常量指针(const修饰指针):指针的指向不可以改,指针的值可以改
o = 20;
//2.const修饰常量
int const *i = &b;
//const修饰常量,此时i为指针常量
//指针常量(const修饰常量):指针的指向可以改,指针的值不可以修改
//3.const既修饰指针又修饰常量
const int const *point = &a;
//此时指针的指向,指针的值均不可修改
return 0;
}
7.6 利用指针访问数组中的元素
void main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int *p = arr;//arr即为数组的首地址,若要单独获取元素的地址,需要加上&与下标
for(int i = 0; i < 10;i++)
{
cout << *p << endl;
//对指针指向的地址进行解引用,由于数组第一个元素与数组地址一致,所以输出arr[0]
p++;
//由于int数组中每个元素相邻4个字节,使指针偏离四个字节便可以指向下个元素的地址
}
}
7.7 指针与函数
void swap01(int a,int b)
{
int temp = a;
a = b;
b = a;
}
void swap02(int *p1,int *p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
void main()
{
int a = 10;
int b = 20;
swap01(a,b);
//此时将主函数中的实参值传递给swap01中的形参中
//完成函数体语句后,形参的数值发生了交换,主函数中的实参数值没改变
//如果将a,b的地址传递给swap02中的两个指针中
//此时对指针进行解引用操作,即可利用指针通过地址间接的修改主函数实参的值
swap02(&a,&b);
}
案例:指针,数组,函数的冒泡排序
#include <iostream>
using namespace std;
//1.输入数组元素
void input_scores(int * p)
//先取输入的总人数,再进行输入
{
cout << "请输入学生们的成绩" << endl;
for (int i = 0; i < 5; i++) {
cin >> *p;
p++;
}
}
//2.进行排序
void bubble_sort(int* p)
{
int temp = 0;
for (int i = 0; i < 5; i++)//进行外部排序
{
for (int j = 0; j < 4 - i; j++)//每循环一次减少一次比较次数
{
if (*(p + j + 1) < *(p+j))
//让指针随着变量偏移
{
temp = *(p+j);
*(p+j) = *(p + j + 1);
*(p +j+ 1) = temp;
}
}
}
}
//3.输出冒泡排序后的值
void output_scores(int * p)
{
cout << "现在输出学生们经过排序后的成绩:" << endl;
for (int i = 0; i < 5; i++)
{
cout << *p << " ";
p++;
}
cout << endl;
}
int main()
{
int arr [5];
input_scores(arr);
bubble_sort(arr);
output_scores(arr);
return 0;
}
指针例题
案例:基础运用
#include <iostream>
using namespace std;
/*定义两个整型变量 a = 10、b = 20,通过指针完成以下操作:
用指针 p1 指向变量 a,输出 a 的值(通过指针访问);
用指针 p2 指向变量 b,通过 p2 修改 b 的值为 200;
交换 p1 和 p2 指向的变量的值(最终 a = 200,b = 10)。*/
void swap(int *p1,int *p2)//地址传递
{
int temp = 0;
temp = *p1;//解引用
*p1 = *p2;
*p2 = temp;
cout << "a=" << *p1 << "\tb=" << *p2;
}
int main()
{
int a = 10;
int b = 20;
int* p1 = &a;
int* p2;
p2 = &b;//定义方式
*p2 = 200;
cout << "a=" << *p1 << "\tb=" << *p2 << endl;
swap(p1, p2);
return 0;
}
案例:指针遍历数组
#include <iostream>
using namespace std;
/*定义一个整型数组 arr = {5, 2, 9, 1, 3},通过指针完成以下操作:
计算数组所有元素的和;
找到数组中的最大值,并输出最大值及其在数组中的索引(从 0 开始);
用指针逆序输出数组元素(如原数组 5,2,9,1,3,逆序输出 3,1,9,2,5)。*/
int sum(int* p, int num)
{
int summation = 0;
for (int i = 0; i < num; i++)
{
summation += *(p + i);
}
return summation;
}
void max(int* p, int num)
{
int maxium = *p; // 假设最大的就是第一个元素
int index = 0;
for (int i = 1; i < num; i++) {
if (maxium < *(p + i)) {
maxium = *(p + i);
index = i;
}
}
std::cout << " max : " << maxium << " max__Index: " << index << std::endl;
}
void flashBack(int* p, int num)
{
for (int i = num -1 ; i >= 0; i--)
{
cout << *(p + i) << endl;
}
}
int main()
{
int array[5] = {9,7,5,3,1};
const int number = 5;
cout << "sum = " << sum(array, number) << endl;
max(array, number);
flashBack(array, number);
return 0;
}
8 结构体
结构体是用户定义的一种数据类型,是数据类型之和
8.1 结构体的定义
struct student
//关键字 数据类型
{
string name ;
int age = 18;//可以先初始化结构体变量
};
8.2 结构体的使用
sturct hero
{
int age;
string name;
};
int main()
{
hero menber;
cin >> menber.age;
//.对结构体的成员进行操作,填写名字
cin >> menber.name;
return 0;
}
8.3 结构体数组
struct student
{
int age;
string name;
int score;
}
int main()
{
student studentMenber [5];
}
8.4 结构体指针
int main()
{
student *p;
cin>>p->age;//利用->运算符进行读写结构体中的成员
return 0;
}
8.5 结构体嵌套
//2.学生的结构体
struct student
{
string name = "student_";
int score;
};
//1.先定义老师的结构体
struct teacher
{
string name = "teacher_";
student std[5];//结构体嵌套并初始化
};
//要修改学生结构体中的数据,既可以单独修改,也可以关联老师结构体修改
void input_massage(teacher* p , int num_tea)
{
for (int i = 0; i < num_tea; i++)//遍历老师结构体数组
{
string nameseed = "ABCDE";//字符串是字符的集合
(p + i)->name += nameseed[i];//输入名字
for (int j = 0; j < 5; j++)
{
(p+i)->std[j].name += nameseed[j];//关联老师结构体
int random = rand() % 60 + 41;//rand函数是对60取模,取值是0~59
(p + i)->std[j].score = random;
}
}
}
8.6 结构体函数参数
- 值传递
- 地址传递
#include <iostream>
#include <string>
using namespace std;
struct stu{
int age;
string name;
};
void swap01 (stu student[2])//值传递
{
stu temp ;
if(student[0].age < student[1].age)
{
temp = student [0];
student [0] = student[1];
student [1] = temp;
}
cout << student[0].age << student[1].age ;
}
void swap02(stu *p)//地址传递
{
stu temp ;
if(p->age < (p+1)->age)
{
temp = *p;
*p = *(p+1);
*(p+1) = temp;
}
cout << *p << *(p+1) ;
}
8.7 结构体中const修饰
struct const hero
{
int age;
string name;
};
//只读不写
结构体例题
案例:教师学生系统
#include<iostream>
#include<string>
#include<ctime>
using namespace std;
//2.学生的结构体
struct student
{
string name = "student_";
int score;
};
//1.先定义老师的结构体
struct teacher
{
string name = "teacher_";
student std[5];//结构体嵌套并初始化
};
//3.输入信息
void input_massage(teacher* p , int num_tea)
{
for (int i = 0; i < num_tea; i++)//遍历老师结构体数组
{
string nameseed = "ABCDE";//字符串是字符的集合
(p + i)->name += nameseed[i];//输入名字
for (int j = 0; j < 5; j++)
{
(p+i)->std[j].name += nameseed[j];
int random = rand() % 60 + 41;//rand函数是对60取模,取值是0~59
(p + i)->std[j].score = random;
}
}
}
//4.输出信息
void output_massage(teacher* p1 , int num_tea)
{
for (int i = 0; i < num_tea; i++)
{
cout << "老师的姓名为: " << (p1+i)->name <<endl;
for (int j = 0; j < 5; j++)
{
cout << "\t学生的姓名为:" << (p1 + i)->std[j].name
<< " 学生的成绩" << (p1 + i)->std[j].score << endl;
}
}
}
int main()
{
srand((unsigned int)time(NULL));//随机数种子
const int num_tea = 3;//定义常量,方便修改
teacher tea_num[num_tea];
input_massage(tea_num,num_tea);
output_massage(tea_num,num_tea);
return 0;
}
案例:英雄排序系统
#include<iostream>
#include<string>
using namespace std;
struct hero
{
string name;
int age;
string sex;
};
void heroMessage (hero arr[5] , int num)
{
for (int i = 0; i < num; i++)
{
cout << "请输入第" << i + 1 << "位英雄的名字" << endl;
cin >> arr[i].name;
cout << "请输入第" << i + 1 << "位英雄的年龄" << endl;
cin >> arr[i].age;
cout << "请输入第" << i + 1 << "位英雄的性别" << endl;
cin >> arr[i].sex;
}
}
void bubble_sort(hero *p, int num)
{
hero temp;
for (int i = 0; i < num; i++)
{
for (int j = 0; j < num - 1 - i; j++)
{
if ((p+j)->age > (p+ j + 1)->age)//别忘了+j!!!!!!!!!!!!!!
{
temp = *(p+j);//直接对整体交换
*(p+j) = *(p + j + 1);
*(p + j + 1) = temp;
}
}
}
}
void showHero(hero arr[5],int num)
{
int i = 0;
while (i < num)
{
cout << "这是第" << i + 1 << "个英雄的信息" << endl
<< "\t名字:" << arr[i].name << " 年龄:" << arr[i].age << " 性别:" << arr[i].sex << endl;
i++;
}
}
int main()
{
cout << "*******欢迎来到英雄排序系统*******" << endl;
const int heroNumber = 5;
hero heroArray[heroNumber];
heroMessage(heroArray, heroNumber);
showHero(heroArray, heroNumber);
bubble_sort(heroArray, heroNumber);
cout << "这是排序后的英雄名单" << endl;
showHero(heroArray, heroNumber);
return 0;
}
案例:判断学生是否成年
#include <iostream>
#include <string>
struct date
{
int year;
int month;
int day;
};
struct student
{
std::string name;
std::string id;
date birthday;
double score;
};
void inputMessage(student data[], int num)
{
std::cout << "请输入学生的基础信息:" << std::endl;
for (int i = 0; i < num; i++)
{
std::cout << "请输入第" << i + 1 << "个学生的基础信息" << std::endl;
std::cout << "姓名 学号 成绩 生日" << std::endl;
std::cin >> data[i].name >> data[i].id >> data[i].score >> data[i].birthday.year >> data[i].birthday.month >> data[i].birthday.day;
}
}
void outputBirthyday(student birthday[], int num)
{
for (int i = 0; i < num; i++)
{
std::cout << "这是" << birthday[i].name << "同学的生日\n" << "年 月 日\n";
std::cout << birthday[i].birthday.year << birthday[i].birthday.month << birthday[i].birthday.day << std::endl;
if (2024 - birthday[i].birthday.year >= 18)
{
std::cout << "这位同学已经成年" << std::endl;
}
else
{
std::cout << "这位同学还未成年" << std::endl;
}
}
}
int main()
{
const int num = 2;
student stdArray[num];
inputMessage(stdArray, num);
outputBirthyday(stdArray, num);
return 0;
}
781

被折叠的 条评论
为什么被折叠?



