C语言中关于字符串的使用,以及字符串的存储方式
由于C语言是最基础的语言,C语言中没有数据类型能够存储字符串,char数据类型仅仅能够存储一个字符的数据,所以对于C语言中字符串的使用,有两种方法
1.定义指针,给其一个指向,完成对字符串的引用。这里需要注意野指针的存在,要给指针一个指向,或者让其指向NULL,指针需要配合字符数组一起使用。或者,运用动态申请内存的方式。
2.定义字符数组,完成对字符串的引用。
以对字符串比较函数为例。
字符串的使用
首先第一种方式。
#include<stdio.h>
#include<string.h>
int main(){
char a1[100],b1[100],c1[100];
//定义一个指针,又定义一个字符数组,此时字符串的存储,在字符数组中本质还是按照字符进行存储,所以字符数组长度要够大,能存下字符串
char *a = a1;
char *b = b1;
char *c = c1;
printf("请输入a1:");
scanf("%s",a1);//因为a1本身就代表数组的首地址,所以无须加&
printf("\n请输入b1:");
scanf("%s",b1);
printf("\n请输入c1:");
scanf("%s",c1);
printf("%d,%d,%d",strcmp(a,"23456"),strcmp(b,"Ab1"),strcmp(c,"Mary"));
return 0;
}
因为scanf传得必须是指针,也就是地址。
比如int a;需要&a;传入a的地址。但是如果是数组,由于数组本身表示的是数组首元素的地址,所以不需要再添加&
如:
char a[10];
scanf("%s",a);
此时传入的a就是本身就是一个地址,是数组首地址。a = &a[0];
当然,如果添加了&,原则上也不会出错,也能通过编译
第二种方式,定义字符数组
#include<stdio.h>
#include<string.h>
int main(){
char a[100];
char b[100];
char c[100];
printf("请输入a:");
scanf("%s",a);
printf("\n请输入b:");
scanf("%s",b);
printf("\n请输入c:");
scanf("%s",c);
printf("比较结果:%d,%d,%d",strcmp(a,"23456"),strcmp(b,"Ab1"),strcmp(c,"Mary"));
return 0;
}
**
对于这里,需要明白字符在字符数组的存储!
**
存储一:单个字符的存储
char a[10];
for(int i = 0;i<10;i++)
scanf("%c",a[i]);//输入qwert12345
//此时存储的字符为 a[0]='q';a[1]='w';a[2]='e';...a[8]='4';a[9]='5';
对于单个字符的存储,如上述,它只是一个普通的存放十个元素的数组,系统不会为其末尾自动添加’\0’,它只是按照你的输入,将你输入的字符存放至指定位置的数组空间,由于循环进行十次,所以你还必然要输入十个元素
可以等效为:
char a[10]={'q','w','e','r','t','1','2','3','4','5'};
//这也只是一个普通的存放十个元素的数组,不会为其末尾自动添加'\0',访问最大的下标是a[9];
存储二:字符串在字符数组的存储方式:
char a[20];
scanf("%s",a);//输入qwert12345
//此时存储的字符还是按照 a[0]='q';a[1]='w';a[2]='e';...a[8]='4';a[9]='5';进行存储,但是需要注意,由于是用字符串进行存储,也就导致了数组长度需要比字符串长度至少多出一位存储空间,字符串末尾系统会自动为其添加'\0'
*当以如此方法存储时:
- char a[]=“qwert12345”;
或给字符串加上大括号: - char a[]={“qwert12345”};
上述两种系统会自动在字符串的末尾加上字符串结束符,即 ‘\0’, (只要是双引号引起的字符串,系统会自动在字符串的末尾加上字符串结束符)
C语言中串的存储看作是一种特殊的一维数组来处理,所以为其添加结束符’\0’ - 当用static char a[10]={‘1’,‘2’,‘3’,‘4’,‘5’};
这种方法定义时,系统会自动从未初始化的元素开始,将之后的元素赋为\0,如上面的数组a中的元素实际上是:‘1’,‘2’,‘3’,‘4’,‘5’,’\0’,’\0’,’\0’,’\0’,’\0’
这里添加的’\0’只是对数组元素的初始化,和上面系统为其字符串结束添加的’\0’标志不同 - char a[10]={‘1’,‘2’,‘3’,‘4’,‘5’};
a[0] = ‘1’;a[1]=‘2’;…a[4] = ‘5’;由于不是静态数组,a[6]-a[9]的值不确定,系统也不会为其初始化添加’\0’。 - 当char a[10]={‘q’,‘w’,‘e’,‘r’,‘t’,‘1’,‘2’,‘3’,‘4’,‘5’};进行存储,系统不会为其自动添加结束符’\0’,只是作为单个字符,单个元素,存进字符数组中相应单元中。*
对于上述直接输入一条串,C语言的存储也是每个数组元素存储一个字符,C语言不具有存储整条串的能力,不可以将"qwert12345"整条串存入数组一个单元内。
用C++进行验证如下:
对于此类情况:
char a[1];
a = “qwert12345”;
是错误的,“qwert12345"是一个字符串常量,而字符串常量代表的是地址值,数组名也是地址常量 ,这样的本质是将地址赋给了地址;更者,由于字符数组长度为1,只有一个存储单元,即使改成
char a[1];
scanf(”%s",a);//输入qwert12345
也是错误的,同上述字符串结束系统自动添加’\0’问题,以及字符串的存储是以每个字符进行存储的,这样的做的结果是导致数组溢出
可以如下:
char *a = “qwert12345”;
这样是将字符串常量的地址赋给指针,即让指针指向该字符串常量。由于是它一个串,所以系统会为此串的末尾加上字符串结束符,即 ‘\0’,
也可以如下:
char a[20];
char *a1 = a;
scanf("%s",a1); //输入 qwert12345
这样是定义一个字符数组,又定义一个指针,让指针指向字符数组首地址,每个字符数组其中存放单个字符,输入一条串,串的第一个字符存入数组a1的首地址的位置,串的第二个字符,存入数组下一个地址…还是按照a[0]=‘q’;a[1]=‘w’;a[2]=‘e’;…a[8]=‘4’;a[9]=‘5’;进行存储,末尾添加结束符’0’