gpt4 book ai didi

c - 从 C 中的 CSV 文件读取每次都返回相同的值

转载 作者:太空宇宙 更新时间:2023-11-04 04:25:30 25 4
gpt4 key购买 nike

我有一个包含值的 csv 文件

1,A,X
2,B,Y
3,C,Z

我必须逐行读取 CSV 文件并将其保存在结构数组中。每次在 for 循环中,这些值都很好。但是最后当我打印数组时,只打印了最后一个值。有人请告诉我我在哪里做逻辑错误吗?

struct proc
{
char *x;
char *y;
};

void main()
{
fflush(stdin);
fflush(stdout);

const char s[2] = ",";
char *token;
int rows=0,i,tokenVal=0,rowCount=0;
FILE *fpCount = fopen("data.csv","r");
if(fpCount != NULL)
{
char lineCount[20];
while(fgets(lineCount, sizeof lineCount, fpCount))
rows++;
}
struct proc *pi[rows];
for(i=0;i<rows;i++)
pi[i] = (struct proc*) malloc(sizeof(struct proc));
FILE *fp = fopen("data.csv", "r");
if(fp != NULL)
{
char line[20];
while(fgets(line, sizeof line, fp) != NULL)
{
printf("Start rowCount = %d\t",rowCount);
token = strtok(line, s);
while(token!=NULL)
{
if(tokenVal==0)
{
pi[rowCount]->Id =token;
}
if(tokenVal==1)
{
pi[rowCount]->act = token;
}
printf("\n");
tokenVal++;
token = strtok(NULL,s);
}

tokenVal = 0;
printf("end rowCount = %d\t",rowCount);
rowCount++;
}
fclose(fp);
} else {
perror("data.csv");
}
printf("total %d",rowCount);
int k=0;
for(k=0;k<rowCount;k++)
{
printf(" %d = %s----%s",k,pi[k]->Id,pi[k]->act);
}
}

最佳答案

诊断

您面临的根本问题是,您在结构中保存指向变量 line 的指针,但每个新行都会覆盖以前在 line 中的内容,因此在结束,只有最后一行的数据存在。幸运的是,您的数据行都是相同的“形状”;如果字段的长度不同,您会得到更有趣但同样错误的结果。

因此,您需要保存每个字段的副本,而不仅仅是指向该字段的指针。简单的方法是使用 POSIX 函数 strdup() .如果您没有该功能,您可以创建它:

char *strdup(const char *str)
{
size_t len = strlen(str) + 1;
char *rv = malloc(len);
if (rv != 0)
memmove(rv, str, len); // or memcpy
return rv;
}

您的代码无法编译;您的数据结构包含元素 xy,但您的代码使用元素 Idact。您使用指向您的 struct proc 的指针的 VLA,但分配结构数组是明智的,无论是作为 VLA 还是通过 malloc() 等。您应该检查内存分配——尽管没有办法检查 VLA(使用动态分配的原因之一)。您可以倒回文件而不是重新打开它。 (使用一个变量来保存文件名是个好主意,即使你只打开它一次;它使错误报告更好。此外,错误应该停止程序,一般来说,虽然你确实使用了 perror() 如果重新打开操作失败——但如果打开失败则不会。)您不需要两个数组来读取这些行。为输入行使用更长的缓冲区是个好主意。您应该释放动态分配的内存。另请参阅 What should main() return in C and C++? ;答案是 int 而不是 void(除非您使用的是 Windows)。

这是您的代码的三个变体,上面概述的问题的各个方面或多或少已得到修复。

指针的VLA

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

struct proc
{
char *x;
char *y;
};

int main(void)
{
const char datafile[] = "data.csv";
const char csv_delim[] = ",\n";
int rows = 0, rowCount = 0;
FILE *fpCount = fopen(datafile, "r");

if (fpCount == NULL)
{
fprintf(stderr, "Failed to open '%s' for reading\n", datafile);
exit(EXIT_FAILURE);
}

char lineCount[2000];
while (fgets(lineCount, sizeof(lineCount), fpCount))
rows++;
fclose(fpCount);

printf("Read %d rows from '%s'\n", rows, datafile);

struct proc *pi[rows];
for (int i = 0; i < rows; i++)
pi[i] = (struct proc *)malloc(sizeof(struct proc));

FILE *fp = fopen(datafile, "r");
if (fp == NULL)
{
fprintf(stderr, "Failed to reopen '%s' for reading\n", datafile);
exit(EXIT_FAILURE);
}

char line[2000];
while (fgets(line, sizeof(line), fp) != NULL)
{
printf("Start rowCount = %d\t", rowCount);
int tokenVal = 0;
char *token = strtok(line, csv_delim);
while (token != NULL)
{
if (tokenVal == 0)
{
pi[rowCount]->x = strdup(token);
}
else if (tokenVal == 1)
{
pi[rowCount]->y = strdup(token);
}
printf("[%s]", token);
tokenVal++;
token = strtok(NULL, csv_delim);
}
printf("\tend rowCount = %d\n", rowCount);
rowCount++;
}

fclose(fp);

/* Data validation */
printf("total %d\n", rowCount);
for (int k = 0; k < rowCount; k++)
{
printf("%d = [%s]----[%s]\n", k, pi[k]->x, pi[k]->y);
}

/* Release allocated memory */
for (int k = 0; k < rowCount; k++)
{
free(pi[k]->x);
free(pi[k]->y);
free(pi[k]);
}

return 0;
}

