将文件中的文本逐行插入到指针传递的字符串数组中的函数

时间:2019-06-01 06:16:01

标签: c fgets getline

我正在尝试创建一个函数read_lines,该函数需要一个文件* fp,一个指向char **行的指针以及一个指向int num_lines的指针。该函数应将每一行文本插入到行中,并将num_lines增加到文件包含的行数。

它可能真的很简单,但是我已经尝试插入文本几个小时了。

这是main.c的外观。除了read_lines之外的所有东西都已经定义并且可以正常工作。

int main(int argc, char* argv[]){

    char** lines = NULL;
    int num_lines = 0;
    FILE* fp = validate_input(argc, argv);
    read_lines(fp, &lines, &num_lines);
    print_lines(lines, num_lines);
    free_lines(lines, num_lines);
    fclose(fp);

    return 0;
}

这是我尝试添加行的尝试之一,但我无法弄清楚。

read_lines.c

void read_lines(FILE *fp, char ***lines, int *num_lines) {
    int i;
    int N = 0;
    char s[200];
    for (i=0; i<3; i++)
    {
        while(fgets(s, 200, fp)!=NULL){N++;}
        char strings[50][200];

        rewind(fp);
        fgets(s, 200, fp);
        strcpy(lines[i],s);
    }

}

感谢您为解决此问题提供的帮助。

3 个答案:

答案 0 :(得分:2)

一种解决方案(不包含标题和错误检查以提高可读性)

void read_lines(FILE *stream, char ***lines_ptr, size_t *num_lines_ptr) {
   char **lines = NULL;
   size_t num_lines = 0;
   char *line = NULL;
   size_t len = 0;
   ssize_t nread;
   while ((nread = getline(&line, &len, stream)) != -1) {
      lines = lines == NULL
         ? malloc(sizeof(char*))
         : realloc(lines, (num_lines+1)*sizeof(char*));

      lines[num_lines] = malloc(nread+1);
      memcpy(lines[num_lines], line);
      ++num_lines;
   }

   free(line);
   *lines_ptr = lines;
   *num_lines_ptr = num_lines;
}

完整解决方案:

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

// lines_ptr:     Output. Initial value ignored. To be freed by caller on success.
// num_lines_ptr: Output. Initial value ignored.
// Returns:       0 on error (errno set). 1 on success.
int read_lines(FILE *stream, char ***lines_ptr, size_t *num_lines_ptr) {
   char ***lines = NULL;
   size_t num_lines = 0;
   char *line = NULL;
   size_t len = 0;
   ssize_t nread;
   while ((nread = getline(&line, &len, stream)) != -1) {
      char **new_lines = lines == NULL
         ? malloc(sizeof(char*))
         : realloc(lines, (num_lines+1)*sizeof(char*));
      if (new_lines == NULL)
         goto error;

      lines = new_lines;

      lines[num_lines] = malloc(nread+1);
      if (lines[num_lines] == NULL)
         goto error;

      memcpy(lines[num_lines], line);
      ++num_lines;
   }

   if (ferror(stream))
      goto error;

   free(line);
   *lines_ptr = lines;
   *num_lines_ptr = num_lines;
   return 1;

error:
   for (size_t i=num_lines; i--; )
      free(lines[i]);

   free(lines);
   free(line);
   *lines_ptr = NULL;
   *num_lines_ptr = 0;
   return 0;
}

(您可以通过使用..._ptr变量来保存三行,而不用在末尾设置它们,但这真的值可读性吗?)

答案 1 :(得分:0)

我发现fget难以使用,麻烦也超过了它的价值。这是一种基于fgetc和基于malloc的方法:

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

    size_t line = 0;
    size_t pos  = 0;
    size_t len  = 64;
    *lines = malloc(1 * sizeof(char*));
    (*lines)[0] = malloc(len);
    while ((c = fgetc(fp)) != EOF) {
        if (c == '\n') {
             (*lines)[line][pos] = '\0';
             line++;
             pos = 0;
             len = 64;
             *lines = realloc(*lines, (line+1) * sizeof(char*));
        } else {
            (*lines)[line][pos] = c;
        }
        pos++;
        if (pos >= len) {
            len *= 2;
            (*lines)[line] = realloc((*lines)[line], len);
        }
    }
    *num_lines = line+1;
}

我还没有检查这个问题,所以如果我有任何错误,请纠正我。另外,在真实代码中,您将在这里进行很多错误检查,而我已经省略了。

答案 2 :(得分:-1)

assuming you have allocated enough memory to lines, following should work
if not you have to malloc/calloc() for lines[i] before doing strcpy() in every 
iteration of the loop.


void read_lines(FILE *fp, char ***lines, int *num_lines) {
       int N = 0;
       char s[200];
       while(fgets(s, 200, fp)!=NULL){
             N++;
             strcpy((*lines)[N],s);
       }
       *num_lines = N; // update pointer with value of N which is number of lines in file
}