因为用习惯了C++的string类,对C字符串char*
的使用也基本忘了。现在因为操作系统实验需要使用回C,把C字符串的使用再次整理一下,也当作复习。
一、C字符
字符类型char
是C语言的基本数据类型之一,一个字符所占空间为1字节(8bit),使用单引号+一个字符定义: char a = 'A'
二、字符串常量
在 C 语言中,字符串实际上是使用 null
字符 '\0'
终止的一维字符数组。一般用一对双引号括起的一串字符来表示字符串常量,字符串常量不可被修改。
char* str = "this is a string";
此时”“中的内容为字符串常量,这部分内容无法修改,str只是一个指向该常量的指针,我们可以对指针进行操作:str++
;但不能对指针指向的内容进行操作:str[0] = 'B'
。
在创建字符串常量时,系统会自动在该连续内存地址的最后填充一个'\0'
,当对字符串进行读取时,从其首地址开始,直到读取到该终止符,表示字符串到达末尾,停止读取。
字符串常量实际上是一个字符数组,但是内容和长度在初始化时就已经固定了,不可更改。
三、字符数组
在 C 语言中,除了字符串常量外,其他所有字符串都必须存储于字符数组或动态分配的内存中。字符数组可以被修改。
char str[] = "string";
char* str = (char*)malloc( N*sizeof(char));
同样,字符数组的最后一个字符是’\0’,所以,一个包含N个字符的字符数组,长度为N+1。
四、常用函数
下面的函数都在C标准库<string.h>
中,可以在这个链接查询具体函数。
1、字符串长度
字符串的长度就是这个字符串所包含字符的个数,但不包含 ‘\0’ 字符。:
size_t strlen(char const *string);
2、复制字符串
char *strcpy(char *dst , char const *src);
strcpy()
的参数为两个字符串,将参数src复制到dst中。
使用时需要必须保证目标字符数组dst的长度足够存放源字符数组src的内容。如果 src 比 dst 长,则 src 剩余部分的字符仍会被复制,而且它们会覆盖 dst 后面的内存空间的值。
另一种复制方式:
char *strncpy(char *dst , char const *src , size_t len);
把src所指向的字符串复制到dst,最多复制len个字符。
1)如果 strlen(src) > len,则只有 len 个字符被复制到 dst 中去,此时 dst 将不会以 NUL 字节结尾(也就是说,strncpy 调用的结果可能不是一个字符串);
2)如果 strlen(src) < len,则 src 中的字符全被复制到 dst 中去,dst 中剩余的部分用null填充。
3、连接字符串
char *strcat(char *dst,char const *src);
将参数 src 字符串连接到参数 dst 字符串的后面。与strcpy函数一个同样的问题是,必须保证 dst 的剩余空间足够存放下 src 整个字符串。
同样,另一种连接方式:
char *strncat(char *dst , char const *src , size_t len);
从 src 中最多复制 len 个字符到目标数组 dst 后面,并且,strncat 总是在结果字符串后面添加一个null字节,而且不会对 dst 剩余的空间用null进行填充。
4、字符串比较
int strcmp(char const *s1 , char sonst *s2);
strcmp
函数会对被比较的两个字符串进行逐字符地比较,直到发现不匹配为止:最先不匹配的字符中较小的那个字符所对应的字符串即被认为小于另一个字符串;如果两者所有字符都匹配,则认为这两个字符串相等;
该函数的返回值如下:
1)s1 小于 s2,返回一个负值;
2)s1 等于 s2,返回 0;
3)s1 大于 s2,返回一个正值。
char *strncmp(char const *s1 , char const *s2 , size_t len);
可以使用 strncmp 函数限定比较的字符的个数,返回值与 strcmp 一样,但是只针对前len个字符进行比较。
5、字符串的查找
查找一个字符
在一个字符串中查找一个特定的字符:
char *strchr(char const *str,int ch);
char *strrchr(char const *str,int ch);
函数 strchr 在字符串 str 中查找字符 ch 第一次出现的位置,并返回一个指向该位置的指针;如果没有找到相应的字符,则返回一个 NULL 指针。
函数 strrchr 在字符串中查找字符 ch 最后一次出现的位置,并返回指向该位置的指针。
查找任意几个字符
查找任何一组字符第一次在字符串中出现的位置:
char *strpbrk(char const *str , char const *group);
函数返回一个指向字符串 str 中第一个匹配 group 中任何一个字符的字符位置,如果没有匹配到,则返回一个 NULL 指针。
查找一个子串
可以使用 strstr 函数来在一个字符串中查找一个子串:
char *strstr(char const *str1 , char const *str2);
在 str1中查找整个字符串str2第一次出现的起始位置,并返回一个指向该位置的指针;如果 str2 并没有完整的出现在 str1 中,则函数将返回一个 NULL 指针;如果 str2 是一个空字符串,则返回str1。
6、字符串与数值相互转换
字符串转数值
strtod(p, ppend)
从字符串 p 中转换 double 类型数值,并将后续的字符串指针存储到 ppend 指向的 char* 类型存储。
strtol(p, ppend, base)
从字符串 p 中转换 long 类型整型数值,base 显式设置转换的整型进制,设置为 0 以根据特定格式判断所用进制,0x, 0X 前缀以解释为十六进制格式整型,0 前缀以解释为八进制格式整型
atoi(p)
字符串转换到 int 整型
atof(p)
字符串转换到 double 符点数
atol(p)
字符串转换到 long 整型
数值转字符串
数字转字符串、字符串合并都可以使用sprintf()实现,这是一个十分方便的函数:
int sprintf(char *str, const char *format, ...)
参数:
- str – 这是指向一个字符数组的指针,该数组存储了 C 字符串。
- format – 这是字符串,包含了要被写入到字符串 str 的文本。它可以包含嵌入的 format 标签,format 标签可被随后的附加参数中指定的值替换,并按需求进行格式化。
- 附加参数 – 根据不同的 format 字符串,函数可能需要一系列的附加参数,每个参数包含了一个要被插入的值,替换了 format 参数中指定的每个 % 标签。参数的个数应与 % 标签的个数相同。
返回值:
- 如果成功,则返回写入的字符总数,不包括字符串追加在字符串末尾的空字符。如果失败,则返回一个负数。
sprintf
的格式和printf
的格式相似,唯一不同的一点是,sprintf
不是将字符串打印出来,而是将其存入第一个参数str
所对应的字符串中。简单实例:
#include <stdio.h>
#include <math.h>
int main()
{
char str[80];
sprintf(str, "Pi 的值 = %f", M_PI);
puts(str);
return(0);
}
7、字符检查(非字符串)
isalpha()
检查是否为字母字符
isupper()
检查是否为大写字母字符
islower()
检查是否为小写字母字符
isdigit()
检查是否为数字
isxdigit()
检查是否为十六进制数字表示的有效字符
isspace()
检查是否为空格类型字符
iscntrl()
检查是否为控制字符
ispunct()
检查是否为标点符号
isalnum()
检查是否为字母和数字
isprint()
检查是否是可打印字符
isgraph()
检查是否是图形字符,等效于 isalnum() | ispunct()
8、字符串输入输出
字符串的输出
常用的输出函数:
- puts():输出字符串并自动换行,该函数只能输出字符串。
- printf():通过格式控制符
%s
输出字符串,不能自动换行。除了字符串,printf() 还能输出其他类型的数据。
输出字符串时只需要给出名字。
字符串的输入
常用的字符串输入函数:
- scanf():通过格式控制符
%s
输入字符串。除了字符串,scanf() 还能输入其他类型的数据。 - gets():直接输入字符串,并且只能输入字符串。
scanf
和 gets
是有区别的:
- scanf() 读取字符串时以空格为分隔,遇到空格就认为当前字符串结束了,所以无法读取含有空格的字符串。
- gets() 认为空格也是字符串的一部分,只有遇到回车键时才认为字符串输入结束,所以,不管输入了多少个空格,只要不按下回车键,对 gets() 来说就是一个完整的字符串。换句话说,gets() 用来读取一整行字符串。
注意,scanf() 在读取数据时需要的是数据的地址,所以对于 int、char、float 等类型的变量用于 scanf() 时都要在前面添加&
,而数组或者字符串用于 scanf() 时不用添加&
,它们本身就会转换为地址。
参考资料
[C 标准库 -