2

我想读取一个文件并将每一行写入char数组。由于我不知道行数,因此我认为最有效的方法是使用 char 指针的二维数组。但是我得到分段错误。

我的问题可能与这个问题重复: 2D array of char pointers --> Segmentation fault?

但我想不出 C 的正确语法,所以我无法尝试。

这是我的代码:

   FILE *file = fopen ( filename, "r" );
   if ( file != NULL )
   {
        char line [ 128 ]; /* or other suitable maximum line size */
        char **new_line;
        int i = 0;
    while ( fgets ( line, sizeof line, file ) != NULL ) /* read a line */
    {
        strcpy(new_line[i], line);
        i++;
    }
4

5 回答 5

2

未分配内存new_line导致分段错误。

如果您知道行数,则可以将其声明为本地数组本身。在这种情况下,您的访问方法将正常工作。

#define MAX_LINES 20
#define MAX_CHARS 128
...
char new_line[MAX_LINES][MAX_CHARS] = {0};
...

您的问题是您不知道最大行数。所以你选择了双指针。在这种情况下,您需要首先malloc使用一些n行数,然后您需要继续使用realloc以增加缓冲区大小。

#define MAX_CHARS 128
#define N_NO_OF_LINES 10
...
char line[MAX_CHARS] = {0};
char **new_line = NULL;
int noOfLines = 0;
int lineCount = 0;

new_line = malloc(sizeof(char*) * N_NO_OF_LINES);
noOfLines = N_NO_OF_LINES;

while (fgets (line, sizeof line, file) != NULL) /* read a line */
{
    if (lineCount >= noOfLines)
    {
        new_line = realloc(new_line, (sizeof(char*)*(noOfLines+N_NO_OF_LINES)));
        noOfLines += N_NO_OF_LINES;
    }

    new_line[lineCount] = strdup(line);
    lineCount++;
}

注意:注意空检查mallocrealloc

于 2013-01-16T05:16:04.450 回答
1

new_line 未初始化为有效的内存块。

大致:

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

int main() {
    FILE *file = fopen ( "test.txt", "r" );
    if ( file != NULL )
    {
#define MAXLINES 128
#define MAXLINELEN 100
       char line [ MAXLINELEN ]; /* or other suitable maximum line size */
       char **new_line = (char **)malloc(sizeof(char *) * MAXLINES);
       int i = 0;

        if (!new_line) exit(-1);

        while ( i < MAXLINES && (fgets ( line, sizeof line, file ) != NULL )) /* read a line */
        {
            new_line[i] = strdup(line);
            i++;
        }
        printf("read %d lines\n", i);
    }
    exit(0);
}
于 2013-01-16T00:19:04.497 回答
0

您需要为字符串分配空间。Malloc 返回一个具有您想要的大小的内存槽,但不允许内存重新分配。为此,您有realloc

使用 malloc,您最终会得到一个固定大小的表,就像您只声明它具有静态但稍后初始化一样(好吧,我有点反对这句话,因为 malloc 远不止于此,但对于这个目的可以安全地说出来)。

Realloc 会这样做,重新分配内存,但如果你没有正确使用 i ,它可能会非常危险。而且,在我看来,这不是最正确的方法。

当你想保存一些你不知道大小的东西时,动态结构是要走的路。您可以使用“类似链接列表”的数据结构,这样您就可以拥有任意数量的单词,然后将该列表转换为数组。

我会用这样的东西:

typedef struct _words{ //Structure to the dynamic insertion of words
  char *word;
  struct _words *next;
}words;

words *last;          //Easier implementation for this case. Not always the best solution

words *init(){        //Is good practice to start with an empty structure for reference passing 
  words *new = malloc(sizeof(words));
  if(new == NULL) exit(0);
  new->next = NULL;   //A good end/next reference
  return new;
}

void insertWord(char *word){
  words *new = malloc (sizeof(words));
  if(new == NULL) exit(0);
  new->word = malloc(strlen(word)*sizeof(char));
  if(new->word == NULL) exit(0);
  new->next = NULL;   //Or new->next = last->next; wich is also null. 
  last->next = new;
  last = new;
}

int main(){           //Or the name of your function
 FILE *file = fopen ( filename, "r" );
 words *list = init();
 last = list;
   if ( file != NULL )
   {
        char line [ 128 ]; /* or other suitable maximum line size */
        int i = 0;
    while ( fgets ( line, sizeof line, file ) != NULL ) /* read a line */
    {
        insertWord(line);
        i++;
    }

    //Here, you already have all the words in your dynamic structure. You can now save them into an array

    char **array = malloc(i*sizeof(char*));   //i is the number of words.
    if(array == NULL) exit(0);
    word *aux = list->next;
    if(aux != NULL){
     for(int j=0;j<i && aux != NULL;j++){
         array[j] = malloc(strlen(aux->word)*sizeof(char));
         if(array[j] == NULL) exit(0);
         strcpy(array[j], aux->word);
         aux = aux->next;                     // jump to the next word
     }
    }
  ...
}

我认为这可能有效,但我没有尝试过。只是为了让您了解如何实现动态结构。

它错过了释放并且不是实际的堆栈,即使是关闭的。

希望这可以帮助。

于 2013-01-16T01:19:26.127 回答
0

您没有为new_line数组分配任何内存。你需要类似的东西:

char **new_line = malloc(sizeof(char *) * MAX_LINES);

然后对于每一行,不要使用strcpy,它将复制到垃圾指针(未初始化的new_line数组)中。你可能想要strdup(3)

new_line[i] = strdup(line);
于 2013-01-16T00:12:47.343 回答
0

您声明new_line为指向 的指针char *,但它从未初始化,因此它指向一些无效的内存地址。当您写入该地址时,您会收到错误消息。

您可能想要分配内存,将其分配给new_line,然后您可以将字符串复制到其中。

于 2013-01-16T00:13:43.557 回答