字符数组详解

用来存放字符数据的数组是字符数组。字符数组中一个元素存一个字符。

一、字符数组的定义

定义方法与前而介绍的类似。例如:

char c[10];

c [o]=’I’;c[1]=’ ’,c[2]=’a’,c[3]=’m’;c[4]=’ ’;c[5]=’h’;c[6]=’a’;c[7]=’p’; c[8]=’p’;c[9]=’y’;

定义c为字符数组,包含10元素。在复制以后数组的状态如下图所示。

c[0] c[1] c[2] c[3] c[4] c[5] c[6] c[7] c[8] c[9]

I

a

m

h

a

p

p

y

由于字符型与整型是互相通用的,因此上面的定义也可改为:

int c[10]; /*合法,但浪费存储空间*/

二、字符数组的初始化

对字符数组初始化,最容易理解的方式是逐个字符赋给数组中各元素。如:

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

把10个字符分别赋给c[0]到c[9]10个元素。

如果花括弧中提供的初值个数(即字符个数)大于数组长度,则按语法错误处理。如果初值个数小于数组长度,则只将这些字符赋给数组中前面那些元素,其余的元素自动定为空字符(即'\0')。如:

char c[10]= {’c’,’ ’,’p’,’r’,’o’,’g’,’r’ ,’a’,’m’} ;

数组状态如下图所示。

c[0] c[1] c[2] c[3] c[4] c[5] c[6] c[7] c[8] c[9]

c

p

r

o

g

r

a

m

\0

如果提供的初值个数与预定的数组长度相同,在定义时可以省略数组长度,系统会自动根据初值个数确定数组长度。如:

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

数组c的长度自动定为10。用这种方式可以不必人工数字符的个数,尤其在赋初值的字符个数较多时,比较方便。

也可以定义和初始化一个二维字符数组,如:

char diamond[5][5]={{’ ’,’ ’,’*’},{’ ’,’*’,’ ’,’*’},{’*’,’ ’,’ ’,’ ’,’*’},{’ ’,’*’,’ ’,’*’},{’ ’,’ ’,’*’}};

用它代表一个钻石形的平面图形,见下图。

    *

  *    *

*        *

  *    *

    *

三、字符数组的引用

可以引用字符数组中的一个元素,得到一个字符。

例6输出一个字符串。

main()

