C语言中, 所有字符串函数操作的对象都是指针指向的内存区域
字符串是以\0结尾的char类型数组
char name[] = {'f', 's', 's', '\0'};
char name[] = {'f', 's', 's'}; // 合法, 但缺少空字符作为结尾, 会引发错误
char *name = "hello world";
char name[] = "hello world";
字符串的输入输出
puts
只输出字符串, 在遇到空字符\0时停止输出, 并且自动输出换行符, 参数为字符串的地址
char *message = "hello world"; // 存储为: hello world\0
puts(message); // 自动输出换行符
puts(message + 5 ); // 从第6个开始输出
puts(&message[5]); // 从第6个开始输出
putchar
输出字符, 参数为需要输出的字符
putchar('\n');
gets
获取用户的输入, 可以用于读取整行输入, 当遇到换行符时, 停止读取, 并且将换行符丢弃, 存储剩余的字符
char *p = (char *)malloc(100 * sizeof(char));
gets(p);
puts(p);
// printf("%s\n", p);
但是从C11开始, 就从标准中抛弃了gets函数, 这是因为gets函数不安全, 它只接收一个参数, 也就是字符数组, 我们知道, 当数组作为参数传递时, 传递的是数组的首地址, 所以gets并不知道该数组的大小, 它会将所有输入的字符都存储到地址; 这样就会导致有可能访问到未被分配的地址, 甚至是其他程序所使用的地址, 这将导致程序段错误
call to 'gets' declared with attribute warning:
Using gets() is always unsafe - use fgets() instead [-Wattribute-warning]gcc
fgets和fputs
fgets可以用于替代不安全的gets, 提供了第二个参数用于限制接收的最大字符数量, 第三个参数用于表示将从什么地方读入文件
与gets不同的是, fgets并不会丢弃字符串的最后一个换行符, 而是会将其存储在字符串内, 因此长度为字符数+1
fputs通常和fgets配套, 提供第二个参数用于表示写入文件到什么地方, 与puts不同的是并不会自动输出换行符
char *p = (char *)malloc(10 * sizeof(char));
fgets(p, 10, stdin); // stdin标准输入, 从键盘读取输入
fputs(p, stdout); // stdout标准输出, 用于在屏幕上输出
fgets返回一个指向char的指针, 正常情况下, 该函数返回的地址与传入的第一个参数相同, 如果遇到文件结尾, 将返回一个空指针null pointer(NULL)
while(fgets(p, 10, stdin) != NULL && p[0] != '\n')
{
fputs(p, stdout);
}
fgets和fputs多用于对文件进行操作
gets_s
gets_s是C11新增的函数, 作为一个可选的扩展, 编译器不一定支持该函数. 该函数同样可以用于替代gets, 函数接收两个参数, 第二个参数用于限制接收的最大字符数量
当遇到换行符时, gets_s会和gets一样将其丢弃
如果读取到超过最大数量的字符时, 首先会将数组首字符设置为空字符\0, 读取并丢弃随后的输入, 直到读到换行符或文件的结尾, 然后返回一个空指针. 接着调用依赖实现的”处理函数”, 可能会中止或退出程序
char *p = (char *)malloc(10 * sizeof(char));
gets_s(p, 10);
scanf
返回正确读取参数的个数或者EOF(读取到文件的结尾), 典型用法是读取并转换混合数据类型为某种标准形式
字符串函数
strlen
包含在头文件string.h中, 用于统计字符串的长度
#include <stdio.h>
#include <string.h>
printf("%d\n", strlen(message));
strcat和strncat
strcat用于将两个字符串拼接在一起, 拼接后的结果将覆盖第一个字符串, 拼接后的长度将等于两个字符串长度之和
stecat接收两个字符串作为参数, 返回一个char *类型的值, 可以直接用于输出
#include <string.h>
char *p1 = (char *)malloc(10 *sizeof(char));
char *p2 = (char *)malloc(10 *sizeof(char));
fgets(p1, 10, stdin); // 使用s_gets(p2, 10);
fgets(p2, 10, stdin); // 使用s_gets(p2, 10);
strcat(p1, p2);
fputs(p1, stdout);
// fputs(strcat(p1, p2), stdout);
像上面的例子一样, 如果使用fgets来获取输入, 那么输出拼接后的字符串将仍然等于p1的值, 因为fgets会在输入的字符串后面保留换行符\n, 所以fputs输出时, 只会输出换行符之前的值, 也就是p1的值; 所以需要在拼接字符串时, 保证字符串中间没有换行符\n, 使用下面这个函数来将换行符替换为空字符\0
char *s_gets(char *str, int size)
{
char *ret_val;
int i = 0;
ret_val = fgets(str, size, stdin);
if(ret_val)
{
while(str[i] != '\n' && str[i] != '\0')
{
i++;
}
if(str[i] == '\n')
{
str[i] = '\0';
}
else // 没有找到换行符, 表示输入字符超过了缓冲区大小
{
// 丢弃缓冲区内剩余的字符
while(getchar() != '\n')
continue;
}
}
return ret_val;
}
strncat用于拼接两个字符串, 接受三个函数, 第三个函数用于指定最大添加的字符数, 表示从第二个字符串选取前几个字符拼接到第一个字符串末尾
strncat(p1, p2, 4);
strcmp和strncmp
strcmp用于将两个字符串进行比较, 接受两个参数, 表示两个需要进行比较的字符串; 如果相同, 返回0, 如果不同, 则返回非0
需要注意的是, strcmp比较的是字符串, 而不是数组, 所以可以用其来比较存储在不同大小数组中的字符串
fgets(p1, 10);
fgets(p2, 10);
printf("%d\n", strcmp(p1, p2));
strncmp用于比较两个字符串的前n个字符, 接受三个参数, 第三个参数表示要比较前几个参数
strncmp(p1, p2, 4);
strcpy和strncpy
strcpy将一个字符串拷贝到另一个字符串, 其返回值类型为char *, 即第一个字符的地址
strcpy(p1, p2); // 将p2拷贝至p1指向的地址
strcpy(p1 + 3, p2);
strncpy可以指定最大拷贝多少个字符
strcpy(p1, p2, 5);
sprintf
函数包含在头文件stdio.h内, 用于把数据写入字符串, 可以把多个元素组合成一个字符串; 第一个参数为目标字符串的地址, 其余的参数与printf相同
char *formal = (char *)malloc(sizeof(10 * sizeof(char)));
char *message1 = "hello";
char *message2 = "world";
sprintf(formal, "%s, %s !", message1, message2);
fputs(formal, stdout);
其他字符串函数还有
strchar(const char *p, int c); // p中是否含有c字符, 返回p, 否则NULL
strpbrk(const char *p1, const char p2); // p1包含p2中任何字符, 返回p1, 否则NULL
strrchr(const char *s, int c); // s中字符c最后出现的位置
strstr(const char *p1, const char *p2); // p1中, p2首次出现的位置
发表回复
要发表评论,您必须先登录。