用c语言一次读取一行csv文件
我有此csv文件包含联系人:用c语言一次读取一行csv文件,c,csv,file,C,Csv,File,我有此csv文件包含联系人: NAME, NUMBER, ADDRESS, EMAIL Kevin Mahendra, +62 812-XXX-XXX, Jln. Anggrek Merah 3 No. 54, kevin@gmail.com Adwi Lanang, +62 821-XXX-XXX, Jln. Ruhui Rahayu, adwi@gmail.com 这是代码: #include <ctype.h> #include <stdbool.h> #incl
NAME, NUMBER, ADDRESS, EMAIL
Kevin Mahendra, +62 812-XXX-XXX, Jln. Anggrek Merah 3 No. 54, kevin@gmail.com
Adwi Lanang, +62 821-XXX-XXX, Jln. Ruhui Rahayu, adwi@gmail.com
这是代码:
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Number of buckets for TABLE
#define N 26
#define MAX 50
typedef struct Contact
{
char name[MAX];
char number[MAX];
char address[MAX];
char email[MAX];
struct Contact* next;
}
Contact;
// Hash table
Contact *table[N];
int main(void)
{
// OPEN CSV FILE
FILE *file = fopen("contacts.csv", "r");
if (file == NULL)
{
printf("Error open file!\n");
return 1;
}
while(!feof(file))
{
Contact *new = malloc(sizeof(Contact));
fscanf(file, "%[^,],%[^,],%[^,],%[^,]", new->name, new->number, new->address, new->email);
printf("%s,%s,%s,%s\n", new->name, new->number, new->address, new->email);
int index = hash(new->name);
new->next = table[index];
table[index] = new;
}
}
#包括
#包括
#包括
#包括
#包括
//表的存储桶数
#定义n26
#定义最大值50
类型定义结构触点
{
字符名[MAX];
字符数[MAX];
字符地址[MAX];
字符电子邮件[MAX];
结构联系人*下一步;
}
接触;
//哈希表
联系人*表[N];
内部主(空)
{
//打开CSV文件
FILE*FILE=fopen(“contacts.csv”、“r”);
if(file==NULL)
{
printf(“打开文件时出错!\n”);
返回1;
}
而(!feof(文件))
{
联系人*new=malloc(sizeof(联系人));
fscanf(文件,“%[^,]”,“%[^,]”,“%[^,]”,“%[^,]”,新建->名称,新建->编号,新建->地址,新建->电子邮件);
printf(“%s,%s,%s,%s\n”,新建->名称,新建->编号,新建->地址,新建->电子邮件);
int index=hash(新建->名称);
新建->下一步=表[索引];
表[索引]=新的;
}
}
如您所见,我尝试将每个联系人放入哈希表中。但它无法正确读取csv文件。因为当我尝试打印它时,结果是变成无限循环
但当我的csv文件只包含一行/行时,它就起作用了。它将正确打印csv内的联系人。但当我在csv文件中添加新联系人/行时,它无法读取
如何一次读取一行csv文件?也可以跳过标题
姓名、号码、地址、电子邮件
?谢谢大家! 使用feof的feof
是错误的-请参阅
此外,您应该始终检查fscanf
返回的值,以查看您已扫描了预期数量的元素
尝试以下方法:
Contact *new = malloc(sizeof(Contact)); // Get a Contact for the first fscanf
if (new == NULL) exit(1);
while(fscanf(file, "%[^,],%[^,],%[^,],%[^,]", new->name, new->number, new->address, new->email) == 4)
{
printf("%s,%s,%s,%s\n", new->name, new->number, new->address, new->email);
int index = hash(new->name);
new->next = table[index];
table[index] = new;
Contact *new = malloc(sizeof(Contact)); // Get a Contact for the next fscanf
if (new == NULL) exit(1);
}
free(new); // Free the unused Contact
每行的最后一个字段后面没有逗号,因此您应该查找换行符。此外,为了防止溢出,您绝不能读取超过一个小于缓冲区长度的字符。这可以通过预处理器技巧实现:
#define STR_VALUE(x) STR(x)
#define STR(x) #x
#define MAX 49
#define MAX_STR STR_VALUE(MAX)
typedef struct Contact
{
char name[MAX + 1];
char number[MAX + 1];
char address[MAX + 1];
char email[MAX + 1];
struct Contact* next;
}
Contact;
...
fscanf(file,
"%" MAX_STR "[^,],%" MAX_STR "[^,],%" MAX_STR "[^,],%" MAX_STR "[^\n]",
new->name, new->number, new->address, new->email);
...
在循环中,当fscanf的结果(即扫描令牌的数量)不是4时,应该停止循环
编辑2021-04-06:宏参数在替换之前展开,除非它们显示为#(字符串表示)或##(串联)的操作数。因此
STR(MAX) => #MAX => "MAX"
鉴于
STR_VALUE(MAX) => STR(49) => #49 => "49"
下面的内容是什么意思:“因为当我尝试打印它时,结果是变成无限循环”?请花一些时间阅读,也请尝试创建一个显示给我们看。@jarmod它只是没有在提示中停止空白打印。@Someprogrammerdude仍然没有得到它。这看起来很棒。谢谢但为什么它只打印新的->名称?而且它也只在csv文件中打印一个联系人/行?谢谢!这是有效的。但是你能解释一下这意味着什么吗?
#define STR#u VALUE(x)STR(x)
#define STR(x)#x#define MAX#u STR#u VALUE(MAX)?有没有办法不在我的csv姓名、号码、地址、电子邮件
中包含标题?@kevinkunformal关于第一个问题,请参阅更新的答案。对于第二个问题,只需从CSV文件中删除标题,或将字符跳到第一个换行符。