第十一章 字符串和字符串函数
11.1 表示字符串和字符串 I/O
11.1.1 在程序中定义字符串
字符串字面量(string literal)/ 字符串常量(string constant):双引号括起来的内容,被视为指向该字符串存储位置的指针。属于静态存储类别(static storage class)。
字符串数组初始化:
const char str1[16] = "I am a string!";
const char str2[16] = {'I', ' ', 'a', 'm', ' ', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', '!', '\0'};
注意:若
str2
没有最后的空字符,则str2
是字符数组。不是字符串,此特性就是常说的C
字符串。
数组和指针:数组表示字符串时,字符串有两份副本,一个是静态内存中的字符常量,一个是存储在数组中的字符串。相同的字符串常量会被优化为在同一块内存中存储;
字符串数组:
char fruit1[3][7] = {"Apple", "Pear", "Orange"};
const char fruit2[3] = {"Apple", "Pear", "Orange"};
使用指针数组比二维字符串数组效率更高,但不能更改字符串内容。
11.2 字符串输入
想要读入一个字符串必须预留足以存储该字符串的空间,然后用输入函数获取该字符串。
char *gets(char *s)
从标准输入读取整行输入,直到遇到换行符时立马写入空字符,然后丢弃换行符。
不建议使用,输入过长时会导致缓冲区溢出。
char *gets_s(char *s, size_t n)
从标准输入读取数据,保证写入空字符。
- 读到换行符时结束并丢弃换行符;
- 读到文件尾时结束;
- 读到
n-1
个字符时,首先把目标数组末尾字符设为空字符,读取并丢弃随后的输入直至读到换行符或文件结尾,然后返回空指针。接着,调用依赖实现的处理函数
,可能会终止或退出程序,或指定自己的处理函数。
不建议使用,C11
新增,stdio.h
输入/输出函数系列中的可选
扩展。
char *fgets(char *s, int n, FILE *stream)
读取整行输入,直到读入 n-1
个字符或遇到换行符,不丢弃换行符,存储在字符串中。保证尾部写入空字符
int scanf(const char *restrict format, ...)
格式化输入
建议使用
fputs/fgets
的组合,它们不会修改源字符串,且写入的字符数量即为从流中读取的数量(不需要考虑对换行的特殊处理)。对输入格式有明确要求时,使用
scanf
,注意在格式中指定限制长度。
/* 如下程序演示了 fgets() 的一种用法:
* 读取整行输入并用空字符代替换行符,或者读取一部分输入,并丢弃其余部分。
*/
char *s_gets(char *st, int n)
{
char *ret_val;
inti=0;
ret_val = fgets(st,n, stdin);
if(ret_val) //即,ret_val != NULL
{
while(st[i] != '\n' && st[i] != '\0')
i++;
if(st[i] == '\n')
st[i]= '\0';
else
while(getchar() !=\n')
continue;
}
return ret_val;
}
11.3 字符串输出
int puts(const char *s)
输出字符串并在末尾添加换行符。
int fputs(const char *s, FILE *stream)
输出字符串,若函数读到文件尾,则返回空指针。不会添加额外的换行符。
int printf( const char *restrict format, ... )
格式化输出
输入输出函数应当一起讲,因为它们的函数是配套使用的。
11.4 定义自己的输入/输出函数
用 putchar
自定义函数。
11.5 字符串函数
size_t strlen(const char *s)
计算字符串长度
char *strcat(char *restrict dest, const char *restrict src)
char *strncat(char *restrict dest, const char *restrict src, size_t n)
将 src
字符串拼接到 dest
末尾。
int strcmp(const char *s1, const char *s2)
int strncmp(const char *s1, const char *s2, size_t n)
比较字符串 s1
,s2
,返回比较结果(按 ASCII
码大小)
-
0
:相等; - 负数:
s1
小于s2
; - 整数:
s1
大于s2
。
char *strcpy(char *restrict dest, const char *src)
char *strncpy(char *restrict dest, const char *restrict src, size_t n)
将字符串 src
拷贝到 dest
。
int sprintf(char *restrict str, const char *restrict format, ...)
int snprintf(char *restrict str, size_t size, const char *restrict format, ...)
将格式化后的字符串输出到 str
;
char *strstr(const char *haystack, const char *needle)
返回指向 s1
字符串中 s2
字符串首次出现的地址的指针。如果 s1
中没有找到 s2
,则返回空指针。
char *strpbrk(const char *s, const char *accept)
如果 s1
字符串中包含 s2
字符串中的任意字符,该函数返回指向 s1
中首个匹配的字符的地址。
使用带缓冲区大小限制的版本
11.6 字符串示例:字符串排序
建议排序指向字符串的指针而不是字符串本身。
11.7 ctype.h 字符函数和字符串
11.8 命令行参数
C
程序启动时可以从外部输入启动参数,会传递给 main
函数
int main(int argc, char *argv[])
argc:参数的个数;
argv:具体参数列表,argv[0] 为本程序名。
11.9 把字符串转换为数字
long strtol(const char *restrict nptr, char **restrict endptr, int base)
nptr:待转换的字符串;
endptr:标识输入数字结束字符的地址;
base:进制。
double strtod(const char *restrict nptr, char **restrict endptr)
float strtof(const char *restrict nptr, char **restrict endptr)
long double strtold(const char *restrict nptr, char **restrict endptr)
网友评论