Читать в текстовом файле - 1 символ за раз.используя C - PullRequest
2 голосов
/ 15 ноября 2010

Я пытаюсь читать текстовые файлы построчно и обрабатывать каждый символ отдельно.

Например, одна строка в моем текстовом файле может выглядеть так: ABC XXXX XXXXXXXX ABC

В строке всегда будет различное количество пробелов. Но такое же количество символов (включая пробелы).

Это то, что у меня есть ...

char currentLine[100];
fgets(currentLine, 22, inputFile);

Затем я пытаюсь перебрать массив CurrentLine и работать с каждым символом ...

for (j = 0; j<22; j++) {
    if (&currentLine[j] == 'x') {
        // character is an x... do something
     }
}

Может кто-нибудь помочь мне с тем, как я должен это сделать?

Как вы, вероятно, можете сказать - я только начал использовать C.

Ответы [ 4 ]

8 голосов
/ 15 ноября 2010

Каноническим способом обработки файла символ за символом может быть что-то вроде следующего:

#include <stdio.h>

int main(int argc, char **argv) 
{

    FILE *fp;
    int c;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s file.txt\n", argv[0]);
        exit(1);
    }
    if (!(fp = fopen(argv[1], "rt"))) {
        perror(argv[1]);
        exit(1);
    }
    while ((c = fgetc(fp)) != EOF) {

        // now do something with each character, c.

    }
    fclose(fp);
    return 0;
}

Обратите внимание, что c объявлено int, а не char, поскольку EOF имеет значение, отличное от всех символов, которые могут быть сохранены в char.

Для более сложного синтаксического анализа, тогда чтение файла за строкой, как правило, является правильным подходом. Вы, однако, хотите быть намного более защищенными от входных данных, которые не отформатированы правильно. По сути, напишите код, который предполагает, что внешний мир враждебен. Никогда не предполагайте, что файл не поврежден, даже если это файл, который вы только что написали.

Например, вы используете 100-символьный буфер для чтения строк, но ограничивает объем чтения до 22 символов (вероятно, потому что вы знаете, что 22 - это «правильная» длина строки). С дополнительным буферным пространством все в порядке, но вы должны учитывать возможность того, что файл может содержать строку неправильной длины. Даже если это ошибка, вы должны решить, как ее обработать, и либо повторно синхронизировать процесс, либо отказаться от него.

Редактировать: Я добавил скелет предполагаемой остальной части программы для простого канонического случая. Есть несколько вещей, на которые следует обратить внимание новым пользователям C. Во-первых, я предположил простой интерфейс командной строки, чтобы получить имя файла для обработки, и проверил, используя argc, что аргумент действительно присутствует. Если нет, я печатаю краткое сообщение об использовании с использованием содержимого argv[0], которое по соглашению именует текущую программу некоторым полезным способом, и выхожу с ненулевым статусом.

Я открываю файл для чтения в текстовом режиме. Различие между текстовым и бинарным режимами неважно на платформах Unix, но может иметь важное значение для других, особенно для Windows. Поскольку речь идет об обработке файла символом за раз, я предполагаю, что файл является текстовым, а не двоичным. Если fopen() терпит неудачу, то он возвращает NULL и устанавливает глобальную переменную errno в описательный код, объясняющий причину сбоя. Вызов perror() переводит errno во что-то понятное человеку и печатает его вместе с предоставленной строкой. Здесь я указал имя файла, который мы пытались открыть. Результат будет выглядеть примерно так: «foo.txt: такого файла нет». В этом случае мы также выходим с ненулевым статусом. Я не беспокоился, но часто имеет смысл выходить с разными ненулевыми кодами состояния по разным причинам, которые могут помочь сценариям оболочки лучше понимать ошибки.

Наконец я закрываю файл. В принципе, я также должен проверить fclose() на неудачу. Для процесса, который просто читает файл, большинство состояний ошибки уже будут обнаружены как некоторая ошибка содержимого, и при закрытии не будет добавлено никакого полезного состояния. Однако при записи в файл вы можете не обнаружить некоторые ошибки ввода / вывода, пока не вызовете fclose(). При записи файла рекомендуется проверять коды возврата и ожидать обработки ошибок ввода-вывода при любом вызове, который касается файла.

4 голосов
/ 15 ноября 2010

Вам не нужен адресный оператор (&). Вы пытаетесь сравнить значение переменной currentLine [j] с 'x', а не с ее адресом.

1 голос
/ 15 ноября 2010

ABC XXXX XXXXXXXX ABC имеет 21 символ. Также есть разрыв строки (22 символа) и завершающий нулевой байт (23 символа).

Вам нужно fgets(currentLine, 23, inputFile);, чтобы прочитать всю строку.

Но вы объявили currentLine как массив из 100. Почему бы не использовать все это?

fgets(currentLine, sizeof currentLine, inputFile);

При использовании всего этого, это не означает, что система будет помещать больше строки при каждом вызове fgets. fgets всегда останавливается после прочтения '\n'.

0 голосов
/ 15 ноября 2010

Попробуйте

while( fgets(currentLine, 100, inputFile) ) {
    for (j = 0; j<22; j++) {
        if (/*&*/currentLine[j] == 'x') { /* <--- without & */
        // character is an x... do something
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...