Чтение текстового файла в 2 отдельных массива символов (в C) - PullRequest
1 голос
/ 16 февраля 2011

Для класса я должен написать программу для чтения в текстовом файле в формате:


T A E D Q Q
Z H P N I U
C K E W D I
V U X O F C
Б П И Р Г К
N R T B R B
EXIT
Символ
БЫСТРЫЙ
BROWN
FOX


Я пытаюсь получить символы в массив символов, каждая строка является собственным массивом. Я могу читать из файла все в порядке, и это код, который я использую для анализа файла:


char** getLinesInFile(char *filepath)  
{  
    FILE *file;  
    const char mode = 'r';  
    file = fopen(filepath, &mode);  
    char **textInFile;  

    /* Reads the number of lines in the file. */
    int numLines = 0;
    char charRead = fgetc(file);
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            numLines++;
        }
        charRead = fgetc(file);
    }

    fseek(file, 0L, SEEK_SET);
    textInFile = (char**) malloc(sizeof(char*) * numLines);

    /* Sizes the array of text lines. */
    int line = 0;
    int numChars = 1;
    charRead = fgetc(file);
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            textInFile[line] = (char*) malloc(sizeof(char) * numChars);
            line++;
            numChars = 0;
        }
        else if(charRead != ' ')
        {
            numChars++;
        }
        charRead = fgetc(file);
    }

    /* Fill the array with the characters */
    fseek(file, 0L, SEEK_SET);
    charRead = fgetc(file);
    line = 0;
    int charNumber = 0;
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            line++;
            charNumber = 0;
        }
        else if(charRead != ' ')
        {
            textInFile[line][charNumber] = charRead;
            charNumber++;
        }
        charRead = fgetc(file);
    }

    return textInFile;
}

Это прогон моей программы:


Добро пожаловать в поиск слов!

Введите файл, который вы хотите, чтобы мы проанализировали: testFile.txt TAEDQQ! ZHPNIU! CKEWDI! VUXOFC! BPIRGK! NRTBRB! ВЫХОД!! БЫСТРО! BROWN! ЛИС Ошибка сегментации


Что происходит? А), почему там восклицательные знаки, и Б) почему в конце я получаю ошибку сегмента? Последнее, что я делаю в основном, это перебираю массив / указатели.

Ответы [ 3 ]

3 голосов
/ 17 февраля 2011

1) В первой части вашей программы вы неправильно подсчитываете количество строк в файле.Фактическое количество строк в файле - 11, но ваша программа получает 10. Вам нужно начать считать с 1, так как в файле всегда будет хотя бы одна строка.Поэтому измените

int numLines = 0;

на

int numLines = 1;

2) Во второй части программы вы неправильно подсчитываете количество символов в каждой строке.Вы должны сохранить ваши инициализации счетчика одинаковыми.В начале сегмента вы инициализируете numChars равным 1. В этом случае вам необходимо сбрасывать счетчик на 1 после каждой итерации, поэтому измените:

numChars = 0;

на

numChars = 1;

Thisдолжен обеспечить достаточно места для всех непробельных символов и для конечного терминатора NULL.Помните, что в Си char * строки всегда заканчиваются NULL.

3) Ваша программа также не учитывает различий в завершении строки, но в моей тестовой среде это не проблема - fgetc возвращает только однусимвол для конца строки, даже если файл сохраняется с разделителями \ r \ n.

4) Во второй части вашей программы вы также не выделяете память для самой последней строки.Это приводит к вашей ошибке в третьей части вашей программы, когда вы пытаетесь получить доступ к нераспределенному пространству.

Обратите внимание, что ваш код сохраняет строки только в том случае, если они заканчиваются на \ r или \ n.Угадайте, что, EOF, который технически является окончанием строки для последней строки, не подходит.Поэтому ваш второй цикл не сохраняет последнюю строку в массиве.

Чтобы исправить это, добавьте это после второй части: textInFile [line] = (char *) malloc (sizeof (char) * numChars);

4) В выходных данных вашей программы вы видите эти странные восклицательные знаки, потому что вы не NULL завершаете свои строки.Поэтому вам нужно добавить строку, помеченную как NULL-завершение ниже:

if(charRead == '\n' || charRead == '\r')
{
    textInFile[line][charNumber] = 0; // NULL termination
    line++;
    charNumber = 0;
}

5) Поскольку вы проверяете EOF, у вас возникает та же проблема в третьем цикле, поэтому вы должны добавить это до возврата

textInFile[line][charNumber] = 0; // NULL termination

6) У меня также возникают головные боли из-за всей структуры программы.Вы читаете один и тот же файл символ за символом 3 раза!Это очень медленно и неэффективно.

Фиксированный код следует ниже:

char** getLinesInFile(char *filepath)  
{  
    FILE *file;  
    const char mode = 'r';  
    file = fopen(filepath, &mode);  
    char **textInFile;

    /* Reads the number of lines in the file. */
    int numLines = 1;
    char charRead = fgetc(file);
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            numLines++;
        }
        charRead = fgetc(file);
    }

    fseek(file, 0L, SEEK_SET);
    textInFile = (char**) malloc(sizeof(char*) * numLines);

    /* Sizes the array of text lines. */
    int line = 0;
    int numChars = 1;
    charRead = fgetc(file);
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            textInFile[line] = (char*) malloc(sizeof(char) * numChars);
            line++;
            numChars = 1;
        }
        else if(charRead != ' ')
        {
            numChars++;
        }
        charRead = fgetc(file);
    }
textInFile[line] = (char*) malloc(sizeof(char) * numChars);

    /* Fill the array with the characters */
    fseek(file, 0L, SEEK_SET);
    charRead = fgetc(file);
    line = 0;
    int charNumber = 0;
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            textInFile[line][charNumber] = 0; // NULL termination
            line++;
            charNumber = 0;
        }
        else if(charRead != ' ')
        {
            textInFile[line][charNumber] = charRead;
            charNumber++;
        }
        charRead = fgetc(file);
    }
    textInFile[line][charNumber] = 0; // NULL termination

    return textInFile;
}
2 голосов
/ 17 февраля 2011

Сделайте это:

if(charRead == '\n')
    {
        textInFile[line] = (char*) malloc(sizeof(char) * (numChars+1));
        line++;
        numChars = 0;
    }

Тогда:

 if(charRead == '\n')
    {
        textInFile[line][charNumber]='\0';
        line++;
        charNumber = 0;
    }

Также вы читаете файл 3 раза! В этой ветке есть хорошее объяснение того, как эффективно читать файл.

2 голосов
/ 17 февраля 2011

Вы не завершаете свои массивы.Это, вероятно, объясняет обе проблемы.Обязательно выделите дополнительный символ для нулевого терминатора.

...