简体   繁体   English

在不使用getc的情况下使用fscanf直到EOF

[英]Using fscanf until EOF without using getc

I have a text file of composed of sequences of 2 bytes which I have to store in an array. 我有一个由2个字节的序列组成的文本文件,必须将其存储在数组中。

I have declared FILE *ptr . 我已经声明了FILE *ptr

How can I loop until EOF without using the method: 我如何不使用方法就循环到EOF:

while(c = getc() != EOF)
{
// do something 
}

I want to implement something along the lines of (PSEUDOCODE): 我想按照(PSEUDOCODE)实现一些东西:

while (ptr is not pointing to the end of the file)
{
fscanf(...)  // I will read in the bytes etc.
}

The getc() method wouldn't work well for me because I am reading in blocks of 2 bytes at a time. getc()方法对我来说效果不佳,因为我一次读取的是2个字节的块。

You can use fread to read more than one byte at a time. 您可以使用fread读取多个字节。 fread returns the number of items it was able to read. fread返回它能够读取的项目数。

For example, to read 2-byte chunks you might use: 例如,要读取2字节的块,可以使用:

while ((fread(target, 2, 1, ptr) == 1) {
    /* ... */
}

Here 2 is the number of bytes in each "item", and 1 is the number of "items" you want to read on each call. 这里2是每个“项目”中的字节数,而1是要在每次调用中读取的“项目”数。

In general, you shouldn't use feof() to control when to terminate an input loop. 通常,您不应使用feof()控制何时终止输入循环。 Use the value returned by whichever input routine you're using. 使用您正在使用的任何输入例程返回的值。 Different input functions vary in the information they provide; 不同的输入功能在它们提供的信息方面有所不同。 you'll have to read the documentation for the one you're using. 您必须阅读所用文档的文档。

Note that this will treat an end-of-line as a single '\\n' character. 请注意,这会将行尾视为单个'\\n'字符。 You say you're reading from a text file; 您说您正在从文本文件中读取; it's not clear how you want to handle line endings. 尚不清楚您要如何处理行尾。 You should also decide what you want to do if the file has an odd number of characters. 如果文件的字符数为奇数,则还应该确定要执行的操作。

Another option is to call getc() twice in the loop, checking its result both times. 另一种选择是在循环中两次调用getc()两次检查其结果。

The only way to tell when you've reached the end of the file is when you try to read past it, and the read fails. 判断何时到达文件末尾的唯一方法是尝试读取过去,但读取失败。 (Yes, there is an feof() function, but it only returns true after you've tried to read past the end of the file.) (是的,有一个feof()函数,但是仅您尝试读取文件末尾之后才返回true。)

This means that, if you're going to use fscanf() to read your input, it's the return value of fscanf() itself that you need to check. 这意味着,如果要使用fscanf()读取输入,则需要检查的是fscanf()本身的返回值。

Specifically, fscanf() returns the number of items it has successfully read, or EOF (which is a negative value, typically -1) if the input ended before anything at all could be read. 具体来说, fscanf()返回已成功读取的项目数,如果输入在可以读取任何内容之前结束,则返回EOF (这是一个负值,通常为-1)。 Thus, your input loop might look something like this: 因此,您的输入循环可能看起来像这样:

while (1) {
    /* ... */

    int n = fscanf(ptr, "...", ...);

    if (n == EOF && !ferror(ptr)) {
        /* we've reached the end of the input; stop the loop */
        break;
    } else if (n < items_requested) {
        if (ferror(ptr)) perror("Error reading input file");
        else fprintf(stderr, "Parse error or unexpected end of input!\n");
        exit(1);  /* or do whatever you want to handle the error */
    }

    /* ... */
}

That said, there may be other options, too. 也就是说,可能还有其他选择。 For example, if your input is structured as lines (which a lot of text input is), you may be better off reading the input line by line with fgets() , and then parsing the lines eg with sscanf() . 例如,如果您的输入被构造为行(很多文本输入是行), 则最好通过fgets()逐行读取输入,然后使用sscanf()解析行。

Also, technically, there is a way to peek one byte ahead in the input, using ungetc() . 此外,技术上, 偷看前面输入一个字节的方式,使用ungetc() That is, you could do something like this: 也就是说,您可以执行以下操作:

int c;
while ((c = getc(ptr)) != EOF) {
    ungetc(c, ptr);
    /* ... now read and parse the input ... */
}

The problem is that this only checks that you can read one more byte before EOF; 问题在于,这只会检查您是否可以在EOF之前再读取一个字节。 it doesn't, and can't , actually check that your fscanf() call will have enough data to match all the requested items. 它没有, 也不能 ,实际上检查您的fscanf()调用是否具有足够的数据来匹配所有请求的项。 Thus, you still need to check the return value of fscanf() anyway — and if you're going to do that, you might as well use it for EOF detection too. 因此,无论如何,您仍然仍然需要检查fscanf()的返回值-如果要执行此操作,也可以将其用于EOF检测。

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

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