【问题标题】:Scanf not accepting second char stringScanf 不接受第二个字符字符串
【发布时间】:2012-03-26 01:50:20
【问题描述】:

我有一个二进制搜索函数,可以在数组中搜索单词,但在搜索数组之前,我需要知道要搜索的单词。我编写了代码来要求用户输入,但程序打印出输入请求但不接受用户的任何内容。我当时认为这是一个缓冲区问题,因为我在程序中有一个初始 scanf,它从外部文件加载所有字符串并将它们放在一个数组中。在我最初的 scanf 之后,我尝试使用 fflush,并且我尝试用 get 重写第二个,正如前面的线程中所指出的那样。也许我没有正确实施它。这是我到目前为止所拥有的,任何关于为什么第二个 scanf 不起作用的提示都值得赞赏。

#include "set.h"
#include "sortAndSearch.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main(){
char names[320][30];
char str[30];  
int i, j;
char *key;
int numOfWords;
char userWord[30];
Set set1, set2, set3;

//scan each char string into array names
for(i=0; scanf("%s", str) != EOF; i++){
        strcpy(names[i], str);
}

//set number of words in file
numOfWords = i;

//sort names array
//bubbleSort(names, numOfWords);

//print out names, sorted
//for(i=0; i<numOfWords; i++){
//      printf("%s\n", names[i]);
//}

printf("What word would you like to search for? ");
scanf("%s", userWord);

//addName2Set(set1, userWord);

return 0;
}

【问题讨论】:

  • 如果你想读取 line 的输入,使用读取一行的函数。否则,您正在阅读单词并离开行尾。

标签: c string scanf


【解决方案1】:

您的第二个scanf 不起作用,因为您的第一个scanf 永远不会终止。 scanf 不会返回 EOF 除非输入流关闭 - 那就是控制台关闭。

由于scanf 返回读取的字符数,因此您应该将循环条件设为scanf(%s, str) != 0。只要用户在不输入任何内容的情况下点击回车,这将使循环结束。

【讨论】:

  • 我更改了for(i=0; scanf("%s", str) != 0; i++),但现在出现分段错误
  • EOF 在那里,因为它从外部文件获取输入,我不知道该文件中有多少数据。直到第二次 scanf 才会提示用户。
  • 第一个scanf() 永远不会执行是什么意思?如果输入是从文件重定向的(有注释说明发生了什么),那么循环将重复执行scanf() 直到文件结束。如果输入来自终端,则在 Windows 上键入 control-Z 或在 Unix 上键入 control-D(通常)将终止输入。在所有情况下,循环中的scanf() 都会愉快地执行。
  • @JonathanLeffler - 意味着永远不会终止,也不会永远执行
  • @manalishi - 如果您将文件重定向到标准输入,那么一旦读取文件,标准输入就位于文件的 EOF。它不会被重定向回控制台。使用fopepnfscanffclose 读取文件。
【解决方案2】:

您最初的 scanf() 在循环中读取所有内容,直到 EOF,因此“您想搜索什么词?”没有任何内容。 scanf()阅读。

解决此问题的一种方法是从文件中读取初始名称(fopen()fscanf()fclose() — 文件名可能是程序的参数或固定名称)。

您可以尝试的另一种方法是在“What word”scanf() 之前使用clearerr(stdin);。那 (clearerr()) 取消设置 EOF 位并允许 scanf() 重试。如果程序的输入是终端,它可以工作;如果程序的输入来自文件,这将无济于事。


int main(int argc, char **argv)
{
    char names[320][30];
    char str[30];  
    int i, j;
    char *key;
    int numOfWords;
    char userWord[30];
    Set set1, set2, set3;
    FILE *fp;

    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s word-file\n", argv[0]);
        exit(1);
    }

    if ((fp = fopen(argv[1], "r")) == 0)
    {
        fprintf(stderr, "Usage: %s word-file\n", argv[0]);
        exit(1);
    }

    //scan each char string into array names
    for (i = 0; i < 320 && fscanf(fp, "%29s", str) != EOF; i++)
    {
        strcpy(names[i], str);
    }

    fclose(fp);

    //set number of words in file
    numOfWords = i;

这要求您使用./a.out example.dat(而不是./a.out &lt; example.dat)。然后它将或多或少地按照您的意愿工作。当然,读取文件的代码应该在一个传递文件名、数组和数组大小的函数中。循环中的 320 是溢出保护,应该是在数组声明和循环中都使用的枚举enum { MAX_WORDS = 320 };29 是溢出保护;很难对其进行参数化,但它比数组的第二维小一。

【讨论】:

  • 为什么 scanf 不会在 data.dat 文件的末尾终止?
  • 文件名不固定,程序运行时提供,./a.out
  • clearerr(stdin); 也没有成功。初始输入来自外部文件,第二个输入来自终端内部。
  • 如果您要从这样的文件重定向输入,那么clearerr() 或其他任何东西都无济于事。你在哪个平台?在 Unix 上,您可以考虑打开并阅读 /dev/tty,甚至(听起来很愚蠢)阅读 stdoutstderr。但是,虽然stdin 是从文件重定向的,但'What word'scanf() 注定要失败;您已经阅读了整个文件,但没有任何内容可供阅读。 (您可以倒带stdin 并随机选择一个单词,但这将不允许您搜索不在列表中的单词。)我建议提供单词列表作为参数。
  • 请注意,当您的第一个循环执行时,它正在从您重定向的文件中读取;当您以./a.out &lt; example.dat 调用程序时,程序不会从终端读取。 'What word' scanf() 也是从同一个地方读取的。 stdin 不会因为输入全部读入程序而神奇地切换。
【解决方案3】:

乍一看,您的问题和代码似乎严重错位...

scanf() 是从文件中读取的错误函数,您需要fscanf(),或者如果文件的格式设置为每个单词都在自己的行上fgets() 也可以工作(换行符停止读取每个字符串) .同样,如果输入只是一个后跟 return(newline) 的字符串,您可以使用 gets() 而不是 scanf() 来读取用户输入。

Everything you need to know about stdio.h

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-24
    • 2020-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-17
    • 2020-02-14
    相关资源
    最近更新 更多