C语言学习--数组

提示:数组是编程中的基本数据结构之一,它允许我们在一个变量中存储多个相同类型的数据。

目录

前言

11.1 为什么需要数组

11.2 数组介绍

11.3 数组快速入门

11.4 数组定义和内存布局

11.4.1 数组的定义

11.4.2 数组内存图(重要)

11.4.3 访问数组元素

11.4.4 快速入门案例

11.4.5 3 种初始化数组的方式

11.5 数组使用注意事项和细节

11.6 数组应用案例

11.7 字符数组与字符串

11.7.1 字符数组基本介绍

11.7.2 字符串注意事项

11.7.3 字符串的访问和遍历

11.8 字符串的表示形式

11.8.1 用字符数组存放一个字符串

11.8.2 用字符指针指向一个字符串

11.8.3 使用字符指针变量和字符数组两种方法表示字符串的讨论

11.9 字符串相关函数

11.9.1 常用字符串函数一览

11.9.2 字符串函数应用案例

11.10字符串(字符数组)使用注意事项和细节

11.11字符串(字符数组)课堂练习

总结

附录


前言

数组是编程中的基本数据结构之一,它允许我们在一个变量中存储多个相同类型的数据。使用数组可以显著简化代码的编写和维护,特别是在处理大量数据时。通过数组,我们可以方便地访问和操作这些数据,避免了多个单独变量的繁琐。本文将介绍数组的基本概念和操作方法,并通过实例展示如何用数组解决实际问题,如计算鸡群的体重总和和平均体重。


11.1 为什么需要数组

一个养鸡场有 6 只鸡,它们的体重分别是 3kg,5kg,1kg, 3.4kg,2kg,50kg 。请问这六只鸡的总体重是多少?平均体重是多少? 请你编一个程序。

c731976e64bb44d18111b078f351498d.png

传统方案

1) 定义 6 个 double 变量

 

2) 统计他们和,并求出平均值

 

3) 传统的方案,不灵活,不能够完成数量大的需求

 

4) 引出我们讲解 数组

11.2 数组介绍

数组可以存放多个同一类型数据。数组也是一种数据类型,是构造类型。传递是以引用的方式传递(即传递的是地址)

11.3 数组快速入门

比如,我们可以用数组来解决上一个问题。

#include <stdio.h>

void main() {

/*

一个养鸡场有 6 只鸡,它们的体重分别是 3kg,5kg,1kg,

3.4kg,2kg,50kg 。请问这六只鸡的总体重是多少?平

均体重是多少? 请你编一个程序。

*/

//1 定义数组

double hens[6];

double totalWeight = 0.0;

double avgWeight = 0.0;

int i, arrLen;

//2. 初始化数组的每个元素

//[下标]

hens[0] = 3; //第一个元素

hens[1] = 5; //第 2 个元素

hens[2] = 1;

hens[3] = 3.4;

hens[4] = 2;

hens[5] = 50;

//3. 遍历数组

//如何得到数组大小

// sizeof(hens) 数组的总的大小

// 6 * 8 = 48

// sizeof(double) 返回 一个 double 占用的字节数

//printf("sizeof(hens)=%d", sizeof(hens));

arrLen = sizeof(hens) / sizeof(double);

for(i = 0; i < arrLen; i++) {

totalWeight += hens[i]; // 累计每只鸡体重

}

avgWeight = totalWeight / 6;

printf("总体重 totalWeight=%.2f 平均体重 avgWeight=%.2f", totalWeight, avgWeight);

getchar();

}

 

11.4 数组定义和内存布局

11.4.1 数组的定义

数据类型 数组名 [数组大小];

 

int a [5]; // a 数组名,类型 int , [5] 大小, 即 a 数组最多存放 5 个 int 数据赋初值 a[0] = 1; a[1] = 30; ....

11.4.2 数组内存图(重要)

aaa1b78313b14017b7f5bc2e8f9ab1c8.png

说明:

 

1) 数组名 就代表 该数组的首地址 ,即 a[0]地址

 

