资源简介 (共35张PPT)C 语言程序设计2023翻转课堂实用教程7.3 字符数组123一维字符数组字符串和字符数组的关系字符串结束符字符数组的输入和输出方式字符串处理函数二维字符数组知识点案例7.3.1案例7.3.2案例7.3.3案例分析练习字符数组的使用练习题1、一维字符数组存放了字符的数组就是字符数组。只有一个下标的就是一维字符数组。定义、初始化、引用都与其他类型的一维数组是一样的。举例:char t[8] = {‘H’,’e’,’l’,’l’,’o’,’ ’,’C’,’!’};等价于:t[0] = ‘H’,t[1] = ‘e’,t[2] = ‘l’,t[3] = ‘l’,t[4] = ‘o’,t[5] = ‘ ’,t[6] = ‘C’,t[7] = ‘!’。char str[9] = {‘H’,’e’,’l’,’l’,’o’,’ ’,’C’,’!’,’\0’};等价于:str[0] = ‘H’,str[1] = ‘e’,str[2] = ‘l’,str[3] = ‘l’,str[4] = ‘o’,str[5] = ‘ ’,str[6] = ‘C’,str[7] = ‘!’,str[8] = ‘\0’较t数组,多了一个‘\0’字符,该字符的ASCII值为0在C语言的字符串处理中,‘\0’字符作为字符串的结束。7.3.1字符数组知识点字符数组名还是字符数组的地址,即首字符的地址。2、字符串与字符数组的关系字符串就是一组连续的字符的集合,它有一个结束标志‘\0’。使用一维字符数组来存储字符串。一维字符数组并不一定是字符串,主要在于一维字符数组中是否在所有字符后保存一个结束符‘\0’。举例:若要保存”Hello C!”这个字符串常量,除了 Hello C!这8个字符外,还有一个结束符‘\0’char str[9] = {‘H’,’e’,’l’,’l’,’o’,’ ’,’C’,’!’,’\0’};7.3.1字符数组知识点2、字符串与字符数组的关系举例:char t[8] = {‘H’,’e’,’l’,’l’,’o’,’ ’,’C’,’!’};char str[9] = {‘H’,’e’,’l’,’l’,’o’,’ ’,’C’,’!’,’\0’};字符数组str的有效长度:87.3.1字符数组知识点str和t数组的区别是什么?t数组没有保存‘\0’,它仅是一个字符数组.str不仅是一个字符数组,它还可以作为一个字符串。str的实际大小:93、字符串结束符访问内存中的一个字符串,需要知道 。'\0'意味着字符串的结束。char str[9] = {‘H’,’e’,’l’,’l’,’o’,’ ’,’C’,’!’,’\0’};C语言在处理字符串时,会从前往后逐个扫描字符,直到遇到第一个'\0'就认为到达了字符串的末尾,结束处理。7.3.1字符数组知识点字符串的地址+字符串的结束符#includeint main(){int i;char s[17] = "Hello C program!";//先给所有元素赋初值printf("%s\n",s);s[0] = 'H';s[1] = 'a';s[2] = 'p';s[3] = 'p';s[4] = 'y';s[5] = '\0';for(i=0;i<16;i++){ //输出s字符数组中所有元素putchar(s[i]);;}printf("\n");printf("%s\n",s); //将s作为一个字符串来处理return 0;}运行结果举例,理解结束符7.3.1字符数组知识点Hello C program!Happy C program!Happy'\0'在输出时不显示内容。4、字符数组的输入和输出分为两种:7.3.1字符数组知识点①逐个元素的处理② 整个数组一次性处理4、字符数组的输入和输出7.3.1字符数组知识点①逐个元素的处理涉及到的函数为:scanf()、printf()、getchar()、putchar(),使用这四个函数时需要添加stdio.h。在scanf()和printf()中使用格式控制说明符%c来进行单个字符的输入和输出。getchar()读取单个字符,并且只能读取单个字符。putchar()输出单个字符,并且只能输出单个字符。举例:char ch;scanf("%c",&ch); //从键盘中读取一个字符,并存到变量ch中printf("%c",'A'); //输出一个字符'A',也可输出一个字符变量ch = getchar(); //从键盘中读取一个字符,并存到变量ch中putchar(ch); //输出一个字符变量,也可以输出字符常量4、字符数组的输入和输出7.3.1字符数组知识点② 整个数组一次性处理涉及到的函数为:scanf()、printf()、gets()、puts()。在scanf()和printf()中使用格式控制说明符%s来进行字符串的输入和输出。scanf遇到空格、tab键或者回车便停止读取字符。gets()读取一行字符串。gets()在读取时,只要不遇到换行符就会一直读取,即使遇到多个空格,也不会停止读取。puts()输出字符串并换行。举例:char str[10]={'\0'};scanf("%s",str);gets(str);puts(str);4、字符数组的输入和输出7.3.1字符数组知识点② 整个数组一次性处理scanf()遇到空格、制表符tab或者换行符停止读取;gets()只会在遇到换行符’\n’停止读取。区别#includeint main(){int i;char s[40];scanf("%s",s);printf("%s\n",s);return 0;}运行结果:We are C language learners.↙We使用scanf()读取字符串#includeint main(){int i;char s[40];gets(s);printf("%s\n",s);return 0;}运行结果:We are C language learners.↙We are C language learners.gets()读取字符串5、字符数组串处理函数7.3.1字符数组知识点常见的处理函数,包含在string.h头文件中。strlen() 计算字符串有效长度strcmp()字符串比较strcat()字符串拼接函数strcpy()字符串拷贝函数strstr()字串查找函数需要#include5、字符数组串处理函数7.3.1字符数组知识点(1)strlen计算字符串有效长度字符串包含两个部分:一组连续的字符序列和结束符’\0’,strlen()返回的是连续字符的个数。#includeint main(){char str1[30] = {"Hello C language!"};char str2[30] = {"language"};char str3[10] = "C++";printf("%d\n",strlen(str1));printf("%d\n",strlen(str2));printf("%d\n",strlen(str3));return 0;}运行结果:18835、字符数组串处理函数7.3.1字符数组知识点(2)strcmp字符串比较函数strcmp(str1,str2)用于比较两个字符串大小,自左往右逐个字符的ASCII码值进行比较,直到出现不同的字符或者遇到‘\0’,其中str1和str2为字符串。0 (当str1和str2中的字符完全一样时,str1等于str2)strcmp(str1,str2) 返回 正数 (当str1>str2)负数 (当str15、字符数组串处理函数7.3.1字符数组知识点(2)strcmp字符串比较函数举例:#includeint main(){char str1[] = "Abc"; //如果对全部元素赋值,数组长度可以省略char str2[] = "Abc";char str3[] = "Acd";char str4[] = "Bbca";char str5[] = "Bbc";printf("str1 VS str2 is %d\n",strcmp(str1,str2));printf("str1 VS str3 is %d\n",strcmp(str1,str3));printf("str3 VS str4 is %d\n",strcmp(str3,str4));printf("str4 VS str5 is %d",strcmp(str4,str5));return 0;}运行结果:str1 VS str2 is 0str1 VS str3 is -1str3 VS str4 is -1str4 VS str5 is 15、字符数组串处理函数7.3.1字符数组知识点(3)strcat字符串拼接函数strcat(str1,str2)用于将str2拼接到str1后面,并返回str1,其中str1和str2为字符串。注意:该函数要求str1的字符数组长度要够长,能够放下str1的有效字符+str2的有效字符+一个结束符。5、字符数组串处理函数7.3.1字符数组知识点(3)strcat字符串拼接函数举例:#includeint main(){char str1[30] = {"Hello"};char str2[5] = {" C"};char str3[10] = {" language!"};strcat(str1,str2);printf("str1: %s\n",str1); //str1中拼接了str2的内容printf("str2: %s\n",str2); //str2字符串内容不变strcat(str1,str3);printf("str1: %s",str1);return 0;}运行结果:str1: Hello Cstr2: Cstr1: Hello C language!5、字符数组串处理函数7.3.1字符数组知识点(4)strcpy字符串拷贝函数strcpy(str1,str2)用于将str2中的内容拷贝到str1中,会清除str1中原有的字符。注意:str1字符数组的大小要足够大能容纳str2数组中的字符,否则出现越界的现象。5、字符数组串处理函数7.3.1字符数组知识点(4)strcpy字符串拷贝函数举例:#includeint main(){char str1[30] = {"Hello"};char str2[30] = {"Language"};printf("before: str1: %s\n",str1);strcpy(str1,str2);printf("after : str1: %s\n",str1);return 0;}运行结果:before: str1: Helloafter : str1: Language5、字符数组串处理函数7.3.1字符数组知识点(5)strstr字串查找函数strstr(str1,str2)用于判断str1是否含有str2这个字符串。如果有,str2则被称为str1的子串。该函数返回指向str1中str2第一个出现的位置的指针;如果str2不是sr1的子串,则返回NULL。5、字符数组串处理函数7.3.1字符数组知识点(5)strstr字串查找函数举例:#includeint main(){char str1[30] = {"Hello C language!"};char str2[30] = {"language"};char str3[10] = "C++";char *p = strstr(str1,str2);printf("%s\n",p); //p指向str1中从'l'开始的"language"子串printf("%d",strstr(str1,str3) == NULL);//str3不是str1的子串,所以strstr返回NULLreturn 0;}运行结果:language!16、二维字符数组7.3.1字符数组知识点二维字符数组,可以理解为多个一维字符数组,如果一维字符数组中存放的是学生姓名,那二维数组就可以存放多个学生的姓名,其初始化、引用都和二维数组一样。举例:char names[3][20] = {{“Peter”},{“Tom”},{“Emily”}};3行20列,表示3个一维字符数组(每个数组最多20个字符),可以保存3个字符串。name[0]name[1]name[2]案例7.3.1:查找特定的字符要求:本例包含两行输入,输入第一行是一串以回车符结束的字符串str(不超过50个字符),第二行是要查找的字符ch。如果在给定的字符串str中找到了字符ch,则输出在str中最先出现ch的下标(从0开始计数);若未找到,则输出“Not Found!”7.3.2字符数组案例分析str数组的长度应该定义为多少?#includeint main(){int i,flag = 0; // flag为0表示没有找到char str[51]={'\0'},ch;gets(str);ch = getchar();for(i=0;str[i]!='\0';i++){if(ch == str[i]){flag = 1;printf("The first index of %c is %d ",ch,i);break;}}if(flag == 0){printf("Not Found!");}}运行结果:Life is like a box of chocolates↙l↙The first index of l is 8运行结果案例7.3.1程序代码7.3.2字符数组案例分析案例7.3.2:删除重复数字字符要求:输入是一串以回车符结束的字符串str(不超过80个字符),编写程序将str字符串重复的数字字符删除,其他字符原样输出。问题分析:(1)定义长度为10的number数组来保存某个数字是否出现过。比如,若6出现过,则number[6]为1,若6没有出现,则number[6]为0;所以number[0]、number[1]、number[2]…number[9]依次表示数字0、1、2…9是否出现过,元素值为1表示出现过,元素值为0表示没出现过。(2)在后续输出str时,对于其中的数字字符,先转化为相应的数字,再判断number[该数字]的值是否为0,为0表示没出现过,便可以直接输出。7.3.2字符数组案例分析#includeint main(){int i,number[10] = {0}; //标记某个数字是否出现过char str[81] = {'\0'};gets(str);for(i=0;str[i]!='\0';i++){if(str[i]>='0' && str[i]<='9'){int index = str[i]-'0'; // 数字字符转对应数字if(number[index] == 0){number[index] = 1;putchar(str[i]);}}elseputchar(str[i]);}return 0;}运行结果:输入数据:ad2f3adj3fea2in4zz5zv4↙输出:ad2f3adjfeain4zz5zv运行结果案例7.3.2程序代码7.3.2字符数组案例分析案例7.3.3: 提取身份证号中的出生年月,进行转化后输出要求: 输入一个整数n,随后输入n个身份证号,最后输入一个offset。为了保密的要求,请提取身份证号中的出生年月日,身份证号为18位,其中7-16位为出生年月,对出生年月日进行如下处理,如’0’—>’9’、’1’—>’8’、’2’—>’7’、’3’—>’6’、’4’—>’5’,’5’—>’4’、’6’—>’3’、’7’—>’2’、’8’—>’1’、’9’—>’0’,最后输出处理过的身份证号。7.3.2字符数组案例分析#includeint main(){int i,n,k;/*定义了19行19列二维字符数组,每一行19个字符=身份证号18个字符+结束符'\0',19行可以保存19个人的身份证号*/char identity[19][19];//n保存身份证号的个数scanf("%d",&n);for(i=0;i//identify[i]为一个一维字符数组,保存第i个身份证号scanf("%s",identity[i]);}for(i=0;i//将identity[i]中第7~14位出生日期进行处理for(k=6;k<=13;k++){//得到当前数字字符对应的数值int num = identity[i][k] - '0';identity[i][k] = '0' + (9-num);}printf("%s\n",identity[i]);}return 0;}案例7.3.3程序代码7.3.2字符数组案例分析输入:3↙330103200110121513↙330602199007191214↙330104200106111313↙输出:330103799889871513330602800992801214330104799893881313运行结果7.3.3字符数组练习题课堂练习题7.3.1:字符串的逆序输出。输入一行字符串,字符个数不超过100个,请将该行字符串逆序输出。课堂练习题7.3.2:输入为一首4句中文藏头诗,每句诗一行,获取这首诗每句的第一个汉字,并组成一个字符串,将其输出。注:每个汉字占两个字节课堂练习题7.3.3:按照指定规则对字符串压缩输入为一行字符串,如果该字符串中某个字符c连续出现了n次,当n≥2时,将这n个连续字符c缩写为nc。【微视频】一维字符数组的定义和使用C语言中数组长度在定义时就已确定,在引用数组元素时,如果下标index<0或者index>=数组长度,就会出现下标越界情况,访问到数组以外的内存。编译器不会对下标是否越界进行检查。如果代码中在引用数组时存在下标越界的情况,编译可以通过,但在运行时可能会出现不可预测的结果。7.4 数组的越界#include int main() {int i;int a[3];a[0] = 1;a[1] = 2;a[2] = 3;a[3] = 4; //下标越界访问for (i = 0; i <= 3; i++){printf("%d ", a[i]);}return 1;}数组下标越界访问7.4 数组的越界实际输出为:1 2 3 3(本例在Dev C++上运行)运行结果预期的输出为:1 2 3 4为什么是这样的运行结果呢?有一些编译器(本例在Dev C++上运行)地址分配方式:数组和循环变量分配在一起,如下图所示:a[3]属于越界访问,它的地址是a[2]后面的那个地址,访问的其实就是变量i,运行下面代码就可以看出来。数组下标越界访问7.4 数组的越界a[0]a[2]ia[1]#include int main() {int i;int a[3];a[0] = 1; a[1] = 2; a[2] = 3; a[3] = 4; //下标越界访问printf("the address of a[0] is %p\n",&a[0]);printf("the address of a[1] is %p\n",&a[1]);printf("the address of a[2] is %p\n",&a[2]);printf("the address of a[3] is %p\n",&a[3]);printf("the address of i is %p\n",&i);return 1;}运行结果:the address of a[0] is 000000000062FE10the address of a[1] is 000000000062FE14the address of a[2] is 000000000062FE18the address of a[3] is 000000000062FE1Cthe address of i is 000000000062FE1Ca[3]和i地址一样总结:当程序中存在越界访问数组元素时,如果该程序对越界访问的内存具有操作权限,该程序可以正常运行,但会发生不可控的结果(如上面的实例)。如果该程序对越界访问的内存没有操作权限,或者该内存没有被分配,程序将会出现崩溃现象。所以在访问数组元素时,要尤其注意下标不要越界。7.4 数组的越界谢谢观看程序设计基础 展开更多...... 收起↑ 资源预览