fgets()/gets()/scanf() 之后 scanf() 的问题

2024年8月28日 | 阅读 4 分钟

scanf() 函数是 C/C++ 中一个常用的函数。尽管其语法基础,但在某些情况下使用它时需要特别注意,这一点至关重要。一个例子就是在 scanf() 之后调用 fgets()。

在本文中,我们将探讨为什么 fgets() 在 scanf() 之后无法正常工作,以及可能的解决方案。首先,让我们看看 scanf() 和 fgets() 函数是如何执行的。

在 C 语言中,scanf() 是一个库函数。它从 stdin 读取标准输入。在 C 语言中,fgets() 也是一个库函数。它从给定的流中读取一行,并将其保存在相关的字符串变量中。它仅在满足以下条件之一时才会结束:

  • 到达文件末尾
  • 读取了 n-1 个字符。
  • 读取了换行符。

下面是一个示例,展示了我们如何使用 scanf() 函数。

C 代码

输入

输出

Enter name: Box
Entered Name: Box

在 C/C++ 中使用 fgets() 函数

在 fgets() 函数中,fgets 是“file get string”(文件获取字符串)的缩写。它基本上是一个从流(文件流或标准输入流)中读取最多 n 个字符并将其转换为字符串 str 的函数。其声明如下:

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

让我们详细分析这个声明的每一部分。

  • int n 代表必须读入字符串的字符数量。
  • FILE* stream 是对包含输入的文件流的引用。当从标准输入访问时,这将被替换为 stdin。
  • 此函数的返回值是指向 str 的指针。

在 scanf() 之后使用 fgets() 的问题

假设我们现在已经理解了 fgets() 和 scanf() 函数的工作方式,让我们来研究一下当我们在 scanf() 函数之后立即使用 fgets() 函数时会发生什么,以及 fgets() 是否在 scanf() 之后仍然有效。

输入

输出

7
a = 7, str = 
Box
dash: 2: Box: not found

可以看到,字符串 "Box" 没有被打印出来。这是什么原因呢?问题的原因在于 scanf() 函数的一个特定功能。

除了从标准输入流读取数据外,scanf() 函数还会在缓冲区中插入一个换行符。因此,在上面的代码中,scanf() 函数在读取整数 a 后留下了一个换行符。fgets() 函数在读取到这个换行符后就结束了处理(回想一下我们讨论的 fgets() 操作结束读取输入的三个条件)。结果,fgets() 方法忽略了字符串 "Box" 并且没有打印它。

在我们使用 scanf() 时,记住它的这一方面至关重要。但是现在需要解决 fgets() 在 scanf() 之后无法工作的问题。如何才能也打印出字符串 "Box" 呢?

问题的解决方案

既然已经探讨了为什么 fgets() 在 scanf() 之后会失败的问题,就可以得出一个解决方案。请注意下面的代码。

C 代码

输入

输出

a = 22, string = Box
  • 有人注意到区别了吗?在 scanf("%d\n", &a) 中,增加了一个额外的 "\n"。这会强制 scanf() 读取一个新行。此外,我们也可以通过在 "%d" 后面加一个空格来实现,如 scanf("%d ", &a)。
  • 在 scanf() 方法之后,添加 getchar() 函数来读取一个额外的换行符。
  • 这样一来,fgets() 函数将读取输入的字符串而不是换行符。因此,为什么 fgets() 在 scanf() 之后失败的问题就解决了。

1. 如何让 Fgets 在 scanf 之后执行?

在 scanf() 中添加一个 "\n",如 scanf("%d\n", &x),或者在 scanf() 之后使用 getchar() 都可以解决这个问题。

2. 使用 scanf() 需要什么语法?

scanf() 函数的语法如下:int scanf(const char *format,...);

3. 为什么 fgets 在 scanf 之后不执行?

在 scanf() 中添加一个 "\n",如 scanf("%d\n", &x),或者在 scanf() 之后使用 getchar() 都可以解决这个问题。fgets() 函数在读取到(由 scanf() 留下的)换行符后结束了操作。

4. C 语言中的 Scanf 返回什么?

Scanf 返回成功输入的总数,或者在出错的情况下返回 EOF(End of Line,应为 End of File)。

5. Fgets 是否比 Scanf 更可取?

在做出选择之前,有几件事需要考虑。虽然 scanf() 只能从标准输入读取,但 fgets() 可以从任何文件流中读取。

6. 使用 fgets() 需要什么语法?

使用 fgets() 的语法如下:char* fgets(char* str, int n, FILE* stream);

结论

如果在 fgets() 方法之前使用了 scanf() 函数,可能会出现一个非常常见的问题。由于 scanf() 方法在缓冲区中留下了一个换行符,导致 fgets() 函数无法读取部分输入。在 scanf() 中添加一个 "\n",如 scanf("%d\n", &x),或者在 scanf() 之后使用 getchar() 都可以解决这个问题。


下一主题#