优秀的编程知识分享平台

网站首页 > 技术文章 正文

7.4 字符串及应用(字符串的作用)

nanyue 2024-10-05 18:46:25 技术文章 14 ℃

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\。

本节主要介绍了字符串常量及用字符串数组保存、输入与输出字符串的方法。字符串的应用很频繁,初学者只有不断加强字符串编程训练才能更好掌握字符串应用。本节就讲到这里,下次再见!

最近发表
标签列表