简体   繁体   English

EOF-scanf和printf

[英]EOF - scanf and printf

I'm tring to do a simple exercise here, but i need to understand how EOF works first. 我想在这里做一个简单的练习,但是我需要先了解EOF的工作原理。

void main()
{
    char s1[1000];
    while (scanf("%s", s1)!=EOF)
        ;
    printf("%s",s1);
}

The idea is to have multiple lines in input, and display them. 想法是在输入中包含多行,并显示它们。

The problem I have is that if I put 我的问题是,如果我把

Hello World
This is stackoverflow

When printf is called, it only prints 调用printf时,仅打印

stackoverflow

Why isn't it printing everything and how do I make it print? 为什么不打印所有内容,如何打印?

Regards 问候

Remove the semicolon ; 删除分号; :

    while (scanf("%s", s1)!=EOF)
        printf("%s",s1);

Note that this will still exhibit odd behavior at end of file depending on how it ends exactly. 请注意,这仍然会在文件结尾显示奇怪的行为,具体取决于它的结尾方式。 Furthermore, it splits the input into words, which are separated by spaces or new lines. 此外,它将输入拆分为单词,这些单词由空格或换行符分隔。 You may want to simply split into lines. 您可能需要简单地分成几行。

So you may be better served with for instance: 因此,例如,可能会更好地为您服务:

    while (gets(s1)!=NULL)
        puts(s1);

This code fragments reads your input line by line until end-of-file. 此代码片段逐行读取您的输入,直到文件结束。

To read everything (or as much as your buffer can hold), you can use: 要读取所有内容(或缓冲区可以容纳的最大内容),可以使用:

    char s1[1000] = "";
    fread(s1, sizeof(s1) - 1, 1, stdin);
    puts(s1);

However, my preferred method of reading a text file is: 但是,我首选的读取文本文件的方法是:

    using namespace std;
    string line;
    while (getline(cin, line))
    {
        cout << line << endl;
    }

That is because usually I want to process a file line by line, and getline with a string ensures the line buffer is always big enough. 那是因为通常我要逐行处理文件,而getlinestring确保行缓冲区始终足够大。

You probably want this: 您可能想要这样:

  char s1[1000][20];

  int i = 0 ;

  while (!feof(stdin))
     fgets(s1[i++], 20, stdin) ;

  int j ;
  for (j = 0; j < i; j++)
    printf("%s\n", s1[j]);

Here you can enter at most 1000 lines that are maximum 19 characters long. 在这里,您最多可以输入1000行,最长19个字符。

What you have is a loop that reads words into a buffer until it reaches EOF (and does nothing with those words), followed by a printf to print the contents of the buffer. 您所拥有的是一个循环,该循环将单词读入缓冲区,直到到达EOF(对这些单词不执行任何操作),然后执行printf打印缓冲区的内容。 The printf is after the loop (not in it), so executes once after the loop completes. printf 循环之后(不在循环中),因此在循环完成执行一次。 At that time, the buffer will contain the last word read, so that is what gets printed. 那时,缓冲区将包含读取的最后一个字,因此将被打印出来。

The EOF return test means "nothing more to be read", which isn't necessarily an end of file (might be an error condition of some kind), but in practice that distinction can be ignored. EOF返回测试的意思是“没什么要读取的”,它不一定是文件的结尾(可能是某种错误情况),但是实际上区别可以忽略。 Looping until your reading function returns EOF or NULL (depends on function) is good practice. 循环直到您的读取函数返回EOFNULL (取决于函数)是一种好习惯。

If you want to print each word as it is read, you need to put a printf in the loop. 如果要在读取每个单词时打印它,则需要循环中放入一个printf

If you want to store the words for later processing, you need to store them somewhere. 如果要存储单词以供以后处理,则需要将它们存储在某个位置。 That means declaring some storage space, or allocating space on the heap, and some bookkeeping to track how much space you've used/allocated. 这意味着声明一些存储空间,或在堆上分配空间,并进行一些簿记以跟踪已使用/分配的空间。

