打印文本文件的最后几行

时间:2019-02-22 20:51:45

标签: c

当前,我正在尝试创建一个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 :(得分:2)

您正在为arr分配空间,这是指向char的指针的指针,但没有在char *内分配任何单独的arr指针。

由于您为arr分配了100 * sizeof(char *)的大小,因此我假设您要在arr中有100个子条目。当然可以:

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以避免重复,这是一种好习惯的错误。

答案 1 :(得分:0)

您并不总是知道最长的行的长度(直到尝试阅读时才知道)或希望跟踪的最后几行(但在运行时给出)。因此,在分配内存或委托给您执行此操作的函数之前,必须先知道这两个值。

#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;
}