如何在不跳过数据的情况下使用 fgets() 从 CSV 文件中读取值?
How to read values from a CSV file with fgets() without skipping data?
我正在尝试读取一个 CSV 文件,其中只有用逗号分隔的双精度值。我正在使用 char *fgets(char *str, int n, FILE *stream)
函数来读取行。在代码中,为了完成 do-while 循环,我使用 getc()
方法读取下一个字符,以确定我是否已读取文件末尾。问题是,getc()
方法从下一行读取第一个字符,所以我丢失了数据(因为下一行的第一个数字丢失了一位)。如您所见,除了第一行,所有第一列条目都丢失了它们的第一个字符。
我应该用什么来控制我的 while 循环?或者我应该使用另一种方法从 CSV 文件中读取数据吗?非常感谢
来自my_file.csv的数据:
3.0000,4.0000,5.0000,6.0000,7.0000
6.0000,5.0000,4.0000,3.0000,2.0000
9.0000,6.0000,3.0000,0.0000,-3.0000
12.0000,7.0000,2.0000,-3.0000,-8.0000
15.0000,8.0000,1.0000,-6.0000,-13.0000
18.0000,9.0000,0.0000,-9.0000,-18.0000
实际输出:
[在此处输入图片描述][1]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getData(char *buff);
int main() {
char folder_addr[] = "C:\my_file.csv";
FILE *fp = fopen(folder_addr, "r");
do {
char buff[1024];
fgets(buff, 1024, (FILE*)fp);
printf(buff);
getData(buff);
} while ((getc(fp)) != EOF);
return 0;
};
void getData(char *buff){
char *token = strtok(buff, ",");
//printf("First value: %s\n", token);
while (token != NULL) {
//printf("First value: %s\n", token);
token = strtok(NULL, ",");
}
}
[1]: https://i.stack.imgur.com/fQzw1.jpg
将您的 do {fgets()...} while(getc);
替换为 while (fgets()) {...}
最好的办法是只做一个 while(fgets())
而不是做一个。我不会说查看单个字符是最好的方法。
对于这样做是合理选择(如果存在这种情况)的情况,您可以执行 fseek(fp, -1, SEEK_CUR)
返回一步。它有点丑,但还不错,它完成了工作。您需要像这样重新排序:
while ((getc(fp)) != EOF) {
fseek(fp, -1, SEEK_CUR);
char buff[1024];
fgets(buff, 1024, (FILE*)fp);
printf(buff);
getData(buff);
}
但是,请注意,如果流不可搜索,例如管道,则 fseek
不能保证工作。最好使用ungetc
。同理。你把刚刚读回的字符放回流中。
类似的方法是这样的:
int c;
while ((c = getc(fp)) != EOF) {
char buff[1024];
buff[0]=c;
fgets(&buff[1], 1023, (FILE*)fp);
printf(buff);
getData(buff);
}
您还应该将 printf(buff)
更改为 puts(buff)
我正在尝试读取一个 CSV 文件,其中只有用逗号分隔的双精度值。我正在使用 char *fgets(char *str, int n, FILE *stream)
函数来读取行。在代码中,为了完成 do-while 循环,我使用 getc()
方法读取下一个字符,以确定我是否已读取文件末尾。问题是,getc()
方法从下一行读取第一个字符,所以我丢失了数据(因为下一行的第一个数字丢失了一位)。如您所见,除了第一行,所有第一列条目都丢失了它们的第一个字符。
我应该用什么来控制我的 while 循环?或者我应该使用另一种方法从 CSV 文件中读取数据吗?非常感谢
来自my_file.csv的数据:
3.0000,4.0000,5.0000,6.0000,7.0000
6.0000,5.0000,4.0000,3.0000,2.0000
9.0000,6.0000,3.0000,0.0000,-3.0000
12.0000,7.0000,2.0000,-3.0000,-8.0000
15.0000,8.0000,1.0000,-6.0000,-13.0000
18.0000,9.0000,0.0000,-9.0000,-18.0000
实际输出:
[在此处输入图片描述][1]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getData(char *buff);
int main() {
char folder_addr[] = "C:\my_file.csv";
FILE *fp = fopen(folder_addr, "r");
do {
char buff[1024];
fgets(buff, 1024, (FILE*)fp);
printf(buff);
getData(buff);
} while ((getc(fp)) != EOF);
return 0;
};
void getData(char *buff){
char *token = strtok(buff, ",");
//printf("First value: %s\n", token);
while (token != NULL) {
//printf("First value: %s\n", token);
token = strtok(NULL, ",");
}
}
[1]: https://i.stack.imgur.com/fQzw1.jpg
将您的 do {fgets()...} while(getc);
替换为 while (fgets()) {...}
最好的办法是只做一个 while(fgets())
而不是做一个。我不会说查看单个字符是最好的方法。
对于这样做是合理选择(如果存在这种情况)的情况,您可以执行 fseek(fp, -1, SEEK_CUR)
返回一步。它有点丑,但还不错,它完成了工作。您需要像这样重新排序:
while ((getc(fp)) != EOF) {
fseek(fp, -1, SEEK_CUR);
char buff[1024];
fgets(buff, 1024, (FILE*)fp);
printf(buff);
getData(buff);
}
但是,请注意,如果流不可搜索,例如管道,则 fseek
不能保证工作。最好使用ungetc
。同理。你把刚刚读回的字符放回流中。
类似的方法是这样的:
int c;
while ((c = getc(fp)) != EOF) {
char buff[1024];
buff[0]=c;
fgets(&buff[1], 1023, (FILE*)fp);
printf(buff);
getData(buff);
}
您还应该将 printf(buff)
更改为 puts(buff)