C语言中fgets函数

fgets 是一个常用的标准库函数,用于从文件或标准输入(如键盘)中读取一行字符串。它的主要特点是安全读取,可以防止缓冲区溢出(buffer overflow),相较于 gets 更安全。

1. fgets 函数原型

char *fgets(char *str, int n, FILE *stream);

参数说明

参数

说明

str

用于存储读取数据的字符数组(缓冲区)。

n

最多读取 n-1 个字符(第 n 个位置自动填充 \0)。

stream

输入流,可以是文件指针(如 FILE*)或标准输入(stdin)。

返回值

  • 成功:返回 str(即传入的缓冲区指针)。
  • 失败或到达文件末尾(EOF):返回 NULL

2. fgets 的特点

(1)读取一行(直到遇到 \n 或 EOF)

  • 如果输入行长度 ≤ n-1,则读取整行(包括 \n)。
  • 如果输入行长度 > n-1,则只读取前 n-1 个字符(剩余部分留在缓冲区,下次读取)。

(2)自动添加 \0 终止符

  • 确保字符串以 \0 结尾,防止越界访问。

(3)不会忽略空格

  • scanf("%s", str) 不同,fgets 会读取空格和制表符。

(4) gets 更安全

  • gets 已被弃用(C11标准移除),因为它不检查缓冲区大小,容易导致溢出。

3. 使用示例

示例1:从标准输入(键盘)读取一行

#include <stdio.h>

// 从标准输入(键盘)读取一行
int main()
{
    char buffer[100];
    printf("please input data:\n");
    if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
        printf("the input is: %s\n", buffer);
    }
    else {
        printf("fgets read fail\n");
    }
    return 0;
}

运行结果:

please input data:
nimehao
the input is: nimehao

示例2:从文件读取

#include <stdio.h>
#include <string.h> // used for strcmp

// 利用fgets从文件读取数据
int main()
{
    FILE *fp = fopen("data.txt", "r");
    if (fp == NULL) {
        perror("fopen error");
        return 1;
    }

    char line[100];
    printf("size of line is :%zu\n", sizeof(line));
    while (fgets(line, sizeof(line), fp) != NULL)
    {
        // two compare method
        // if (strcmp(line, "\n") == 0)
        if (line[0] == '\n')
        {
            printf("empty line\n");
            continue;
        }
        printf("line:%s", line);
    }

    fclose(fp);
    return 0;
}

data.txt

hello, c nihao

I get you.

output:

size of line is :100
line:hello, c nihao
empty line
line:I get you.

4. 关键注意事项

(1) 换行符 \n 的处理

  • fgets 会保留换行符(如果一行完整读取)。
  • 检查是否读取了换行符
if (buffer[strlen(buffer) - 1] == '\n') {
    buffer[strlen(buffer) - 1] = '\0'; // 去掉换行符
}

(2) 缓冲区大小 n 的选择

  • 必须预留1字节给 \0
    • 如果 char buf[100],则 n 应设为 100(最多读99字符 + \0)。
  • 缓冲区不足时
    • 如果一行超过 n-1 字符,剩余部分会在下一次 fgets 调用时读取。

(3) 与 scanf 的区别

特性

fgets

scanf

读取方式

按行读取(含空格)

按格式读取(遇空格停止)

安全性

安全(指定缓冲区大小)

可能溢出(如 scanf("%s", buf)

换行符

保留

不保留

推荐:优先使用 fgets + sscanf 组合,避免 scanf 的安全问题。

fgets 负责安全地读取一行输入(避免 getsscanf 直接读导致的溢出)。

scanffgets 读取的字符串中提取结构化数据(如整数、浮点数、字符串等)

具体为:

  1. fgets 读取一行到缓冲区。
  2. sscanf 从缓冲区中提取数据。
  3. 检查 sscanf 的返回值,确保解析成功。

示例如下:

#include <stdio.h>

// fgets + sscanf 组合使用
// fgets 负责安全地读取一行输入(避免 gets 或 scanf 直接读导致的溢出)。
// sscanf 从 fgets 读取的字符串中提取结构化数据(如整数、浮点数、字符串等)
int main()
{
    char buffer[100];
    int num1, num2;

    printf("please input two integer(eg:10 20):\n");
    if (fgets(buffer, sizeof(buffer), stdin) == NULL)
    {
        printf("fgets read error\n");
        return 1;
    }

    if (sscanf(buffer, "%d %d", &num1, &num2) != 2)
    {
        printf("input format error\n");
        return 1;
    }

    printf("the input data is %d and %d\n", num1, num2);
    return 0;
}

output:

please input two integer(eg:10 20):
12 334
the input data is 12 and 334

5. 常见问题

Q1: fgets 为什么会读到空行?

  • 原因:文件中有空行(仅 \n),fgets 会读取为 "\n\0"
  • 解决方法
if (buffer[0] == '\n') {
    // 处理空行
}

Q2: fgets 能否读取二进制文件?

  • 不推荐fgets 是文本行读取函数,遇到 \0 会停止。
  • 二进制文件应使用 fread
fread(buffer, 1, size, file); // 按字节读取

6. 总结

特性

说明

用途

安全读取文本行(文件或标准输入)。

换行符处理

保留 \n,需手动去除(如用 strcspn)。

缓冲区安全

必须指定最大长度(n),防止溢出。

替代 gets

是更安全的替代方案。

二进制文件

不适用,应使用 fread

最佳实践

  • 始终检查 fgets 的返回值(是否为 NULL)。
  • 处理换行符(\n)以避免后续问题。
  • 优先使用 fgets + sscanf 替代 scanf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值