【408专项篇】C语言笔记-第五章(一维数组与字符数组)
创始人
2024-02-06 14:07:39
0

第五章:一维数组与字符数组

第一节:一维数组

1. 数组的定义

C语言提供的数组,通过一个符号来访问多个元素。

特点:

  1. 具有相同的数据类型。
  2. 使用过程中需要保留原始数据。

数组是构造数据类型。所谓数组,是指一组具有相同数据类型的数据的有序集合。

格式:

类型说明符 数组名[常量表达式];

例如:int a[10];

声明数组时要遵循以下规则:

  1. 数组名的命名规则和变量名相同,即遵循标识符命名规则。
  2. 在定义数组时,需要指定数组中元素的个数,方括号中的常量表达式用来表示元素的个数,即数组长度。
  3. 常量表达式中可以包含常量和符号常量,但不能包含变量。即不允许对数组大小的做动态定义。

2. 一维数组在内存中的存储

数组元素下标从0开始。

一维数组初始化方法:

  1. 在定义数组时对数组元素赋初值。int a[10]={0,1,2,3,4,5,6,7,8,9};
  2. 可以只给一部分元素赋值。int a[10]={0,1,2,3,4,};表示只给前5个元素赋初值,后5个元素的值为0
  3. 如果要使一个数组中的全部元素值为0,可以写成:int a[10]={0,0,0,0,0,0,0,0,0,0};或int a[10]={0};
  4. 在对全部数组元素赋初始值时,由于数组的个数已经确定,因此可以不指定数组的长度。int a[]={1,2,3,4,5};

第二节:数组访问越界与传递

1. 数组的访问越界

#include int main() {int a[5]={1,2,3,4,5};int j=20;int i=30;a[5]=6;  // 越界访问a[6]=7;  // 越界访问导致其他变量值发生变化,异常printf("i=%d\n",i);  // i发生变化printf("j=%d\n",j);return 0;
}
F:\Computer\Project\practice\5\5.1-transboundary\cmake-build-debug\5_1_transboundary.exe
i=7
j=20进程已结束,退出代码为 0

解析:a[5],a[6]属于越界访问。在内存中,读取到的变量值是紧挨在一起的,如果越界,就会导致其他变量的值被修改。

需要注意的是,编译器并不检查程序对数组下标的引用是否在合法范围内。好处是效率更高,坏处是无法检测出无效的下标引用。需要做好检查

2. 数组的传递

一维数组在传递时,其长度是传递不过去的,所以我们通过借助另外一个参数len来传递数组中的元素个数。

#include void print(int b[],int len){  // 子函数需要两个形式参数int i;for (int i = 0; i < len; i++) {printf("%3d",b[i]);}b[4]=20;printf("\n");
}int main() {int a[5]={1,2,3,4,5};printf("before a[4]=%d\n",a[4]);print(a,5);  // 5是数组a的长度printf("after a[4]=%d\n",a[4]);  // a[4]的值已被修改return 0;
}
F:\Computer\Project\practice\5\5.2-transmit\cmake-build-debug\5_2_transmit.exe
before a[4]=51  2  3  4  5
after a[4]=20进程已结束,退出代码为 0

解析:实际数组名中存储的数组的首地址,在调用函数时,试将数组的首地址给了变量b(指针类型),print函数对数组的修改,同等于main函数中对数组的修改。另外通过len将数组长度传递给了函数。

第三节:字符数组与scanf读取字符串

1. 字符数组初始化及传递

字符数组定义:
例如:char c[10];

字符数组初始化和一维数组类似:

char c[10]={‘I’,‘a’,‘m’,‘h’,‘a’,‘p’,‘p’,‘y’};

或者:

c[0]=‘I’;c[1]=‘a’;c[2]=‘m’;…

因为字符数组一般用来存取字符串,所以通常采用的初始化方法是 char c[10]=“hello”。

字符数组存储的字符串长度必须比字符数组定义长度少1个字节,例如:char c[10]最长存储9个字节,剩余的1个字符用来存储’\0’。

#include int main() {char c[5]={'h','e','l','l','o'};  // 5个字符,定义长度是5,会出现乱码,因为字符没有结束符。最少要定义长度为6char d[5]="how";   // 3个字符,定义长度为5,不会出现乱码printf("%s\n",c);printf("%s\n",d);return 0;
}
F:\Computer\Project\practice\5\5.3-char\cmake-build-debug\5_3_char.exe
hello?
how进程已结束,退出代码为 0

