【问题标题】:Issues with scanf() and accepting user inputscanf() 和接受用户输入的问题
【发布时间】:2021-11-17 05:08:06
【问题描述】:

我正在尝试使用空格接收用户输入并将其存储在字符数组中。 之后,我想接受一个字符值并将其存储为一个字符。 但是,当我运行我的代码时,字符的提示会被忽略,而是填充一个空格。我怎样才能接受一个字符数组并且仍然允许在之后提示单个字符?

void main()
{
    char userIn[30];
    char findChar;


    printf("Please enter a string: ");
    scanf("%[^\n]s", userIn);

    printf("Please enter a character to search for: ");
    scanf("%c", &findChar);

    //this was put here to see why my single char wasnt working in a function I had
    printf("%c", findChar);

}

【问题讨论】:

  • “scanf 的问题”实际上是不言而喻:sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html
  • 是这样吗?我几乎不会从 java 进入 C,所以这对我来说是一个新现象。
  • 提醒scanf 确实会返回有价值的结果,以帮助指示成功扫描的项目数。您可以通过实际检查该结果来缓解其中一些问题。
  • 这能回答你的问题吗? scanf() leaves the new line char in the buffer
  • TLDR 来自建议的副本:在 scanf 中的 %c 格式之前添加一个空格以跳过缓冲区中剩余的换行符。

标签: c scanf user-input


【解决方案1】:

scanf("%c", &findChar); 读取输入流中待处理的下一个字符。此字符将是用户输入的停止先前转换的换行符,因此findChar 将设置为值'\n',无需等待任何用户输入,printf 将输出此换行符而没有任何其他可见效果。

将调用修改为scanf(" %c", &findChar) 以忽略待处理的空白并从用户那里获取下一个字符,或者更可靠地编写一个循环来读取输入行的读取和忽略。

还要注意scanf("%[^\n]s", userIn); 不正确:

  • 如果用户键入的输入超过 29 个字节,scanf() 可能会存储超出 userIn 末尾的字节。
  • ] 之后的s 是一个错误,字符类的转换格式不是%s 转换的变体。

其他问题:

  • void 不是 main() 函数的返回值的正确类型。
  • 此代码需要 <stdio.h> 标头。

这是修改后的版本:

#include <stdio.h>

int main() {
    char userIn[30];
    int c;
    char findChar;
    int i, found;

    printf("Please enter a string: ");
    if (scanf("%29[^\n]", userIn) != 1) {
        fprintf(stderr, "Input failure\n");
        return 1;
    }
    /* read and ignore the rest of input line */
    while ((c = getchar()) != EOF && c != '\n')
        continue;

    printf("Please enter a character to search for: ");
    if (scanf("%c", &findChar) != 1) {
        fprintf(stderr, "Input failure\n");
        return 1;
    }

    printf("Searching for '%c'\n", findChar);
    found = 0;
    for (i = 0; userIn[i] != '\0'; i++) {
        if (userIn[i] == findChar) {
            found++;
            printf("found '%c' at offset %d\n", c, i);
        }
    }
    if (!found) {
        printf("character '%c' not found\n", c);
    }
    return 0;
}

【讨论】:

  • 请注意,这使得用户无法输入空格作为搜索字符。
  • @WilliamPursell:确实scanf(" %c", &amp;findChar) 不允许搜索空格,但我发布的代码使用了另一种方法:读取并丢弃第一行的其余部分并扫描单个字节scanf(" %c", &amp;findChar),相当于findChar = getchar(),除了处理文件结尾和输入错误。
  • 啊,是的,干得好。
【解决方案2】:

scanf("%[^\n]s", userIn); 有点奇怪。 s 保证不匹配,因为该字符将始终为 \n。此外,您应该使用宽度修饰符来避免缓冲区溢出。使用scanf("%29[^\n]", userIn); 仅此一项并不能解决问题,因为下一个 scanf 将使用换行符。有几个选项。您可以在第一个 scanf 中使用换行符:

scanf("%29[^\n]%*c", userIn);

或在下一次调用中丢弃所有空格

scanf(" %c", &findChar);

在长度超过 29 个字符的输入行或用户尝试将空格分配给 findChar 时,行为会有所不同,因此您使用哪种解决方案取决于您要如何处理这些情况。

【讨论】:

  • 那么当你说在第一个scanF中消耗新行时,是不是将新行存储在我的char数组中??
  • @DavidHernandez 否。%*c 中的 * 告诉 scanf 丢弃该字符。
  • 我明白了,这真是一个漂亮的工具,谢谢你的知识。
  • @DavidHernandez:但是请注意,如果用户输入的字符超过 29 个,%*c 转换只会读取并忽略下一个字符,而不是换行符。
  • 如果输入为"\n"scanf("%29[^\n]%*c", userIn); 无法读取任何输入,而在stdinuserIn 中留下"\n" 未写入。
猜你喜欢
  • 2011-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多