用c语言一次读取一行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

我有此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>
#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文件中删除标题,或将字符跳到第一个换行符。