2025-02-26 学习记录--C/C++-C 库函数gets()、fgets()、strcspn()、puts()
合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。💪🏻
一、C
库函数 - gets()
🍭
C 标准库 - <stdio.h>
下面是
gets()
函数的声明:👇🏻
char *gets(char *str)
gets()
函数 从标准输入stdin
读取一行,并把它存储在str
所指向的字符串中。当读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
- 如果成功,该函数返回
str
。- 如果发生错误或者到达文件末尾时还未读取任何字符,则返回
NULL
。str
– 这是指向一个字符数组的指针,该数组存储了C
字符串。
#include <stdio.h> // 引入标准输入输出库,用于使用 printf 和 gets 等函数int main() // 主函数,程序入口
{char str[50]; // 定义一个字符数组 str,用于存储用户输入的字符串,最大长度为 49 个字符(最后一个字符是字符串结束符 '\0')printf("请输入一个字符串:"); // 提示用户输入一个字符串gets(str); // 使用 gets 函数从标准输入读取用户输入的字符串,并存储到字符数组 str 中printf("您输入的字符串是:%s", str); // 输出用户输入的字符串,%s 是格式化字符串的占位符return 0; // 返回 0,表示程序正常结束
}
二、C
中使用 gets()
提示 warning: this program uses gets(), which is unsafe.
gets()
不安全是因为你给了他一个缓冲区,但是你却没有告诉它这个缓冲区到底有多大,也不知道输入的内容到底有多大,输入的内容可能超出缓冲区的结尾,引起你的程序崩溃。
解决方法可以使用
fgets()
替代:👇🏻
// 使用 gets()
char buffer[4096]; // 定义一个字符数组 buffer,用于存储用户输入的字符串,大小为 4096 个字符
gets(buffer); // 使用 gets 函数从标准输入读取用户输入的字符串,并存储到 buffer 中// 使用 fgets() 替换 gets()
char buffer[4096]; // 定义一个字符数组 buffer,用于存储用户输入的字符串,大小为 4096 个字符
fgets(buffer, (sizeof buffer / sizeof buffer[0]), stdin); // 使用 fgets 函数从标准输入读取用户输入的字符串,并存储到 buffer 中
// fgets 的第二个参数是缓冲区的大小,这里通过 (sizeof buffer / sizeof buffer[0]) 计算数组的实际大小。
// (sizeof buffer / sizeof buffer[0]) 是一种通用的计算数组大小的方式,适用于任何类型的数组。
// stdin 表示从标准输入(通常是键盘)读取数据。
fgets
会限制输入的字符数量,确保不会超过缓冲区的大小,从而避免缓冲区溢出。fgets
会读取一行内容(直到遇到换行符或文件末尾),并将换行符(如果有)也存储到字符串中。- 【注意】🌹 如果不需要换行符,可以手动去除: 👇🏻
- buffer[strcspn(buffer, “\n”)] = ‘\0’; // 去除换行符
以下是使用 fgets
的完整示例代码,包括去除换行符: 👇🏻
#include <stdio.h> // 引入标准输入输出库,用于使用 printf 和 fgets 等函数
#include <string.h> // 引入字符串处理库,用于使用 strcspn 函数【strcspn 函数用于查找字符串中第一个匹配指定字符集中任意字符的位置】int main() // 主函数,程序入口
{char buffer[4096]; // 定义一个字符数组 buffer,用于存储用户输入的字符串,大小为 4096 个字符printf("请输入一个字符串:"); // 提示用户输入一个字符串fgets(buffer, (sizeof buffer / sizeof buffer[0]), stdin); // 使用 fgets 函数从标准输入读取用户输入的字符串,并存储到 buffer 中// 参数说明:// - buffer:目标字符数组,用于存储输入的字符串。// - (sizeof buffer / sizeof buffer[0]):计算 buffer 的大小,确保不会超出缓冲区范围。// - stdin:表示从标准输入(通常是键盘)读取数据。// 去除 fgets 可能读取的换行符buffer[strcspn(buffer, "\n")] = '\0'; // 使用 strcspn 查找换行符的位置,并将其替换为字符串结束符 '\0'// 参数说明:// - buffer:要查找的字符串。// - "\n":要查找的字符集(这里只有换行符)。// - strcspn 返回第一个匹配字符的索引,如果没有匹配字符,则返回字符串的长度。printf("您输入的字符串是:%s\n", buffer); // 输出用户输入的字符串// %s 是格式化字符串的占位符,表示输出一个字符串。return 0; // 返回 0,表示程序正常结束
}
总结: 🐯
-
gets
的问题:不安全,容易导致缓冲区溢出,不推荐使用。 -
fgets
的优点:安全,可以限制输入长度,避免缓冲区溢出。 -
改进建议:在实际开发中,始终使用
fgets
替代gets
,并根据需要处理换行符。
三、C
库函数 - fgets()
🍭
C 标准库 - <stdio.h>
下面是
fgets()
函数的声明:👇🏻
char *fgets(char *str, int n, FILE *stream)
fgets()
函数 从指定的流stream
读取一行,并把它存储在str
所指向的字符串内。当读取(n-1)
个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
- 如果成功,该函数返回相同的
str
参数。- 如果到达文件末尾或者没有读取到任何字符,
str
的内容保持不变,并返回一个空指针。- 如果发生错误,返回一个空指针。
str
– 这是指向一个字符数组的指针,该数组存储了要读取的字符串。n
– 这是要读取的最大字符数(包括最后的空字符)。通常是使用以str
传递的数组长度。stream
– 这是指向FILE
对象的指针,该FILE
对象标识了要从中读取字符的流。
#include <stdio.h> // 引入标准输入输出库,用于使用文件操作函数(如 fopen、fgets、puts 等)int main() // 主函数,程序入口
{FILE *fp; // 定义一个文件指针 fp,用于操作文件char str[60]; // 定义一个字符数组 str,用于存储从文件中读取的内容,最大长度为 59 个字符(最后一个字符是字符串结束符 '\0')/* 打开用于读取的文件 */fp = fopen("file.txt", "r"); // 以只读模式打开名为 "file.txt" 的文件,并将文件指针赋值给 fpif (fp == NULL) { // 检查文件是否成功打开perror("打开文件时发生错误"); // 如果文件打开失败,使用 perror 输出错误信息return -1; // 返回 -1,表示程序异常结束}/* 从文件中读取内容 */if (fgets(str, 60, fp) != NULL) { // 使用 fgets 从文件中读取一行内容(最多 59 个字符),并存储到 str 中/* 向标准输出 stdout 写入内容 */puts(str); // 使用 puts 将读取的内容输出到标准输出(通常是屏幕)}fclose(fp); // 关闭文件,释放文件指针return 0; // 返回 0,表示程序正常结束
}
四、C
库函数 - strcspn()
🍭
C 标准库 - <string.h>
下面是
strcspn()
函数的声明:👇🏻
size_t strcspn(const char *str1, const char *str2)
strcspn()
函数 检索字符串str1
开头连续有几个字符都不含字符串str2
中的字符。
- 该函数返回
str1
开头连续都不含字符串str2
中字符的字符数。str1
– 要被检索的C
字符串。str2
– 该字符串包含了要在str1
中进行匹配的字符列表。
#include <stdio.h> // 引入标准输入输出库,用于使用 printf 等函数
#include <string.h> // 引入字符串处理库,用于使用 strcspn 等函数int main() // 主函数,程序入口
{int len; // 定义一个整型变量 len,用于存储 strcspn 函数的返回值const char str1[] = "ABCDEF4960910"; // 定义一个常量字符数组 str1,初始化为 "ABCDEF4960910"const char str2[] = "013"; // 定义一个常量字符数组 str2,初始化为 "013"// 使用 strcspn 函数计算 str1 开头连续都不含字符串 str2 中字符的字符数:ABCDEF496 共9个len = strcspn(str1, str2); // 输出结果:第一个匹配的字符 前 有 len 个,所以 第一个匹配的字符 位置 是 len + 1printf("第一个匹配的字符是在 %d\n", len + 1);return 0; // 返回 0,表示程序正常结束
}
五、C
库函数 - puts()
🍭
C 标准库 - <stdio.h>
下面是
puts()
函数的声明:👇🏻
int puts(const char *str)
puts()
函数 把一个字符串写入到标准输出stdout
,直到空字符,但不包括空字符。换行符会被追加到输出中。
- 如果成功,该函数返回一个非负值为字符串长度(包括末尾的
\0
);- 如果发生错误则返回
EOF
。str
– 这是要被写入的C
字符串。
#include <stdio.h> // 引入标准输入输出库,用于使用 puts 等函数
#include <string.h> // 引入字符串处理库,用于使用 strncpy 等函数int main() // 主函数,程序入口
{char str1[15]; // 定义一个字符数组 str1,用于存储字符串,大小为 15 个字符char str2[15]; // 定义一个字符数组 str2,用于存储字符串,大小为 15 个字符// 使用 strncpy 替代 strcpy,指定最大复制长度strncpy(str1, "FIGHTING1", sizeof(str1) - 1); // 将字符串 "FIGHTING1" 复制到 str1 中,最多复制 sizeof(str1) - 1 个字符strncpy(str2, "FIGHTING2", sizeof(str2) - 1); // 将字符串 "FIGHTING2" 复制到 str2 中,最多复制 sizeof(str2) - 1 个字符// 手动添加字符串结束符str1[sizeof(str1) - 1] = '\0'; // 确保 str1 的最后一个字符是字符串结束符 '\0'str2[sizeof(str2) - 1] = '\0'; // 确保 str2 的最后一个字符是字符串结束符 '\0'puts(str1); // 使用 puts 函数输出 str1 的内容(自动添加换行符)puts(str2); // 使用 puts 函数输出 str2 的内容(自动添加换行符)return 0; // 返回 0,表示程序正常结束
}