2015-02-11 85 views
-1

我已经搜索并搜索了解决方案,可以找到关于int,float,double,但不包含char *的多维数组的大量答案。我认为我掌握了指针的原理,知道char,char *和char []等之间的区别,但是指向二维char指针数组的指针已经变得更好了。我试图解析一个csv文件,并用字符串(char *)填充我的二维数组。这里是我的代码:使用C读取csv文件的字符串到2D char *数组使用C

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

#define COLS 10 
#define ROWS 1000 

int main (void) { 
     char***myarray; 
     FILE *fp; 
     char charTemp[100]; 
     char *varTemp = NULL; 
     char *strTemp = NULL; 
     int i, j; 

     // allocate memory to hold array ROWS 
     if ((myarray = (char***) malloc(ROWS * sizeof(char**))) == NULL) 
      return -1; 

     // then allocate memory to hold array COLS 
     for (i = 0; i < ROWS; i++) 
     { 
      if ((myarray[i] = (char**) malloc(COLS * sizeof(char**))) == NULL) 
       return -2; 
     } 

     // read file 
     if ((fp = fopen ("myfile.csv", "r")) == NULL) 
      return -3; 

     // parse and fill 'myarray' 
     i = 0; 
     j = 0; 

     while (!feof(fp) && fgets(charTemp, sizeof charTemp, fp)) { 
       strTemp = strtok(charTemp, ","); 
       while (strTemp != NULL) { 
        sscanf(strTemp, "%s", &varTemp); 
        myarray[i][j] = varTemp; 
        printf("%s ", myarray[i][j]); 
        j++; 
        if (j > COLS - 1) 
         j = 0; 
        strTemp = strtok(NULL, ","); 
       } 
       printf("\n"); 
       i++; 
      } 
     return 0; 
} 

myfile.csv看起来是这样的:

ABCD,1,0.2,0.5,0,A123,ZZ,1,120,1 
BCDE,1.038,0,0.525,0,B321,YY,1.25,100,0.7 
CDEF,1,0.2,0.5,0,C3P0,XX,1,120,1 
DEFG,,,,,,,,, 
EFGH,1,0.3,0.8,0,R2D2,WW,1.25,120,1 
FGHI,,,,,,,,, 
etc..... 

我知道有些是整型和浮点等,但我想他们都去为char *然后我就可以ATOI或者什么时候我需要使用它们。

printf只是查看我已加载测试的内容。如果我使用令牌%。* s显示,如果使用%s,则在printf行处显示segfaults。我认为这意味着我在我的字符串末尾缺少空指针?

调试建议varTemp使用内存越界。此外,在第一个键后没有数据的行上使用带有%.*s的printf时,它将在COL 1位置打印COL 0以及应该有NULL指针。即:

ABCD 1 0.2 0.5 0 A123 ZZ 1 120 1 
BCDE 1.038 0 0.525 0 B321 YY 1.25 100 0.7 
CDEF 1 0.2 0.5 0 C3P0 XX 1 120 1 
DEFG DEFG 
EFGH 1 0.3 0.8 0 R2D2 WW 1.25 120 1 
FGHI FGHI 
etc..... 

我很困惑,有什么想法?

+0

'char *** myarray;'......不,我不是一个三星程序员。我也很困惑:-) – 2015-02-11 11:27:35

+1

首先,[在C中你不应该使用'malloc'结果](http://stackoverflow.com/questions/605845/do-i-cast-the-result-的-的malloc)。要继续,请看看分配内存的第二个循环,以及它分配的内容。然后意识到你所设置的所有'myarray [i] [j]'指针,你设置的完全一样。 – 2015-02-11 11:28:43

+1

哦,你不需要在循环条件中检查'!feof(fp)',如果你在*'feof(fp)之前命中文件结束并退出循环,'fgets'将返回'NULL'返回true。 – 2015-02-11 11:30:35

回答

2

你从不为varTemp分配空间,你需要的scanf() d字符串空间存储,所以你可以试试这个

char varTemp[100]; 

scanf()这样

sscanf(strTemp, "%99s", varTemp); 

,然后复制varTemp字符串由malloc() ing,然后strcpy() ing。

您需要复制字符串的原因是因为您将在后续调用sscanf()时覆盖它,因此您将其复制并使用varTemp作为缓冲区来存储scanf() ed字符串。

而且Don't cast malloc(),这!feof(fp)检查在while环是多余的,它永远不会是真实的,因为当你到达文件的末尾fgets()将返回NULL并在那之后feof()将是真实的,所以它从来没有当评估它会返回true。

它不会在这种情况下,因为sizeof(char *) == sizeof(char **)重要,但作为一项规则,你应该malloc()一个明星小于指针,你是malloc()荷兰国际集团的,所以

if ((myarray[i] = malloc(COLS * sizeof(char *))) == NULL) 

会更容易理解,并且在失败时你只需从main()返回而不释放先前分配的指针。

最后,如果COLSROWS是固定值,也绝对没有必要malloc()除非你的阵列将在稍后调整或他们是太大堆栈来保存它们。

char *varTemp是一个指针,它是有效的,应该指向的地方,你可以把它通过malloc()通过请求来自操作系统,somewher点的地方,像

char *varTemp; 
varTemp = malloc(NumberOfBytesIWant); 
if (varTemp == NULL) 
    ohNo_TheSystemDidNotGiveMeMemory_PerhapsThereIsNoMemoryLeft_IShouldNotContinue(); 
/* now varTemp is accessible and you are allowed to write NumberOfBytesIWant 
* into it. But you must remember to calll 'free(varTemp)' later when you no 
* longer need the data. 
*/ 

I'ts不是唯一的方法你可以把它指向某个地方,这样你就可以动态地分配空间,而且当你找到需要的字节数时,这通常是适当的解决方案,然后只需要索要这个数量,没有其他的东西,不过也是这样工作

char array[100]; 
char *varTemp; 

varTemp = array; 

数组在c衰减到指针,所以上面是有效的,在这个例子中varTemp也可以访问,你可以例如sscanf(sourceString, "%99s", varTemp);

但是,当您没有指向任何有效的内存地址与您的指针,尝试访问它是未定义的行为,因为它的未定义指针指向。

+0

感谢iharob,非常丰富。澄清,如何来char * varTemp是不好的和char varTemp [100]是必需的? sscanf是否需要一个字符数组来用作缓冲区而不是链接列表? – Charlton 2015-02-11 13:37:13

+0

@ user4554380我想我现在已经说清楚了,如果我没有请让我知道。 – 2015-02-11 13:52:00

相关问题