If you want lines rather than words, you should use fgets instead of scanf("%s" . Note that fgets returns NULL rather than EOF when there's nothing more to be read. 如果要用而不是单词,则应使用fgets而不是scanf("%s" 。请注意,当没有更多内容可读取时, fgets返回NULL而不是EOF

Because it only prints the last thing that is read from the file ("stackoverflow"). 因为它仅打印从文件读取的最后一个内容(“ stackoverflow”)。 This is caused by the semicolon after the end of your while(...); 这是由while(...);结束后的分号引起的while(...); - this means that you are doing while(...) { /* do nothing */} - which is probably not what you wanted -这意味着您正在执行while(...) { /* do nothing */} -这可能不是您想要的

Also, printf("%s",s1)!='\\0'; 另外, printf("%s",s1)!='\\0'; makes no sense at all. 毫无意义。 For one thing, printf returns the number of characters printed - '\\0' is the value zero written as a character constant. 一方面, printf返回打印的字符数- '\\0'是作为字符常量写入的零值。 And of course, doing != 0 of the result without some sort of use of the comparison is pretty much pointless too. 当然,不使用某种比较就对结果进行!= 0也是毫无意义的。

Use fgets instead of scanf if you want to read one line at at time. 如果您想一次读取一行,请使用fgets而不是scanf scanf will stop reading when it finds a whitespace. 当找到空白时, scanf将停止读取。 fgets will read till the end of the line. fgets会读取到该行的末尾。

Use fgets() . 使用fgets() Simple and sweet 简单而甜美

char buf[1000];
while (fgets(buf, sizeof buf, stdin) != NULL) {
  fputs(buf, stdout);
}

Here is how end-of-file works in C. The input channels are called input streams ; 这是文件尾在C中的工作方式。输入通道称为输入流 disk files and stdin are both input streams. 磁盘文件和stdin都是输入流。 The "end-of-file" state is a flag that a stream has, and that flag is triggered when you try to read from a stream, but it turns out there are no more characters in the stream, and there never will be any more. “文件结束”状态是流具有的标志,当您尝试从流中读取该标志时将触发该标志,但是事实证明流中不再有字符,并且永远不会有任何字符更多。 (If the stream is still active but just waiting for user input for example, it is not considered to be end-of-file; read operations will block). (例如,如果流仍处于活动状态,但仅在等待用户输入,则不将其视为文件结束;读取操作将被阻止)。

Streams can have other error states, so looping until "end-of-file" is set is usually wrong. 流可以具有其他错误状态,因此循环进行直到设置“文件结束”通常是错误的。 If the stream does go into an error state then your loop will never exit (aka. "infinite loop"). 如果流确实进入错误状态,则您的循环将永远不会退出(也称为“无限循环”)。

The end-of-file state can be checked by feof . 文件结束状态可以通过feof检查。 However, some input operations also can signal an error as well as, or instead of, returning the actual data they were intended to read. 但是,某些输入操作也可能会发出错误信号,或者返回而不是返回要读取的实际数据。 These functions can return the value EOF . 这些函数可以返回值EOF Usually these functions return EOF in both cases: end-of-file, and stream error. 通常,在以下两种情况下,这些函数都会返回EOF :文件结束和流错误。 This is different to feof which only returns true in the case of end-of-file. 这与feof不同, feof仅在文件结束时返回true

For example, getchar() and scanf will return EOF if it was end-of-file, but also if the stream is in an error state. 例如,如果getchar()scanf是文件末尾,而且流处于错误状态,则它将返回EOF

So it is OK to use getchar() 's result as a loop condition, but not feof on its own. 因此可以将getchar()的结果用作循环条件,但不能feof

Also, it is sometimes not OK to use scanf() != EOF as a loop condition. 同样,有时不适合使用scanf() != EOF作为循环条件。 It's possible that there is no stream error, but just that the data you requested wasn't there. 可能没有流错误,只是您所请求的数据不存在。 For example, if you scan for "%d" but there are letters in the stream. 例如,如果您扫描"%d"但流中有字母。 Instead, it's better to check for successful conversion (scanf returns the number of successful conversions it performed). 相反,最好检查转换是否成功(scanf返回其执行的转换成功次数)。 Then when you exit your loop, you can go on to call feof and ferror to see whether it was due to end-of-file, or error, or just unexpected input. 然后,当您退出循环时,可以继续调用feofferror来查看这是由于文件结尾,错误还是仅是意外输入引起的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM