2

我有一个 ASCII 二进制文件,它看起来像:

00010110001001000110011001000111
01011000011100001010100001001000
11110001011010000010010101111010
00000000000000000000000000000000
01011010101000010001010101110000

每行有 32 个字符(因此它的长度为 33,带有\n)。我正在尝试将我的文件指针指向该行之后的0x0行(上例中的第 4 行)。

我所做的如下。首先,我计算了文件中有多少行。所以5在这种情况下。我还在保留该行的行处保留了一个索引0x0。所以4在这种情况下。我乘以4which33返回0x0is 之后的第一个数字的哪个字符(我必须添加一个 1 ,因为这实际上返回了行\n尾的 the 0x0

在那之后,我只是使用fseek. 但是,它不起作用。这里有什么问题?这是我的代码:

int bytes = 33 * c;
fseek(fp, bytes+1, SEEK_SET);
char test[34];
printf("HERE: '%s'", fgets(test, 34, fp));

谢谢!

4

1 回答 1

4

不,您根本不必添加一个。文件中第一个字符的偏移量为 0。

如果第二行的第一个字符是 33,则偏移量(假设您的行尾确实换行符,而不是 CR/LF 组合)。

第三行的第一个字符在偏移量 66 处。

所以你的代码实际上应该是:

int bytes = 33 * c;
fseek (fp, bytes, SEEK_SET);  // no "+1" here.
char test[34];
printf ("HERE: '%s'", fgets(test, 34, fp));

这是一个显示在行动中的成绩单:

pax$ cat qq.in
00010110001001000110011001000111
01011000011100001010100001001000
11110001011010000010010101111010
00000000000000000000000000000000
11110000111100001111000011110000

pax$ cat qq.c
#include <stdio.h>

int main (void) {
    char test[34];
    int c = 4;
    FILE *fp = fopen ("qq.in", "r");

    int bytes = 33 * c;
    fseek (fp, bytes, SEEK_SET);
    printf("HERE: %s", fgets(test, 34, fp));

    fclose (fp);
    return 0;
}

pax$ gcc -o qq qq.c ; ./qq
HERE: 11110000111100001111000011110000

在您的环境中尝试该代码,看看会发生什么。如果您没有得到正确的数据,那么您的代码和某种类型的输入文件之间存在不匹配。

您尚未指定您所在的平台,因此您实际上可能在行\r\n尾拥有,而不仅仅是\n. 您也可能以错误的模式打开它(尽管这通常只在 Windows 上很重要)。

对文件进行转储以验证其内容是个好主意。例如,在 UNIXy 系统中:

pax$ od -xcb qq.in

0000000    3030    3130    3130    3031    3030    3031    3130    3030
          0   0   0   1   0   1   1   0   0   0   1   0   0   1   0   0
        060 060 060 061 060 061 061 060 060 060 061 060 060 061 060 060
0000020    3130    3031    3130    3031    3130    3030    3130    3131
          0   1   1   0   0   1   1   0   0   1   0   0   0   1   1   1
        060 061 061 060 060 061 061 060 060 061 060 060 060 061 061 061
0000040    300a    3031    3131    3030    3030    3131    3031    3030
         \n   0   1   0   1   1   0   0   0   0   1   1   1   0   0   0
        012 060 061 060 061 061 060 060 060 060 061 061 061 060 060 060
:
<< Unnecessary Detail Removed >>
:
0000240    3030    3030    000a
          0   0   0   0  \n
        060 060 060 060 012
0000245

此外,您可能希望在使用它们之前打印出它们c的值。bytes如果出现错误或在读取任何数据之前到达 EOF,该fgets函数只会返回 NULL。

因此,如果您将 NULL 作为返回值,那么您可能已经超出了文件的末尾(可能),或者您遇到了错误(不太可能但并非不可能)。

于 2011-11-15T01:39:29.427 回答