一、字符数组定义
用来存放字符的数组称为字符数组,例如:
char a[10]; //定义一维字符数组 ,数组里面元素的值是未知的
char b[10]={'c', 'p', 'r', 'o'};//给部分一维字符数组赋值,未赋值数组系统,默认为'\0'
char c[5] = {'h', 'e', 'l', 'l', 'o'};
字符数组实际上是一系列字符的集合,也就是字符串(String)。在C语言中,没有专门的字符串变量,没有string类型,通常就用一个字符数组来存放一个字符串。
C语言规定,可以将字符串直接赋值给字符数组,例如:
char a[20] = {"C progarm"};//给一维字符数组赋值字符串
char d[10] = "hello"; //给一维字符数组赋值字符串
数组第 0 个元素为'C',第 1 个元素为' ',第 2 个元素为'p',后面的元素以此类推。
这里需要留意,字符数组只有在定义时才能将整个字符串一次性地赋值给它,一旦定义完了,就只能一个字符一个字符地赋值了。请看下面的例子:
char str[7];
str = "adc123"; //这是错误的
//正确
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
str[3] = '1';
str[4] = '2';
str[5] = '3';
二、字符串结束标志
字符串是一系列连续的字符的组合,要想在内存中定位一个字符串,除了要知道它的开头,还要知道它的结尾。找到字符串的开头很容易,知道它的名字(字符数组名或者字符串名)就可以;然而,如何找到字符串的结尾呢?C语言的解决方案有点奇妙,或者说有点奇葩。
在C语言中,字符串总是以'\0'作为结尾,所以'\0'也被称为字符串结束标志,或者字符串结束符。
'\0'是 ASCII 码表中的第 0 个字符,英文称为 NUL,中文称为“空字符”。该字符既不能显示,也没有控制功能,输出该字符不会有任何效果,它在C语言中唯一的作用就是作为字符串结束标志。
C语言在处理字符串时,会从前往后逐个扫描字符,一旦遇到'\0'就认为到达了字符串的末尾,就结束处理。'\0'至关重要,没有'\0'就意味着永远也到达不了字符串的结尾。
char str[7] = "adc123";
由" "包围的字符串会自动在末尾添加'\0'。例如,"abc123"从表面看起来只包含了 6 个字符,其实不然,C语言会在最后隐式地添加一个'\0',这个过程是在后台默默地进行的,所以我们感受不到。
下面的代码演示了"C program"在内存中的存储情形:
#include <stdio.h>
int main(void)
{
int i;
char str[15] = "C program"; //用双引号括起来字符,就是字符"C" 'C'
for(i=0; i<15; i++)
{
printf("%d ", str[i]);
}
printf("\n");
return 0;
}
输出:
输出
C ' ' p r o g r a m '\0'
67 32 112 114 111 103 114 97 109 0 0 0 0 0 0
需要注意的是,逐个字符地给数组赋值并不会自动添加'\0',例如:
char str[] = {'a', 'b', 'c'}
数组 str 的长度为 3,而不是 4,因为最后没有'\0'。
当用字符数组存储字符串时,要特别注意'\0',要为'\0'留个位置;这意味着,字符数组的长度至少要比字符串的长度大 1。
三、字符串长度
所谓字符串长度,就是字符串包含了多少个字符(不包括最后的结束符'\0')。例如"abc"的长度是 3,而不是 4。
在C语言中,我们使用string.h头文件中的 strlen() 函数来求字符串的长度,它的用法为:
length strlen(strname);
strname 是字符串的名字,或者字符数组的名字;length 是使用 strlen() 后得到的字符串长度,是一个整数。
例子:
#include <stdio.h>
#include <string.h> //这个头文件包含strlen函数声明
int main(void)
{
int len;
char str[30] = "www.baidu.com";
len = strlen(str); //这个是系统提供的函数,要用到头文件 string.h
printf("len:%d\n", len);
return 0;
}
运行结果:
len:13
四、数组长度
数组长度是指数组所有内存的大小,按字节来计算,通过C语言关键字sizeof
#include <stdio.h>
#include <string.h>
int main(void)
{
int len;
int arr[4] = {1, 2, 3, 4};
char str[30] = "www.baidu.com";
printf("数组arr所占空间大小:%d\n", sizeof(arr));
printf("数组str所占空间大小:%d\n", sizeof(str));
return 0;
}
输出:
数组arr所占空间大小:16
数组str所占空间大小:30
记住:数组长度公式: 元素个数*数据类型所占空间大小
五、字符串的输入和输出
在C语言中,有两个函数可以让用户从键盘上输入字符串,它们分别是:
- scanf():通过格式控制符%s输入字符串。除了字符串,scanf() 还能输入其他类型的数据。
- gets():直接输入字符串,并且只能输入字符串。
但是,scanf() 和 gets() 是有区别的:
- scanf() 读取字符串时以空格为分隔,遇到空格就认为当前字符串结束了,所以无法读取含有空格的字符串。
- gets() 认为空格也是字符串的一部分,只有遇到回车键时才认为字符串输入结束,所以,不管输入了多少个空格,只要不按下回车键,对 gets() 来说就是一个完整的字符串。换句话说,gets() 用来读取一整行字符串。
在C语言中,有两个函数可以在控制台(显示器)上输出字符串,它们分别是:
- puts():输出字符串并自动换行,该函数只能输出字符串。
- printf():通过格式控制符%s输出字符串,不能自动换行。除了字符串,printf() 还能输出其他类型的数据。
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[30] = {0};
char str2[30] = {0};
char str3[30] = {0};
printf("gets请输入字符串:");
gets(str1);
printf("scanf请输入字符串:");
scanf("%s", str2); //数组名字就是地址
scanf("%s", str3);
printf("str1:%s\n", str1);
printf("str2:%s\n", str2);
puts(str3);
return 0;
}
结果:
gets请输入字符串:C Program
scanf请输入字符串:PHP JAVA C
str1:C Program
str2:PHP
str3:JAVA
第一次输入的字符串被 gets() 全部读取,并存入 str1 中。第二次输入的字符串,前半部分被第一个 scanf() 读取并存入 str2 中,后半部分被第二个 scanf() 读取并存入 str3 中。
注意,scanf() 在读取数据时需要的是数据的地址,这一点是恒定不变的,所以对于 int、char、float 等类型的变量都要在前边添加&以获取它们的地址。但是在本段代码中,我们只给出了字符串的名字,却没有在前边添加&,这是为什么呢?因为字符串名字或者数组名字在使用的过程中一般都会转换为地址,所以再添加&就是多此一举,甚至会导致错误了。
就目前笔者写到的知识而言,int、char、float 等类型的变量用于 scanf() 时都要在前面添加&,而数组或者字符串用于 scanf() 时不用添加&,它们本身就会转换为地址。