c - 解析 CSV 文件问题
问题描述
我尝试将 csv 文件中给出的数据解析为“数据”文件中的 ID、AGE 和 GPA 字段,但我认为我做的不对(当我尝试打印数据时,它打印出奇怪的数字)。我究竟做错了什么?
char data[1000];
FILE *x = fopen("database.csv","rt");
char NAME[300];
int ID[300],AGE[300],GPA[300];
int i,j;
i = 0;
while(!feof(x)) {
fgets(data,999,x);
for (j = 0; j < 300 && data[i] != ','; j++, i++) {
ID[j] = data[i];
i++;
}
for (j = 0; j < 300 && data[i] != ','; j++, i++) {
NAME[j] = data[i];
i++;
}
for (j = 0; j < 300 && ( data[i] != '\0' || data[i] != '\r' || data[i] != data[i] != '\n'); j++, i++) {
GPA[j] = data[i];
}
}
解决方案
首先:对于您正在做的事情,您可能需要仔细查看函数strtok
和atoi
宏。但是鉴于您发布的代码,这可能还是有点太高级了,所以我在这里采取了更长的方式。
假设这条线是这样的
172,924,1182
那么你需要解析这些数字。数字 172 实际上由内存中的两个或四个字节表示,格式非常不同,字节“0”与数字 0 完全不同。您将读取的是 ASCII 码,即十进制的 48,或者十六进制的 0x30。
如果你把一个数字的ASCII值减去48,你会得到一个数字,因为幸运的是数字是按数字顺序存储的,所以“0”是48,“1”是49等等。
但是您仍然有将三个数字 1 7 2 转换为 172 的问题。
因此,一旦您拥有“数据”:(我添加了注释代码来处理 CSV 中未引用、未转义的文本字段,因为在您的问题中您提到了 AGE 字段,但您似乎想使用 NAME 字段。文本字段被引用或转义的情况完全是另一罐蠕虫)
size_t i = 0;
int number = 0;
int c;
int field = 0; // Fields start at 0 (ID).
// size_t x = 0;
// A for loop that never ends until we issue a "break"
for(;;) {
c = data[i++];
// What character did we just read?
if ((',' == c) || (0x0c == c) || (0x0a == c) || (0x00 == c)) {
// We have completed read of a number field. Which field was it?
switch(field) {
case 0: ID[j] = number; break;
case 1: AGE[j] = number; break;
// case 1: NAME[j][x] = 0; break; // we have already read in NAME, but we need the ASCIIZ string terminator.
case 2: GPA[j] = number; break;
}
// Are we at the end of line?
if ((0x0a == c) || (0x0c == c)) {
// Yes, break the cycle and read the next line
break;
}
// Read the next field. Reinitialize number.
field++;
number = 0;
// x = 0; // if we had another text field
continue;
}
// Each time we get a digit, the old value of number is shifted one order of magnitude, and c gets added. This is called Horner's algorithm:
// Number Read You get
// 0 "1" 0*10+1 = 1
// 1 "7" 1*10+7 = 17
// 17 "2" 17*10+2 = 172
// 172 "," Finished. Store 172 in the appropriate place.
if (c >= '0' && c <= '9') {
number = number * 10 + (c - '0');
}
/*
switch (field) {
case 1:
NAME[j][x++] = c;
break;
}
*/
}
推荐阅读
- html - OneNote 加载项 API 中的 HTML
- c++ - 时间测量在特定地方反复出错
- java - 如何计算每日饮用水的 ProgressBar 百分比
- mysql - MySQL - 每日概览仅显示当前预订而不是全部
- jquery - 数据表根据列不同的过滤器?
- c++ - Linux 共享内存段:互斥断言错误
- javascript - 如何验证钢琴键盘上按键的顺序?
- javascript - 尽管代码似乎在 ASP.NET MVC 5 中工作,但显示的日期格式并不是理想的结果
- ios - 为什么我修改了 LaunchScreen.xib 但模拟器屏幕没有改变?
- java - 如何在 android Seekbar thumb 下方自动移动 Textview?