网站首页 > 技术文章 正文
7.4 字符串及应用
上一节介绍了二维数组的定义、初赋值、内存映象及数组元素的使用。本节主要讲字符串、字符串的的存储和使用。
文字处理是计算机应用的重要工作。近年来,计算机更多地被用来文字处理而非数值处理,如文字的输入、编辑、排版、查找、替换和输出等。为了能进行简单文字处理,C语言可以通过定义字符型数据来完成一些的工作。如:
char ch;
ch=getchar( );
putchar(ch);
以上代码定义了一个字型变量,并且可以通过getchar函数输入一个字符存放到字符变量ch中,再通过putchar(ch)把字符输出来。字符常量用单引号定界,可以是普通字符,如'A'、'#'、'9'等,也可以是转义字符,如'\n'、'\t'、'\x41'、'\101等。如果两个单引号之间什么也没有,如'',则称为空字符,这与空白' '字符不同,空白字符中有一个称为空格的符号。
很多时候,我们要处理更多的字符,因此我们可以把这些字符按顺序排列,并用一对双引号("")定界,称为字符串常量。回顾一下,我们在学习scanf与printf函数时,函数的第一个参数——格式控制字符串就是字符串。如:
"Hello,world!\n"
"a=%d,b=%d\n"
如果要让屏幕上显示的Hello,world两端带有双引号("),则字符串要写成这样的形式:
"\"Hello,world!\"\n"
此时字符串用转义符号'\"'表示双引号,目的是要与用来定界的双引号区别开。
字符串常量可以用printf输出,此时要用%s格式符表示。如;
printf("Hello,%s","world!\n");
printf函数执行时,会把字符串"world!\n"去代替格式控制字符串中的%s,因此屏幕上显示:
Hello,world!
字符串常量被保存在连续的存储空间中,最后用一个特殊的字符'\0'表示字符串的结束,如“Hello,world!”在内存中是这样保存的:
地址 | 内空空间 | 编号 |
xxx0D | 12 | |
xxx0C | '\0' | 11 |
xxx0B | 'd' | 10 |
xxx0A | 'l' | 9 |
xxx09 | 'r' | 8 |
xxx08 | 'o' | 7 |
xxx07 | 'w' | 6 |
xxx06 | ',' | 5 |
xxx05 | 'o' | 4 |
xxx04 | 'l' | 3 |
xxx03 | 'l' | 2 |
xxx02 | 'e' | 1 |
xxx01 | 'H' | 0 |
字符串常量"Hello,world!"占用的存储空间中的内容是不可被改变的。我们看到的是一串符号,但在计算机中字符串常量是其第一个字符的首地址,如上图,"Hello,world!"的值是一个地址数值xxx01,即字符'H'的首地址。我们可以通过以下输出来验证字符串是一个地址的事实:
printf("%d","Hello,world!\n");
注意这里用的格式符是%d,而不是%s。因此语句执行后显示的结果是一个整数,而不是字符串本身。
很遗憾C语言没有提供字符串变量,这使操作字符串时稍稍麻烦些。由于字符串占用连续存储空间,所以可以通过定义字符数组来保存字符串。如:
char str[80];
字符数组str可以存放79个字符的字符串,因为要留一个字符来存储字符串结束标志'\0'。字符串在定义的同时是可以被赋初值的,有以下几种赋初值的办法:
char str[80]={'H','e','l','l','o','!','\0'};
char str[80]="Hello!";
char str[80]={"Hello!"};
三种赋初值的结果都一样,但是第一种很显然要麻烦得多,因为一个字符一个字符赋值,并且在最后不能忘记字符串结束标'\0'。而后两种赋初值,会依次把每个字符复制到字符数组str的每个元素中,含最后的字符串结束符号'\0'。
字符串的输出可以用printf或puts函数实现。用printf函数时,要在格式控制字符串中用格式符%s指定,用puts不需要指它格式符,如:
printf("%s",str);
puts(str);
我们前面讲过,数组名字是地址常量,因此str是一个地址。那么怎么输出字符串呢?执行以上语句时,printf函数从str地址对应的字符开始逐个字符输出,直到碰到字符串结束标志'\0'为止。我们可以用前面学习的数组元素的输出方法(逐个元素)来输出字符串,即:
for(i=0;str[i]!='\0';i++)
putchar(str[i]);
与一维数组输出不同是循环控制条件。前面用i小于数组长度来表示。字符串的长度可以用strlen函数来确定,但如果先求字符串长度再输出显示多消耗了一些时间。因为知道字符串以'\0'结束。因此,循环条件可设为为str[i]!='\0',即当第i个字符为'\0'时,表示字符串结束,退出循环。
知道了字符串的输出方法后,我们来看一如何输入字符串保存到数组中。我们可以用getchar函数一个字符一个字符地输入,输入一个就保存到数组对应的元素中,此时需要一个计数器记录当前输入的字符个数,只要不碰到回车我们继续输入。给字符数组输入字符串的代码段为:
cnt=0; //计数器为零,表示初始没有字符
while( (ch=getchar( ))!='\0'){
str[cnt]=ch;
cnt++;
}
str[cnt]='\0';
以上代码能完成了字符串的输入并保存到字符数组str中,但是这里假定了str数组是无限长的,在实际应用时,还要限定输入字符串的长度,如cnt<maxLen。由于cnt使用完后再加1,因此可以把字符串输入代码改写为:
cnt=0;
while( (ch=getchar( ))!='\n' && cnt<maxLen)
str[cnt++]=ch;
str[cnt]='\0';
当然我们可以用scanf函数来实现字符串的输入,此时格式控制字符串中要使用%s格式符,如:
scanf("%d",str);
由于数组名str本身是一个地址常量,所以不能在str的前面用取地址运算符&。但是scanf只能实现没有空格的字符串输入,如果输入的字符串含有空格,只取空格前的字符串放到数组中。
也可以用使用gets函数来实现字符串的输入,与scanf相比,可以输入带有空格的字符串,输入方式为:
gets(str);
上面,我们已经学习字符串的概念、存储与字符串的输入与输出,以下通过几个实例深入掌握字符串的应用。
例1:输入一个以回车符为结束标志的字符串(少于80个字符),判断该字符串是否为回文。回文指的是字符串中心对称或正向读与反向读都是一样的,如“abcba” “abccba”是回文,“abcdba”不是回文。
字符串的输入与输出,我们可以直接使用前面的方法实现,所以本例的关键是判断字符串str是否回文。为此,可设两个变量i、j,i保存字符串前面的字符的下标,j保存字符串后面字符的下标,初始时i为0,j为字符串最后一个字符下标(字符串长度-1)。比较str[i]与str[j],如果两个字符相等,则分别让i加1、j减1。如果不等或者i比j大,则程序结束。
完整的程序如下:
#include <stdio.h>
int main( )
{
char str[80],ch;
int cnt=0,i,j;
while( cnt<80 && ( ch=getchar( ))!='\0')
str[cnt++]=ch;
str[cnt]='\0';
i=0;j=cnt-1;
while(i<j && str[i]==str[j]){
i++;j--;
}
if( i >= j) printf("It is a plalindrome\n");
else printf("It is not a plalindrome\n");
return 0;
}
程序使用i>=j判断是否回文,原因是如果不是回文,一定是因为条件str[i]!=str[j]退出的,此时i小于j。只有从条件i>=j退出,此时说明是回文。
例2:输入一个以回车符为结束标志的字符串(少于80个字符),统计其中数字字符'0'……'9'的个数。
本例我们用gets输入字符串str,然后依次检验每个字符str[i]是否是数字,如果是则让记数器cnt加1。检验字符str[i]的代码为:
if(str[i]>='0' && str[i]<='9')
cnt++;
由于'\0'之前的每个字符都要被检验到,因此可以使用for循环或while循环实现,用for循环如下:
for(i=0;str[i]!='\0';i++) //str[i]!='\0'可简写为str[i]
if(str[i]>='0' && str[i]<='9')
cnt++;
完整的程序如下:
#include<stdio.h>
int main( )
{
char str[80];
int cnt=0;
gets(str);
for(i=0;str[i]!='\0';i++) //str[i]!='\0'可简写为str[i]
if(str[i]>='0' && str[i]<='9')
cnt++;
printf("count=%d\n",cnt);
return 0;
}
例3:输入一个以回车符为结束标志的字符串(少于20个字符),提取其中所有的数字字符( '0'……'9' ),将其转换为一个十进制整数输出。
分析:如有字符串“abc1xyz2uvw3#yuv”,提取的数字字符应该是'1'、'2'、'3',因此构成的十进制整数是123。如何才能把'1'、'2'、'3'变成十进制整数呢?
假设该十进制数为x,则x的初值为0。然后碰到'1'后,要把1放在x的之后(01),可让x乘以10再加上'1'对应的数1,即:x=x*10+'1'-'0'=1;当碰到'2'时,要把2放在x之后(12),可让x乘以10再加上'2'对应的数2,即:x=x*10+'2'-'0'=10+2=12。最后,要把'3'放在x之后(123),即让x=x*10+'3'-'0'=12*10+3=123。因此当str[i]是数字时要作如下处理:
if(str[i]>='0' && str[i]<='9')
x=x*10+str[i]-'0'; //让str[i]作为x的个位
用for循环对字符串每个字符进行处理,代码如下:
for(i=0;str[i];i++)
if(str[i]>='0' && str[i]<='9')
x=x*10+str[i]-'0';
完整的程序如下:
#include <stdio.h>
int main( )
{
char str[20],ch;
long long x=0;
short int cnt=0,i;
while( cnt<20 && ( ch=getchar( ) )!='\0')
str[cnt++]=ch;
str[cnt]='\0';
for(i=0;str[i];i++)
if(str[i]>='0' && str[i]<='9')
x=x*10+str[i]-'0';
printf("%Ld\n",x);
return 0;
}
最后讲一下字符串的长度,字符串的长度指的是字符串中包含字符的个数。空字符串""指的是不包括任何字符的串,只有一个字符结束符'\0',因此字符串长度为0。字符串"Hello world!"的字符个数为12。但是如果字符串中含有转义符,则多个符号表示的转义符只算作一个字符,如:字符串"\\\x41\\"长度为3而不是8,因为'\\'是一个字符,'\x41'是一个字符'A',如果用printf输出,显示为:\A\。
本节主要介绍了字符串常量及用字符串数组保存、输入与输出字符串的方法。字符串的应用很频繁,初学者只有不断加强字符串编程训练才能更好掌握字符串应用。本节就讲到这里,下次再见!
猜你喜欢
- 2024-10-05 Python基础知识——字符串(python字符串的常用方法)
- 2024-10-05 你会在 Python 中使用字符串吗?(python字符串需要用什么包裹)
- 2024-10-05 javascript内置对象总结 - String
- 2024-10-05 Python 中字符串和字符串处理的综合指南
- 2024-10-05 C++中的string用法(c++ string用法总结)
- 2024-10-05 Excel文本函数——CONCATENATE函数详解
- 2024-10-05 探究C语言中字符串大小和长度易错点
- 2024-10-05 【PythonTip题库300题】第47题:字符串中缺失的字母
- 2024-10-05 Rust: 字符串总结,虽常见但非常重要
- 2024-10-05 这些字符串处理函数你用过吗(字符串常用操作函数)
- 08-03MySQL数据库的预处理详解
- 08-03《阿常·MySQL 70讲》全套教学视频
- 08-03隐式等待、显示等待和强制等待
- 08-03零基础C#上位机框架项目实例(完结篇)
- 08-03一文搞懂构建Web内容的技术
- 08-03西门子WINCC中的VBScript(VBS)常用于自动化脚本开发
- 08-03力控和sql2000之间的数据转储
- 08-03组态王|通过日历控件选择时间段查询历史报警
- 1521℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 627℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 527℃MySQL service启动脚本浅析(r12笔记第59天)
- 492℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 492℃启用MySQL查询缓存(mysql8.0查询缓存)
- 479℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 461℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 458℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- windowsscripthost (69)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- htmlbackground-image (68)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)