【C】数组

news/2025/2/21 7:13:24/文章来源:https://www.cnblogs.com/Shima-Rin/p/18716149

数组

数组的定义

  • 语法:类型 数组名[元素个数] (方括号内只能是常量或者常量表达式)

    int a[6];

    char b[24];

    double c[3];

  • 上面几个类型分别占用内存的字节数为:

    int a[6] ==> 4 * 6 = 24

    char b[24] ==> 1 * 24 = 24

    double c[3] ==> 8 * 3 = 24

数组不能动态定义

C语言不允许在程序运行过程中修改数组空间大小

访问数组中的元素

  • 语法: 数组名[下标]

    a[0]; //访问a数组中的第个元素

    b[1]; //访问b数组中的第个元素

    c[5]l //访问c数组中的第个元素

  • 注意

    • int a[5]; //创建一个具有五个元素的数组
    • a[0]; //访问第一个元素,第一个元素下标为0,不是1
    • a[5]; //报错, 第五个元素下标为a[4]

循环跟数组的关系

  • 实现一个执行10次的循环,我们通常是这么写的:

    for (i = 0; i < 10; i++)
    {...
    }
    
  • 而不是这么写:

    for (i = 1; i <= 10; i++)
    {...
    } 
    
  • 这是因为我们常常需要使用循环来访问数组:

    int a[10];
    for (i = 0; i < 10; i++)
    {a[i] = i;
    }
    
  • 举个例子,我们尝试用数组存放班里5位同学的数学成绩,并计算出平均数。

    #include<stdio.h>
    #define NUM 5  //常量宏定义,可以在此直接修改存放的学生个数
    int main()
    {int s[NUM]; //学生数组int i, sum = 0;for (i = 0; i < NUM; i++) //循环次数为学生个数{printf("请输入第%i位同学的成绩:",i+1);  scanf("%d",&s[i]); //将输入的成绩存放到对应的数组下标sum += s[i];}printf("成绩录入完毕,该次考试的平均分是:%.2f\n", (double)sum / NUM ); //计算结果并转换为浮点型return 0;
    }
    

数组的初始化

在定义数组的同时给它赋值,称为数组的初始化

方式为:

  • 将数组中所有元素初始化为0,可以这么写:

    • int a[10] = {0}; //事实上这里只是将第一个元素赋值为0
  • 如果是赋予不同的值,那么用逗号隔开即可:

    • int a[10] = {1,2,3,4,5,6,7,8,9,0};
  • 也可以只给一部分元素赋值,未被赋值的元素自动初始化为0:

    • int a[10] = {1,2,3,4,5,6};

      // 表示为前边6个元素赋值,后边4个元素系统自动初始化为0

  • 有时还可以偷懒,可以只给出各个元素的值,而不指定数组的长度(因为编译器会根据值的个数自动判断数组的长度):

    • int a[] = {1,2,3,4,5,6,7,8,9,0};
  • C99增加了一种新特性:指定初始化的元素。这样就可以只对数组中的某些指定元素进行初始化,而未被赋值的元素自动初始化为0:

    • int a[10] = {[3]=3,[5]=5,[8]=8};
  • 使用sizeof可以计算数组占用内存的大小

    int a[10]={0};
    printf("%d\n",sizeof(a));
    

    结果

    40  // int有4个字节,4*10=40
    

字符数组

  • 字符串常量: "Hello","ABC"

  • 字符数组:

    char str[10];
    str[0] = 'H';
    str[1] = 'e';
    str[2] = 'l';
    str[3] = 'l';
    str[4] = 'o';
    str[5] = '\0';
    ...
    

字符串处理函数

请参考:C语言标准函数库分类

获取字符串长度

  • strlen函数,用于获取字符串的长度: (注意:获取的是长度,不是尺寸)
#include<stdio.h>
#include<string.h>  //头文件
int main()
{char str[] = "Hello!";printf("sizeof str = %d\n",sizeof(str));printf("strlen str = %u\n",strlen(str));return 0;
}

运行结果

sizeof str = 7  \\包含'\0'
strlen str = 6 \\字符的个数,不包含'\0'

拷贝字符串

strcpy和strncpy函数

  1. strcpy函数用于拷贝字符串,包含最后的结束符 '\0'
  • 语法:strcpy(目标字符串,源字符串)

    注意

    • 为了避免溢出,必须确保用于存放的数组长度足以容纳待拷贝的字符串(注意:长度需要包含结束符 '\0')。
    • 源字符串和目标数组的位置不应该重叠。
