目录
在前面的学习中就会发现,仅仅能用一个字符表示的事物少之又少,对于地名、人名等都需要多个字符来完成。
字符串就是字符序列,下面我们来学习字符串和字符串字面量的基本知识。
字符串字面量
想“ABC”那样带双引号的一系列字符称为字符串字面量(string literal)。
在字符串字面量的末尾会被加上一个叫做null字符的值为0的字符,用八进制转义字符表示null字符就是‘\0’,用整数来表示就是0.
由三个字符组成的字符串字面量“ABC”实际上是占用了4个字符的内存空间,而双引号中没有任何字符的字符串字面量“ ”表示的就是null字符,如下图所示:
字符串字面量的长度
表示字符串字面量的长度,即所占有的内存空间的程序如下:
#include<stdio.h>
int main()
{
printf("sizeof(\"123\" = %u\n ", (unsigned)sizeof("123")) ;
printf("sizeof(\"AB\\tC\" = %u\n ", (unsigned)sizeof("AB\tC")) ;
printf("sizeof(\"abc\\0def\" = %u\n ", (unsigned)sizeof("abc\\0def")) ;
return 0;
}
下面我们来看它们在内存中的存储形式:
由运行结果可知,对于字符串字面量,运行环境会在末尾自动加上一个null字符,另外字符串字面量“AB\tC”中的“\t”表面上是两个字符,实际上是表示水平制表的转义字符,因此算作一个字符。
下面我们来总结下字符串字面量的性质:
◆具有静态生命周期
void func()
{
puts("abc");
puts("abc");
}
在上面的代码函数的功能是显示两次“abc”,调用该函数时就必须把字符串字面量传入puts函数,因此字符串字面量“abc”就必须“活在”程序的开始到结束的整个生命周期。
所以字符串字面量自然被赋予了静态生命周期。
◆对于同一个字符串字面量的处理方式依赖于编译器
func函数中有两个拼写完全相同的的字符串字面量“abc”,让我们来看下它们的储存方式:
如果将它们视为相同,并共用一个字符串字面量,这样就只需要5个空间即可,这样能减少所需要内存空间,如果将其视为不同,则需要10个字符的内存空间。
字符串
字符串字面量类似于整数的2、浮点数的3.14等常量,数值型数据可以通过变量的数据类型进行混合运算,而表示字符序列的字符串(string)也可以以对象的形式保存并灵活处理。
字符串最适合放在char数组中存储
例如,要表示字符串“abc”,数组元素必须按下列顺序依次保存:
‘a’、‘b’、‘c’、‘\0’
“abc" | a | b | c | \0 |
数组下标 | 0 | 1 | 2 | 3 |
末尾的null字符‘\0’是字符串结束的标志。
注意:字符串字面量“abc”是字符串,而字符串字面量“abc\0cd”却不是字符串。
以字符数组的形式保存并显示字符串“abc”的程序如下:
#include<stdio.h>
int main()
{
char str[4];
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
str[3] = '\0';
printf("字符串str为\"%s\".\n", str);
return 0;
}
通过字符赋值给char[4]型的数组str的各元素,生成字符串“abc”,printf函数中表示字符串转换说明为%s(s表示的是字符串string的缩写),实参传递的是数组名。
字符数组的初始化赋值
为保存字符串而将每个字符逐一赋予数组的各个元素并不是一件轻松的事情,所以我们可以进行如下声明:
char str[4] = {'a', 'b', 'c', '\0'};
这样不仅简洁,而且也能确保数组的初始化,且在形式上与int型、double型等初始化一致,另外还可以简化为以下形式:
char str[4] = "abc";
但是除了初始化的时候,我们不能将数组的初始值或字符串直接赋予变量,错误形式如下:
char s[4];
s = {'a', 'b', 'c', '\0'};
s = "abc";
空字符串
一个字符也没有的字符串,称为空字符串(null string),因为即使没有字符也需要表示结束的null字符,所以在内存空间上只有一个null字符,如下为声明空字符串的数组的声明示例:
char ns[] = " ";
//或者
char ns[] = {'\0'};
字符串的读取
下面我们来学习从键盘输入字符串的方法,下面是显示输入人名的程序:
#include<stdio.h>
int main()
{
char name[50];
printf("请输入你的名字:");
scanf("%s", name);//这时scanf函数中的数组名前不能加上&
printf("您好,%s先生/女士!!\n", name);
return 0;
}
我们实现无法知道需要输入多少个字符,因此数组元素必须要容纳足够多的字符。
为了从标准输入读取字符串,需要把scanf函数的转换说明设为%s,还必须传入数组name,但是name前面不带&。
在scanf函数读取字符串存储数组中,会在末尾加上null字符,形式如下:
数组元素 | M | i | k | e | \0 |
数组下标 | 0 | 1 | 2 | 3 | 4 |