字符串处理
字符串的处理,字符串是以 '\0' 结尾的 char 类型数组。因此数组和指针的操作可以应用于字符串处理。C 库也提供了许多处理字符串的函数。
字符串表示
#define MSG "string content"
#define MAX_LENGTH 80
int main()
{
char words[MAX_LENGTH] = "string array";
const char *ptr = "pointer at string";
puts(MSG);
puts(words);
puts(ptr);
return 0;
}puts 函数只用来输出字符串,并自动在末尾加上换行符 '\n'
字符串字面量,或者叫字符串常量,""里的内容在编译时会自动加上 \0 ,ANSI C 标准规定,字符串字面量之间没有间隔或只用空格分隔,等效于一整个字符串字面量。
char txt[50] = "hello" "world";字符串常量(字符串字面量)为静态存储类型(static) ,在整个程序的生命周期内都存在。双引号的内容视为指向字符串存储位置的指针。理解下面的操作在干什么
定义字符串数组必须要让编译器知道多少空间。关于字符串数组的初始化
数组的末尾全都是 \0,字符串存储在静态存储区,程序加载时字符串常量就在了,但是数组在运行到的时候才会分配内存,此时将字符串复制到数组中。程序中有两个副本,一个是在静态内存中的字符串字面量,一个是在数组中的字符串。这是初始化字符串数组不一样的地方。
初始化一个字符串指针,只把字符串的地址赋值给指针,没有拷贝内容的过程。
一个例子
两个副本,以及编译器的优化,内容一致的字符串只留了一个副本。
字符串数组的两种方式
mytalents 是一个指针数组,yourtalents 是一个二维数组。
字符串会涉及到指针,绝大多数操作都是通过指针完成的。
字符串输入
读字符串的第一件事,分配空间。最简单的方式 char txt[80] ,然后可以使用 scanf gets fgets 来读取了。
gets puts
使用 scanf("%s", txt) 只能读取一个单词,读取整行使用 gets() 更方便,此函数读取整行知道遇到 ,然后丢弃 存储其他内容,并在末尾加 \0。对应的输出函数为 puts()。
gcc 9.5.0 编译会给一个警告信息,
问题在于,gets 只有一个参数,导致无法检查数组是否装得下,数组名会转换为数组首元素地址来处理,gets只知道数组的开始处,不知道数据中有多少个元素。如果输入的字符过多,就会导致缓冲区溢出(buffer overflow),
因此在 C99 标准中建议不在使用此函数,所以使用此函数编译器会给出警告。C11 标准中直接废除了此函数。
fgets fputs
gets 的代替函数。fgets()
参数
str: 指向一个字符数组的指针,用于存储读取到的字符串。这个数组必须足够大以容纳读取的数据及一个终止空字符 '\0'。
n: 读取的最大字符数(包括终止空字符)。fgets 会读取至多 n-1 个字符,确保最后一个位置留给终止空字符 '\0'。
stream: 指向 FILE 对象的指针,指定从哪个文件流中读取数据。可以是 stdin(标准输入)、文件指针等。
返回值
如果成功,fgets 返回 str(即存储读取数据的字符数组的指针)。
如果发生错误或到达文件末尾且没有读取到任何字符,fgets 返回 NULL。
fgets 读到换行符 \n 也会存储到字符串中,所以输出使用配套的 fputs ,此函数不会在末尾再添加换行。
关于 fgets 和 fputs 的使用
一个有意思的例子
虽然 words 的长度很短,但是也正确的处理所所有的内容。linux 系统使用缓冲的 IO,按下 enter 之前,输入在缓冲区中,按下 enter 后,换行符也送入缓冲区同属吧整行发给 fgets,输出时,fputs 把字符发送给另一个缓冲区,直到遇到换行符,缓冲区的内容出现在屏幕上。
此外还有一个代替函数是 gets_s(),
在读取长度小于给定参数时,此函数用起来和 gets 一模一样。
scanf
scanf 只读到空格,更像是获取单词的函数。此函数返回读取的单词数或者 EOF。例子
字符串输出
puts()
非常好用,puts 在遇到 \0 就停止输出,然后在自动输出一个 \n。所以一定要确保有空字符。
gets() 丢弃换行符,puts自动补上换行符。
fputs()
puts 向文件输出的版本。
参数 stream 指明要输出的文件。如果要输出到显示器上则为 stdout。此函数不会自动添加
fgets() 保留换行符,fputs() 不添加换行符。
printf()
printf 不会为字符串结尾自动换行,因此需要指定
自己的输入输出函数
如果 C 库函数满足不了要求,那么完全可以使用 getchar() 和 putchar() 的基础上实现自己的函数。
比如实习一个不自动换行的 puts
字符串函数
C 库 string.h 提供的库函数
strlen()
strlen 用于计算字符串的长度(不包括终止的空字符 '\0')。
str: 指向要计算长度的以 '\0' 结尾的字符串的指针。
返回字符串的长度(不包括终止空字符 '\0'),类型为 size_t。
一个例子改变字符串的长度
strcat()
字符串拼接函数,把第 2 个字符串附加在第 1 个后面。
通过参数能看出来,此函数只修改 dest,
此函数不检查第一个数组是否能容纳第二个字符串,也会有溢出问题。和 gets 的问题类似
strncat()
更安全的拼接
参数说明
dest: 指向目标字符串的指针,该字符串必须已经以 '\0' 结尾,并且有足够的空间容纳 src 的 n 个字符以及终止的空字符 '\0'。
src: 指向源字符串的指针,这个字符串的前 n 个字符将被追加到 dest 的末尾。src 字符串必须以 '\0' 结尾。
n: 要追加的字符数,最多为 src 字符串的长度。如果 n 大于 src 的长度,strncat 只追加 src 中实际存在的字符。
返回值
返回指向目标字符串 dest 的指针。
但是 C11 标准没有废除 strcat,来自于 C 语言相信程序员。gets 的输入来自用户,而 strcat 的问题在于程序员没有做好检查。因此写代码的人有义务确保 strcat 的安全。
strcmp()
strncmp
strcpy strncpy
sprintf
命令行参数的传递
字符串转换为数字
最后更新于
这有帮助吗?