Чтение данных текстового файла в массив структур (без учета строк комментариев) - PullRequest
0 голосов
/ 08 апреля 2020

Обзор:

Цель следующей программы - построчно считывать данные из входного файла в массив структур, одновременно игнорируя любые строки комментариев во входном файле. которые начинаются с character '#'. Затем программа должна выполнить итерацию по массиву структур и распечатать содержимое, чтобы подтвердить, что программа работает должным образом.

Вот пример входного файла, где 3 строки данных без комментариев видимы. Количество строк без комментариев известно до компиляции, как видно из следующей попытки: int Nbodies = 3.

30 07 6991
# some comment
28 02 4991
09 09 2991

Примечание: Обратите внимание, что следующие вопросы SO среди прочего, были изучены, прежде чем решить опубликовать этот вопрос:

Чтение текстового файла и игнорирование закомментированных строк в C

Игнорирование комментариев при чтение в файле

Чтение текстового файла без учета комментариев

Дилемма:

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

Это ожидаемый результат:

30 07 6991
28 02 4991
09 09 2991

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

30 07 6991
-842150451 -842150451 -842150451
28 02 4991

Текущая попытка:

fgets был использован для чтения каждой строки и, таким образом, определения, начинается ли начало строки с '#'. Эта проверка комментариев выполняется в операторе IF, который увеличивает переменную Nbodies в условии FOR l oop (чтобы итерация не терялась в строке комментария, если это имеет смысл?) , После этого sscanf используется при попытке прочитать три значения текущей строки без комментариев в массив структур. fscanf также был попыткой метода, который не работал. При использовании continue; в выражении IF, показанном в примере, не следует ли пропускать sscanf при обнаружении строки комментария? Кажется, он работает не так, как ожидалось.

Код до сих пор:

#include "stdio.h"

#define EXIT_SUCCESS 0
#define EXIT_FAILURE !EXIT_SUCCESS

int main() {

    typedef struct {
        int a1, b1, c1;
    }DATA;

    FILE *file = fopen("delete.nbody", "r");
    if (file == NULL)
    {
        printf(stderr, "ERROR: file not opened.\n");
        return EXIT_FAILURE;
    }

    int Nbodies = 3;
    int comment_count = 0;
    DATA* data = malloc(Nbodies * sizeof * data); // Dynamic allocation for array
    char line[128]; // Length won't be longer than 128
    int x;
    for (x = 0; x < Nbodies; x++)
    {
        fgets(line, sizeof(line), file);
        if (line[0] == '#')
        {
            comment_count++;
            Nbodies++;// Advance Nbodies so that iteration isn't 'wasted' on a comment line
            continue;
        }

        // QUESTION: doesn't "continue;" within above IF mean that the 
        // following sscanf shouldn't scan the comment line?
        sscanf(line, "%d %d %d", &data[x].a1, &data[x].b1, &data[x].c1);
    }

    // Nbodies - comment_count, because Nbodies advanced
    // every time a comment was detected in the above FOR loop
    for (x = 0; x < Nbodies - comment_count; x++)
    {
        printf("%d %d %d\n", data[x].a1, data[x].b1, data[x].c1);
    }

    return (EXIT_SUCCESS);
}

Вопрос:

Может кто-нибудь увидеть, почему эта программа не будет работать? Я бы подумал, что слово continue пропустило бы sscanf при чтении строк комментариев. Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

1 голос
/ 08 апреля 2020

Если вы получили комментарий, то не с шагом Nbodies.

Это неправильный подход, поскольку data ограничен значением оригинал Nbodies из-за пре-l oop malloc

И вы введете разрыв в массиве data.

Вот лучший способ, так что data содержит только действительные данные. Строки комментариев становятся полностью «невидимыми» (то есть они не влияют на количество данных):

int
main()
{

    typedef struct {
        int a1,
         b1,
         c1;
    } DATA;

    FILE *file = fopen("delete.nbody", "r");

    if (file == NULL) {
        printf(stderr, "ERROR: file not opened.\n");
        return EXIT_FAILURE;
    }

    int Nbodies = 3;
    int comment_count = 0;

    // Dynamic allocation for array
    DATA *data = malloc(Nbodies * sizeof *data);

    char line[128]; // Length won't be longer than 128
    int x;

#if 0
    for (x = 0; x < Nbodies; x++) {
        fgets(line, sizeof(line), file);

        if (line[0] == '#') {
            comment_count++;
            // Advance Nbodies so that iteration isn't 'wasted' on a comment
            Nbodies++;
            continue;
        }

        // QUESTION: doesn't "continue;" within above IF mean that the
        // following sscanf shouldn't scan the comment line?
        sscanf(line, "%d %d %d", &data[x].a1, &data[x].b1, &data[x].c1);
    }
#else
    int inc = 1;
    for (x = 0; x < Nbodies; x += inc) {
        fgets(line, sizeof(line), file);

        inc = (line[0] != '#');

        if (! inc) {
            comment_count++;
            continue;
        }

        // QUESTION: doesn't "continue;" within above IF mean that the
        // following sscanf shouldn't scan the comment line?
        sscanf(line, "%d %d %d", &data[x].a1, &data[x].b1, &data[x].c1);
    }
#endif

    // Nbodies - comment_count, because Nbodies advanced
    // every time a comment was detected in the above FOR loop
#if 0
    for (x = 0; x < Nbodies - comment_count; x++) {
#else
    for (x = 0; x < Nbodies; x++) {
#endif
        printf("%d %d %d\n", data[x].a1, data[x].b1, data[x].c1);
    }

    return (EXIT_SUCCESS);
}
1 голос
/ 08 апреля 2020
  • увеличивает индекс массива только в том случае, если вы фактически присваиваете
  • check Оба условия: индекс массива и успех ввода

for (x = 0; x < Nbodies; ) {
        int rc;
        if ( !fgets(line, sizeof line, file)) break;
        if (line[0] == '#')
        {
            comment_count++;
            continue;
        }

        rc = sscanf(line, "%d %d %d", &data[x].a1, &data[x].b1, &data[x].c1);
        if (rc != 3) continue;
        x++; 
    }
...