{char c[10]={’I’,’ ’,’a’ ,’m’,’ ’,’a’,’ ’ ,’b’,’o’,’y’};

int i;

for (i=0;i<10;i++)

printf("%c",c[i]);

printf("\n");

运行结果: I am a boy

例输出一个钻石图形。

main()

{char diamond[][5]={{’ ’,’ ’,’*’},{’ ’,’*’,’ ’,’*’},{’*’,’ ’,’ ’,’ ’,’*’},{’ ’,’*’,’ ’,’*’},{’ ’,’ ’,’*’}};

int i,j;

for (i=0;i<5;i++)

{for(j=0;j<5;j++)

printf("%c",diamond[i][j]);

printf("\n");

}

}

运行结果为:

    *

  *    *

*        *

  *    *

    *

四、字符串和字符串结束标志

在C语言中,将字符串作为字符数组来处理。例6就是用一个一维的字符数组存放一个字符串"I am a boy"中的字符。这个字符串的实际长度与数组长度相等。有时,人们关心的是有效字符申的长度而不是字符数组的长度。例如,定义一个字符数组长度为100,而实际有效字符只有40个。为了测定字符串的实际长度,C语言规定了一个“字符串结束标志”,以字符’\0’代表。如果有一个字符串,其中第10个字符为’\0’,则此字符串的有效字符为9个。也就是说,在遇到字符\0时,表示字符串结束,由它前面的字符组成字符串。

系统对字符串常量也自动加一个’\0’作为结束符。例如”C Program”共有9个字符,但在内存中占10个字节,最后一字节’\0’是系统自动加上的。字符作为一维数组放在内存中。

有了结束标志’\0’后,字符数组的长度就显得不那么重要了。在程序中往往依靠检测’\0’的位置来判定字符串是否结束,而不是根据数组的长度来决定字符串长度。当然在定义字符数组时应估计实际字符串长度,保证数组长度始终大于字符串实际长度。如果在一个字符数组中先后存放多个不同长度的字符串,则应使数组长度大于最长的字符串的长度。

说明:’\0’代表ASCHI码为0的字符,从ASCII码表中可以查到,ASCII码为0的字符不是一个可以显示的字符,而是一个“空操作符”,即它什么也不干。用它来作为字符串结束标志不会产生附加的操作或增加有效字符,只起一个供辨别的标志。

我们以前曾用过以下的语句:

printf("How do you do? \n");

即输出一个字符串。在执行此语句时系统怎么知道应该输出到哪里为止呢?实际上,在内存中存放时,系统自动在最后一个字符’\n’的后面加了一个’\0’作为字符串结束标志,在执行printf函数时,每输出一个字符检查一次,看下一个字符是否’\0’。遇’\0’就停止输出。

对C语言处理字符串的方法有以上的了解后,我们再对字符数组初始化的方法补充一种方法,可以用字符串常量来使字符数组初始化。例如

char c[]={"I am happy"};

也可以省略花括弧,直接写成

char c[]="I am happy";

不是用单个字符作为初值,而是用一个字符串(注意字符串的两端是用双撇号而不是单撇号括起来的)作为初值。显然,这种方法直观、方便、符合人们的习惯。数组c的长度不是10,而是11,这点务请注意。因为字符串常量的最后由系统加上一个’\0’。因此,上面的初始化与下面的初始化等价。

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

而不与下面的等价;

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

前者的长度为11,后者的长度为10。如果有

char c[10]={“China”};

数组c的前5个元索为’C’,’h’,’i’,’n’,’a’第6个元素为’\0’,后4个元素为空字符,见图

C

h

i

n

a

\0

\0

\0

\0

\0

需要说明的是:字符数组并不要求它的最后一个字符为’\0’,甚至可以不包含’\0’。像以下这样写完全是合法的:

char c[5]={’C’,’h’,’i’,’n’,’a’);

是否需要加’\0’,完全根据需要决定。但是由于系统对字符串常量自动加一个’\0’。因此,人们为了使处理方法一致,便于测定字符串的实际长度,以及在程序中作相应的处理,在字符数组也常常人为地加上一个'\0'。如:

char c[6]= (’C’,’h’,’i’,’n’,’a’,' \0' } ;

五、字符数组的输入输出

字符数组的输人输出可以有两种方法:

(1)逐个字符输入输出。用格式符“%c”输人或输出一个字符,如例6。

(2)将整个字符串一次输入或输出。用“%s”格式符,意思是输出字符串(String)。例如:

char c[]={“China”};

printf(“%s”,c);

在内存中数组c的状态如图所示。输出时,遇结束符’\0’就停止输出。输出结果为:

China

C

h

i

n

a

\0

请注意:

(1)输出字符不包括结束符\0’。

(2)用“%s”格式符输出字符串时,printf函数中的输出项是字符数组名,而不是数组元素名。写成下面这样是不对的;

printf("%s",c[0]);

(3)如果数组长度大于字符串实际长度,也只输出到遇'\0'结束。如

char c[10]= {"China"} ;

printf("%s",c);

也只输出“China"5个字符,而不是出10个字,这就是用字符串结束标志的好处。

  1. 如果一个字符数组中包含一个以上'\0',遇第一时输结束。

可以用scanf函数输入一个字符申。例如

scanf("%s",c);

 scanf函数中的输人项c是字符数组名,它应该在先前已被定义。从键盘输人的字符串应短于已定文的字符数组的长度。例如,已定义

char c[6];

从键盘输人:

China

系统自动在后面加一个'\0'结束符。如果利用一个scanf函数输入多个字符串,则以空格分隔。例如:

char str1[5],str2[5],str3[5];

scanf(“%s%s%s”,str1,str2,str3);

输入数据: How are you?

输入后str1、str2、str3 数组状态。数组中未被赋值的元素的值自动置'\o'若改为

char str[13]:

scanf("%s".str);

如果输入以下12个字符

How are you?

实际上并不是把这12个字符加上'\0'送到数组str中,而只将空格前的字符“How”送到str中,由于把“How”作为一个字符串处理,因此在其后加'\0'。str数组状态见图

H

o

w

\0

\0

\0

\0

\0

\0

\0

\0

\0

需要注意:scanf函数中的输入项是字符数组名。输入项为字符数组名时,不要再加地址符&,因为在C语言中数组名代表该数组的起始地址。下面写法不对:

printf("%o",c);

可以输出数组c的起始地址2000。

前面介绍的输出字符串的方法:

printf("%s",c);

实际上是这样执行的:按字符数组名c找到其数组起始地址, 然后逐个输出其中的字符,直到遇到'\0'为止。

由于C语言用一维字符数组存放字符串,而且允许用数组名进行输入或输出一字符串,因此,可以把一维字符数组看作相当于其他语言(如BASIC)中的”字符串变量”。

六、字符串处理函数

在C的函数库中提供了一些用来处理字符串的函数,使用方便。几乎所有版本的C都提供这些函数。下面介绍几种常用的函数。

1.puts(字符数组)

其作用是:将一个字符串(以'\0'结束的字符序列)输出到终端。假如已定义str是一个字符数组名,且该数组已被初始化为"China"。则执行

puts(str);

其结果是在终端上输出China.由于可以用printf数输出字符串,因此puts函数用的不多。用puts函数输出的字符串中可以包含转义字符。例如:

char str[]-{"China\nBeijing"} ;

puts(str);输出: China Beijing

在输出时将字符串结束标志'\o'转换成'\n',即输出完字符串后换行。

2.gets(字符数组)

其作用是:从终端输人一个字符串到字符数组,并且得到一个函数值。该函数值是字符数组的起始地址。如执行下面的函数:

gets(str)

从键盘输入:Computer

将输入的字符串"Computer"送给字符数组str(请注意送给数组的共有9个字符,而不是8个字符),函数值为字符数组str的起始地址。一般利用gets函数的目的是向字符数组输入一个字符串,而不大关心其函数值。

注意:用puts和gets函数只能输入或输出一个字符串,不能写成

puts(str1,str2)或gets(strl,str2)

3.streat(字符数组1,字符数组2)

strcat 是STRing CATenate(字符串连接)的缩写。其作用是:连接两个字符数组中的字符串,把字符串2接到字符串1的后面,结果放在字符数组1,数调用后得到一个函数值-字符数组1的地址。例如:

char str1[30]={"People's Republic of ")

char str2[]={“China”}:

printf("%s",strcat(strl,str2));

输出:

People's Republic of China

说明:

(1)字符数组必须足够大,以便容纳接后的新字符串。本例中定义strl的长度为30,是足够大的,如果在定义时改用

str1[]=("People's Rebuplic of");就会出问题,因长度不够。

(2)连接前两个字符串的后面都有一个'\0',连接时将字符串1后面的'\0'取消,只在新串最后保留一个'\0'。

4.strcpy(字符数组1字符串2)

strcpy是STRing CoPY(字符串复制)的缩写。它是“字符串复制函数”。作用是将字符串2复制到字符数组1中去。例如:

char str1[10],str2[]=("China"};

strcpy(str1,str2);

执行后,strl的状态如图

C

h

i

n

a

\0

\0

\0

\0

\0

说明:

(1)字符数组1必须定义得足够大,以便容纳被复制的字符串。字符数组1的长度不应小于字符串2的长度。

(2)“字符数组1”必须写成数组名形式(如str1),“字符串2”可以是字符数组名,也可以是一个字符串常量。如

strcpy(strl,"China");作用与前相同。

  1. 复制时连同字符串后面的'\0'一起复制到字符数组1中。
  2. 不能用赋值语句将一个字符申常量或字符数组直接给一个字符数组。如下面两行都是不合法的: str1={"China"};

str1=str2;

而只能用strcpy函数处理。用赋值语句只能将一个字符赋给一个字符型变量或字符数组元素。如下面是合法的:

char a[5],c1,c2;

c1='A';c2='B’;’C’,’h’,’i’,’n’,’a’

a[0]='C';a[1]=’h’';a[2]=’i’;a[3]=’n’;a[4]=’a’;

(5)可以用strncpy函数将字符串2中前面n个字符复制到字符数组1中去。例如: strncpy(strl,str2,2);

作用是将str2中前面2个字符复制到 str1 中去,取代str1中前面的2个字符。

5.strcmp(字符串1,字符串2)

strcmp是STRing CoMPare(字符串比较)的缩写。作用是比较字符串1和字符串2。例如:

strcmp(str1,str2);

strcmp("China","Korea");

strcmp(str1,"Beijing");

字符串比较的规则与其他语言中的规则相同,即对两个字符串自左至右逐个字符相比(按ASCII码值大小比较),直到出现不同的字符或遇到'\0'为止。如全部字符相同,则认为相等;若出现不相同的字符,则以第一个不相同的字符的比较结果为准。例如:

"A"<"B","a">"A","computer">"compare","these">"that","36+54" >"! $&#","CHINA">"CANADA" ,"DOG"<"cat".

如果参加比较的两个字符串都由英文字母组成,则有一个简单的规律:在英文字典中位置在后面的为“大”。例如computer在字典中的位置在compare之后。但应注意小写字母比大写字母“大”,所以“DOG”<“cat”。

比较的结果由函数值带回。

(1)如果字符串1=字符串2,函数值为0。

(2)如果字符串1>字符串2,函数值为一正整数。

(3)如果字符串 1<字符串2,函数值为一负整数。

注意:对两个字符串比较,不能用以下形式:

if(str1==str2) printf("yes");

而只能用

If(strcmp(str1,str2)==0)printf("yes");

6. strlen(字符数组)

strlen是STRing LENght(字符串长度)的缩写。它是测试字符串长度的函数。函数的值为字符串中的实际长度,不包括\0'在内。如:

char str[10]={“China”};

printf("%d",strlen(str));

输出结果不是10,也不是6,而是5。也可以直接测试字符串常量的长度,如

strlen(“China”):

7.strlwr(字符串)

strlwr是STRing LoWeRcase(字符串小写)的缩写。函数的作用是将字符串中大写字母换成小写字母。

8. strupr(字符串)

strupr是STRing UPpeRcase(字符串大写)的缩写。函数的作用是将字符串中小写字母换成大写字母。

以上介绍了常用的8种字符串处理函数,应当再次强调:库函数并非C语言本身的组成部分,而是人们为使用方便而编写、提供大家使用的公共函数。每个系统提供的函数数量和函数名、函数功能都不尽相同,使用时要小心,必要时查一下库函数手册。当然,有一些基本的函数(包括函数名和函数功能),不同的系统所提供的是相同的,这就为程序的通用性提供了基础。

七、字符数组应用举例

例输入一行字符,统计其中有多少个单词,单词之间用空格分隔开。程序如下:

#include <stdio.h>

main()

{

char string[81];

Int i,num=0,word=0;

char c;

gets(string);

for(i=0;(c=string[i])!=\0'i++)

if(c==’ ’)word=0;

else if(word==0)

{word=1;

num++;

}

printf("There are %d  words in the line. \n",num);

运行情况如下: I am a boy.

There are 4 words in the line.

程序中变量i作为循环变量,num用来统计单词个数,word作为判别是否单词的标志,若word==0表示未出现单词,如出现单词word置成1。

解题的思路是这样的:单词的数目可以由空格出现的次数决定(连续的若干个空格作为出现一次空格;一行开头的空格不统计在内)。如果测出某一个字符为非空格,而它的前面的字符是空格,则表示“新的单词开始了”,此时使num(单词数)累加1。如果当前字符为非空格而其前面的字符也是非空格,则意味着仍然是原来那个单词的继续,num不应再累加1。前面一个字符是否空格可以从word的值看出来,若word等于0,则表示前一个字符是空格;如果word等于1,意味着前一个字符为非空格。

程序中for语句中的“循环条件”为(c=string[i])!=’\0’

它的作用是先将字符数组的某一元素(一个字符)赋给字符变量c。此时赋值表达式的值就是该字符,然后再判断它是否结束符。这个“循环条件”包含了一个赋值操作和一个关系运算。可以看到用for循环可以使程序简练。

如前所述,可以把str[0]、str[1]str[2]看作3个一维字符数组,它们各有20元素。可以把它们如同一维数组那样进行处理。可以用gets函数分别读入3个字符串。经过二次比较,就可得到值最大者,把它放在一维字符数组string中。

程序如下:

#include<stdio.h>

#include<string. h>

main()

{

char string[20];

char str[3] [20];

int i;

for (i=0;i<3;i++)

gets (str[i]);

if (strcmp(str[0],str[1])>0)

strcpy(string,str[0]);

else strcpy(string;str[1]);

if(strcmp(str[2],string)>0)

strcpy(string,str[2]);

printf("\nthe largest string is:\n%s\n",string);

}

运行结果如下; CHINA

HOLLAND

AMERICA

the largest string is :

HOLLAND

当然,这个也可以不采用二维数组,而设3个一维字符数组来处理。

  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光向日葵之沈阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值