Распечатать последние несколько строк текстового файла - PullRequest
0 голосов
/ 22 февраля 2019

В настоящее время я пытаюсь создать программу на C, которая печатает последние несколько строк текстового файла, прочитанного через командную строку.Однако, в настоящее время это вызывает ошибку сегментации, когда я пытаюсь скопировать строки из fgets в основной массив.Я не смог это исправить, и поэтому не смог протестировать остальную часть моего кода.Как бы я начал исправлять ошибку сегментации?Я разместил код ниже:

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

int main(int argc, char *argv[])
{
   int i=1,j,printNumber;
   char **arr = (char **) malloc (100 * sizeof(char *));
   char *line = (char *) malloc (80 * sizeof(char));

   if (argc == 1) {
      printNumber = 10;
   }
   else {
      printNumber = atoi(argv[1]);
   }

   while (fgets(line,80,stdin) != NULL) {
      if (line != NULL) {
         line[strlen(line)-1] = '\0';
         strcpy(arr[i],line);  //SEGMENTATION ERROR!!!!
      }
      else {
         free(line);
         strcpy(arr[i],NULL);
      }
      i++;
      printf("%d ",i);
   }
   free(arr);

   for (j = i-printNumber-1; j < i-1; j++) {
      printf("%s ", arr[j]);
   }
   printf("\n");
   return 0;
}

Ответы [ 2 ]

0 голосов
/ 23 февраля 2019

Вы не всегда знаете длину самой длинной строки (не до тех пор, пока не попытаетесь прочитать) ИЛИ сколько последних строк вы должны отслеживать (но дается во время выполнения).Таким образом, оба этих значения должны быть известны до того, как вы выделите память или делегированы функции, которая делает это за вас.

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

struct Line {
    char *line; // content
    size_t storage_sz; // allocation size of line memory
    ssize_t sz; // size of line, not including terminating null byte ('\0')
};

int main(int argc, char *argv[]) {
    int max_lines = 10;
    if (argc > 1) {
        max_lines = atoi(argv[1]);
    }
    if (max_lines < 0) {
        fprintf(stderr, "%s\n", "Sorry, no defined behaviour of negative values (yet)\n");
        return EXIT_FAILURE;
    }

    // keep an extra slot for the last failed read at EOF
    struct Line *lines = (struct Line *) calloc(max_lines + 1, sizeof(struct Line));
    int end = 0;
    int size = 0;

    // only keep track of the last couple of lines
    while ((lines[end].sz = getline(&lines[end].line, &lines[end].storage_sz, stdin)) != -1) {
        end++;
        if (end > max_lines) {
            end = 0;
        }
        if (size < max_lines) {
            size++;
        }
    }

    // time to print them back
    int first = end - size;
    if (first < 0) {
        first += size + 1;
    }
    for (int count = size; count; count--) {
        // lines might contain null bytes we can't use printf("%s", lines[first].line);
        fwrite(lines[first].line, lines[first].sz, 1u, stdout);
        first++;
        if (first > size) {
            first = 0;
        }
    }

    // clear up memory after use
    for (int idx = 0; idx <= max_lines; idx++) {
        free(lines[idx].line);
    }
    free(lines);
    return EXIT_SUCCESS;
}
0 голосов
/ 23 февраля 2019

Вы выделяете пространство для arr, который является указателем на указатель на char, но не выделяет какие-либо отдельные char * указатели в arr.

Поскольку вы выделили arrс размером 100 * sizeof(char *) я предполагаю, что вы хотите 100 вложенных записей в arr.Конечно:

for(i = 0; i < 100; i++)
     arr[i] = malloc(80 * sizeof(char));

Затем при освобождении arr:

for(i = 0; i < 100; i++)
    free(arr[i]);

free(arr);

Обратите внимание, что рекомендуется всегда проверять malloc на неудачу (возвращаемое значение NULL) и обработать его, а также установить указатели на NULL после их однократного освобождения, чтобы избежать двойных ошибок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...