字符串与指针

来源:互联网 发布:硬盘分区不丢失数据 编辑:程序博客网 时间:2024/05/16 15:26

字符串与指针

1、  字符串的表示形式

C语言中,我们可以用两种方式访问字符串

(1)       用字符数组存放一个字符串,然后输出该字符串。

main(){

   char string[]="I love China!";

   printf("%s\n", string);

}

(2)       用字符指针指向一个字符串。可以不定义字符数组,而定义一个字符指针。用字符指针指向字符串中的字符。

main(){

   char *string="I love China!";

   printf("%s\n", string);

}

    在这里,我们没有定义字符数组,而是在程序中定义了一个字符指针变量string,用字符串常量"I love China!",对它进行初始化。C语言对字符串常量是按字符数组处理的,在内存中开辟了一个字符数组用来才存放该字符串常量。对字符指针变量初始化,实际上是把字符串第1个元素的地址(即存放字符串的字符数组的首元素地址)赋给string有人认为string是一个字符串变量,以为在定义时把"I love China!"这几个字符赋给该字符串变量,这是不对的!!

      实际上,char *string="I love China!"; 等价于:

Char  *string

String = “I love China!”;

    可以看到,string被定义为一个指针变量,指向字符型数据,请注意它只是指向了一个字符变量或其他字符类型数据,不能同时指向多个字符数据,更不是把“I love China!”这些字符存放到string中(指针变量只能存放地址),也不是把字符串赋给*string只是把“I love China!”的第一个字符的地址赋给指针变量string

在输出时,要用:printf(“%s\n”, string);,其中“%s”是输出字符串时所用的格式符,在输出项中给出字符指针变量名,则系统先输出它所指向的一个字符数据,然后自动是string1,使之指向下一个字符,然后再输出一个字符……如此知道遇到字符串结束标志“\0”为止。

注意:可以通过字符数组名或者字符指针变量输出一个字符串。而对一个数值型数组,是不能企图用数组名输出它的全部元素的。例如:

Int i[10];

………

Printf”%d\n”, i);

是不行的,只能逐个输出!!!!!!显然%s可以对一个字符串进行整体的输入和输出。

 

2、  字符串指针作函数参数

将一个字符串从一个函数传递到另外一个函数,可以用地址传递的方法,即用字符数组名作参数或用指向字符的指针变量做参数。在被调用的函数中可以改变字符串内容,在主调函数中可以得到改变了的字符串。

 

注意:对于实参和形参的用法,十分灵活,我们可以慢慢去熟悉它,这里列出一个表格便于大家记忆:

实参

形参

数组名

数组名

数组名

字符指针变量

字符指针变量

字符指针变量

字符指针变量

数组名

 


字符'/0'和'0'的区别

字符’0’对应的ASCII码为十六进制30;而’/0’即为ASCII码中的0,其对应字符空字符NUL。

     char c = '/0';çèchar c = 0 // NUL

     char c = '0';çèchar c = 48;

最典型如memset函数:void *memset( void *buffer, int ch, size_t count );

将一段长为count字节的内存块初始化为ASCII码值0,字符为NUL:

memset(pBuffer, '/0', sizeof(pBuffer) );çèmemset(pBuffer, 0, sizeof(pBuffer) );

 

字符串

字符串常量是双引号括起的任意字符序列。

例如:"Hello World","Fantasy","Please enter your full name:",……

C语言没有专门定义字符串数据类型(如其他语言中的string) ,所谓的字符串,只是对字符数组的一种特殊应用而已,它用以'/0'结尾的字符数组来表示一个逻辑意义上的字符串。

在字符串常量中,显然不能直接写双引号,因为这将被认为是字符串的结束。转义序列在字符串常量中要包含双引号,需要用“/"”表示。如:"Hello /"Accp/""

与字符数组不同的是:在存完字符串常量的所有字符之后,还要另存一个空字符'/0'作为结束的标志,空字符是ASCII码值为0的字符,C语言中用'/0'标识字符串的结束,所以也称为结束符。如果在程序里写了字符串:char hello[]="HELLO"或{"HELLO"};虽然只有5个字符,在内存中却需要占用6个字节存储,其中'/0'表示空字符。存储情况如:

