如何使用 `sscanf()` 读取逗号分隔的 csv 文件
How to read comma-separated csv file with `sscanf()`
我正在尝试打印从 Excel 中的 CSV 文件读取的结构数组。但是,只打印学生证件;还打印了其他信息,但打印了一些令人困惑的稀有字符。你能告诉我这段代码有什么问题吗?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student {
char ID[8];
char name[32];
int score;
} student;
int main(int argc, char *argv[]) {
student student_list[100];
FILE *source = fopen("students.csv", "r");
if (source == NULL) {
perror("Unable to open the source file.");
exit(1);
}
char buffer[1024];
fgets(buffer, sizeof(buffer), source);
int num_student = 0;
while (!feof(source)) {
student *one_student = student_list + num_student;
sscanf(buffer, "%8[^,] %32[^,] %3[^,]",
&one_student->ID, &one_student->name, &one_student->score);
fgets(buffer, sizeof(buffer), source);
num_student++;
}
for (int i = 0; i < num_student; i++) {
printf("ID: %s name: %-9s score: %-3d\n",
student_list[i].ID, student_list[i].name, student_list[i].score);
}
fclose(source);
return 0;
}
这是一个示例输入文件students.csv:
B213350,John Adam Smith,80
B191835,Mary Elizabeth Smith,71
B201304,Yamazaki Fuyumi,95
B201832,Liam,57
B201834,Alfonso Hernández,65
存在多个问题:
你不应该使用 feof()
。阅读 Why is “while ( !feof (file) )” always wrong?
请改用此循环:
while (fgets(buffer, sizeof buffer, source)) {
// handle the line
}
sscanf()
格式字符串不正确:字符数过多,缺少 ,
。它应该是 " %7[^,\n], %31[^,\n], %d"
,您应该检查 return 值是否为 3,即预期的成功转换次数。
当学生数组满了就停止
这是修改后的版本:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student {
char ID[8];
char name[32];
int score;
} student;
int main(int argc, char *argv[]) {
student student_list[100];
FILE *source = fopen("students.csv", "r");
if (source == NULL) {
fprintf(stderr, "Cannot open file students.csv: %s\n", strerror(errno));
return 1;
}
char buffer[1024];
int num_student = 0;
while (num_student < 100 && fgets(buffer, sizeof(buffer), source)) {
student *one_student = &student_list[num_student];
if (sscanf(buffer, " %7[^,\n], %31[^,\n], %d",
one_student->ID, one_student->name,
&one_student->score) == 3) {
num_student++;
} else {
printf("invalid CSV line: %s", buffer);
}
}
for (int i = 0; i < num_student; i++) {
printf("ID: %-9s name: %-32s score: %-3d\n",
student_list[i].ID, student_list[i].name,
student_list[i].score);
}
fclose(source);
return 0;
}
请注意,这种解析 CSV 文件的方法无法处理空字段。解析带有 strtok()
的行也不起作用,因为连续的逗号将作为单个分隔符处理。您需要使用 strcspn()
或 strchr()
.
的不同方法
我正在尝试打印从 Excel 中的 CSV 文件读取的结构数组。但是,只打印学生证件;还打印了其他信息,但打印了一些令人困惑的稀有字符。你能告诉我这段代码有什么问题吗?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student {
char ID[8];
char name[32];
int score;
} student;
int main(int argc, char *argv[]) {
student student_list[100];
FILE *source = fopen("students.csv", "r");
if (source == NULL) {
perror("Unable to open the source file.");
exit(1);
}
char buffer[1024];
fgets(buffer, sizeof(buffer), source);
int num_student = 0;
while (!feof(source)) {
student *one_student = student_list + num_student;
sscanf(buffer, "%8[^,] %32[^,] %3[^,]",
&one_student->ID, &one_student->name, &one_student->score);
fgets(buffer, sizeof(buffer), source);
num_student++;
}
for (int i = 0; i < num_student; i++) {
printf("ID: %s name: %-9s score: %-3d\n",
student_list[i].ID, student_list[i].name, student_list[i].score);
}
fclose(source);
return 0;
}
这是一个示例输入文件students.csv:
B213350,John Adam Smith,80
B191835,Mary Elizabeth Smith,71
B201304,Yamazaki Fuyumi,95
B201832,Liam,57
B201834,Alfonso Hernández,65
存在多个问题:
你不应该使用
feof()
。阅读 Why is “while ( !feof (file) )” always wrong?
请改用此循环:while (fgets(buffer, sizeof buffer, source)) { // handle the line }
sscanf()
格式字符串不正确:字符数过多,缺少,
。它应该是" %7[^,\n], %31[^,\n], %d"
,您应该检查 return 值是否为 3,即预期的成功转换次数。当学生数组满了就停止
这是修改后的版本:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student {
char ID[8];
char name[32];
int score;
} student;
int main(int argc, char *argv[]) {
student student_list[100];
FILE *source = fopen("students.csv", "r");
if (source == NULL) {
fprintf(stderr, "Cannot open file students.csv: %s\n", strerror(errno));
return 1;
}
char buffer[1024];
int num_student = 0;
while (num_student < 100 && fgets(buffer, sizeof(buffer), source)) {
student *one_student = &student_list[num_student];
if (sscanf(buffer, " %7[^,\n], %31[^,\n], %d",
one_student->ID, one_student->name,
&one_student->score) == 3) {
num_student++;
} else {
printf("invalid CSV line: %s", buffer);
}
}
for (int i = 0; i < num_student; i++) {
printf("ID: %-9s name: %-32s score: %-3d\n",
student_list[i].ID, student_list[i].name,
student_list[i].score);
}
fclose(source);
return 0;
}
请注意,这种解析 CSV 文件的方法无法处理空字段。解析带有 strtok()
的行也不起作用,因为连续的逗号将作为单个分隔符处理。您需要使用 strcspn()
或 strchr()
.