#include<stdio.h>
#include<string.h>  //头文件
int main()
{char str1[] = "Original String"; //长度15char str2[] = "New String";   //长度10char str3[100];strcpy(str1, str2); //将str2中的字符(包括'\0')拷贝到str1strcpy(str3, "Copy Successful");printf("str1: %s\n",str1);printf("str2: %s\n",str2);printf("str3: %s\n",str3);return 0;
}

运行结果

str1: New String //拷贝完后,str1的长度改变了,为10.但sizeof没有变化,仍为16
str2: New String
str3: Copy Successful    

若源字符串长度大于目标字符串:

char str1[] = "Original String"; //长度15
char str2[] = "New String";  //长度10
strcpy(str2, str1); 
printf("str1: %s\n",str1);
printf("str2: %s\n",str2);

运行结果

str1: ring
str2: Original String

拷贝时,源字符串过长,目标字符串溢出,导致拷贝后源字符串发生变化。

因此在程序实现拷贝时,应该限制源字符串的长度,确保目标字符串在执行完拷贝后不会发生溢出

  1. strncpy函数

    • strcpy函数一样,strncpy(dest, src, n) 函数将拷贝源字符串的 n 个字符到目标数组中。如果源字符串的长度小于 n,那么就用 '\0' 填充额外的空间。如果源字符串的长度大于或等于 n,那么只有 n 个字符被拷贝到目标数组中(注意:这样的话将不会以结束符 '\0' 结尾)。
    • 提示:为了使该函数更“安全”,建议使用dest[sizeof(dest) - 1] = '\0'; 语句确保目标字符串是以 '\0' 结尾
    • 源字符串和目标数组的位置不应该重叠。
    #include<stdio.h>
    #include<string.h>  //头文件
    int main()
    {char str1[] = "To be or not to be"; char str2[40]; strncpy(str2, str1,5); //拷贝str1中5个字符到str2中str2[5] = '\0'; //追加结束字符printf("str2: %s\n",str2);return 0;
    }
    

    运行结果

    str2: To be
    

    注意:如果源字符串的长度大于或等于 n,在拷贝完后需要对目标字符串追加结束符,否则结果会乱码

连接字符串

  • 连接字符串: strcat和strncat

    连接字符串用于将一个字符串连接到另一个字符串的后边,也叫字符串的拼接。(注意:目标数组里必须包含一个字符,可以是空字符)

  1. strcat -- 连接字符串

    • strcat函数用于连接两个字符串。

    • 将源字符串拷贝并连接到目标数组存放的字符串后边,此过程将覆盖第一个参数的结束符 '\0'。

    • 两个参数的位置不应该重叠

    #include<stdio.h>
    #include<string.h>  //头文件
    int main()
    {char str1[] = "I love"; char str2[] = "this world!"; strcat(str1," "); //在str1末尾连接一个空格strcat(str1, str2); //将str2连接到str1末尾printf("str1: %s\n",str1);return 0;
    }
    

    运行结果

    str1: I love this world!
    
  2. strncat -- 连接字符串(受限)

    • strncat函数用于拷贝源字符串中的 n 个字符到目标数组的字符串后边,并在末尾添加结束符 '\0'。
    • 如果源字符串的长度小于 n,那么不会像strncpy函数那样使用 '\0' 进行填充(但结束符 '\0' 还是有的)。
    • 另外,目标数组中的原有的字符串并不算在 n 中

比较字符串

  • 比较字符串: strcmpstrncmp

    比较字符串用于比较两个字符串是否完全一致。如果一致,则返回0;如果不一致,那么根据情况,返回大于0或小于0的值。(从第一个字符开始,依次对比两个字符串每一个字符的ASCII码。如果第一个字符串ASCII码小于第二个字符串对于的字符,则返回一个小于0的值,反之则相反。)

  1. strcmp -- 比较字符串

    strcmp函数用于比较两个字符串。

    该函数从第一个字符开始,依次比较每个字符的 ASCII 码大小,直到发现两个字符不相等或抵达结束符('\0')为止

    #include<stdio.h>
    #include<string.h>  //头文件
    int main()
    {char str1[] = "Hello World!"; char str2[] = "Hello World"; if (!strcmp(str1,str2)) //比较两个字符串返回值是否等于0{printf("两个字符串完全一致!\n");}else{printf("两个字符串存在差异!\n");}return 0;
    }
    

    运行结果

    两个字符串完全一致!
    
  2. strncmp -- 比较字符串(受限)

    strncmp函数用于比较两个字符串的前 n 个字符。

    该函数从第一个字符开始,依次比较每个字符的 ASCII 码大小,发现两个字符不相等或抵达结束符('\0')为止,或者前 n 个字符完全一样,也会停止比较。

二维数组

如果说一维数组是一条线,那么二维数组就可以说是一个面。二维数组也称为矩阵

科目\学号 1 2 3 4 5 ...
语文 80 92 85 86 99
数学 78 65 89 70 99
英语 67 78 76 89 99
综合 88 68 98 90 99

上表是一个记录了各个同学各个科目的成绩。对于上表,如果使用一维数组,则需分别定义4个数组

int chinese[50];
int math[50];
int english[50];
int comprehensive[50];

但如果使用二维数组,我们只需要定义一个数组就可以解决了,如:

int score[4][50];
score[0][0] = 80;
score[1][0] = 78;
score[2][0] = 67;
score[3][0] = 88;
...

二维数组的定义

  • 类型 数组名[常量表达式][常量表达式]

    int a[6][6]; // 6*6,6行6列

    char b[4][5]; // 4*5, 4行5列

    double c[6][3]; // 6*3,6行3列

  • 在C语言中,内存的存放是线性的。所以不管是一维数组还是二维、三维数组,它们的存放都是线性的。

    以二维数组int b[4][5]为例

    首先它在内存中定义一个一维数组出来,进而再在一维数组中每一个元素中再定义一个一维数组出来。也可以说是一维数组的嵌套。

二维数组的访问

与一维数组相似,二维数组同样是以下标来访问

  • **数组名[下标][下标] **

    a[0][0]; // 访问a数组中第1行第1列的元素

    b[1][3]; // 访问b数组中第2行第4列的元素

    c[3][3]; // 访问c数组中第4行第4列的元素

  • 同样需要注意下标的取值范围,以防止数组的越界访问

    • 比如int a[3][4],其“行下标”的取值范围是0 ~ 2,“列下标”的取值范围是0 ~ 3,超出任何一个下标的访问都是越界访问。

二维数组的初始化

  • 由于二维数组在内存中是线性存放的,因此可以将所有的数据写在一个花括号内:

    int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

    int main()
    {int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};int i, j;for (i=0;i<3;i++){for (j=0;j<4;j++){printf("%d", a[i][j]);}printf("\n");}return 0;
    }
    

    运行结果

    1  2  3  4  
    5  6  7  8
    9  10  11  12
    
  • 为了更直观地表示元素的分布,可以用大括号将每一行的元素括起来:

    int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};

    或者

    int a[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}
    };
    
  • 二维数组也可以仅对部分元素赋初值:

    int a[3][4] = {{1}, {5}, {9}};

    这样会把前三行中每行第一个元素进行赋值,剩余未被赋值元素会用0代替

    int main()
    {int a[3][4] = {{1}, {5}, {9}};int i, j;for (i=0;i<3;i++){for (j=0;j<4;j++){printf("%d  ", a[i][j]);}printf("\n");}return 0;
    }
    

    运行结果

    1   0   0   0   
    5   0   0   0
    9   0   0   0
    
  • 如果希望整个二维数组初始化为0,那么直接在大括号里写一个0即可:

    int a[3][4] = {0};

    int main()
    {int a[3][4] = {0};int i, j;for (i=0;i<3;i++){for (j=0;j<4;j++){printf("%d  ", a[i][j]);}printf("\n");}return 0;
    }
    

    运行结果:

    0  0  0  0  
    0  0  0  0
    0  0  0  0
    
  • C99同样增加了一种新特性:指定初始化的元素。这样就可以只对数组中某些指定元素进行初始化赋值,而未被赋值的元素自动初始化为0:

    int a[3][4] = {[0][0] = 1, [1][1] = 2, [2][2] = 3};

    int main()
    {int a[3][4] = {[0][0] = 1, [1][1] = 2, [2][2] = 3};int i, j;for (i=0;i<3;i++){for (j=0;j<4;j++){printf("%d  ", a[i][j]);}printf("\n");}return 0;
    }
    

    运行结果:

    1  0  0  0  
    0  2  0  0
    0  0  3  0
    
  • 二维数组的初始化也能偷懒,让编译器根据元素的数量计算数组的长度。但只有第1维的元素个数可以不写,其他维度必须写上:

    int a[][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};

    int main()
    {int a[][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};int i, j;for (i=0;i<3;i++){for (j=0;j<4;j++){printf("%d  ", a[i][j]);}printf("\n");}return 0;
    }
    

    运行结果

    1  2  3  4  
    5  6  7  8
    9  10  11  12
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/883914.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【牛客训练记录】牛客小白月赛110

训练情况赛后反思 C题没看到偶数,导致打错表了TAT,然后浪费了一点时间 A题 编号每 \(500\) 一组,我们分别除 \(500\) 和取模 \(500\) 就行了点击查看代码 #include <bits/stdc++.h> // #define int long long #define endl \nusing namespace std;void solve(){int x;…

