第7章 字符串1207.docx
- 文档编号:13012385
- 上传时间:2023-06-10
- 格式:DOCX
- 页数:35
- 大小:592.49KB
第7章 字符串1207.docx
《第7章 字符串1207.docx》由会员分享,可在线阅读,更多相关《第7章 字符串1207.docx(35页珍藏版)》请在冰点文库上搜索。
第7章字符串1207
第1章字符串
学习目标
理解字符串与字符数组的概念
掌握字符指针的使用,能用字符指针对字符串进行各种操作
掌握字符串函数的使用,能灵活运用这些函数操作字符串
日常生活中的信息都是通过文字来描述的,例如,发送电子邮件、在论坛上发表文章、记录学生信息都需要用到文本。
程序中也同样会用到文本,C语言中文本信息都是通过字符串来实现的。
本章将针对字符串及字符串的相关函数进行详细地讲解。
字符串和字符数组
字符数组
前面第5章中以整型数组为例讲解了数组的相关知识,在C语言中,字符数组也很常用。
字符数组是存放字符数据的数组,其中每一个元素存放的值都是单个字符。
1、字符数组的定义
字符数组定义的语法格式如下:
char数组名[常量表达式];/*一维字符数组*/
char数组名[常量表达式1][常量表达式2];/*二维字符数组*/
在上述语法格式中,分别列举了定义一维字符数组和二维字符数组的语法格式。
以一维字符数组语法格式为例,其中的“char”表示字符数据类型,“数组名”表示数组的名称,它的命名遵循标识符的命名规范,“常量表达式”表示数组中存放元素的个数。
定义字符数组的示例代码如下:
charch[6];
上述示例代码表示定义了一个一维字符数组,数组名为ch,数组的长度为6。
可以存放六个字符,例如,ch[0]=’a’,ch[1]=’b’,ch[2]=’c’,ch[3]=’d’,ch[4]=’e’,ch[5]=’f’。
2、字符数组的初始化
在数组定义的同时也可以对数组中的元素进行赋值,这个过程称为数组的初始化。
示例代码如下:
charc[5]={'h','e','l','l','o'};
上面的示例代码的作用就是定义了一个字符数组,数组名为c,数组包含5个字符类型的元素,该字符数组在内存中的状态如图7-1所示。
图7-1字符数组c的元素分配情况
脚下留心:
字符数组初始化时注意事项
字符数组的初始化很简单,但是要注意以下几点:
(1)初始项不能多于字符数组的大小,否则编绎器会报错。
如下代码所示:
charstr[2]={'a','b','c'};//错误写法
(2)如果初始项值少于数组长度,则空余元素均会被赋值为空字符(’\0’)。
charstr[5]={'a','b','c'};//后面剩余的两个元素均被赋值为'\0'
str数组在内存中的表现如图7-2所示。
图7-2str在内存中的表现
(3)如果没有指定数组大小,则编绎器会根据初始项的个数为数组分配长度。
charstr[]={'a','b','c'};//与charstr[]={'a','b','c'};相同
(4)也可以初始化二维数组。
charstr[2][2]={{'a','b'},{'c','d'}};
3、输出字符数组的元素
字符数组获取元素的方式与整数数组类似,都是通过下标来实现的。
接下来通过一个案例来演示,如例7-1所示。
1#include
2voidmain()
3{
4charchar_array[5]={'h','e','l','l','o'};//声明一个字符数组并初始化
5inti;
6//通过sizeof关键字得到数组长度,并遍历打印其内容
7for(i=0;i 8{ 9printf("%c",char_array[i]); 10printf("\n"); 11} 12} 运行结果如图7-3所示。 图7-3运行结果 从图7-3中可以看出,字符数组char_array中的元素被依次输出了。 由此可见,通过数组角标的方式,可以实现字符数组元素的访问。 需要注意的是,在字符数组初始化时,如果提供的初值个数与数组的长度相同,在定义数组时可以省略数组的长度,系统会根据初值的个数自动确定数组的长度。 例如,charc[]={'h','e','l','l','o'};。 如果字符数组中的初值个数大于数组长度,则按语法错误处理。 如果字符数组中的初值个数小于数组长度,没有赋值的元素会默认赋值为空字符(‘\0’),具体示例如下: charc[8]={'h','e','l','l','o'}; 在上述代码中,定义了一个长度为8的字符数组,当为数组赋5个初值时,字符数组c的元素分配内存情况如图7-4所示。 图7-4字符数组c的元素分配内存情况 字符串概念 1、字符串的概念 字符串是由数字、字母、下划线、空格等各种字符组成的一串字符,由一对英文半角状态下的双引号("")括起来。 字符串在末尾都默认有一个’\0’作为结束符。 "abcde"; ""; 上面定义的两行代码都是字符串,只是第二个字符串中的字符都是空格。 字符串在各种语言编程中都是非常重要的数据类型,但是在C语言中并没有提供“字符串”这个特定类型,通常用字符数组的形式来存储和处理字符串,这种字符数组必须以空字符’\0’(空字符)结尾。 当把一个字符串存入一个字符数组时,也把结束符’\0’存入数组,因此该字符数组的长度是字符串实际字符数加1。 例如字符串"abcde",在数组中的存放形式如图7-5所示。 图7-5"abcde"字符串在数组中的存储形式 2、用字符串初始化字符数组 为了便于对字符数组进行初始化操作,可以直接使用一个字符串常量来为一个字符数组赋值,具体示例如下: charchar_array[6]={"hello"}; charchar_array[]={"hello"}; 在定义数组时,数组的大小可以省略,让编译器自动确定长度,因此,上述两种初始化字符串的方式是等同的。 双引号之间的“hello”是一个字符串常量,字符数组char_array在指定长度时之所以定义6,是因为在字符串的末尾还有一个结束标志‘\0’。 它的作用等同于下列代码: charchar_array[6]={'h','e','l','l','o','\0'}; 为了帮助大家更好地理解字符串的定义方式,接下来通过一个案例来输出字符串中的字符,如例7-2所示。 13#include 14voidmain() 15{ 16charchar_array[6]={"hello"};//声明一个长度为6的字符数组并初始化为hello 17inti; 18//通过sizeof关键字得到数组长度 19for(i=0;i 20{ 21//通过printf输出char_array[]中的字符串 22printf("char_array的第%d个是%d\n",i,char_array[i]); 23} 24} 运行结果如图7-6所示。 图7-6运行结果 在例7-2中,定义了一个字符数组char_array,该字符数组中保存的是字符串“hello”。 从图7-6中可以看出,字符数组char_array输出了6个字符,并且最后一个字符是空字符‘\0’。 3、获取字符串长度 字符串用数组来存储,第2章中曾学过用sizeof()运算符来求各种数据类型的长度,那么sizeof()运算符也可以用来求字符串的度。 例如sizeof(“abcde”)。 除了可以使用sizeof运算符获取字符串长度外,还可以使用strlen()函数来获取,strlen()函数声明如下: unsignedintstrlen(char*s); 在上述声明中,s是指向字符串的指针,返回值是字符串的长度。 需要注意的是使用strlen()函数得到的字符串的长度,并不包括末尾的空字符‘\0’。 接下来通过一个案例来演示如何使用strlen()函数获取用户输入字符串的长度,如例7-3所示。 25#include 26#include 27voidmain() 28{ 29charstr[10]="hello"; 30printf("%d\n",strlen(str)); 31printf("%d\n",strlen("hello")); 32printf("%d\n",sizeof(str)); 33printf("%d\n",sizeof("hello")); 34} 运行结果如图7-7所示。 图7-7获取用户输入字符串的长度 从图7-7中可以看出,strlen(“str”)和strlen(“hello”)的大小都为5,都只包含字符串中的字符个数,不包括末尾的’\0’。 sizeof(str)的大小为10,是数组在内存所占的大小;sizeof(“hello”)的大小为6,包括”hello”字符串中的5个字符和末尾的’\0’。 通过例7-3可以看出sizeof()与strlen()在求字符串时是有所不同的,我们来简单总结一下strlen()函数与sizeof运算符的区别,具体如下: (1)sizeof是运算符;strlen()是C语言标准库函数,包含在string.h头文件中。 (2)sizeof运算符功能是获得所建立的对象的字节大小,计算的是类型所占内存的多少;strlen()函数是获得字符串所占内存的有效字节数。 (3)sizeof运算符的参数可以是数组、指针、类型、对象、函数等;strlen()函数的参数必须是字符型指针,即它的参数必须是以字符串为目标,且必须是以’\0’结尾。 (4)sizeof运算符计算大小是在编绎时就完成,因此不能用来计算动态分配内存的大小;strlen()结果要在运行时才能计算出来。 多学一招: 字符与字符串的转换 C语言中的字符串实际上是字符数组,而C语言中的字符则是一种基本数据类型。 因此在字符和字符串之间进行转换是很容易的。 接下来,将chara='A'转为字符串,具体步骤如下: (1)创建一个长度为2的字符数组 chara_str[2]; (2)将第一个元素设置为对应的字符,第二个元素设置为空字符。 a_str[0]=a; a_str[1]='\0'; 同理,将字符串转为字符也很简单,具体示例如下: chara_str[]="AB"; chara=a_str[0]; charb=a_str[1]; 在上述代码中,定义了一个字符数组a_str,该字符数组中保存的是字符串“AB”。 只要将字符串中的每个字符赋给字符变量a和b,就可以完成字符串转为字符的操作。 脚下留心: 空字符‘\0’的使用 通过前面的讲解不难发现,字符串其实就是一个以空字符‘\0’结尾的字符数组。 先来看一个例子,如例7-4所示。 35#include 36voidmain() 37{ 38charchar_array[]={'h','e','l','l','o','\0','W','o','r','l','d'}; 39printf("%s\n",char_array); 40} 运行结果如图7-8所示。 图7-8运行结果 从图7-8中可以看出,字符数组char_array中存储的字符串只输出了一部分。 这是因为程序中字符串的结束是通过‘\0’来检测的。 在例7-4中,字符数组char_array的第6个字符是‘\0’,程序会认为到了字符串的末尾,从而输出“hello”。 同样,如果定义一个字符数组时,忘记在字符数组的末尾添加空字符‘\0’,程序也会出现一些奇怪的现象,接下来,通过一个案例来演示,如例7-5所示。 41#include 42voidmain() 43{ 44charchar_array[]={'h','e','l','l','o'}; 45printf("%s\n",char_array); 46} 运行结果如图7-9所示。 图7-9没有空字符结尾的字符串 从图7-9中可以看出,程序不仅输出了我们想要的“hello”,还输出了一些奇怪的字符。 这是因为在使用printf()函数输出字符串时,如果没有遇到空字符,就会继续后面的内存数据,直到遇到第一个空字符‘\0’。 因此,在定义字符数组时,一定不能忘记空字符‘\0’。 字符串与指针 在C语言中,字符型指针用char*来定义,它不仅可以指向一个字符型常量,还可以指向一个字符串。 为了描述字符串与指针之间的关系,先来看一段示例代码,具体如下: charchar_array[]="hello"; char*chr=char_array; 上述代码定义了一个字符型指针chr,该指针指向字符串“hello”,字符指针chr和字符串“hello”的关系如图7-10所示。 图7-10指针chr指向字符串hello 从图7-10中可以看出,字符指针chr既指向了字符‘h’,又指向了字符串“hello”。 这是因为字符‘h’位于字符串“hello”的起始处,因此,chr也是指向字符‘h’的字符指针。 在输出这块内存中的数据时,根据输出格式的不同会输出不同的数据。 如果以%c输出,则只输出当前指针指向的字符即可。 如果以%s输出,则会输出后面连续的内存空间的数据,直到遇到’\0’停止。 为了帮助读者更好地理解指针,接下来,通过一个案例来演示如何使用指针修改字符串中的字符,如例7-6所示。 47#include 48intmain() 49{ 50charchar_array[]="helloworld! "; 51char*ptr; 52printf("修改前的字符串如下: %s\n",char_array); 53ptr=char_array;//将一个字符型指针指向字符型数组char_array的首地址 54//开始修改字符串 55while(*ptr! ='\0')//检测是否到串末尾 56{ 57if(*ptr=='') 58{ 59*ptr='! '; 60} 61ptr++; 62} 63printf("修改后的字符串如下: %s\n",char_array); 64return0; 65} 运行结果如图7-11所示。 图7-11运行结果 在例7-6中,由于字符串总是以空字符‘\0’结尾,因此在使用while循环遍历字符串时,只需要判断当前位置的字符是否为空即可。 从图7-11中可以看出,使用自增的字符指针可以实现字符串的访问和修改。 字符数组与字符指针 字符串用字符数组存储,也可以取地址赋值给字符型指针。 字符数组与字符指针围绕字符串就发生了千丝万缕的联系,这一节来总结一下两者的区别与联系: 1、存储方式 字符数组在用字符串初始化时,这个字符串就存放在了字符数组开辟的内存空间中;而字符指针变量在用字符串常量初始化时,指针变量中存储的是字符串的首地址,但字符串存储在常量区。 上面的文字描述稍显晦涩难懂,下面通过一段示例代码来辅助理解,具体如下: charstr[6]="hello”; char*p="hello"; 上面两行代码在内存区的存储方式如图7-12所示。 图7-12字符数组与字符指针的字符串的存储方式 从图7-12可以看出,字符数组str在使用字符串常量“hello”初始化时,字符串存储在栈区,而指针变量p在使用字符串常量“hello”初始化时,栈区只存放了字符串的首地址,而字符串却存储在常量区。 存储在栈区、堆区、静态区上的数据都是可更改的,但是常量区的数据是不可变的,一量赋值就不能再改变。 2、初始化及赋值方式 (1)初始化方式 可以对字符指针变量赋值,但不能对数组名赋值。 示例代码如下: char*p="hello";//等价于char*p;p="hello"; charstr[6]="hello";//charstr[6];str="hello";这种写法错误 (2)赋值方式 字符数组(或字符串)之间只能单个元素赋值或使用复制函数;字符指针则无此限制。 示例代码如下: char*p1="hello",*p2;p2=p1; charstr1[6]="hello",str2[6];//str2=str1;错误,数组赋值,数组章节讲解过,这里不再赘述 3、字符串指针与数组名 字符指针变量的值是可以改变的,而数组名是一个指针常量,其值不可以改变。 代码示例如下: char*p="chuanzhiboke,niu! "; p+=7; 而对字符数组charstr[6]=“hello”;来说,数组名是常量指针,是不可以改变的。 4、字符串中字符的引用 数组可以用下标法和地址法引用数组元素;字符指针也可以用地址法、指针变量加下标法来引用字符串的字符元素。 示例代码如下: char*str[100]="chuanzhiboke,niu! "; charch1=str[6]; char*p="chuanzhiboke,niu! "; charch2=p[6];//等价于charch2=*(p+6); 关于字符串、字符数组、字符指针的区别与联系的诸多细节,需要读者在学习应用当中慢慢体会。 字符串的输入输出 在第四章中大家学习了printf()和scanf()函数,它们分别用于向控制台中输出内容和从控制台上接收用户的输入。 针对字符串的读取和输出,C语言还专门提供了puts()函数gets()函数,本节将针对这两个函数进行详细地讲解。 gets()函数 gets()函数用于从控制台读入用户输入的字符串,其语法格式如下: char*gets(char*str); 从上面的语法格式可以看出,函数gets()接收一个字符指针作为参数,该字符指针应指向已经分配好空间的一个字符数组。 当调用gets()函数时,将读取到的字符串赋值给该字符数组。 当使用gets()函数读入用户输入的字符串时,会把换行符之前所有的字符读取进来(不包括换行符本身),并在字符串的末尾添加一个空字符‘\0’用来标记字符串的结束,读取到的字符串会以指针形式返回。 为了帮助大家更好地理解gets()函数的用法,接下来通过一个具体的案例实现读取用户输入的电话号码,如例7-7所示。 66#include 67#pragmawarning 68voidmain() 69{ 70charphoneNumber[12]; 71printf("请输入手机号码: "); 72gets(phoneNumber); 73printf("您的手机号码是: %s\n",phoneNumber); 74} 运行结果如图7-13所示。 图7-13使用gets()函数读入手机号码 从图7-13中可以看出,当用户输入电话号码后,程序会自动在控制台输出号码,这是因为程序的第6行代码使用了gets()函数,该函数可以读取用户输入的手机号码,由此可见使用gets()函数可以实现字符串的输入操作。 注意: 1、在VS开发工具中,在例7-7的代码中加入预处理指令#pragmawarning(disable: 4996)是要消除警告。 因为gets()是不安全的函数,如果不加上此条预处理指令,VS会发出警告不让通过编绎。 读者可以换用安全的fgets()函数,此函数与gets()函数用法一样。 2、使用gets()函数时,用户定义的字符数组的长度必须大于用户输入的字符串长度,否则程序会发生“缓冲区溢出”错误。 puts()函数 puts()函数用于向控制台输出一整行字符串,其语法格式如下: intputs(constchar*str); 从上面的语法格式中可以看出,函数puts()接收的参数是一个字符串指针,该指针指向要输出的字符串,并且会自动在字符串末尾追加换行符‘\n’。 如果调用成功后返回一个int类型的正数,否则返回EOF。 为了让大家更深入的理解puts()函数的用法,接下来通过具体的案例来演示,如例7-8所示。 75#include 76voidmain() 77{ 78charbuf[100]; 79puts("请输入一个字符串: "); 80gets(buf); 81puts("您输入的是: \n"); 82puts(buf); 83} 运行结果如图7-14所示。 图7-14运行结果 从图7-14的运行结果可以看出,在“您输入的是: \n”后面出现了两次换行,这是因为使用puts()函数输出字符串时,会在字符串的末尾追加一个换行符‘\n’,而输出的字符串本身也有一个换行符‘\n’。 多学一招: printf()与puts()的区别 与puts()函数相比,printf()函数不会一次输出一整行字符串,而是根据格式化字符串输出一个个“单词”。 由于进行了额外的数据格式化工作,因此在性能上,printf()比puts()慢。 另外printf()还可以直接输出各种不同类型的数据,从这个角度来说,它比puts()使用的更广泛。 字符串函数 在程序中,经常需要对字符串进行操作,如字符串的比较、查找、替换等。 在C语言中,提供了许多操作字符串的函数,这些函数都位于string.h文件中。 本节将针对这些函数进行详细地讲解。 字符串比较函数 在程序中,经常需要对字符串进行比较,如判断用户输入的密码是否正确,为此C语言提供了strcmp()函数和strncmp()函数。 关于这两个函数的相关讲解,具体如下: 1、strcmp()函数 在C语言中,strcmp()函数用于比较两个字符串的内容是否相等,其语法格式如下所示: intstrcmp(constchar*str1,constchar*str2); 在上述语法格式中,参数str1和str2代表要进行比较的两个字符串。 如果两个字符串的内容相同,strcmp()返回0,否则返回非零值。 为了帮助大家更好地理解strcmp()函数的用法,接下来通过案例来演示用户名和密码的比较,具体如例7-9所示。 84#include 85#include 86voidmain() 87{ 88charusername[100];//定义存放用户名的字符数组 89charpassword[100];//定义存放密码的字符数组 90printf("登录\n"); 91printf("请输入用户名: "); 92gets(username);//获取用户输入的用户名 93printf("请输入密码: ");
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第7章 字符串1207 字符串 1207
![提示](https://static.bingdoc.com/images/bang_tan.gif)