在C中使用char指针的2D数组

时间:2013-01-16 00:10:34

标签: c pointers char segmentation-fault

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

5 个答案:

答案 0 :(得分:2)

没有为导致分段错误的new_line分配内存。

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

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

你的问题是你不知道最大行数。所以你选择了双指针。在这种情况下,您需要先mallocn行,然后您需要继续使用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

进行空检查

答案 1 :(得分: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);
}

答案 2 :(得分:0)

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

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

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

new_line[i] = strdup(line);

答案 3 :(得分:0)

您将new_line声明为指向char *的指针,但它永远不会被初始化,因此它指向一些无效的内存地址。写入该地址时会出现错误。

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

答案 4 :(得分:0)

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

使用malloc,你最终会得到一个固定大小的表,就像你只声明它有静态但后来初始化一样(好吧,我再说一遍这句话因为malloc远不止于此,但为了这个目的,它是安全的说。)

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

如果您想保存一些您不了解尺寸的东西,那么动态结构就是您的选择。 您可以使用&#39;链接列表,例如&#39;数据结构,因此您可以拥有任意数量的单词,然后将该列表转换为数组。

我会选择这样的东西:

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
     }
    }
  ...
}

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

它错过了释放并且不是真正的堆栈,即使它已经接近了。

希望这会有所帮助。