Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
需要帮助解析.csv文件C中的数据吗_C_Csv - Fatal编程技术网

需要帮助解析.csv文件C中的数据吗

需要帮助解析.csv文件C中的数据吗,c,csv,C,Csv,我有以下.csv文件,其中包含有关歌曲、艺术家、发行年份(如果指定)和收听次数的信息: Look What The Cat Dragged In,Poison,,Look What The Cat Dragged In by Poison,1,0,1,0 Nothin' But A Good Time,Poison,1988,Nothin' But A Good Time by Poison,1,1,21,21 Something To Believe In,Poison,1990,Someth

我有以下
.csv
文件,其中包含有关歌曲、艺术家、发行年份(如果指定)和收听次数的信息:

Look What The Cat Dragged In,Poison,,Look What The Cat Dragged In by Poison,1,0,1,0 Nothin' But A Good Time,Poison,1988,Nothin' But A Good Time by Poison,1,1,21,21 Something To Believe In,Poison,1990,Something To Believe In by Poison,1,1,1,1 Talk Dirty To Me,Poison,1978,Talk Dirty To Me by Poison,1,1,1,1 A Salty Dog,Procol Harum,1969,A Salty Dog by Procol Harum,1,1,1,1 A Whiter Shade of Pale,Procol Harum,1967,A Whiter Shade of Pale by Procol Harum,1,1,3,3 Blurry,Puddle of Mudd,2001,Blurry by Puddle of Mudd,1,1,1,1 Amie,Pure Prairie League,,Amie by Pure Prairie League,1,0,4,0 Another One Bites the Dust,Queen,1980,Another One Bites the Dust by Queen,1,1,102,102 Bicycle Race,Queen,1978,Bicycle Race by Queen,1,1,3,3 Kiss You All Over,Kiss,1978,Kiss You All Over by Kiss,1,1,5,5 代码:

