Как выделить память для строк файла в C? - PullRequest
0 голосов
/ 06 июня 2019

Я создал функции, которые должны находить количество строк в файле (find_numlines ()), и функцию для чтения строк файла в строки с символами *** (read_lines ()). Остальные функции в моем основном были предоставлены, поэтому проблемы не в этих функциях.

read_lines.c (ОБНОВЛЕНО):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "read_lines.h"


int findnum_lines(FILE* fp){

  int num_lines = 0;
  int line;

  line = getc(fp);
  if (line != EOF) {
    num_lines++;
    do {
      if (line == '\n') {
        num_lines = num_lines + 1;
      }
      line = getc(fp);
    }
    while (line != EOF);
  }
  rewind(fp);
  return num_lines;
}


void read_lines(FILE* fp, char*** lines, int* num_lines){

  int i;

  (*lines) = malloc(*num_lines * sizeof(char*));

  for (i=0; i < *num_lines; i++)
  {
    (*lines)[i] = malloc(1000);
    (*lines)[i][0] = '\0';
    fgets((*lines)[i], 1000, fp);
  }
}

main.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "read_lines.h"


void print_lines(char** lines, int num_lines){
    int i;
    for(i = 0 ; i < num_lines; ++i){
        printf("%d. %s", i+1, lines[i]);
    }
}

void free_lines(char** lines, int num_lines){
    int i;

    for(i = 0 ; i < num_lines; ++i){
        free(lines[i]);
    }

    if(lines != NULL && num_lines > 0){
        free(lines);
    }

}

FILE* validate_input(int argc, char* argv[]){

    FILE* fp = NULL;

    if(argc < 2){
        printf("Not enough arguments entered.\nEnding program.\n");
        exit(0);
    }
    else if(argc > 2){
        printf("Too many arguments entered.\nEnding program.\n");
        exit(0);
    }

    fp = fopen(argv[1], "r");

    if(fp == NULL){
        perror("fopen");
        printf("Unable to open file: %s\nEnding program.\n", argv[1]);
        //fprintf(stderr, "Unable to open file %s: %s\n", argv[1], strerror(errno));
        exit(0);
    }

    return fp;

}


int main(int argc, char* argv[]){
    char** lines = NULL;
    int num_lines = 0;
    FILE* fp = validate_input(argc, argv);

    num_lines = findnum_lines(fp);
    read_lines(fp, &lines, &num_lines);
    print_lines(lines, num_lines);
    free_lines(lines, num_lines);
    fclose(fp);

    return 0;
}

read_lines.h:

#ifndef READ_LINES
    #define READ_LINES
    #include <stdio.h>
    void read_lines(FILE* fp, char*** lines, int* num_lines);
    int findnum_lines(FILE* fp);
#endif

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

Файл примера normal.txt:

Hello Class
This is what I would call a normal file
It isn't very special
But it still is important

Выход должен быть:

1. Hello Class
2. This is what I would call a normal file
3. It isn't very special
4. But it still is important

1 Ответ

1 голос
/ 07 июня 2019

В следующем коде я добавил команду rewind (упомянутую xing) и выделение памяти для каждой строки и «таблицы строк». Дальнейшие улучшения были выполнены в коде для подсчета строк и обработки ошибок.

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

int findnum_lines(FILE* fp){

  int num_lines = 0;
  int c;

  c = getc(fp);
  if (c != EOF) {
    num_lines++;
    do {
        if (c == '\n') {
            num_lines = num_lines + 1;
        }
        c = getc(fp);
    }
    while (c != EOF);
  }
  rewind(fp);
  return num_lines;
}

void read_lines(FILE* fp, char*** lines, int* num_lines){

  int i;

  // allocate memory for pointers to start of lines
  (*lines) = malloc(*num_lines * sizeof(char*));

  for (i=0; i < *num_lines; i++)
  {
    (*lines)[i] = malloc(1000);
    (*lines)[i][0] = '\0'; // terminate for the case that last line does not contain characters
    fgets((*lines)[i], 1000, fp); // read up to 999 characters and terminate string
  }

}

void print_lines(char** lines, int num_lines){
    int i;
    for(i = 0 ; i < num_lines; ++i){
        printf("%d. %s", i+1, lines[i]);
    }
    printf("\n");
}

void free_lines(char** lines, int num_lines){
    int i;
    for (i = 0 ; i < num_lines; ++i) {
        if (lines[i]!=NULL) {
            free(lines[i]);
        }
    }
    if (lines != NULL){
        free(lines);
    }
}

FILE* validate_input(int argc, char* argv[]){

    FILE* fp = NULL;

    if (argc < 2){
        printf("Not enough arguments entered.\n");
    }
    else if (argc > 2){
        printf("Too many arguments entered.\n");
    }
    else {
        fp = fopen(argv[1], "r");
        if (fp == NULL){
            printf("Unable to open file: %s\n", argv[1]);
        }
    }
    return fp;
}


int main(int argc, char* argv[]){
    char** lines = NULL;
    int num_lines = 0;
    FILE* fp = validate_input(argc, argv);
    if (fp != NULL)
    {
        num_lines = findnum_lines(fp);
        read_lines(fp, &lines, &num_lines);
        print_lines(lines, num_lines);
        free_lines(lines, num_lines);
        fclose(fp);
    }
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...