【问题标题】:Using 2D array of char pointer in C在 C 中使用 char 指针的二维数组
【发布时间】:2012-12-30 05:39:36
【问题描述】:

我想读取一个文件并将每一行写入 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++;
    }

【问题讨论】:

  • 你没有为new_line分配任何内存

标签: c pointers char segmentation-fault


【解决方案1】:

没有为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++;
}

注意:注意对 malloc 和 realloc 进行空检查

【讨论】:

  • 对于realloc,它给出了一个错误并说参数太少了。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

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

    new_line[i] = strdup(line);
    

    【讨论】:

    • 不知何故我收到char **new_line = malloc(sizeof(char *) * MAX_LINES); 的警告消息,这是不兼容的隐式声明。
    • 您需要#include &lt;stdlib.h&gt; 才能获得malloc() 的原型。
    • 哦,对不起,我的错。有点奇怪,它实际上在“fclose (file);”的程序中给出了这个错误。其中错误为*** glibc detected *** ./vidprocess: corrupted double-linked list: 0x0000000000ce2270 ***
    • 真的吗?使用您在这里展示的程序?你不能向我们展示什么。
    • pastebin.com/sWDHMpP0 这是函数本身。如果我注释掉 fclose(file) 它工作得很好,如果我不这样做,我就会得到那个错误......
    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

      您需要为字符串分配空间。 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
           }
          }
        ...
      }
      

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

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

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-11
        • 1970-01-01
        • 2018-01-04
        • 2017-04-26
        • 1970-01-01
        • 2017-06-11
        • 1970-01-01
        • 2023-03-29
        相关资源
        最近更新 更多