#包括
#包括
#包括
#包括
#定义最大值300
类型定义结构{
char-song[101],*艺术家,*行;
长整年;
}音乐;
整数校验年(字符*字)
{
for(int i=0;i年份=strtol(word和p,10);
如果(数组->年份==atoi(argv[2]))
{
//printf(“年:%ld\t%d\n”,数组->年,原子(argv[2]);
如果(扫描(“%100[^,]”,数组->歌曲)==1)
{
printf(“歌曲:%s\n”,数组->歌曲);
}
}
}
word=strtok(空,“,”);
}
}
//printf(“我已经读了%d行\n”,nLines);
财务总监(财务);
返回0;
}
到目前为止,它还不错,我可以从每行中提取指定的年份,但现在我只需要从这些行中打印歌曲的名称(行中的第一个标记)。我曾想过使用
scanf(“%[^,]”
读取并打印所有内容,直到第一个逗号,但它只是陷入了一个无休止的循环。你能给我一个主意吗?提前谢谢

关于:
scanf(“%[^,]”)
这将使用(不包括)逗号


因此,下一条指令需要类似于
getchar()
来使用逗号。否则,在下一个循环中不会读取任何内容,因为
stdin
中的第一个字符是同一个逗号。

代码中存在多个问题:

  • 您没有检查是否在命令行上传递了足够的参数,如果没有,可能会调用未定义的行为
  • 您不需要分配
    音乐
    结构:您只需解析前3个字段,检查年份并直接输出歌曲名称
  • strtok()
    不适合从csv文件分割字段,因为它将分隔符序列视为单个分隔符,这是不正确的,如果某些字段为空,则会导致无效解析
  • sscanf(“%[^,]”,…)
    将无法转换空字段
要从csv行分割字段,我建议您使用一个类似于
strtok_r()
但为csv行定制的实用函数。简化版本将在
\n
上停止,并用空字节替换它们,返回初始指针并更新下一个字段的指针。更高级的版本也可以处理引号

以下是修改后的版本:

#include <stdio.h>
#include <string.h>

#define MAX 300

char *get_field(char **pp) {
    char *p, *start;
    for (p = start = *pp; *p; p++) {
        if (*p == ',' || *p == '\n') {
            *p++ = '\0';
            break;
        }
    }
    *pp = p;
    return start;
}
     
int main(int argc, char *argv[]) {
    char buf[MAX];
    FILE *fin;
    char *filename;
    char *select_year;

    if (argc < 3) {
        printf("Missing arguments\n");
        return 1;
    }
    filename = argv[1];
    select_year = argv[2];
    fin = fopen(filename, "r");
    if (!fin) {
        printf("Error opening the file %s.\n", filename);
        return 1;
    }

    while (fgets(buf, sizeof buf, fin)) {
        char *p = buf;
        char *song = get_field(&p);
        char *artist = get_field(&p);
        char *year = get_field(&p);
        if (!strcmp(year, target_year)) {
            printf("%s\n", song);
        }
    }
    fclose(fin);
    return 0;
}
#包括
#包括
#定义最大值300
字符*获取字段(字符**pp){
字符*p,*开始;
对于(p=start=*pp;*p;p++){
如果(*p==','| |*p=='\n'){
*p++='\0';
打破
}
}
*pp=p;
返回启动;
}
int main(int argc,char*argv[]){
char buf[MAX];
文件*fin;
字符*文件名;
字符*选择年份;
如果(argc<3){
printf(“缺少参数\n”);
返回1;
}
filename=argv[1];
选择_year=argv[2];
fin=fopen(文件名为“r”);
如果(!fin){
printf(“打开文件%s时出错。\n”,文件名);
返回1;
}
而(fgets(buf、sizeof buf、fin)){
char*p=buf;
char*song=get_字段(&p);
char*artist=get_字段(&p);
char*year=get_字段(&p);
如果(!strcmp(年,目标年)){
printf(“%s\n”,歌曲);
}
}
财务总监(财务);
返回0;
}

关于:
文件*fin=fopen(argv[1],“r”)
在未首先选中
argc
以确保用户实际输入了命令行参数的情况下,禁止访问超出
argv[0]
。还建议在对已在使用strtok的文件调用
fopen()
之前,使用
stat()
检查文件是否实际存在。为什么要添加
scanf
?关于:
printf(“打开文件时出错。\n”)错误消息应输出到
stderr
,而不是
stdout
,当错误指示来自C库函数时,还应输出(到stderr)系统认为发生错误的文本原因。建议:
perror(“fopen失败”)因为该函数是为此而创建的purpose@xing你说得对,非常感谢@user3629249-检查
fopen
返回NOTNULL就足够了。不需要
stat
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX 300

typedef struct {
    char song[101], *artist, *line;
    long int year;
} music;

int checkYear(char *word)
{
    for (int i = 0; i < strlen(word); i++) {
        if (!isdigit(word[i]))
            return 0;
    }
    return 1;
}

int main(int argc, char **argv)
{
    FILE *fin = fopen(argv[1], "r");
    if (!fin)
    {
        printf("Error opening the file.\n");
        return 1;
    }
    char buf[MAX];
    //int nLines = 0; //count the number of lines
    //music *array = NULL;
    while( fgets(buf, MAX, fin))
    {
        buf[strcspn(buf, "\n")] = '\0';  // strip the trailing newline
        char *word = strtok(buf, ",");
        while (word)
        {
            //printf("Word is : %s\n", word);
            if (checkYear(word))
            {
                //printf("Year : %s\n", word);
                music *array = (music *)malloc(sizeof(music));
                char *p;
                array->year = strtol(word, &p, 10);
                if (array->year == atoi(argv[2]))
                {
                    //printf("Year : %ld\t%d\n", array->year, atoi(argv[2]));
                    if (scanf("%100[^,]", array->song) == 1)
                    {
                        printf("Song : %s\n", array->song);
                    }
                }
            }
            word = strtok(NULL, ",");
        }
    }
    //printf("I've read %d lines\n", nLines);
    fclose(fin);
    return 0;
}
#include <stdio.h>
#include <string.h>

#define MAX 300

char *get_field(char **pp) {
    char *p, *start;
    for (p = start = *pp; *p; p++) {
        if (*p == ',' || *p == '\n') {
            *p++ = '\0';
            break;
        }
    }
    *pp = p;
    return start;
}
     
int main(int argc, char *argv[]) {
    char buf[MAX];
    FILE *fin;
    char *filename;
    char *select_year;

    if (argc < 3) {
        printf("Missing arguments\n");
        return 1;
    }
    filename = argv[1];
    select_year = argv[2];
    fin = fopen(filename, "r");
    if (!fin) {
        printf("Error opening the file %s.\n", filename);
        return 1;
    }

    while (fgets(buf, sizeof buf, fin)) {
        char *p = buf;
        char *song = get_field(&p);
        char *artist = get_field(&p);
        char *year = get_field(&p);
        if (!strcmp(year, target_year)) {
            printf("%s\n", song);
        }
    }
    fclose(fin);
    return 0;
}