当前位置: 首页 > news >正文

C语言程序设计第10天/数组

数组概念

数组是一组相同类型元素的集合;

  • 数组可以存放1个或多个数据,但是数据元素个数不能为0;
  • 数组中存放的多个数据,类型必须相同;

数组分为一维数组和多维数组,多维数组中常见的是二维数组。

一维数组的创建与初始化

type arr_name[常量值1];

基本语法:

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

如:

int numbers[10]; // 10 个 int 类型的数组
float prices[5]; // 5 个 float 类型的数组
char name[20]; // 20 个 char 类型的数组(字符串)

数组的初始化

1.定义时初始化

int arr1[5] = {85, 90, 78, 92, 88};

2.部分初始化

int arr1[5] = {85, 90};
// 结果:{85, 90, 0, 0, 0}

3.全部初始化为0

int arr1[5] = {85, 90};
// 结果:{85, 90, 0, 0, 0}

4.不指定大小

int arr1[] = {85, 90, 78, 92, 88};
// 编译器自动算出大小是 5

数组的类型

  • int是数组元素的类型;
  • int []是数组的类型;

一维数组的使用

数组的访问

数组使用下标(索引)访问,从0开始;

最大的下标是数组的大小减去1;

int arr1[5] = {85, 90, 78, 92, 88}

索引: [0] [1] [2] [3] [4]
值: 85 90 78 92 88

数组的输入与元素打印

//用户输入1—10;随后遍历输出 #include<stdio.h> int main(){ int arr1[10]; for (int i = 0; i < 10; i++) { printf("输入数字\n"); scanf("%d",&arr1[i]); } for ( int r = 0; r < 10; r++) { printf("%d\n",arr1[r]); } return 0; }

一维数组在内存中的储存

使用%p来查看地址后发现从低到高排列了数组中每个数据的地址,而差值刚好是4,因为int是数组元素的类型,而int类型占的内存为4字节。

sizeof计算数组元素个数

sizeof是c语言中的一个操作符(并不是函数),用来计算某个类型或变量在内存中占用的字节数。

  • 注意%zu是专门打印size_t类型(sizeof的返回值类型)的格式符。

由于int类型占用字节为4,所以40/4=10,元素个数为10;

char: 1 字节
int: 4 字节
float: 4 字节
double: 8 字节

二维数组的创建

二维数组的概念

前面学习的数组被称为一维数组,数组的元素都是内置类型的,如果我们把一维数组做为数组的元素,这时候就是二维数组,二维数组作为数组元素的数组被称为三维数组,二维数组以上的数组统称为多维数组;

简成一句话就是:一维装数据,二维装一维,三维装二维,更高维就是继续套娃;

二维数组的创建

type arr_name [常量值1][常量值2];

也就是 数据类型 数组名 [行数] [列数];

int arr1_int [3] [4]; // 3行4列的整数矩阵
float arr1_float [5] [3]; // 5个学生,每人3科成绩
char arr1_char [8] [8]; // 8x8 的棋盘(国际象棋)

二维数组的初始化

1.完全初始化

int arr1 [3] [4] =

{

{1,2,3,4},

{11,12,13,14},

{21,22,23,24}

};

2.完全初始化(写在一行)

int arr1 [3][4]={1,2,3,4,11,12,13,14,21,22,23,24};

效果与上面一样,但是分行看更清晰

3.部分初始化(未初始化的自动为0)

int matrix[3][4] = {
{1, 2},
{5, 6, 7},
{9}
};

4.省略行数(行数可以省略但列数坚决不能省略)

