所谓的字符串,就是一连串的字符。在c语言中,并没有单独的字符串类型,字符串是使用以’\0’结尾的字符数组表示的。
字符串就是’\0’结尾的字符数组
例如字符串”Hello”,在内存中是这样表示的
因此,要用一个char数组存放字符串hello,就必须分配5+1个空间,多余的一个用来存放空字符’\0’。
‘\0’ 、 ‘0’ 和0
‘\0’是ASCII表中的0号字符,‘\0’的值就是数字0,只不过使用’\0’说明用于字符串结尾标记,提高可读性。
‘0’是字符0,在ASCII表中是十进制48 ,所以’0’的值是48 。
用字符指针表示字符串
由于字符串使用’\0’作为结束标志,我们只需要知道最开始的第一个字符串的位置,就可以顺着位置一直找到’\0’为止。很多处理字符串的函数,都是使用指向 字符串中第一个字符的指针来表示字符串。
下面的例子充分说明了这一点。
双引号
双引号表示的字符串的值是一个地址
双引号可以表示字符串,但是双引号并不是字符串的一部分,只是告诉编译器这是个字符串。编译器会给这个字符串(包括结束的’\0’)分配一个内存。例如:
char *p = “Hello”;
“Hello”使编译器在文字常量区开辟一段内存,而”Hello”的值就是这段内存的起始地址
可以使用printf(“%p\n”, “Hello”);查看字符串Hello所在的内存
因此执行后,p指向’H’ 。
p[0]就是字符’H’
p[1]就是字符’e’
既然”Hello”的值就是地址,那么”Hello”完全可以当做p用
“Hello”[0]就是字符’H’
“Hello”[1]就是字符’e’
双引号表示的字符串不可修改
注意:双引号表示的字符串存储在常量区,字符串的内容不允许被修改。因此,p[0] = ‘R’是错误的。
‘A’和”A”的区别
‘A’是一个字符,它的值就是字符A的编码,ASCII中是数字65
“A”代表了一个字符串常量,”A”的值是一个地址,这个地址上存放了字符’A’和表示结尾的空字符’\0’ 。
字符数组
可以使用字符数组存放字符串。要注意数组空间足够放下字符串和结尾的’\0′ 。
初始化语句和赋值语句
只有初始化的时候可以直接使用””来初始化。
char m[10] = “Hello”;
但是赋值的时候不能使用””
char m[10];
m = “Hello”
是错误的。因为一旦定义了char m[10],m的值就是固定的一个内存地址,而”Hello”的值是一个地址,显然数组名不能修改为”Hello”的地址。
char m[10] = “Hello”;是合法的,因为这是初始化语句,不是赋值语句。可以认为就是这样规定的,这句话执行之后,m数组的元素如下:
常用的字符串库函数
C语言标准提供了许多处理字符串的函数。
字符串长度
size_t strlen( const char *str );
strlen函数返回字符串的长度,不包括’\0′
也就是从str指向的字符开始向后数,遇到’\0’就会结束。
例如”Hello”字符串长度是5.
字符串比较函数
int strcmp( const char *lhs, const char *rhs );
strcmp函数比较lhs和rhs两个字符串,按照字典中的顺序,返回值是 第一个字符串 – 第二个字符串
如果返回值是0,则两个字符串相等。
如果返回值是正数,则第一个字符串在字典中(机器编码)在第二个字符串后面。
如果返回值是负数,则第一个字符串在字典中(机器编码)在第二个字符串前面。
如果两个字符串开始的字母相等,则会继续下一个字母,一直到两边不匹配 或者 某一个字符串遇到’\0’为止。
int strncmp( const char *lhs, const char *rhs, size_t count );
多加了一个参数count,指定比较前count个字符。
字符串复制
char *strcpy( char *dest, const char *src );
将src指向的字符串复制到dest指向的地址,包括最后的’\0′ 。如果src很长(一直遇不到’\0’),则会发生未知结果。
注意:必须给dest指向的地方分配内存。
返回值:strcpy的返回值是第一个参数dest的值。
char *strncpy( char *dest, const char *src, size_t count );
strncpy第三个参数 指定最多复制多少个字符。
如果src的长度小于count ,则该函数作用和strcpy相同。
如果src的长度大于count,则会将src的前count个字符复制进dest,这时dest末尾没有结束符’\0′.因此经常用这种形式