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

问题描述 投票:2回答:1

我有一个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));

谢谢!

c fseek
1个回答
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的值。 fgets函数只有在出现错误时才返回NULL,或者在读取任何数据之前达到EOF。

因此,如果您将NULL作为返回值,要么您已经寻找超出文件末尾(可能),要么您遇到了错误(可能性稍差但不是不可能)。

© www.soinside.com 2019 - 2024. All rights reserved.