2) 数组的各个元素是 连续分布的, 假如 a[0] 地址 0x1122 a[1] 地址= a[0]的地址+int 字节数(4) = 0x1122 + 4 =0x1126,后面 a[2] 地址 = a[1]地址 + int 字节数(4) = 0x1126 + 4 = 0x112A, 依次类推

11.4.3 访问数组元素

数组名[下标] 比如:你要使用 a 数组的第三个元素 a[2], 下标是从 0 开始计算

11.4.4 快速入门案例

从终端循环输入 5 个成绩,保存到 double 数组,并输出

#include <stdio.h>

void main() {

/*

从终端循环输入 5 个成绩,保存到 double 数组,并输出

*/

//定义数组和初始化数组的方式

int arr2[3] = {10, 20, 80};

//如果在定义时,直接就指定值,可以省略数组大小

int arr3[] = {110, 220, 800};

//定义一个数组

double arr[5];

int arrLen = sizeof(arr) / sizeof(double);

int i;

for(i = 0; i < arrLen; i++) {

printf("\n 请输入一个小数");

scanf("%lf", &arr[i]);

}

//输出整个数组

printf("\n======================\n");

for(i = 0; i < arrLen; i++) {

printf("arr[%d]=%.2f ", i, arr[i]);

}

getchar(); //过滤回车

getchar();

}

 

11.4.5 3 种初始化数组的方式

e12813578c8f4f089226c3765f47c4f9.png

11.5 数组使用注意事项和细节

1) 数组是多个相同类型数据的组合,一个数组一旦声明/定义了,其长度是固定的, 不能动态变化。

2) 数组创建后,如果没有赋值,则遵守如下规则

全局数组默认值 0

非全局数组初值是机器垃圾值(即:原来系统分配给这块空间的值)

3) 使用数组的步骤 1. 定义数组 2 给数组各个元素赋值 3 使用数组, 也可以一步到位

4) 数组的下标是从 0 开始的, 不是从 1 开始。

5) 数组下标必须在指定范围内使用,编译通过,在运行时会因为数组越界而异常中断:

比如 int arr [5] 有效下标为 0-4

6) C 的数组属构造类型, 是引用传递(传递的是地址),因此当把一个数组传递给一个函数时/或者变量,函数/变量操作数组会影响到原数组. [内存图!!!.]

#include <stdio.h>

void f1(int arr[]) {

printf("\nf1 函数中 的 arr 的地址 = %p", arr);

arr[0] = arr[0] + 1;

}

void main() {

int arr[3] = {3,4,5};

int i;

printf("\nmain 函数中 的 arr 的地址 = %p", arr);

//数组默认是以 地址传递(传递指针)

f1(arr);

//遍历 main 函数中的 arr

for(i = 0; i < 3; i++) {

printf("arr[%d]=%d ", i , arr[i]); // 4,4,5

}

getchar();

}

上面案例对应的内存图

590bc218abbb4a06a04ef5129dbd190c.png

 

11.6 数组应用案例

1) 创建一个 char 类型的 26 个元素的数组,分别 放置'A'-'Z‘。使用 for 循环访问所有元素并打印出来。提示:字符数据运算 'A'+1 -> 'B'

void main() {

/*

创建一个 char 类型的 26 个元素的数组,分别 放置'A'-'Z‘。

使用 for 循环访问所有元素并打印出来。提示:字符数据运算 'A'+1 -> 'B'

*/

char arr[26];

int i;

for (i =0; i < 26; i++) {

arr[i] = 'A' + i;

}

//输出

for(i = 0; i < 26; i++ ){

printf("%c ", arr[i]);

}

getchar();

}

 

2) 请求出一个数组的最大值,并得到对应的下标。

