C++基础:第5~6章:数组\函数

简介: C++基础:第5~6章:数组\函数

考题:

什么是数组以及其特点是什么?还有它的内存空间的位置是如何排列的?

一维数组有哪三种定义方式?

一维数组组名的用途有哪些?


数组:


5.1 概述

Q:什么是数组以及其特点是什么?

A:数组是一个集合,里面存放了相同类型的数据元素,同时它是由连续的内存位置组成


ps:这里也就说明了为什么指针指向数组首元素,就相当于找到了数组所有元素的地址


所谓数组,就是一个集合,里面存放了相同类型的数据元素


特点1:数组中的每个数据元素都是相同的数据类型


特点2:数组是由连续的内存位置组成的


5.2 一维数组


5.2.1 一维数组定义方式

一维数组定义的三种方式:


1.数据类型 数组名[ 数组长度 ];

2.数据类型 数组名[ 数组长度 ] = { 值1,值2 ...};

3.数据类型 数组名= { 值1,值2 ...};


▪案例:

int main() { 
  //定义方式1
  //数据类型 数组名[元素个数];
  int score[10];
  //利用下标赋值
  score[0] = 100;
  score[1] = 99;
  score[2] = 85;
  //利用下标输出
  cout << score[0] << endl;
  cout << score[1] << endl;
  cout << score[2] << endl;
  //第二种定义方式
  //数据类型 数组名[元素个数] =  {值1,值2 ,值3 ...};
  //如果{}内不足10个数据,剩余数据用0补全
  int score2[10] = { 100, 90,80,70,60,50,40,30,20,10 };
  //逐个输出
  //cout << score2[0] << endl;
  //cout << score2[1] << endl;
  //一个一个输出太麻烦,因此可以利用循环进行输出
  for (int i = 0; i < 10; i++)
  {
    cout << score2[i] << endl;
  }
  //定义方式3
  //数据类型 数组名[] =  {值1,值2 ,值3 ...};
  int score3[] = { 100,90,80,70,60,50,40,30,20,10 };
  for (int i = 0; i < 10; i++)
  {
    cout << score3[i] << endl;
  }
  system("pause");
  return 0;
}

! :数组中下标是从0开始索引


5.2.2 一维数组数组名

一维数组名称的用途:

1.可以统计整个数组在内存中的长度

2.可以获取数组在内存中的首地址


▪案例:

int main() {
  //数组名用途
  //1、可以获取整个数组占用内存空间大小
  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
  cout << "整个数组所占内存空间为: " << sizeof(arr) << endl;
  cout << "每个元素所占内存空间为: " << sizeof(arr[0]) << endl;
  cout << "数组的元素个数为: " << sizeof(arr) / sizeof(arr[0]) << endl;
  //2、可以通过数组名获取到数组首地址
  cout << "数组首地址为: " << (int)arr << endl;
  cout << "数组中第一个元素地址为: " << (int)&arr[0] << endl;
  cout << "数组中第二个元素地址为: " << (int)&arr[1] << endl;
  //arr = 100; 错误,数组名是常量,因此不可以赋值
  system("pause");
  return 0;
}

补充:数组首元素地址和数组地址的关系:


https://blog.csdn.net/Raven_csdn/article/details/87874679


1、首先数组首元素的地址和数组地址的值是相等的。


2、数组首元素的地址和数组地址是两个不同的概念。


a的值是数组首元素的地址,所以a+1,就是第二个元素的地址,int类型占用4个字节,所以相差4


而&a是整个数组的地址,所以&a+1,就是向后移动(10*4)个单位。所以相差40.


5ca76301f159467683c4dfc583d2dd5f.png


注意:数组名是常量,不可以赋值

总结1:直接打印数组名,可以查看数组所占内存的首地址

总结2:对数组名进行sizeof,可以获取整个数组占内存空间的大小

▪案例:


练习案例1:五只小猪称体重


案例描述:

在一个数组中记录了五只小猪的体重,如:int arr[5] = {300,350,200,400,250};