int matrix[][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 编译器自动算出行数 = 3

注意,部分初始化和完全未初始化不一样

部分初始化int a[5] = {1, 2};自动为 0编译器自动填充 0
完全未初始化int a[5];垃圾值(不确定)只分配内存,不赋值

二维数组的使用

二维数组的下标

二维数组的下标与一维数组差不多,都是从0开始的

这样的话我们可以根据行数列数来具体定位到数组中的元素了。

#include<stdio.h> int main(){ int arr2[3][4] = { {1,2,3,4}, {11,12,13,14}, {21,22,23,24} }; printf("%d",arr2[1][3]); return 0 ; }

定位信息为第二行第四列。输出结果14

二维数组的输入和输出

遍历二维数组

#include<stdio.h> int main(){ int arr2[3][4] = { {1,2,3,4}, {11,12,13,14}, {21,22,23,24} }; for (int i = 0; i < 3; i++) //行下标 { for (int j = 0; j < 4; j++) //列下标 { printf("%d\t",arr2[i][j]); } printf("\n"); } return 0 ; }

当把其中的代码修改一下就可以进行输入了;

#include<stdio.h> int main(){ int arr2[3][4] ; for (int i = 0; i < 3; i++) //行下标 { for (int j = 0; j < 4; j++) //列下标 { int b = i + 1; int c = j + 1; printf("输入第%d行,第%d列的数据",b,c); scanf("%d",&arr2[i][j]); } printf("\n"); } for (int i = 0; i < 3; i++) //行下标 { for (int j = 0; j < 4; j++) //列下标 { printf("%d\t",arr2[i][j]); } printf("\n"); } return 0 ; }

二维数组的使用及在内存中的存储

#include <stdio.h> int main() { int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; printf("arr[0][0] 的地址: %p\n", &arr[0][0]); printf("arr[0][1] 的地址: %p\n", &arr[0][1]); printf("arr[0][2] 的地址: %p\n", &arr[0][2]); printf("arr[0][3] 的地址: %p\n", &arr[0][3]); printf("arr[1][0] 的地址: %p\n", &arr[1][0]); printf("arr[1][1] 的地址: %p\n", &arr[1][1]); // 计算相邻元素地址差 printf("\n地址差: %ld 字节\n", (char*)&arr[0][1] - (char*)&arr[0][0]); return 0; }

可以看到并没有像二维数组的概念中的图一样换行,他们在一行。

因为逻辑视图与物理视图是不一样的

逻辑中

内存中

变长数组

下面是一个逆序输出的程序

#include <stdio.h> int main() { char arr_input[100]; printf("请输入(不超过100位):"); scanf("%[^\n]",arr_input); /*将原来的int改为字符串这样不管是数字还是字符都可以逆序输出。%[^\n]意为读取所以不是换行符的字符*/ int i = 0; while (arr_input[i] != '\0') //记录数组有多少个元素;\0意为 空字符(Null)标记字符串结束。 { i++; } printf("逆序输出:"); for ( i = i-1 ; i >= 0; i--) //记录有i组后 由于数组是由0开始计数所以需要i-1,当i>=0时进入循环打印当前数组内的数据,i--。 { printf("%c",arr_input[i]); } return 0; }

假如100不够呢,用户想输入101个,200个?

这个时候可以使用变长数组

在arr_input[100]改为arr_input[n],再由用户输入想输入几位数,来自定义数组元素的个数。

这样会出现两个scanf,当前面的scanf读取完后会留下\n换行符,后面的sanf读取到换行符就没有办法正常运行了,使用getchar()消除掉第一个scanf留下的换行符,这样就可以正常运行了。

#include <stdio.h> int main() { int n = 0; printf("请输入需要逆序的位数:\n"); scanf("%d",&n); char arr_input[n]; printf("请输入(不超过100位):"); getchar(); scanf("%[^\n]",arr_input); /*将原来的int改为字符串这样不管是数字还是字符都可以逆序输出。%[^\n]意为读取所以不是换行符的字符*/ int i = 0; while (arr_input[i] != '\0') //记录数组有多少个元素;\0意为 空字符(Null)标记字符串结束。 { i++; } printf("逆序输出:"); for ( i = i-1 ; i >= 0; i--) //记录有i组后 由于数组是由0开始计数所以需要i-1,当i>=0时进入循环打印当前数组内的数据,i--。 { printf("%c",arr_input[i]); } return 0; }

但这样并不完美,我发现在运行后位数只有20位,而输出的有20多位,会导致缓冲区溢出也就是数据写入数组之外的内存区域,而且如果用户输入过大的位数栈会爆掉。

可以加入一个判断从而限制不要超过这一上限,确保栈不会爆掉。也能进行动态分配

if (n <= 0 || n > 1000) { // 设置一个合理上限 printf("位数必须在1-1000之间\n"); return 1; }
http://www.jsqmd.com/news/1257130/

相关文章:

  • MCU芯片AS32X601如何使用 DMA 单次模式搬运 ADC 多通道采样数据?
  • 5分钟快速上手:Sketchfab 3D模型下载终极指南
  • 阿里巴巴造出0.8B超小文档解析神器,端到端解析时代来了?
  • HarmonyOS7 暗黑模式:3 步让你的 App 支持深色主题
  • 「盘点」界面控件DevExtreme (v23.1, v23.2)可访问性增强
  • Sketchfab 3D模型下载完整指南:免费获取高质量3D资源
  • 零成本AI股票分析:5分钟打造你的个人智能投资助手
  • 2026深圳招商加盟服务行业GEO优化公司选型指南丨生成式引擎优化服务商深度测评 - 企业新闻快传
  • API中转站成本控制:测试流量和正式账单必须分开
  • Token 单价更低,Agent 任务为什么反而更贵:4 层成本口径 + 最小事件账本 + 3 个决策问题
  • FastbootEnhance:Windows上最完整的Android设备管理工具终极指南
  • Qwen3.8 上百炼:国产推理 API 这条路,又往前推了一步
  • WarcraftHelper:魔兽争霸3玩家的5大游戏体验优化解决方案
  • 【Rust中级教程】2.11. API设计原则之受约束性(constrained) Pt.2:封闭trait(sealed trait)、重新导出(re-exports)、自动trait
  • StreamFX终极指南:5分钟掌握OBS专业级直播特效
  • Veeam备份虚拟机报错Unable to allocate RAM for VM snapshot完整解决方案
  • 3分钟快速上手:Beyond Compare 5密钥生成完整指南
  • 短视频封面转化率卡在2.3%?权威实测:9种AI工具横向评测(附GPU占用/出图速度/版权风险矩阵表)
  • Code date creation的开发技术介绍
  • 零基础掌握AI股票分析:3步打造个人智能投资系统
  • 构建基于LLM的智能股票分析系统:架构设计与实战应用
  • 深圳零食消费品牌行业GEO优化公司选型指南丨2026年生成式引擎优化服务商深度测评 - 企业新闻快传
  • DB升级 23.26.2:/opt 空间临界导致 OPatch 失败的处理记录
  • RTL8852CE常用命令
  • 小白python入门 - 17. Python面向对象编程入门
  • 初识C++语言
  • 当AI学会“听“懂整首乐队合奏
  • Beyond Compare 5企业级永久授权方案:5分钟实现全平台文件对比工具激活
  • 文档切片失效、嵌入失真、答案幻觉频发,Dify知识库问答上线前必须验证的9项生产级检查清单
  • Spring 源码系列(9): 循环依赖终极拷问:为什么用三级缓存而不是二级