void main() {

/*

请求出一个数组的最大值,并得到对应的下标

分析

1. 定义数组 大小 5

2. 假定 max = arr[0] 就是最大值,然后我们依次和数组后面的数进行比较,如果发现比 有比 max更大数,就相应的变化(把更大数赋给 max),当我们遍历完整个数组,max 就是最大数

*/

int arr[] = {0,-1,89, 99, 4,0,23,876, 9876,3,4,6};

int arrLen = sizeof(arr) / sizeof(int);

int max = arr[0];

int maxIndex = 0;

int i ;

for(i = 1; i < arrLen; i++) {

//如果发现比 有比 max 更大数,就相应的变化(把更大数赋给 max)

if( arr[i] > max) {

max = arr[i];

maxIndex = i;

}

}

printf("max=%d maxIndex=%d", max, maxIndex);

getchar();

}

 

11.7 字符数组与字符串

11.7.1 字符数组基本介绍

用来存放字符的数组称为字符数组, 看几个案例

1) char a[10]; //一维字符数组, 长度为 10

 

2) char b[5][10]; //二维字符数组, 后面我们详细介绍二维数组

 

3) char c[20]={'c', ' ', 'p', 'r', 'o', 'g', 'r', 'a','m'}; // 给部分数组元素赋值

 

字符数组实际上是一系列字符的集合,也就是字符串(String)。在 C 语言中,没有专门的字符串变量,没有string 类型,通常就用一个字符数组来存放一个字符串

11.7.2 字符串注意事项

1) 在 C 语言中,字符串实际上是使用 null 字符 ('\0') 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。

2) '\0'是 ASCII 码表中的第 0 个字符,用 NUL 表示,称为空字符。该字符既不能显示,也不是控制字符,输出该字符不会有任何效果,它在 C 语言中仅作为字符串的结束标志。

3) 字符数组(字符串)在内存中的布局分析 [案例]

6b74ef6ee0c44c67a421c6b07353bf67.png

4) 思考 char str[3] = {'a','b','c'} 输出什么? 为什么?

结论:如果在给某个字符数组赋值时,(1)赋给的元素的个数小于该数组的长度,则会自动在后面加 '\0', 表示字符串结束,(2)赋给的元素的个数等于该数组的长度,则不会自动添加 '\0'

 

char str2[] = {'t','m','o'} 输出什么? 输出的是 tmo 乱码

5) 案例演示

#include <stdio.h>

void main() {

//c 是一个一维字符数组,给部分元素赋值

char c[7]={'t','o','m'};

char str[4] = {'a','b','c','\0'};

char str2[] = {'j','a','c','k'}; // 这个后面系统也不会自动添加 '\0'

//输出 c , 系统会这样处理

//1. 从第一个字符开始输出,直到遇到 \0 , 表示该字符串结束

printf("\nc=%s", c);

printf("\nstr=%s", str); // abc?

printf("\nstr2=%s", str2); // jack 乱码

getchar();

}

 

11.7.3 字符串的访问和遍历

因为字符串的本质就是字符数组,因此可以按照数组的方式遍历和访问某个元素即可, 案例如下

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

void main() {

char greeting[] = "Hello";

int i;

int len = strlen(greeting); // len = 5

printf("\n greeting=%s", greeting);

printf("\nlen=%d", len); //5

printf("\n 字符串第 3 个字符是=%c", greeting[2]); //l

printf("\n");

for(i = 0; i < len; i++) {//遍历

printf("%c ", greeting[i]); //H e l l o

}

system("pause");

}

 

Ø 对应的内存分析图

afb526f5d58c477fa16965354f35a246.png

11.8 字符串的表示形式

11.8.1 用字符数组存放一个字符串

用字符数组存放一个字符串,

1) char str[]="hello tom";

2) char str2[] = {'h', 'e'};

11.8.2 用字符指针指向一个字符串

比如: char* pStr=" hello tom";

1) C 语言对字符串常量" hello tom"是按字符数组处理的,在内存中开辟了一个字符数组用来存放字符串常量,程序在定义字符串指针变量 str 时只是把字符串首地址(即存放字符串的字符数组的首地址)赋给 pStr

2) printf("%s\n",str); 可以输出 str 指向的字符串

3) 对应的内存布局图(!!)

7fb72320b7aa43858b4d6030dd96d9ca.png

