在C中分配多维char指针

时间:2014-01-20 22:44:42

标签: c pointers multidimensional-array

我正在尝试从文件中读取行并将它们存储在多维char指针中。当我运行我的代码时,它运行没有错误,但是,我的main()函数中的行不会正确打印,而是在getline()函数中正确打印。任何人都可以解释发生了什么,以及我如何正确地将它们存储在我的多维指针中?

我的代码:

int main (int argc, const char * argv[]) {
    char **s = (char**) malloc(sizeof(char*) * 1000);
    int i = 0;
    while (getline(s[i]) != -1){
        printf("In array: %s \n", s[i]);
        i++;
    }
    return 0;
}

int getline(char *s){
    s = malloc(sizeof(char*) * 1000);
    int c, i = 0;
    while ((c = getchar()) != '\n' && c != EOF) {
        s[i++] = c;
    }
    s[i] = '\0';
    printf("String: %s \n", s);
    if (c == EOF) {
        return -1;
    }
    return 0;
}  

和我的输出:

String: First line
<br>In array: (null) 
<br>String: Second line 
<br>In array: (null) 
<br>String: Third line 
<br>In array: (null) 

4 个答案:

答案 0 :(得分:2)

你正在经历价值。即使您在*s中更改getline()的值,但主要不会看到它。您必须传递s[i]的地址,以便getline()可以更改它:

int getline(char **s) {
  * s= malloc( sizeof(char) * 1000) ;
  ...
}

此外,如果您希望内存更高效,请根据需要将该行读入本地缓冲区(大小为1000)。然后,当您完成读取该行时,仅分配存储实际字符串所需的内存。

int getline( char ** s )
{
  char tmpstr[1000] ;
  ...
    tmpstr[i++]= c ;
  }
  tmpstr[i]= '\0' ;

  * s= strdup( tmpstr) ;
  return 0 ;
}

如果你想进一步改进,那就退后一步吧。 1)在两个不同的函数中分配多维数组的两个部分将使其他人更难理解。 2)从外部传递一个临时字符串到getline()将使它变得更加简单:

int main()
{
  char ** s= (char **) malloc( 1000 * sizeof(char *)) ;
  char tmpstr[1000] ;
  int i ;

  while ( -1 != getline( tmpstr))
  {
    s[i ++]= strdup( tmpstr) ;
  }

  return 0 ;
}

int getline( char * s)
{
  int c, i = 0 ;
  while (( '\n' != ( c= getchar())) && ( EOF != c )) { s[i ++]= c ; }
  s[i]= '\0' ;

  return ( EOF == c ) ? -1 : 0 ;
} 

现在,getline只是关于IO,s的所有分配都在一个地方处理,因此更容易推理。

答案 1 :(得分:1)

问题是getline函数内的这一行

s = malloc(sizeof(char) * 1000); // Should be sizeof(char), not sizeof(char*)

对传入的s[i]指针没有影响。这是因为指针是按值传递的。

你有两个选择:

  • 将内存分配移至main,并继续传递指针,或
  • 将您的分配保留在getline中,但将指针传递给指向main的指针。

以下是您为第一个选项更改main的方式:

int main (int argc, const char * argv[]) {
    char **s = malloc(sizeof(char*) * 1000);
    int i = 0;
    for ( ; ; ) {
        s[i] = malloc(sizeof(char) * 1000);
        if (getline(s[i]) == -1) break;
        printf("In array: %s \n", s[i]);
        i++;
    }
    return 0;
}

答案 2 :(得分:0)

为什么首先使用malloc。 malloc非常危险!! 只需使用s[1000][1000]并传递&s[0][0]作为第一行,&s[1][0]作为第二行等。

打印printf("%s \n", s[i]);,其中i是您想要的行。

答案 3 :(得分:0)

我的建议:完全避免编写自己的getline()函数,并避免使用所有固定大小的缓冲区。在POSIX.1-2008标准中,已经有getline()函数。所以你可以这样做:

//Tell stdio.h that we want POSIX.1-2008 functions
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>

int main() {
    char** s = NULL;
    int count = 0;
    do {
        count++;
        s = realloc(s, count*sizeof(char*));
        s[count-1] = NULL;    //so that getline() will allocate the memory itself
    } while(getline(&s[count-1], NULL, stdin));

    for(int i = 0; i < count; i++) printf(s[i]);
}