fgets的使用方法详解

fgets的使用

前言(吹水,不看也罢)

鼠鼠今天在B站上大学的时候,做到了一题倒序输出字符串的题,本着能开摆就不学新内容的精神,本鼠决定使用之前学过的gets() 函数作为输入,但是在编译的时候遇到了这样一个警告(之前好像是提示该函数被弃用,升级VS版本后直接提示未定义,见下图),程序能跑,但是这个错误激起了鼠鼠的好奇心。

在这里插入图片描述

经过查找,本鼠发现,gets() 函数在C99中被弃用,在 C11 中被删除,此时需要用 fgets() 代替 gets() ,在好奇心的驱使下,本鼠简单学习了一下 fgets() 的使用方法。

fgets 的基本语法

fgets 的基本语法为

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

参数

string – 指向字符串(即 char 为元素的数组)

n – 输入字符串的长度

stream – 数据来源(一般为 stdin ,即标准输入流(键盘输入))

返回值

成功时为 str,失败时为 NULL

使用示例

以倒序输出字符串为示例(注释中写到的注意事项会在下面讲解)

//倒序输出字符串
#include <stdio.h>
#include <string.h>

void reverse(char arr[], int length);

int main()
{
    char arr[20] = { 0 };
    //gets在C11被弃用
    //gets(arr);

    //注意fgets会把缓冲区中的\n也读取,并放在字符串中,而gtes()是将\n取出后丢弃
    //如果输入的长度恰好只剩一个位置的话,\n不会被存入字符串
    //最后一个位置一定是留给\0的
    fgets(arr, 18, stdin);
    int length = (int)strlen(arr);
    //strlen计算长度不包括\0

    reverse(arr, length);
    printf("%s", arr);
    return 0;
}

void reverse(char arr[], int length)
{
    char* pointer = arr + (length - 2);
    //考虑到\n占的位置
    //当\n不被存入字符串时,这里应该是-1
    int len = length;
    while (pointer >= arr)
    {
        char temp = *arr;
        *arr = *pointer;
        *pointer = temp;
        arr++;
        pointer--;
    }
}

fgets() 对输入的处理的特点

注意,以下结果均为自行测试得到,如有错误,敬请指正

测试代码

#include <stdio.h>

int main()
{
	char arr1[5] = { 0 };
	char arr2[5] = { 0 };
	fgets(arr1, 5, stdin);
	fgets(arr2, 5, stdin);
	
	printf("arr1 = %s\n", arr1);
	printf("arr2 = %s", arr2);
	return 0;
}
#include <stdio.h>

int main()
{
    char arr1[5] = { 0 };
    char arr2[5] = { 0 };
    gets(arr1);
    gets(arr2);

    printf("arr1 = %s\n", arr1);
    printf("arr2 = %s\n", arr2);
    return 0;
}

在使用 fgets() 时,当输入的字符串长度小于(规定最大长度 - 1)时,函数会将 \n 放在字符串的最后,并在 \n 后加上 \0 ,因此,打印该字符串时不需要输入换行符

在这里插入图片描述

而当输入字符串长达大于(规定最大长度 - 1)时,fgets() 会截取(规定最大长度 - 1)的字符,并在最后加上 \0 ,其余字符串包括 \n则会被留在缓冲区,这就导致了包括 \n 在内的字符会在下一次使用 fgets() 时被当作输入,使得该次 fgets() 被“跳过”

即 fgets() 保证 \0 的存在

在这里插入图片描述

缓冲区:可以看作输入设备和程序之间的一块区域,输入设备将字符输入至缓冲区,程序在需要时从缓冲区中取得字符


有时,缓冲区中的数据会对程序造成干扰,需要对缓冲区进行清理

//利用循环清理缓冲区
	int a = 0;
	while ((a = getchar()) != '\n')
	{
		;
	}

gets() 与 fgets() 的主要区别

  1. gets() 在输入时并不会考虑 \0 在字符串中的存在,因此当输入的字符串长度大于设定长度时,会因为 \0 不存在而导致越界访问,而 fgets() 一定会有 \0 的存在(输入abcdefghijklmnopqrst为示例),不会造成越界

在这里插入图片描述

在这里插入图片描述

  1. 即使输入的字符串长度超过设定长度,gets()也不会影响下一次的输入(但是会造成越界)