结构的VLA

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

struct proc
{
char *x;
char *y;
};

int main(void)
{
const char datafile[] = "data.csv";
const char csv_delim[] = ",\n";
int rows = 0, rowCount = 0;
FILE *fpCount = fopen(datafile, "r");

if (fpCount == NULL)
{
fprintf(stderr, "Failed to open '%s' for reading\n", datafile);
exit(EXIT_FAILURE);
}

char lineCount[2000];
while (fgets(lineCount, sizeof(lineCount), fpCount))
rows++;
fclose(fpCount);

printf("Read %d rows from '%s'\n", rows, datafile);

struct proc pi[rows];

FILE *fp = fopen(datafile, "r");
if (fp == NULL)
{
fprintf(stderr, "Failed to reopen '%s' for reading\n", datafile);
exit(EXIT_FAILURE);
}

char line[2000];
while (fgets(line, sizeof(line), fp) != NULL)
{
printf("Start rowCount = %d\t", rowCount);
int tokenVal = 0;
char *token = strtok(line, csv_delim);
while (token != NULL)
{
if (tokenVal == 0)
{
pi[rowCount].x = strdup(token);
}
else if (tokenVal == 1)
{
pi[rowCount].y = strdup(token);
}
printf("[%s]", token);
tokenVal++;
token = strtok(NULL, csv_delim);
}
printf("\tend rowCount = %d\n", rowCount);
rowCount++;
}

fclose(fp);

/* Data validation */
printf("total %d\n", rowCount);
for (int k = 0; k < rowCount; k++)
{
printf("%d = [%s]----[%s]\n", k, pi[k].x, pi[k].y);
}

/* Release allocated memory */
for (int k = 0; k < rowCount; k++)
{
free(pi[k].x);
free(pi[k].y);
}

return 0;
}

结构的动态数组

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

struct proc
{
char *x;
char *y;
};

int main(void)
{
const char datafile[] = "data.csv";
const char csv_delim[] = ",\n";
int num_rows = 0, rowCount = 0;
FILE *fp = fopen(datafile, "r");

if (fp == NULL)
{
fprintf(stderr, "Failed to open '%s' for reading\n", datafile);
exit(EXIT_FAILURE);
}

char line[2000];
while (fgets(line, sizeof(line), fp))
num_rows++;
rewind(fp);

printf("Read %d rows from '%s'\n", num_rows, datafile);

struct proc *pi = calloc(num_rows, sizeof(*pi));
if (pi == 0)
{
fprintf(stderr, "Failed to allocate %zu bytes of memory\n", num_rows * sizeof(*pi));
exit(EXIT_FAILURE);
}

while (fgets(line, sizeof(line), fp) != NULL)
{
printf("Start rowCount = %d\t", rowCount);
int tokenVal = 0;
char *token = strtok(line, csv_delim);
while (token != NULL)
{
if (tokenVal == 0)
{
pi[rowCount].x = strdup(token);
// null check
}
else if (tokenVal == 1)
{
pi[rowCount].y = strdup(token);
// null check
}
printf("[%s]", token);
tokenVal++;
token = strtok(NULL, csv_delim);
}
printf("\tend rowCount = %d\n", rowCount);
rowCount++;
}

fclose(fp);

/* Data validation */
printf("total %d\n", rowCount);
for (int k = 0; k < rowCount; k++)
{
printf("%d = [%s]----[%s]\n", k, pi[k].x, pi[k].y);
}

/* Release allocated memory */
for (int k = 0; k < rowCount; k++)
{
free(pi[k].x);
free(pi[k].y);
}
free(pi);

return 0;
}

给定一个数据文件:

1,A,X
2,B,Y
3,C,Z
3192-2146-9913,Abelone,Zoophyte

所有三个程序产生相同的输出:

Read 4 rows from 'data.csv'
Start rowCount = 0 [1][A][X] end rowCount = 0
Start rowCount = 1 [2][B][Y] end rowCount = 1
Start rowCount = 2 [3][C][Z] end rowCount = 2
Start rowCount = 3 [3192-2146-9913][Abelone][Zoophyte] end rowCount = 3
total 4
0 = [1]----[A]
1 = [2]----[B]
2 = [3]----[C]
3 = [3192-2146-9913]----[Abelone]

关于c - 从 C 中的 CSV 文件读取每次都返回相同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42044549/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com