11.8.3 使用字符指针变量和字符数组两种方法表示字符串的讨论

1) 字符数组由若干个元素组成,每个元素放一个字符;而字符指针变量中存放的是地址(字符串/字符数组的首地址),绝不是将字符串放到字符指针变量中(是字符串首地址)

2) 对字符数组只能对各个元素赋值,不能用以下方法对字符数组赋值

char str[14];

str=" hello tom"; //错误

str[0] = 'i'; //ok

3) 对字符指针变量,采用下面方法赋值, 是可以的

char* a="yes";

a=" hello tom";

分析上面的结论

157dcb6bc7404616821732ad38352066.png

5) 如果定义了一个字符数组,那么它有确定的内存地址(即字符数组名是一个常量);而定义一个字符指针变量时,它并未指向某个确定的字符数据,并且可以多次赋值 [代码+图解]

11.9 字符串相关函数

11.9.1 常用字符串函数一览

4ab36c1ad14845f6b50dd1654c3279d1.png

 

11.9.2 字符串函数应用案例

#include <stdio.h>

#include <string.h>

void main() {

char str1[12] = "Hello";

char str2[12] = "World";

char str3[12];

int len ;

/* 复制 str1 到 str3 */

strcpy(str3, str1); // str3 内容 "Hello"

printf("strcpy( str3, str1) : %s\n", str3 ); //"Hello"

/* 连接 str1 和 str2 */

strcat( str1, str2);

printf("strcat( str1, str2): %s\n", str1 ); //"HelloWorld"

/* 连接后,str1 的总长度 */

len = strlen(str1);//

printf("strlen(str1) : %d\n", len );//10

getchar();

}

11.10字符串(字符数组)使用注意事项和细节

1) 程序中往往依靠检测 '\0' 的位置来判定字符串是否结束,而不是根据数组的长度来决定字符串长度。因此,字符串长度不会统计 '\0', 字符数组长度会统计 [案例]

2) 在定义字符数组时应估计实际字符串长度,保证数组长度始终大于字符串实际长度, 否则,在输出字符数组时可能出现未知字符。

3) 系统对字符串常量也自动加一个'\0'作为结束符。例如"C Program”共有 9 个字符,但在内存中占 10 个字节,最后一个字节'\0'是系统自动加上的。(通过 sizeof()函数可验证)

4) 定义字符数组时,如果 给的字符个数 比 数组的长度小,则系统会默认将剩余的元素空间,全部设置为 '\0', 比如 char str[6] = "ab" , str 内存布局就是[a][b][\0][\0][\0][\0]

5) 字符数组定义和初始化的方式比较多,比如

#include <stdio.h>

void main() {

char str1[ ]={"I am happy"}; // 默认后面加 '\0'

char str2[ ]="I am happy"; // 省略{}号 ,默认后面加 '\0'

char str3[ ]={'I',' ','a','m',' ','h','a','p','p','y'}; // 字符数组后面不会加 '\0', 可能有乱码

char str4[5]={'C','h','i','n','a'}; //字符数组后面不会加 '\0', 可能有乱码

char * pStr = "hello";//ok

printf("\n str1=%s", str1);

printf("\n str2=%s", str2);//ok

printf("\n str3=%s", str3);//乱码

printf("\n str4=%s", str4);//乱码

getchar();

}

 

11.11字符串(字符数组)课堂练习

char str[ ];

str="I am happy";

题 1

错误,因为 str 是常量


总结

数组为程序提供了一种高效的数据组织方式,使得处理多个数据项变得更加灵活和方便。通过定义数组并利用其下标访问元素,我们能够轻松地执行各种操作,如求和、平均值计算等。数组的应用不仅限于基础数据处理,还可以扩展到更复杂的数据结构和算法中。掌握数组的使用,将为编程提供坚实的基础,帮助开发者在面对各种数据处理任务时更加得心应手。

附录

参考:【尚硅谷C语言零基础快速入门教程-哔哩哔哩】 https://b23.tv/vS3vTDp

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值