首页 关于 微信公众号
欢迎关注我的微信公众号

C字符串

字符串字面量

所谓的字符串字面变量就是用一对双引号括起来的字符序列。例如 “abc” ,就是一个字符串字面变量。

字符串字面量的存储

C语言把字符串字面变量当做字符数组来处理,所以是利用数组来存储的。结尾元素都是’\0’.

字符串字面量的操作

通常情况下可以再任何C语言允许使用 char* 指针的地方使用字符串字面量。例如:

char *p;
p = "abc";

这个赋值操作不是复制”abc“中的字符,而仅仅是使p指向字符串的第一个字符。

C语言允许对指针添加下标,因此可以给字符串字面量添加下标:

char ch*;
ch = "abc"[2]; // 输出结果c

注意: 允许改变字符串字面量中的字符,但是不推荐这么做:

char *p = "abc";
*p = 'b';  /* string literal is now "bbc" */

对于一些编译器而言,改变字符串字面量可能会导致程序异常。

字符串变量

初始化字符串变量

可以利用一下几种形式:

char str1[] = "huhuhaha";
char str2[8] = {'h','u','h','u','h','a','h','a','\0'};

字符数组与字符指针

一下两种方法创建的字符串:

char date[] = “June 14”; char *date = “June 14”;

不能错误的认为上面两种date可以互换,两者之家有显著的差异:

如果需要可以修改的字符串,那么就要建立字符数组用来存储字符串。这时声明指针变量是不够的,下面的声明使编译器为指针变量分配了足够的存储空间:

char *p;

此时,它不为字符串分配空间。在使用p作为字符串之前,必须把p指向字符数组。如果不初始化,那么我们就不知道它指向了哪里,可能会对程序产生无法预期的影响。

字符串读写

写字符串-printf,puts

printf函数会逐个写字符串中的字符,直到遇到空字符才停止,如果空字符丢失,pringf函数会越过字符串的末尾继续写,知道最终在内存的某个地方找到空字符为止。如果只显示字符串的一部分,可以使用转换说明 %.ps, 这里的p是要显示的字符数量.

char str[] = "Are we having fun yet?";
printf("%.6s\n",str); // 结果: Are we

puts函数只有一个参数,此参数就是要显示的字符串。 puts(str); 在写完字符串后,puts函数总会添加一个额外的换行符。

读字符串-scanf,gets

scanf函数读入字符串永远不会包含空白字符。因此scanf通常不会读入一整行输入。换行符会使scanf函数停止读入,空格符和制表符也会产生同样的效果。

读入一整行数据使用gets函数。gets函数和scanf函数有以下区别:

字符串库

声明在中的每个函数至少需要一个字符串作为实际参数。把字符串参数声明为 char * 类型,同时允许实际参数可以是字符数组、char *类型变量或者字符串字面量,上述这些都适合作为字符串。然而,要注意哪些没有声明为const的字符串形式,所以对应的实际参数不应该是字符串字面量。

strcopy函数

函数原型如下:

char *strcpy(char *s1, const char *s2);

strcpy函数把字符串s2复制给字符串s1 。 也就是说,strcpy函数把s2中的字符复制到s1中直到遇到s2中的一个空字符为止。strcpy函数返回s1。因为不会改变s2指向的字符串,因此声明为const 。

大多数情况下会忽略掉strcpy函数的返回值。但是,有些时候,返回值会比较有用。比如,strcpy函数的调用作为较大表达式的一部分时,使用函数的返回值就非常有用。

strcat函数

函数原型如下:

char *strcat(char *s1,const char *s2);

strcat函数把字符串s2的内容追加到字符串s1的末尾,并返回字符串s1.

strcmp函数

函数原型如下:

int strcmp(const char *s1,const char *s2);

strcmp函数比较字符串s1和字符串s2,然后根据s1是否小于、等于、或大于s2,函数会返回小于、等于、或大于0的值。

类似于字典中单词的编排方式,strcmp函数利用字典顺序进行字符串比较。当比较两个字符串中的字符时,strcmp函数会查看表示字符的数字码。一些底层字符集的只是可以帮助预测strcmp函数的结果。下面是strcmp函数会遵循的一些规则:

strlen函数

函数原型如下:

size_t strlen(const char *s);

strlen函数的作用是求字符串长度。size_t是无符号整数类型。strlen函数返回s中第一个空字符前的字符个数,但不包括第一个空字符。

字符串惯用法

处理字符串的函数是特别丰富的惯用法资源。

搜索字符串的结尾

许多字符串操作需要搜索字符串的结尾。strlen就是一个重要例子。下面我重写一下strlen函数:

size_t strlen(const char *s)
{
	size_t n = 0;
	for(; *s != '\0';s++)
		n++
	return n;
}

以上能正确的返回字符串s的长度。但是条件 *s != ‘\0’ 与 *s != 0 是一样的,因为空字符的ASCII码值就是0. 但是测试 *s!=0 与测试 *s 是一样的,两者都是在 *s不为0时结果为真。所以以上程序可以改写成如此:

size_t strlen(const char *s)
{
	size_t n = 0;
	for(; *s ;s++)
		n++;
	return n;
}

用while语句替换for语句,可以得到如下版本的 strlen函数:

size_t strlen(const char *s)
{
	size_t n = 0;
	while(*s++)
		n++;
	return n;
}

虽然已经对strlen函数进行了相当大的精简,但是可能仍没有提高它的运行速度,至少对于一些编译器来说下面版本确实会运行更快一些:

size_t strlen(const char *s)
{
	const char *p = s;
	while(*s)
		s++;
	return s - p ;
}

此版本的strlen函数通过定位空字符位置的方式来计算字符串长度,然后用空字符地址减去字符串中第一个字符的地址。

字符串追加

下面直接重写字符串追加的方法 strcat:

char *strcat(char *s1,const char *s2)
{
	char *p;
	p = s1;
	while( *p != '\0')
		p++;
	while(*s2 != '\0'){
		*p = *s2;
		p++;
		s2++;
	}
	*p = '\0';
	return s1;
}

strcat函数的这种写法采用了两步算法:(1) 查找字符串s1末尾空字符的位置,并且使指针p指向它; (2)把字符串s2中的字符逐个复制到p所指向的位置。

通过对比strlen函数所采用的方法,可以简化strcat函数的定义,得到如下写法:

char *strcat(char *s1,const char *s2)
{
	char *p = s1;
	while(*p)
		p++;
	while(*p++ = *s2++);
	return s1;
}

int main(int argc,char *argv[])
{
char str1[] = "China";
char str2[] = "Zhejiang";
strcat(str1, str2);
printf("%s",str1);
return 0;
}

Blog

Opinion

Project