H

E

L

L

O

/0

5005

5006

5007   

5008

5009

500A

而字符数组char hello[]={'H','E','L','L','O'};的长度和大小则为5.

根据字符串存储形式的规定,只要在数组里顺序存入所需字符,随后存一个空字符,这个字符数组里的数据就有了字符串的表现形式,这个数组也就可以当作字符串使用了。分析char str[]="abc";因为定义的是一个字符数组,所以就相当于定义了一些空间来存放"abc",而又因为字符数组就是把字符一个一个地存放的,所以编译器把这个语句解析为char str[3] = {'a','b','c'};根据上面的总结,所以charstr[]="abc";的最终结果是char str[4] = {'a','b','c','/0'};即char str[] = {'a','b','c','/0'}<==> char str[]="abc"

值得注意的是只有在程序中对字符串进行处理时,才考虑字符串结束标志的问题。考虑字符数组char a[4]={'B','O','Y','/0'};a数组中存放的是字符串“BOY”。如果执行语句a[1]= '/0';后,a数组的内容为'B','/0','Y','/0'此时系统认为a数组中存放了一个字符串“B”,printf("a=%s/n",a);输出的结果是a=B; printf("length a=%d/n",strlen(a))输出的结果是length a=1,而printf("sizeof a=%d/n",sizeof(a));输出结果为4.不要认为数组中只有'B''/0'了,只不过按系统对字符串的处理方式来看就是这样的。

char s3[10]="HELLO";//s3是编译期大小已经固定的数组

int a=strlen(s3); //a=5;//strlen()在运行起确定

int b=sizeof(s3); //b=10;//sizeof()在编译期确定

 

sizeof(s)

strlen(s)

char *s="HELLO";

4

char s[]="HELLO";

6

5

char s[10]="HELLO";

10

5

注意printf("hello is %s/n",hello);和cout<<hello;以及头文件<string.h>中的库函数只能操作以'/0'结尾的字符串,故对char hello[]={'H','E','L','L','O'};操作无效。

以下为四种hello字符串的定义:

char hello1[]="HELLO";

char hello2[]={"HELLO"}; //等同于hello1

char hello3[]={'H','E','L','L','O','/0'};//等价于hello1

char *hello4="HELLO";//区别:hello1是字符数组,hello4是字符指针。

用strlen函数测试hello1, hello2, hello3, hello4的结果均为5,因为不计末尾结束符’/0’。常用hello1或hello4来定义字符串。 

 

字符串与指针

C语言中许多字符串的操作都由指向字符数组的指针及指针的运算来实现的。因为对字符串来说一般都是严格顺序存取,使用指针可以打破这种存取方式,使字符串的处理更加灵活。

以下代码利用指针简洁的实现了字符串拷贝函数:

    void strcpy(s,t)//copy t to s

        char *s,*t;

    {

        while(*s++=*t++);

}

解析:*s++=*t++,先赋值*s=*t,然后指针后移t++,s++,当遇到*t= '/0'时,则拷贝操作完成。

char *pChar;    

char *text = "hello";

pChar = new char[strlen(text) + 1]; // 注意这里考虑终止字符!

cout << strcpy(pChartext) << endl// 不能用pChar = text;

cout << (strcmp(pChartext) == 0) << endl// 不能用pChar == text;

 

字符串常量

当一个字符串常量出现于表达式中时,它的值是个指针常量。编译器把这些指定字符的一份拷贝存储在内存的某个位置,并存储一个指向第一个字符的指针

    "xyz"+1;//这个表达式计算指针值加上的值,返回一个指针,指向字符串中的第二个字符'y'

    *"xyz";//返回第一个字符'x'

    "xyz"[2];//返回第三个字符'z'

*("xyz"+4);//偏移量超过了这个字符串的范围,返回一个不可预测的字符

那什么使用会用到上述表达式呢?我们考虑把二进制转换为字符并把它们打印出来。

     remainder = value % 16;//value对求余保存到remainder

     if(remainder < 10)//0~9

         putchar(remainder + '0');

     else////10~15

         putchar(remainder - 10 + 'A');

下面的代码用一种不同的方法解决这个问题:

 putchar("0123456789ABCDEF"[value % 16]);

0 0