使用 C 将字符串的 csv 文件读取到 2D char* 数组
Read csv file of strings to 2D char* array using C
我搜索并寻找了解决方案,可以找到很多关于 int、float、double 多维数组但没有 char* 的答案。我想我掌握了指针的原理,知道 char、char* 和 char[] 等之间的区别,但是指向 char 指针的二维数组的指针让我变得更好。我正在尝试解析一个 csv 文件并用字符串 (char*) 填充我的二维数组。这是我的代码:
#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 行出现段错误。我认为这意味着我在字符串末尾缺少空指针??
调试表明 varTemp 正在越界使用内存。此外,当在第一个键后没有数据的行上使用带有 %.*s
的 printf 时,它会在 COL 1 位置以及应该有 NULL
指针的位置打印 COL 0。即:
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.....
我很困惑,有什么想法吗?!
你永远不会为 varTemp
分配 space,你需要 space 来存储 scanf()
d 字符串,所以你可以试试这个
char varTemp[100];
和scanf()
这样
sscanf(strTemp, "%99s", varTemp);
然后通过 malloc()
ing 然后 strcpy()
ing 将 varTemp
字符串复制到数组。
您需要复制字符串的原因是您将在后续调用 sscanf()
时覆盖它,因此您复制它并使用 varTemp
作为缓冲区来存储 scanf()
编辑字符串。
还有Don't cast malloc()
,而这个!feof(fp)
在while
循环中的检查是多余的,它永远不会为真,因为当你到达文件末尾时fgets()
将 return NULL
之后 feof()
将为真,因此它永远不会在 return 为真时进行评估。
在这种情况下没关系,因为 sizeof(char *) == sizeof(char **)
但作为一项规则,您应该 malloc()
比您 malloc()
想要的指针少一颗星,所以
if ((myarray[i] = malloc(COLS * sizeof(char *))) == NULL)
会更容易理解,而且在失败时你只是从 main()
return 而没有释放之前分配的指针。
最后,如果 COLS
和 ROWS
是固定值,则绝对不需要 malloc()
除非您的数组稍后会调整大小或者它们太大而堆栈无法容纳它们.
char *varTemp
是一个指针,为了使它有效,它应该指向某处,您可以通过 malloc()
从 OS 请求某处来使其指向某处,例如
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.
*/
这不是让它指向某处的唯一方法,这种方法可以动态分配 space,当您找到所需的字节数时,这通常是合适的解决方案,然后只要求那个数量,不多也不少,但这也行
char array[100];
char *varTemp;
varTemp = array;
c 中的数组衰减为指针,因此上述内容有效,在此示例中 varTemp
也可访问,例如 sscanf(sourceString, "%99s", varTemp);
.
但是当你的指针没有指向任何有效的内存地址时,试图访问它是未定义的行为,因为它未定义指针指向的位置。
我搜索并寻找了解决方案,可以找到很多关于 int、float、double 多维数组但没有 char* 的答案。我想我掌握了指针的原理,知道 char、char* 和 char[] 等之间的区别,但是指向 char 指针的二维数组的指针让我变得更好。我正在尝试解析一个 csv 文件并用字符串 (char*) 填充我的二维数组。这是我的代码:
#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 行出现段错误。我认为这意味着我在字符串末尾缺少空指针??
调试表明 varTemp 正在越界使用内存。此外,当在第一个键后没有数据的行上使用带有 %.*s
的 printf 时,它会在 COL 1 位置以及应该有 NULL
指针的位置打印 COL 0。即:
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.....
我很困惑,有什么想法吗?!
你永远不会为 varTemp
分配 space,你需要 space 来存储 scanf()
d 字符串,所以你可以试试这个
char varTemp[100];
和scanf()
这样
sscanf(strTemp, "%99s", varTemp);
然后通过 malloc()
ing 然后 strcpy()
ing 将 varTemp
字符串复制到数组。
您需要复制字符串的原因是您将在后续调用 sscanf()
时覆盖它,因此您复制它并使用 varTemp
作为缓冲区来存储 scanf()
编辑字符串。
还有Don't cast malloc()
,而这个!feof(fp)
在while
循环中的检查是多余的,它永远不会为真,因为当你到达文件末尾时fgets()
将 return NULL
之后 feof()
将为真,因此它永远不会在 return 为真时进行评估。
在这种情况下没关系,因为 sizeof(char *) == sizeof(char **)
但作为一项规则,您应该 malloc()
比您 malloc()
想要的指针少一颗星,所以
if ((myarray[i] = malloc(COLS * sizeof(char *))) == NULL)
会更容易理解,而且在失败时你只是从 main()
return 而没有释放之前分配的指针。
最后,如果 COLS
和 ROWS
是固定值,则绝对不需要 malloc()
除非您的数组稍后会调整大小或者它们太大而堆栈无法容纳它们.
char *varTemp
是一个指针,为了使它有效,它应该指向某处,您可以通过 malloc()
从 OS 请求某处来使其指向某处,例如
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.
*/
这不是让它指向某处的唯一方法,这种方法可以动态分配 space,当您找到所需的字节数时,这通常是合适的解决方案,然后只要求那个数量,不多也不少,但这也行
char array[100];
char *varTemp;
varTemp = array;
c 中的数组衰减为指针,因此上述内容有效,在此示例中 varTemp
也可访问,例如 sscanf(sourceString, "%99s", varTemp);
.
但是当你的指针没有指向任何有效的内存地址时,试图访问它是未定义的行为,因为它未定义指针指向的位置。