【问题标题】:Is there a way to control when(or where) gets() or fgets() functions start taking Input?有没有办法控制gets() 或fgets() 函数何时(或何处)开始接受输入?
【发布时间】:2018-12-08 22:13:16
【问题描述】:

首先我想提一下我是编程新手。

我正在尝试编写一个接受多个输入的程序,其中最后一个是字符串,当我使用 get() 或 fgets() 函数时,它们会在前一个输入完成后读取输入。比如:

printf("Enter decimal:\n");
scanf("%d",&x);
printf("Enter string:\n");
gets(str[100]);
printf("%d\n%s",x,str);

示例输入/输出:

Enter decimal:
3\n            //If I change line after inputting the decimal the program continues as if it already read the string
Enter string:
3  

但是如果输入如下:

Enter decimal:
3 Hello World\n            
Enter string:
3  
Hello World

我想这就是 gets() 和 fgets() 函数的工作方式,但是有没有一种方法可以控制它或者是否有替代方法(输入的字符串可能很长 )

提前致谢。

【问题讨论】:

  • gets 很危险且已弃用。根本不要使用它。 stackoverflow.com/questions/1694036/…
  • 请注意gets() 已被弃用且不安全。永远不要使用它。 fgets() 可以使用。
  • 你的问题很不清楚。请尝试改进它。
  • gets() 不仅已被弃用,而且 C11 从语言中删除它。它仅作为向后兼容性的扩展保留在现代 C 实现中。
  • 下次提供一些minimal reproducible example

标签: c scanf fgets


【解决方案1】:

阅读有关C standard IO 的更多信息。请注意,gets 已被弃用且危险,但现在已从 C 标准中删除。你永远不应该使用它(请忘记它已经存在)。假设strchars 的一些数组,可能你的意思是fgets(str, sizeof(str), stdin) 而不是你对消失的gets 的调用,例如声明为char str[100];

您可以使用fgets(甚至getline(3),参见this)读取整行,然后解析该缓冲区,可能使用sscanf(或strtol,或strtok,或使用您自己的lexing & parsing 技术)。

请注意sscanf(如fscanfscanf)返回扫描的项目计数(并接受%n)但不关心行尾。你需要使用它。

仔细阅读您正在使用的函数的文档。

从正版文件中读取时,您还可以使用fseek(使用ftell)在其中重新定位。这在控制台上不起作用(因为终端通常不是seekable)。

也许你可以使用一些terminal 相关的库(例如ncursesreadline)。这些不在 C11 标准 n1570 中,并且可能在您的操作系统上不可用(但在 Linux 和其他一些操作系统上,您拥有它们)。

请记住,您的标准输入并不总是终端。想想redirectionspipelines

另请阅读How to Debug Small Programs。请务必使用所有警告和调试信息编译您的代码(如果使用GCC,则为gcc -Wall -Wextra -g)。

如果您使用的是 Linux 或某些 POSIX 操作系统,请注意 stdinfile descriptor 0(命名为 STDIN_FILENO)相关。因此,如果您想等到某些输入可用,请考虑在该文件描述符上使用 poll(2)

附言。你的问题真的不清楚。我只能猜到你想做什么......在阅读更多文档后考虑改进它......

【讨论】:

  • 谢谢,您提供的资源非常有帮助。由于我是新编程,我对技术措辞还不太熟悉,我一定会阅读更多!
【解决方案2】:

您的代码存在多个问题:

  • gets() 已过时且有风险,因为目标数组大小未传递给函数,因此如果用户输入太长,它无法防止缓冲区溢出。它终于从最新版本的 C 标准中删除了。请改用fgets()
  • 混合scanf()fgets() 容易出错,因为scanf() 会留下部分用户输入待处理,例如用户在数字后键入的换行符,并且此待处理输入将由fgets() 读取,这在这种特殊情况下将立即返回,因为待处理的换行符正是 fgets() 期望结束其输入的内容。

我建议使用fgets() 逐行读取输入,并使用sscanf 将输入转换为预期的类型。它还有一个额外的优点是可以轻松恢复错误。

这是修改后的版本:

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

int main() {
    char buf[100];
    int x;

    for (;;) {
        printf("Enter decimal: ");
        if (!fgets(buf, sizeof buf, stdin))
            return 1;
        if (sscanf(buf, "%d", &x) == 1)
            break;
        printf("Invalid input: not a number\n");
    }
    for (;;) {
        printf("Enter string:\n");
        if (!fgets(buf, sizeof buf, stdin))
            return 1;
        buf[strcspn(buf, "\n")] = '\0';  // strip the trailing newline if any
        if (buf[0] != '\0')
            break;
        printf("Invalid input: empty string\n");
    }
    printf("%d\n%s\n", x, buf);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-13
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    • 2020-02-23
    • 1970-01-01
    • 1970-01-01
    • 2015-03-13
    相关资源
    最近更新 更多