和java不同,在C语言中没有string类型,需要用char型数组来定义。(在java中的string底层也是适用的char型数组)
char string[10]; // 定义一维数组
char string[2][5]; // 定义二维数组
C语言规定,字符数组只有在定义时才能将整个字符串一次性的赋值给它,一旦定义后就只能一个一个的添加!正确的赋值如下:
string[0] = 'c';
string[1] = ' ';
string[2] = 'p';
string[3] = 'r';
string[4] = 'o';
string[5] = 'g';
string[6] = 'r';
string[7] = 'a';
string[8] = 'm';
错误的方式(编译不通过):
string = "c program";
string = {'c',' ','p','r','o','g','r','a','m'};
char string[10]={'c',' ','p','r','o','g','r','a','m'}; // 直接给部分数组赋值
printf("string3:%s",string3); // 打印结果:string3:c program
// 省去长度创建
char string[] = {'c',' ','p','r','o','g','r','a','m'};
printf("string4:%s",string4); // 打印结果:string4:c programc program 后续因为寻找'\0'乱码
在这里我们需要注意一个问题,为什么第二种省去长度创建的字符串打印出来会出现乱码呢?
这是因为在 C语言在处理字符串时,以'/0'为字符串的结束标志。会从前往后逐个扫描字符,一旦遇到'\0'就认为到达了字符串的末尾,就结束处理。没有'\0'就意味着永远也到达不了字符串的结尾。
而在没有指定长度的情况下,逐个字符地给数组赋值 并不会自动添加'\0'。因为如果在不指定长度的情况下还通过逐个字符赋值,编译器会给该字符串的长度定义为输入字符的长度,这样就没有多余的空间存放0。那我们如果自己手动的在末尾加上'\0'就能变成想要的字符串了!由于字符'0'的ASKII码为0,所以也可以直接加上0。
当我们用strlen去取字符串的长度时,这个结束字符并不会算进去!但末尾如果没有'\0',那么长度应该是一个广义上的随机值(具体长度取决于什么时候找到那个0)。如果是用sizeof去计算,则会算上'\0'。
char string1[] = {'a','b','c'};
// string[0]=97'a' string[1]=98'b' string[2]=99'c'
char string2[] = {'a','b','c',0};
// string[0]=97'a' string[1]=98'b' string[2]=99'c' string[3]=0'\0'
// string9:abcjhs,string10:abc
printf("string1:%s,string2:%s\n",string1,string2);
// string1的长度:6, string2的长度:3
printf("string1的长度:%lu,string2的长度:%lu",strlen(string9), strlen(string10));
这么定义好像太麻烦了,那我们一般是在字符串初始化的时候就直接使用字符串的方式给它赋值,如下:
C语言规定可以直接将字符串直接赋值给字符数组
char string[30] = {"c program"};
char string[30] = "c program"; // 省略大括号
char string = "c program"; // 省略长度
最重要的是,由" "包围的字符串会自动在末尾添加'\0'。这样我们就不必担心其他问题。证明如下:当我们用debug运行时可以看到:
char string8[] = "abc";
// string[0]=97'a'
// string[1]=98'b'
// string[2]=99'c'
// string[3]=0'\0'
如果我们给字符串预先指定了长度,就需要为'\0'留个位置;字符数组的长度至少要比字符串的长度大 1(如下为正确方式)。如果指定的长度不够,这种方式也是会引起乱码的!
char string[7] = "abc123";
char string[7] = {'a','b','c','1','2','3'};
一旦指定的长度不够,或者是不指定长度通过挨个赋值字符的方式都会引起乱码!而最保险的方式就是不指定长度的情况下,是用双引号的方式给字符串赋值!