在这里插入图片描述

  1. fgets() 会将 \n 一并存入字符串,而 gets() 会将 \n 丢弃

在这里插入图片描述

总结

相较于get() ,fgets() 的使用更加复杂,但是更加安全,不存在越界访问等问题,同时,因为其可以设定输入长度,在某些特定情况下相较于gets()更加便利,将 fgets() 与清理缓冲区的代码搭配使用会是一个不错的选择。

04-26
### C语言 `fgets` 函数的用法与解析 #### 1. 函数简介 `fgets` 是标准C库中的一个重要函数,主要用于从指定的流(如文件或标准输入)中读取一行或多行数据。它可以灵活地控制读取的数据量,并支持多种应用场景。 --- #### 2. 函数原型 `fgets` 的函数原型如下所示: ```c char *fgets(char *str, int n, FILE *stream); ``` - 参数 `str`: 这是一个指向字符数组的指针,`fgets` 将把读取到的字符串存入此数组。 - 参数 `n`: 表示最多可读取的字符数(包括最后的空字符 `\0`),因此实际读取的有效字符数应为 `n-1`。 - 参数 `stream`: 指向 `FILE` 对象的指针,表示要从中读取的流。例如,`stdin` 表示标准输入流(通常是键盘),而打开的文件句柄则代表文件流[^4]。 返回值: - 成功时返回指向读取字符串的指针 `str`。 - 如果发生错误或者到达文件末尾,则返回 `NULL`[^4]。 --- #### 3. 示例程序 ##### (1) 从标准输入读取一行文本 以下代码演示了如何使用 `fgets` 从标准输入(键盘)读取一行文本。 ```c #include <stdio.h> int main() { char buffer[100]; printf("请输入一行文本:"); fgets(buffer, sizeof(buffer), stdin); // 从标准输入读取 printf("您输入的内容是:%s", buffer); return 0; } ``` 在这段代码中,`buffer` 数组用于存储用户输入的文本。注意,`sizeof(buffer)` 提供了一个安全的方式来设置最大读取长度,防止缓冲区溢出[^3]。 --- ##### (2) 从文件中读取内容 假设有一个名为 `example.txt` 的文件,其中包含若干行文字。我们可以使用 `fgets` 来逐行读取这些内容。 ```c #include <stdio.h> int main() { FILE *file = fopen("example.txt", "r"); // 打开文件以只读模式 if (!file) { perror("无法打开文件"); return 1; } char line[256]; while (fgets(line, sizeof(line), file)) { // 循环读取每一行 printf("%s", line); } fclose(file); // 关闭文件 return 0; } ``` 在此示例中,`fgets` 被放置在一个循环结构中,以便能够逐行读取整个文件的内容。当遇到文件结束标志 (`EOF`) 或者其他错误条件时,`fgets` 将停止工作并退出循环[^1]。 --- ##### (3) 控制读取字符的数量 有时候可能只需要部分而非全部的一行数据。在这种情况下,可以通过调整第二个参数来限制读取的字符数目。 ```c #include <stdio.h> int main() { char partial_buffer[11]; // 定义较小的缓冲区 printf("请输入一串较长的文字:"); fgets(partial_buffer, 10, stdin); // 只读前9个有效字符加'\0' printf("截断后的输入是:%s", partial_buffer); return 0; } ``` 这里设置了较大的输入范围但仅允许读取有限的部分,从而实现了对输入长度的人工裁剪[^2]。 --- #### 4. 常见问题及解决方案 - **问**: 如果输入超过缓冲区大小怎么办? - **答**: 当输入超出设定的缓冲区大小时,剩余部分会被丢弃直到下一个换行符为止。为了避免这种情况,应该始终提供足够大的缓冲区或将多余的信息手动清理掉[^4]。 - **问**: 怎样判断是否成功完成了读取操作? - **答**: 需要检查 `fgets` 的返回值。如果返回非 NULL 则表明至少有一部分内容被正常读取;反之可能是由于达到 EOF 或出现了 I/O 错误所致。 - **问**: 输入结束后是否会自动附加换行符? - **答**: 是的,除非正好填满了缓冲区且最后一个位置留给 '\0',否则原始输入中的换行符也会保留下来成为结果的一部分。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值