华为FusionCompute虚拟化平台

一、华为FusionCompute虚拟化套件介绍 华为FusionCompute虚拟化套件是业界领先的虚拟化解决方案,能够帮助客户带来如下的价值,从而大幅提升数据中心基础设施的效率。帮助客户提升数据中心基础设施的资源利用率; 帮助客户成倍缩短业务上线周期; 帮助客户成倍降低数据中心能耗…

卡特兰数学习笔记

引入 从 \((0,0)\) 走到 \((n,n)\),求不越过 \(y=x\) 的方案数。 不考虑是否合法的方案数是 \(\binom{2n}{n}\),即从 \(2n\) 个移动中选 \(n\) 个向右的。 接下来考虑不合法的情况,不合法当且仅当碰到了 \(y=x+1\) 这条直线,设这个点是 \((p,p+1)\),将后面的折线沿着 \(y=…

SpringCloud自定义loadbalancer实现标签路由

一、背景最近前端反应开发环境有时候调接口会很慢,原因是有开发图方便将本地服务注册到开发环境,请求路由到开发本地导致, 为了解决该问题想到可以通过标签路由的方式避免该问题,实现前端联调和开发自测互不干扰。该方案除了用于本地调试,还可以用于用户灰度发布。 二、实…

2025.2.14鲜花

ln将卷积转为加法。推歌 (看fengwu博客时候看见的) 《堕》 星河挂在天上 保护璀璨月亮 而你在我心中宛如月光 为你痴为你狂 为你笑为你闯 为你悲为你伤 为你扬 她是踏碎星河落入我梦境的幻想 环遍星系为你寻找的力量 神明给我在最难熬的时光 留下唯一的星光 堕入日月星辉之中…

解密prompt系列48. DeepSeek R1 Kimi 1.5长思维链 - RL Scaling

春节前DeepSeek R1和Kimi1.5炸翻天了,之前大家推测的O1的实现路径,多数都集中在MCTS推理优化,以及STaR等样本自优化方案等等,结果DeepSeek和Kiim直接出手揭示了reasoning的新路线不一定在SFT和Inference Scaling,也可以在RL。也算是Post Train阶段新的Scaling方向,几个核…

求勾股数

基本概念 众所周知(3,4,5)和(6,8,10)是两组勾股数,区别是前一组三个数的公因数是一而后一组的不是。像第一组勾股数一样三个数之间两两互质的就叫做 本原勾股数。而且将一组本原勾股数里的三个数同时扩大相同的倍数得到的一组数还是勾股数(只不过不是本原勾股数)。所…

腾讯元宝接入 DeepSeek R1 模型,支持深度思考 + 联网搜索,好用不卡机!

前言 腾讯元宝AI产品于2025年2月13日在应用商店发布更新,正式接入了DeepSeek R1模型,并宣布该模型已联网、满血上线,DeepSeek+腾讯混元,好用不卡机。腾讯元宝介绍 腾讯元宝是依托于腾讯混元、DeepSeek等大模型,基于跨知识领域和自然语言理解能力的大模型AI产品。元宝期望通…

QFileSystemWatcher+QTableView监控目录下文件变化

目标监控目录下的指定类型的文件,显示文件的序号、名称以及大小。 目录下的文件变化时(删除文件,新增文件后),程序界面可以实时显示目录下的状态。效果图监控目录下的 .h 文件完整源码 #include <QApplication> #include <QTableView> #include <QFileSyst…

服务器安装Nginx

环境CentOS 8 使用编译安装 NginxNginx使用Docker安装确实有点麻烦,需要将很多前端文件映射到容器内部,不推荐 正式环境 1、安装环境需要的依赖包 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel2、在你的linux服务器上创建目录:nginx cd /root &…

WPF的DataGrid简单使用

简单做个记录。有时候会忘记某个样式怎么调整; 首先写一个DataGrid,AlternatingRowBackground表示隔行更改背景色;AlternationCount表示隔的行数;:1 <DataGrid Grid.Row="1" 2 AlternatingRowBackground="Snow" 3 Alternation…

报名丨Computer useVoice Agent :使用 TEN 搭建你的 Mac Assistant

与 TEN 相聚在「LET’S VISION 2025」大会,欢迎来展位上跟我们交流。这次我们还准备了一场聚焦「computer use」的工作坊,功能新鲜上线,线下首波体验!📅 TEN 展位:2025年3月1日-2日TEN workshop:2025年3月2日 13:30开始📍 上海浦东鲜花港TEN Framework 是一个主流对话…