【问题标题】:fscanf for stdin not prompting for input标准输入的 fscanf 不提示输入
【发布时间】:2013-10-09 18:07:40
【问题描述】:

下面给出的是我的代码中的一个 sn-p。我学会了使用fscanf 而不是scanf 更好。但是 fscanf 不等待输入

switch (argc) {
            case 2: printf("\nEnter the subject code: ");
                while(fgets(temp_op->subject, BUF_NOTES, stdin)==NULL);
            case 3: printf("\nEnter the topic: ");
                while(fgets(temp_op->topic, BUF_TOPIC, stdin)==NULL);
            case 4: printf("\nEnter the Level: ");
                flag = fscanf(stdin,"%d",&temp_op->level);
            case 5: printf("\nEnter the Answer Key: ");
                while(fgets(temp_op->key, BUF_KEY, stdin)==NULL);
            case 6: printf("\nEnter any additional notes(optional): ");
                while(fgets(temp_op->notes, BUF_NOTES, stdin)==NULL);
                break;
            default:printf("\nExcess Arguments");
        }

问题出在case 5。 fgets 不等待输入,但案例 6 做得很好。

但是,如果我注释掉case 4 行“flag =...”,那么下一个 fget 将提示输入。奇怪。我想知道为什么以前的 fscanf 会影响后面的 fgets。我的结构定义是:

typedef struct {
int mode ;
int level;
char subject[BUF_SUBJECT], topic[BUF_TOPIC], notes[BUF_NOTES], key[BUF_KEY];
} operation;

完整来源在http://pastebin.com/HVvGC3B7

可能出了什么问题?

【问题讨论】:

  • fscanf 是否将换行符留在缓冲区中?
  • 尝试fflush() 强制输出缓冲区发射,这通常发生在\n
  • 顺便说一句,你在 switch 中忘记了break;
  • fscanf() 可能没有消耗所有输入,因此fgets() 找到了一些缓冲字符,不需要等待用户的额外输入。
  • @Grijesh Chauhan 我认为 OP 故意省略了break。在我的编码手册中,任何时候 case "drop through` 到下一行代码(即不是 break),都必须包含 特定 注释。也许就像 // drop through 一样简单.

标签: c pointers struct fgets scanf


【解决方案1】:

您将scanf()fgets() 混合在一起——最好避免。

fscanf(stdin,"%d",...\n 留在输入队列中,随后的fgets() 无需等待其他输入即可使用。

建议使用fgets() thoguhout 并使用sscanf(buffer, "%d", ... 来获取您的整数。

【讨论】:

  • @Jay Aurabind BTW:看起来像一个无限循环while(fgets(..., ..., stdin)==NULL) 如果您遇到 EOF 或 I/O 错误。
  • 但是当我需要使用 sscanf 从标准输入接收时,我应该用什么代替 buffer? stdin 会产生警告,也不起作用,因为缓冲区应该是手册中提到的const char *。只有getchar() 似乎有效
  • 关于无限循环,反之亦然! :P 如果我不把 NULL 放在那里,我会得到循环:)
  • @Jay Aurabind,不使用sscanf() 直接读取stdin。读入缓冲区然后扫描缓冲区:char buffer[sizeof(int)*3+3]; if (fgets(buffer, sizeof buffer, stdin) == NULL) handle_EOR_or_error_IO(); if (1 != sscanf(buffer, "%d", &temp_op->level) handle_format_error();
  • 我认为你误解了constsscanf(const char *, 中的使用。提供给sscanf() 的缓冲区参数可以是char *const char * 类型。 const 意味着sscanf() 不会尝试将数据指针更改为buffer。并不是const char * 必须 提供给sscanf()
【解决方案2】:
             case 4: printf("\nEnter the Level: ");
                flag = fscanf(stdin,"%d",&temp_op->level);
                //Here Return key left in buffer
             case 5: printf("\nEnter the Answer Key: ");
                while(fgets(temp_op->key, BUF_KEY, stdin)==NULL); // escapes because of newline 

为了避免在 case 5 之前添加 getchar();

或者按照 chux 的建议,您也可以使用 sscanf()

【讨论】:

    猜你喜欢
    • 2015-11-05
    • 1970-01-01
    • 2013-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 2015-12-20
    • 1970-01-01
    相关资源
    最近更新 更多