C语言getc()与gets()函数对比及安全替代方案

唐可
唐可
发布时间:2026-10-13| 5人浏览过
原创

在C语言编程中,正确选择输入函数至关重要。getc()用于从文件流中逐个读取字符,适合底层数据交互;而gets()虽能方便地读取整行字符串,但因不检查边界极易导致缓冲区溢出。本文对比两者的工作原理与代码实现,并指出使用fgets()作为安全替代方案的必要性。

结果与目标

掌握getc()和gets()函数的基本用法,理解它们在处理标准输入和文件流时的区别,识别gets()带来的安全隐患,并学会如何在实际编码中规避相关风险。

准备条件

  • 已安装支持C/C++的编译器(如GCC)。
  • 创建测试文件test.txt用于文件读取实验。
  • 理解基本的指针、数组及文件操作概念。

真实操作顺序

第1步:使用getc()逐字符读取文件

目的:演示如何通过getc()从文件中逐个提取字符,直至文件末尾。

入口:标准输入输出库 <stdio.h> 及字符串库 <string.h>。

动作:

  1. 定义文件指针FILE *fstream。
  2. 使用fopen("test.txt", "at+")打开文件,模式为追加读写。
  3. 声明整型变量ch接收返回值,因为EOF通常为负值,不能存入char。
  4. 利用while循环调用getc(fstream),直到返回值等于EOF。
  5. 在循环体内使用putchar(ch)输出每个字符。

重要参数:文件路径"test.txt",打开模式"at+"。

完成状态:控制台打印出文件原有内容,并将指定字符串追加写入文件尾部。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main(void)
{
  int ch;
  int len;
  int i=0;
  FILE* fstream;
  char msg[100] = "Hello!I have read this file.";
  
  fstream=fopen("test.txt","at+");
  if(fstream==NULL)
  {
    printf("read file test.txt failed!\n");
    exit(1);
  }
  
  /* getc从文件流中读取字符 */
  while( (ch = getc(fstream))!=EOF)
  {
    putchar(ch);
  }
  putchar('\n');
  
  len = strlen(msg);
  while(len>0)/*循环写入*/
  {
    putc(msg[i],fstream);
    putchar(msg[i]);
    len--;
    i++;
  }
  fclose(fstream);
  return 0;
}

第2步:使用gets()读取标准输入字符串

目的:展示gets()如何从标准输入获取一行文本并存入缓冲区。

入口:标准库 <stdio.h>。

动作:

  1. 声明字符数组char str[10]作为缓冲区。
  2. 提示用户输入字符串。
  3. 调用gets(str)读取输入。
  4. 使用printf输出读取到的字符串。

注意:此方法极具风险,具体演示见下方排错部分。

#include <stdio.h>

int main(void)
{
  char str[10];
  printf("Input a string.\n");
  gets(str);
  printf("The string you input is: %s\n",str);
}

第3步:验证缓冲区溢出风险

目的:通过故意输入超长字符串,证明gets()不检查边界的缺陷。

动作:

  1. 运行上述程序。
  2. 输入长度小于10的字符串(如123456),程序正常输出。
  3. 输入长度大于10的字符串(如12345678901234567890)。

观察结果:程序可能输出混乱字符或直接崩溃(Segmentation Fault)。这是因为gets()无视str的大小限制,将超出部分写入了相邻内存区域,破坏栈结构。

现代编译器警告:在使用GCC编译时,直接使用gets()会被标记为危险函数,甚至直接阻止编译通过,提示:
the 'gets' function is dangerous and should not be used.

完成判断

当你能熟练编写使用getc()处理文件的代码,并理解为何应避免使用gets()时,即掌握了本节核心内容。在实际工作中,推荐始终使用fgets(char *str, int n, FILE *stream)来替代gets(),它允许指定最大读取长度,从而彻底杜绝缓冲区溢出问题。

原文有依据的排错

  • 错误现象:程序接收到输入后突然退出或产生不可预知行为。
  • 原因分析:使用了gets()且输入长度超过缓冲区定义大小。
  • 修正方案:
    1. 弃用gets()。
    2. 改用fgets(str, sizeof(str), stdin)。
    3. 确保第二个参数不超过数组的实际大小。

简要总结

getc()是逐字符处理的利器,适合文件流操作;gets()虽然语法简单,但因其固有的安全风险已被主流标准废弃。开发者应养成使用fgets()等安全检查函数的习惯,以提升代码的健壮性。以上就是C语言getc()函数和gets()函数的使用对比的详细内容,更多关于C语言标准输入输出函数的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。