字符数组通过结尾标识’\0’来判断是否结尾。一维数组没有标识,所以需要传递长度,而字符数组不需要传递长度

#include void print(char c[]){int i=0;while (c[i]){printf("%c",c[i]);i++;}
}int main() {char c[5]={'h','e','l','l','o'};  // 5个字符,定义长度是5,会出现乱码,因为字符没有结束符。最少要定义长度为6char d[5]="how";   // 3个字符,定义长度为5,不会出现乱码printf("%s\n",c);  // 使用%s直接输出字符串printf("%s\n",d);
//    printf("================\n");
//    printf("%x\n",*c);  用于打印内存信息
//    printf("%x\n",*(c+1));
//    printf("%x\n",*(c+2));
//    printf("%x\n",*(c+3));
//    printf("%x\n",*(c+4));
//    printf("%x\n",*(c+5));
//    printf("%x\n",*(c+6));
//    printf("%x\n",*(c+7));print(d);return 0;
}
F:\Computer\Project\practice\5\5.3-char\cmake-build-debug\5_3_char.exe
hello?q
how
how
进程已结束,退出代码为 0

2. scanf读取字符串

scanf读取字符串使用%s

#include int main() {char c[10];char d[10];scanf("%s",c);printf("%s\n",c);scanf("%s%s",c,d);printf("c=%s,d=%s\n",c,d);return 0;
}
F:\Computer\Project\practice\5\5.3-scarry_char\cmake-build-debug\5_3_scarry_char.exe
hello
hello
are you
c=are,d=you进程已结束,退出代码为 0

解析:scanf通过%s读取字符串,对c和d分别输入"are"和"you"(中间加一个空格),scanf在使用%s读取字符串时,会忽略空格和回车,这一点和%d和%f类似

第四节:gets、puts、str系列讲解

1. gets函数与puts函数

gets函数类似于scanf函数,用于读取标准输入。区别是scanf遇到空格就认为读取结束,而gets不会,所以某些场景下需要使用gets函数。

gets函数读取字符并把它们加载到str(字符串)中,遇到’\n’才认为读取结束,但不会存储’\n’,而是存储成空字符’\0’。

puts函数类似于printf函数,用于输出标准输出。

puts函数把str(字符串)写入标准输出。并打印到屏幕上,同时打印换行。相对于printf函数,puts只能用于输出字符串,同时多打印一个换行符,等价于printf{“%s\n”,c};

#include int main() {char c[20];gets(c);   // 相当于scanfputs(c);   // 相当于printfreturn 0;
}
F:\Computer\Project\practice\5\5.4-gets_puts\cmake-build-debug\5_4_gets_puts.exe
how are you
how are you进程已结束,退出代码为 0

2. str系列字符串操作函数

strlen:用于统计字符串长度。

strcpy:用于将某个字符串复制到字符数组中。

strcmp:用于比较两个字符串的大小。

strcat:用于将两个字符串连接到一起。

str系列操作函数需要引入标准输入流#include

#include 
#include int mystrlen(char c[]){int i=0;while (c[i]){i++;}return i;
}int main() {int len;char c[20];char d[100]="world";gets(c);  // 给c输入helloputs(c);len= strlen(c);printf("len=%d\n",len);  // 打印c的长度len=mystrlen(c);printf("mylen=%d\n",len);printf("%s\n",strcat(c,d));  // 将d拼接在c的后面,并打印printf("%s\n",strcpy(d,c));  // 将c的值赋给d,并打印puts(d);  // 打印此刻d的值printf("c?d %d\n", strcmp(c,d));  // 比较c和d的大小,并打印。return 0;
}
F:\Computer\Project\practice\5\5.4-str\cmake-build-debug\5_4_str.exe
hello
hello
len=5
mylen=5
helloworld
helloworld
helloworld
c?d 0进程已结束,退出代码为 0

解析:对于赋值和拼接的场景,目标数组一定要大于字符串大小,即sizeof(d)>strlen©,否则会造成访问越界。

比较大小方法:将每个字母转换成ASCII码值,从前到后依次比较。如果相等,则返回0。如果前边比后边大,返回1。如果前边比后边小,返回-1。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...