因为字符串是由多个字符组成的序列,所以如果要存储字符串,可以先将其拆分为字符,然后将这些字符分别存储,即存储在字符数组中。 字符数组是存储字符的数组。 数组中的一个元素存储字符串的一个字符。
字符数组的定义 因为字符数组首先是一个数组,所以上面提到的所有数组内容都适用。 其次,它是一个存储字符的数组,即数组的类型是char。 例如:
char name[10];
表示定义了一个10字节的连续内存空间。
1)如果字符串的长度大于10,则存在语法错误。 这里需要注意的是,这里所说的“字符串的长度”包括最后一个'\0'。 也就是说,虽然系统会自动在字符串末尾添加'\0',但不会自动为'\0'开辟内存空间。 所以定义数组长度时一定要考虑'\0'。
2)如果字符串的长度小于数组的长度,则仅将字符串中的字符分配给数组中前面的元素,剩余的内存空间将被系统自动用\0'填充。
字符数组的初始化 字符数组的初始化与数组的初始化相同,可以在定义时初始化,也可以在定义后初始化。 我们来写一个程序来说明这个问题:
# includeint main(void) { char a[10]; a[0] = 'i'; a[1] = ' '; a[2] = 'l'; a[3] = 'o'; a[4] = 'v'; //空格字符的单引号内一定要敲空格 a[5] = 'e'; a[6] = ' '; a[7] = 'y'; a[8] = 'o'; a[9] = 'u'; //空格字符的单引号内一定要敲空格 a[10] = '\0'; char b[10]; b[0] = 'i'; b[1] = ' '; b[2] = 'm'; b[3] = 'i'; b[4] = 's'; //空格字符的单引号内一定要敲空格 b[5] = 's'; b[6] = ' '; b[7] = 'y'; b[8] = 'o'; b[9] = 'u'; //空格字符的单引号内一定要敲空格 char c[] = "i believe you"; char d[] = {'i',' ','l','i','k','e','y','o','u','\0'}; //空格字符的单引号内一定要敲空格 char e[] = {'H','W','r','d'}; //空格字符的单引号内一定要敲空格 char f[] = "上课睡觉觉,下课打闹闹,考试死翘翘"; char g[10] = ""; printf("a = %s\n",a); //输出字符串用%s,输出参数必须写数组名 printf("b = %s\n",b); printf("c = %s\n",c); printf("d = %s\n",d); printf("e = %s\n",e); printf("f = %s\n",f); printf("g = %s\n",g); return 0; }
输出是:
一个=我爱你
b = 我想你,我爱你
c=我你
d = 我喜欢你
e = Hello World娨像你一样
f = 上课睡觉、考试不及格
克=
首先要注意的是,这个程序只能在.cpp文件中运行,在.c文件中会出现很多错误。 因为我们之前说过,C89标准规定变量只能在程序开头定义,或者说变量定义前面不能有其他非声明或非定义语句。 .cpp 文件用于编写 C++ 程序。 C++完全向后兼容C,它对变量定义的位置没有特殊要求,只要在使用位置之前即可。
数组a先定义,然后初始化。 一方面,它与之前提到的数值数组相同。 先定义后初始化必须一一赋值,不能整体赋值。 另一方面,它与前面提到的数值数组不同。 对于字符串,也可以先定义后初始化。 整体赋值,但是需要调用一个函数,这个后面会讲到。
总之,上面程序中逐一初始化数组a的方法是非常麻烦的。 而且这样写的时候需要注意:前面说过,系统会自动在字符串末尾添加结束标识符'\0',但是在逐一赋值时,系统不会自动添加结束标识符'\0'添加'\0'并且必须手动添加。 如果我们忘记添加它,虽然没有语法错误,但程序也达不到我们想要的功能。 数组b就是这样一个例子。
另外,空格字符必须在单引号内“键入”一个空格,而不能“键入”任何内容。 没有任何内容的“打字”是语法错误。 你不能“输入”太多,因为单引号中只能输入一个字符,而“输入”多个空格就意味着多个字符。
数组 b 是在末尾不手动添加 '\0' 的示例。 程序希望数组b输出“我想你”,但输出结果却是“我想你或者我爱你”。 原因是系统没有在末尾加'\0'。
虽然程序中对数组b的长度进行了限制,即长度为10,但由于内存单元是连续的,对于字符串来说,只要系统不遇到'\0',就会认为该字符串是还没有结束。 它将继续搜索,直到遇到“\0”。 所有已搜索到的内存位置都将被输出,从而超出定义的 10 个字节。
数组 c 在定义时被初始化。 定义时初始化可以整体赋值。 全局分配有一个明显的优势——方便。 定义时初始化时不需要指定数组的长度,但先定义再初始化时必须指定数组的长度,如数组a、数组b。 不必指定数组长度的一个好处是:不需要手动确定需要多少字节的内存空间,系统会根据初始化的内容自动分配准确数量的内存空间。 而对于数组c的写法,系统会自动在末尾添加结束标识符'\0',无需手动添加。
数组d在定义时也被初始化,但它既属于整体赋值,又属于逐一赋值。 之所以说是全局赋值,是因为不需要写 d[0], d[1]... ,之所以说是一对一赋值,是因为它将整个句子逐个分成字符一。 数组c的写法比较方便,而对于数组d的写法,系统不会自动在末尾添加结束标识符'\0',必须手动添加。 如果忘记添加,会出现与数组b相同的错误。 这可以从数组 e 的输出看出。
数组f存储的是汉字。 汉字不能像数组a、数组d那样一一赋值。 因为一个汉字占2个字节,如果单独赋值,由于单引号中只能放一个字符,也就是一个字节,所以放一个占2个字节的汉字当然会出错。 因此,如果使用字符数组来存储汉字,必须将值整体赋值,即要么在定义时初始化,要么调用函数。
数组g被初始化为一对双引号,这意味着字符数组中的10个元素的内容都是'\0'。 下面编写程序进行验证:
# includeint main(void) { char str[3] = ""; str[2] = 'a'; printf("str = %s\n",str); return 0; }
输出是:
str =
程序定义了一个长度为3的字符数组,然后将值'a'赋给第三个元素,然后输出整个字符数组。 但输出结果却什么都没有。 原因是直接初始化为一对双引号。 此时字符数组中的所有元素都是'\0'。 所以虽然第三个元素是'a',但是无法输出,因为第一个元素是'\0',而'\0'是字符串的结束标识符。
需要注意的是,使用这种初始化方法时,必须指定数组的长度,否则默认数组长度为1。
综上所述,字符数组和上面提到的数值数组有很大的区别。 即字符数组可以通过“%s”一次性全部输出,而数值数组只能逐个输出每个元素。