2016-01-29 1 views
0

Я действительно новичок в C, и я хочу создать программу, которая читает два входных файла, которые включают только строки. Я создал для связанных строк файла. Я имею дело с какой-то проблемой, и я не мог понять, там есть какая-то ошибка сегментации. (Спросил-иа)Чтение строк файлов

Вот мой код:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <stdbool.h> 

typedef struct linked_list { 
    char my_data[256]; 
    struct linked_list *next_it; 
} node_t; 

int main(int argc, char *argv[]) { 
    /* 
    if(argc != 4) { 
     fprintf(stderr, "Requiring 2 input 1 output file name to start!\n"); 
     exit(EXIT_FAILURE); 
    }*/ 

    FILE *my_s; 
    FILE *my_f; 
    // FILE *my_o; 
    bool mybool = true; 
    int my_ch; // our char to read 
    char my_buffer[256]; 
    bool check_all = true; 

    node_t *set_a = malloc(sizeof(node_t)); 
    node_t *set_b = malloc(sizeof(node_t)); 
    my_f = fopen(argv[1], "r"); // first textfile to read 
    my_s = fopen(argv[2], "r"); // second textfile to read 

    if (my_f != NULL && my_s != NULL) { 
     while (fgetc(my_f) != EOF && mybool != false && check_all != false) { 
      my_ch = fgetc(my_f); 
      int i = 0; 
      while (my_ch >= 0) { 
       my_buffer[i++] = my_ch; 
       my_ch = fgetc(my_f); 
      } 
      strcpy(set_a->my_data, my_buffer); 
      if (feof(my_f)) { 
       mybool = false; 
      } else { 
       set_a->next_it = malloc(sizeof(node_t)); 
       set_a = set_a->next_it; 
      } 
     } 
     mybool = false; 
     printf("First File Copy Done!\n"); 
     while (fgetc(my_s) != EOF && mybool != true && check_all != false) { 
      my_ch = fgetc(my_s); 
      int i = 0; 
      while (my_ch >= 0) { 
       my_buffer[i++] = my_ch; 
       my_ch = fgetc(my_s); 
      } 
      strcpy(set_b->my_data, my_buffer); 
      if (feof(my_s)) { 
       check_all = false; 
      } else { 
       set_b->next_it = malloc(sizeof(node_t)); 
       set_b = set_b->next_it; 
      } 
     } 
     printf("Second File Copy Done!\n"); 
    } else { 
     fprintf(stderr, "Cannot read from %s and %s\n", argv[1], argv[2]); 
    } 

    while (set_a != NULL) { 
     int j = 0; 
     printf("No: %d, Var: %s",j++, set_a->my_data); 
     node_t *set_c = set_a; 
     set_a = set_a->next_it; 
     free(set_c); 
    } 
    while (set_b != NULL) { 
     int j = 0; 
     printf("No: %d, Var: %s",j++, set_b->my_data); 
     node_t *set_c = set_b; 
     set_b = set_b->next_it; 
     free(set_c); 
    } 
    return 0; 
} 
+1

Ваш код не был отступом. Научитесь отступать от кода и использовать пробелы, чтобы прочитать код. Изучите, как я переформатировал его и сделаю это по мере ввода, это поможет вам избежать многих глупых ошибок. – chqrlie

ответ

0

Вашего кода имеет несколько проблем:

  • Вы инициализировать список с неинициализированным первым узлом. Нет способа проверить что-либо в этом узле ... Почему бы не инициализировать пустой список как NULL.
  • Вы проверяете конец файла, читая следующий байт из каждого файла, но вы не храните этот байт ... поэтому он теряется. Позже вы проверяете feof(my_s), но эта функция не делает то, что вы думаете. Гораздо лучше проверить fgetc() возвращает EOF, но сохраните байт, который он прочитал.
  • Почему вы начинаете каждое локальное имя переменной с my или my_, это не помогает, просто используйте короткие имена, они вообще не должны обозначать что-либо глобальное.
  • Вы не держите указатель на голову каждого списка, вы устанавливаете set_a и set_b, чтобы указать на следующий узел, теперь нет возможности найти начальную часть списков.
  • Сбрасывается j на 0 на каждой итерации печати и свободного цикла, все узлы будут печатать с номером 0.
  • Вы должны использовать функции для загрузки, печати и освобождения списков, чтобы избежать повторения одного и того же кода дважды.

Вот улучшенная версия:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <stdbool.h> 

typedef struct linked_list { 
    char *data; 
    struct linked_list *next; 
} node_t; 

node_t *load_lines(const char *filename) { 
    node_t *head = NULL; 
    FILE *fp = fopen(filename, "r"); 
    if (fp != NULL) { 
     char buffer[256]; 
     size_t i = 0; 
     int c; 
     node_t **tailp = &head; 

     for (;;) { 
      c = fgetc(fp); 
      if (c != EOF && c != '\n') { 
       if (i < sizeof(buffer) - 1) { 
        buffer[i++] = c; 
       } 
       continue; 
      } 
      if (i > 0) { 
       buffer[i] = '\0'; 
       /* allocate a new node */ 
       *tailp = malloc(sizeof(**tailp)); 
       (*tailp)->next = NULL; 
       (*tailp)->data = strdup(buffer); 
       tailp = &(*tailp)->next; 
       i = 0; 
      } 
      if (c == EOF) { 
       break; 
      } 
     } 
     fclose(fp); 
    } 
    return head; 
} 

void print_word(node_t *np) { 
    int j = 0; 
    while (np != NULL) { 
     printf("No: %d, Var: %s", j++, np->data); 
     np = np->next; 
    } 
} 

void free_words(node_t *np) { 
    while (np != NULL) { 
     node_t *next = np->next; 
     free(np->data); 
     free(np); 
     np = next; 
    } 
} 

int main(int argc, char *argv[]) { 
    /* 
    if (argc != 4) { 
     fprintf(stderr, "Requiring 2 input 1 output file name to start!\n"); 
     exit(EXIT_FAILURE); 
    }*/ 

    node_t *set_a, *set_b; 

    if ((set_a = load_words(argv[1])) != NULL) { 
     printf("First File Copy Done!\n"); 
    } 
    if ((set_b = load_words(argv[2])) != NULL) { 
     printf("Second File Copy Done!\n"); 
    } 
    if (!set_a && !set_b) { 
     fprintf(stderr, "Cannot read from %s and %s\n", argv[1], argv[2]); 
    } 

    print_words(set_a); 
    free_words(set_a); 
    print_words(set_b); 
    free_words(set_b); 
    return 0; 
} 
+0

Большое вам спасибо, сэр. Я тоже рассмотрел ваши заметки. Best, -ua –

+0

На самом деле, это работает очень хорошо, но из моего собственного примера входного файла код не выводит последнюю строку строки. (т. е. печатает 24 из 25, без последней строки). Я думаю, что последняя строка строки отсутствует в нашем связанном списке, потому что в части print_word она заканчивается после достижения переменной NULL. –

+0

. В приведенном выше коде предполагается, что файл заканчивается линией перевода строки. Если в последней строке файла нет окончательного '\ n', он не добавляется в связанный список. Я должен изменить код для обработки этого случая, но для всех текстовых файлов предпочтительнее иметь окончательный фид строки. – chqrlie

0

Вы не указывая хвост из двух связанных списков в «NULL» после достижения конца файла и вы не maitaining головы каждого связанного списка. Вы меняете голову каждый раз, читая строку. Таким образом, на заключительном этапе «set_a» и «set_b» стал последним узлом без NULL хвоста

Смежные вопросы