Искать номер строки в текстовом файле, используя C - PullRequest
2 голосов
/ 15 ноября 2011

У меня есть двоичный файл 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 Ответ

3 голосов
/ 15 ноября 2011

Нет, вам не нужно добавлять его вообще. Смещение первого символа в файле равно 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 перед их использованием. Функция fgets будет возвращать NULL только в случае ошибки или если вы достигнете EOF до того, как прочитаны какие-либо данные.

Итак, если вы получаете NULL в качестве возвращаемого значения, либо вы искали за пределами файла (вероятно), либо вы столкнулись с ошибкой (несколько менее вероятно, но не невозможно).

...