找出并打印最重的小猪体重。

#include <iostream>
using namespace std;
int main(){
  //1.创建5只小猪体重的数组
  int arr[5]={300,350,200,400,250};
  //2.从数组中找到最大值
  int max=0;
  for(int i=0;i<5;i++){
    if(arr[i]>max){
      max=arr[i];
    }
  }
  //3.打印最大值
  cout<<"最重的小猪体重为:"<<max<<endl;
  system("pause");
  return 0;
}

**练习案例2:**数组元素逆置


**案例描述:**请声明一个5个元素的数组,并且将元素逆置.


(如原数组元素为:1,3,2,5,4;逆置后输出结果为:4,5,2,3,1);


#include <iostream>
using namespace std;
int main(){
  //实现数组元素的逆置
  //1.创建数组
  int arr[5]={1,3,2,5,4};
  int len=sizeof(arr)/sizeof(arr[0]);  //获取数组的长度
  cout<<"数组逆置前:";
  for(int i=0;i<len;i++){
    cout<<arr[i]<<"  ";
  }
  cout<<endl;
  //2.实现逆置
  //2.1记录起始下标位置
  //2.2记录结束下标位置
  //2.3起始下标与结束下标的元素互换
  //2.4 起始位置++  结束位置--
  //2.5循环执行2.1操作,直到起始位置》=结束位置
  int start=0;//起始下标
  int end=len-1;//结束下标
  while(start<end){
    //实现元素互换
    int temp=arr[start];
    arr[start]=arr[end];
    arr[end]=temp;
    //下标更新
    start++;
    end--;
  }
  //打印逆置后的数组
  cout<<"数组逆置后:";
  for(int i=0;i<len;i++){
    cout<<arr[i]<<"  ";
  }
  cout<<endl;
  system("pause");
  return 0;
}
//以上采取镜像转换的方式来逆序排序

冒泡排序

作用: 最常用的排序算法,对数组内元素进行排序


步骤:


1.每轮比较相邻元素。若前比后大,则交换二者。


注:对每一对相邻元素做同样的工作,执行后,找到第一个最大值。就像泡泡越升越大。


2.重复以上的步骤,每次比较次数-1(因为最大已找到),直到不需要比较


示例: 将数组 { 4,2,8,0,5,7,1,3,9 } 进行升序排序


#include <iostream>
using namespace std;
int main() {
  int arr[9] = { 4,2,8,0,5,7,1,3,9 };
  int len=sizeof(arr)/sizeof(arr[0]);
  for (int i = 0; i < len - 1; i++)//趟数 len-1 ,9个数意味着要比较8趟,即需要把大的数浮到表面的次数为8次
  {
    for (int j = 0; j < len - 1 - i; j++) //每一趟的比较次数 len-1-i
    {
      if (arr[j] > arr[j + 1])
      {
        int temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
      }
    }
  }
  for (int i = 0; i < len; i++)
  {
    cout << arr[i] << " ";
  }
    cout<<endl;
system("pause");
  return 0;
}


5.3 二维数组

二维数组就是在一维数组上,多加一个维度。


5.3.1 二维数组定义方式

二维数组定义的四种方式:


1.数据类型 数组名[ 行数 ][ 列数 ];

2.数据类型 数组名[ 行数 ][ 列数 ] = { {数据1,数据2 } ,{数据3,数据4 } };

3.数据类型 数组名[ 行数 ][ 列数 ] = { 数据1,数据2,数据3,数据4};

4.数据类型 数组名[ ][ 列数 ] = { 数据1,数据2,数据3,数据4};

建议:以上4种定义方式,利用第二种更加直观,提高代码的可读性

▪案例:

