fgets的使用
文章目录
- fgets的使用
- 前言(吹水,不看也罢)
- fgets 的基本语法
- 使用示例
- fgets() 对输入的处理的特点
- gets() 与 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() 的主要区别
- gets() 在输入时并不会考虑 \0 在字符串中的存在,因此当输入的字符串长度大于设定长度时,会因为 \0 不存在而导致越界访问,而 fgets() 一定会有 \0 的存在(输入abcdefghijklmnopqrst为示例),不会造成越界
- 即使输入的字符串长度超过设定长度,gets()也不会影响下一次的输入(但是会造成越界)
- fgets() 会将 \n 一并存入字符串,而 gets() 会将 \n 丢弃
总结
相较于get() ,fgets() 的使用更加复杂,但是更加安全,不存在越界访问等问题,同时,因为其可以设定输入长度,在某些特定情况下相较于gets()更加便利,将 fgets() 与清理缓冲区的代码搭配使用会是一个不错的选择。