使用C在文本文件中查找行号

时间:2011-11-15 01:36:11

标签: c fseek

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

00010110001001000110011001000111
01011000011100001010100001001000
11110001011010000010010101111010
00000000000000000000000000000000
01011010101000010001010101110000

每行有32个字符(所以长度为33,\n)。我试图找到我的文件指针,指向0x0行之后的行(上例中的第4行)。

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

之后,我只使用了fseek。但是,它不起作用。这有什么不对?这是我的代码:

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

谢谢!

1 个答案:

答案 0 :(得分:3)

不,你必须添加一个。文件中第一个字符的偏移量为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

此外,您可能希望在使用之前打印出cbytes的值。只有在出现错误或在读取任何数据之前达到EOF时,fgets函数才会返回NULL。

所以,如果你得到NULL作为返回值,要么你已经寻找超出文件末尾(可能),要么你遇到了错误(有些不太可能但不是不可能)。

相关问题