int main() {
  //方式1  
  //数组类型 数组名 [行数][列数]
  int arr[2][3];
  arr[0][0] = 1;
  arr[0][1] = 2;
  arr[0][2] = 3;
  arr[1][0] = 4;
  arr[1][1] = 5;
  arr[1][2] = 6;
  for (int i = 0; i < 2; i++)
  {
    for (int j = 0; j < 3; j++)
    {
      cout << arr[i][j] << " ";
    }
    cout << endl;
  }
  //方式2 
  //数据类型 数组名[行数][列数] = { {数据1,数据2 } ,{数据3,数据4 } };
  int arr2[2][3] =
  {
    {1,2,3},
    {4,5,6}
  };
  //方式3
  //数据类型 数组名[行数][列数] = { 数据1,数据2 ,数据3,数据4  };
  int arr3[2][3] = { 1,2,3,4,5,6 }; 
  //方式4 
  //数据类型 数组名[][列数] = { 数据1,数据2 ,数据3,数据4  };
  int arr4[][3] = { 1,2,3,4,5,6 };
  system("pause");
  return 0;
}


注意点:

▪注意点:

  for (int i = 0; i < 2; i++)
  {
    for (int j = 0; j < 3; j++)
    {
      cout << arr[i][j] << " ";
    }
    cout << endl; //换行加缓冲区刷新
  }

注意红字部分,只有这么写输出的才是


123


456


总结:在定义二维数组时,如果初始化了数据,可以省略行数

5.3.2 二维数组数组名

▪查看二维数组所占内存空间


▪获取二维数组首地址


▪案例:

int main() {
  //二维数组数组名
  int arr[2][3] =
  {
    {1,2,3},
    {4,5,6}
  };
  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;
  //地址
  cout << "二维数组首地址:" << arr << endl;
  cout << "二维数组第一行地址:" << arr[0] << endl;
  cout << "二维数组第二行地址:" << arr[1] << endl;
  cout << "二维数组第一个元素地址:" << &arr[0][0] << endl;
  cout << "二维数组第二个元素地址:" << &arr[0][1] << endl;
  system("pause");
  return 0;
}

总结1:二维数组名就是这个数组的首地址

总结2:对二维数组名进行sizeof时,可以获取整个二维数组占用的内存空间大小

5.3.3 二维数组应用案例


▪案例:


考试成绩统计:


案例描述:有三名同学(张三,李四,王五),在一次考试中的成绩分别如下表,请分别输出三名同学的总成绩


int main() {
  int scores[3][3] =
  {
    {100,100,100},
    {90,50,100},
    {60,70,80},
  };
  string names[3] = { "张三","李四","王五" };
  for (int i = 0; i < 3; i++)
  {
    int sum = 0;  /
    for (int j = 0; j < 3; j++)
    {
      sum += scores[i][j];
    }
    cout << names[i] << "同学总成绩为: " << sum << endl;
  }
  system("pause");
  return 0;
}

注意点:


int sum = 0 这一块要理解,


它的功能不仅是赋值,而且还附带将sum清0的效果


函数:

6.1 概述

作用:将一段经常使用的代码封装起来,减少重复代码


一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。


6.2 函数的定义

函数的定义一般主要有5个步骤:


1、返回值类型


2、函数名


3、参数表列


4、函数体语句


5、return 表达式

返回值类型 函数名 (参数列表)
{
       函数体语句
       return表达式
}

▪返回值类型 :一个函数可以返回一个值。在函数定义中

▪函数名:给函数起个名称

▪参数列表:使用该函数时,传入的数据

▪函数体语句:花括号内的代码,函数内需要执行的语句

▪return表达式: 和返回值类型挂钩,函数执行完后,返回相应的数据


示例:定义一个加法函数,实现两个数相加

//函数定义
int add(int num1, int num2)
{
  int sum = num1 + num2;
  return sum;
}

6.3 函数的调用

功能:使用定义好的函数


语法:函数名(参数)


示例:

//函数定义
int add(int num1, int num2) //定义中的num1,num2称为形式参数,简称形参
{
  int sum = num1 + num2;
  return sum;
}
int main() {
  int a = 10;
  int b = 10;
  //调用add函数
  int sum = add(a, b);//调用时的a,b称为实际参数,简称实参
  cout << "sum = " << sum << endl;
  a = 100;
  b = 100;
  sum = add(a, b);
  cout << "sum = " << sum << endl;
  system("pause");
  return 0;
}

总结:函数定义里小括号内称为形参,函数调用时传入的参数称为实参

6.5 函数的常见样式

常见的函数样式有4种


1.无参无返

2.有参无返

3.无参有返

4.有参有返


示例:

//函数常见样式
//1、 无参无返
void test01()
{
  //void a = 10; //无类型不可以创建变量,原因无法分配内存
  cout << "this is test01" << endl;
  //test01(); 函数调用
}
//2、 有参无返
void test02(int a)
{
  cout << "this is test02" << endl;
  cout << "a = " << a << endl;
}
//3、无参有返
int test03()
{
  cout << "this is test03 " << endl;
  return 10;
}
//4、有参有返
int test04(int a, int b)
{
  cout << "this is test04 " << endl;
  int sum = a + b;
  return sum;
}

6.6 函数的声明

作用: 告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。


▪函数的声明可以多次,但是函数的定义只能有一次


示例:

//声明可以多次,定义只能一次
//声明
int max(int a, int b);
int max(int a, int b);
//定义
int max(int a, int b)
{
  return a > b ? a : b;
}
int main() {
  int a = 100;
  int b = 200;
  cout << max(a, b) << endl;
  system("pause");
  return 0;
}

6.7 函数的分文件编写

作用:让代码结构更加清晰


函数分文件编写一般有4个步骤


1.创建后缀名为.h的头文件

2.创建后缀名为.cpp的源文件

3.在头文件中写函数的声明

4.在源文件中写函数的定义


示例:

//swap.h文件
#include<iostream>
using namespace std;
//实现两个数字交换的函数声明
void swap(int a, int b);
//main函数文件
#include "swap.h"
int main() {
  int a = 100;
  int b = 200;
  swap(a, b);
  system("pause");
  return 0;
}
//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;
}

文件分布如下:

9af3341ba04a494a805266b84588f8cc.png

相关文章
|
2月前
|
搜索推荐 编译器 C语言
【C++核心】特殊的元素集合-数组与字符串详解
这篇文章详细讲解了C++中数组和字符串的基本概念、操作和应用,包括一维数组、二维数组的定义和使用,以及C风格字符串和C++字符串类的对比。
78 4
|
27天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
1月前
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
45 6
|
1月前
|
C++
C++ 多线程之线程管理函数
这篇文章介绍了C++中多线程编程的几个关键函数,包括获取线程ID的`get_id()`,延时函数`sleep_for()`,线程让步函数`yield()`,以及阻塞线程直到指定时间的`sleep_until()`。
23 0
C++ 多线程之线程管理函数
|
1月前
|
编译器 C语言 C++
C++入门3——类与对象2-2(类的6个默认成员函数)
C++入门3——类与对象2-2(类的6个默认成员函数)
23 3
|
1月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
154 1
|
1月前
|
存储 编译器 C++
C++入门3——类与对象2-1(类的6个默认成员函数)
C++入门3——类与对象2-1(类的6个默认成员函数)
30 1
|
1月前
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
41 0
C++入门6——模板(泛型编程、函数模板、类模板)
|
2月前
|
编译器 C++
【C++核心】函数的应用和提高详解
这篇文章详细讲解了C++函数的定义、调用、值传递、常见样式、声明、分文件编写以及函数提高的内容,包括函数默认参数、占位参数、重载等高级用法。
22 3
|
2月前
|
C++
C++(十一)对象数组
本文介绍了C++中对象数组的使用方法及其注意事项。通过示例展示了如何定义和初始化对象数组,并解释了栈对象数组与堆对象数组在初始化时的区别。重点强调了构造器设计时应考虑无参构造器的重要性,以及在需要进一步初始化的情况下采用二段式初始化策略的应用场景。