现在位置: 首页 > C 教程 > 正文

C 库函数 - gets()

C 标准库 - <stdio.h> C 标准库 - <stdio.h>


在 C 语言中,gets() 是一个用于从标准输入读取字符串的经典函数。虽然它使用简单,但需要注意安全性问题。

gets() 函数从 标准输入 stdin 读取一行字符串,并将其存储在指定的字符数组中。它会读取字符直到遇到换行符或文件末尾为止。

重要警告gets() 存在严重的安全漏洞,无法指定缓冲区大小,容易导致缓冲区溢出。因此在现代 C 编程中,fgets() 是更好的选择。

单词释义get 是"获取"的意思,s 代表"字符串" (string),合起来就是"获取字符串"。


基本语法与参数

gets() 是 C 标准库中的一个函数,需要包含头文件 <stdio.h>

语法格式

char *gets(char *str);

参数说明

  • 参数str
    • 类型: char * (指向字符数组的指针)
    • 描述: 一个指向字符数组的指针,该数组用于存储读取到的 C 字符串。需要确保数组足够大,能够容纳输入的字符串。

函数说明

  • 返回值: 如果成功,返回指向 str 的指针。如果发生错误或到达文件末尾时还未读取任何字符,则返回 NULL
  • 效果: 读取的字符串(不包含换行符)会被存储在 str 指向的数组中,并在末尾自动添加空字符 \0 作为字符串结束标志。

实例

让我们通过例子来掌握 gets() 的用法。

示例 1:基础用法 - 读取字符串

实例

#include <stdio.h>

int main()
{
   char str[50];

   printf("请输入一个字符串:");
   gets(str);

   printf("您输入的字符串是:%s", str);

   return(0);
}

运行结果预期:

请输入一个字符串:runoob
您输入的字符串是:runoob

代码解析:

  1. #include <stdio.h> 是使用 gets() 函数的前提。
  2. char str[50]; 定义了一个长度为 50 的字符数组,用于存储输入的字符串。
  3. gets(str); 从标准输入读取一行字符串,并存储到 str 中。
  4. printf("您输入的字符串是:%s", str); 使用 %s 格式化符输出字符串。

示例 2:处理返回值为 NULL 的情况

在实际编程中,应该检查 gets() 的返回值,以处理可能的错误。

实例

#include <stdio.h>

int main()
{
   char str[100];
   char *result;

   printf("请输入一些内容(输入 Ctrl+D 可结束):\n");
   result = gets(str);

   if (result != NULL) {
       printf("成功读取,内容是:\n%s\n", str);
   } else {
       printf("读取失败或已到达文件末尾!\n");
   }

   return(0);
}

代码解析:

  • gets() 返回指向同一字符串的指针,如果失败则返回 NULL
  • 当用户按下 Ctrl+D(Linux/Mac)或 Ctrl+Z(Windows)时,会触发文件结束条件,gets() 返回 NULL
  • 在实际项目中,建议使用更安全的 fgets() 替代 gets()

示例 3:gets() 的安全问题(⚠️ 演示危险操作)

下面的例子展示了为什么 gets() 是不安全的。

实例

#include <stdio.h>

int main()
{
   // 注意:这个例子很危险,仅用于演示!
   char buffer[10];

   printf("请输入一个较长的字符串(超过10个字符):\n");
   gets(buffer);  // 没有边界检查,可能导致缓冲区溢出

   printf("您输入的是:%s\n", buffer);

   return(0);
}

代码解析:

  • buffer[10] 只分配了 10 个字节的空间。
  • 如果用户输入的字符串超过 9 个字符(加上结尾的 \0),就会发生缓冲区溢出,可能覆盖相邻的内存区域。
  • 这会被攻击者利用来执行恶意代码,因此 gets() 在 C99 标准中已被标记为废弃,在 C11 标准中更是被移除。

更好的替代方案:fgets()

强烈建议使用 fgets() 代替 gets(),因为它可以指定缓冲区大小。

实例

#include <stdio.h>

int main()
{
   char str[50];

   printf("请输入一个字符串:");
   // fgets(缓冲区, 缓冲区大小, 文件流)
   fgets(str, sizeof(str), stdin);

   // 移除 fgets 读取的换行符
   // 方法:查找换行符并替换为空字符
   for (int i = 0; str[i] != '\0'; i++) {
       if (str[i] == '\n') {
           str[i] = '\0';
           break;
       }
   }

   printf("您输入的字符串是:%s\n", str);

   return(0);
}

fgets() 的优势:

  • 可以指定最大读取字符数,防止缓冲区溢出。
  • 会在字符串末尾保留换行符(如需要可手动移除)。
  • 可以指定输入来源(标准输入、文件等)。

C 标准库 - <stdio.h> C 标准库 - <stdio.h>