我们常接触的字符串输入函数有常见的gets() fgets() scanf("%s") 我们将分开介绍
0)什么是不检查边界?
假如一个int数组申请了十个元素的空间,但是有些函数在输入的时候不会检查边界,如果输入超过10个元素,会直接越界修改后面的内存中的元素。
可能会导致:缓冲区溢出攻击、程序崩溃、数据损坏。
1)gets()
gets()不检查函数边界,在C11被废弃。会导致缓冲区溢出。他会一直读取到换行符,换行符已经被读取,但是并不存储(读取并丢弃)。会在字符串末尾添加'\0'。


2)fgets()
fgets()是最为推荐的函数,
#include <stdio.h> // 必需的头文件
char *fgets(char *str, int n, FILE *stream);

请注意,n是包含'\0'的。

他的特点是:安全(不会从缓冲区溢出),读取整行(包括空格和换行符)。
#include <stdio.h> #include <string.h> // 用于字符串处理int main() {char name[50];printf("请输入你的名字: ");fgets(name, sizeof(name), stdin);// 去掉换行符name[strcspn(name, "\n")] = '\0';printf("你好,%s!\n", name);return 0; }
#include <stdio.h> #include <string.h>int main() {FILE *file = fopen("data.txt", "r");char line[256];if (file == NULL) {printf("无法打开文件\n");return 1;}// 逐行读取文件while (fgets(line, sizeof(line), file) != NULL) {// 去掉换行符line[strcspn(line, "\n")] = '\0';printf("%s\n", line);}fclose(file);return 0; }
那么如何处理多读进来的换行符呢?以下是三种方式,建议第一种。
char str[100]; fgets(str, sizeof(str), stdin); str[strcspn(str, "\n")] = '\0'; // 简洁高效
char str[100]; fgets(str, sizeof(str), stdin);char *newline = strchr(str, '\n'); // 找第一个元素出现的地方 if (newline) {*newline = '\0'; }
char str[100]; fgets(str, sizeof(str), stdin);size_t len = strlen(str); if (len > 0 && str[len-1] == '\n') {str[len-1] = '\0'; }
Windows和Linux换行符差异
// Windows: \r\n // Linux: \n // OJ通常是Linux环境// 安全处理:同时去掉\r和\n char *pos; if ((pos = strchr(str, '\r')) != NULL) *pos = '\0'; if ((pos = strchr(str, '\n')) != NULL) *pos = '\0';
fgets() 读取空行
// 用户直接按回车 fgets(str, sizeof(str), stdin); // str的内容是: "\n\0"// 处理:检查是否空行 if (str[0] == '\n') {printf("输入了空行\n");str[0] = '\0'; // 设为空字符串 }
混合输入(数字+字符串)
#include <stdio.h> #include <string.h>int main() {int age;char name[50];printf("年龄: ");scanf("%d", &age);// 关键:清除输入缓冲区中的换行符while (getchar() != '\n');printf("姓名: ");fgets(name, sizeof(name), stdin);name[strcspn(name, "\n")] = '\0';printf("%s今年%d岁\n", name, age);return 0; }
3)scanf("s");
仍然不检查边界,可以通过“9s"来检查边界。
-
遇到空白字符(空格、制表符、换行符)就停止
- 不会读取空白字符,留它们在输入缓冲区
- 在字符串末尾添加
\0
所以需要我们用getchar()清除掉空白符。或用" %s"清除前导空白符。