C将逗号分隔的字符串转换为数组

时间:2018-03-20 18:09:20

标签: c arrays string csv split

我有一个逗号分隔字符串的存档我想将每一行都滑入2个数组:v [i] .date和v [i] .value。 但是,当我运行代码时,它会显示数组的随机值。 有什么我应该改变的吗?

  

输入
  1761
  2月20日/ 18,11403.7
  2月19日/ 18,11225.3
  2月18日/ 18,10551.8
  2月17日/ 18,11112.7
  2月16日/ 18,10233.9

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


typedef struct{
    char data[10];
    double valor;

}vetor;

int main(int argc,char *argv[]){
    FILE *csv;



        if((csv=fopen(argv[1], "r")) == NULL  )
        {
            printf("not found csv\n");
            exit(1);
        }


        long int a=0;

        char linha[256];

        char *token = NULL;

        if(fgets(linha, sizeof(linha), csv))
        {
            token = strtok(linha, "\n");
            a =(atoi(token));
        }


        printf("%d\n", a);

        rewind(csv);

        vetor *v;

        v=(vetor*)malloc(a*sizeof(vetor));

        char linha2[256];

        while (fgets(linha2, sizeof(linha2), csv) != 0)
        {
            fseek(csv, +1, SEEK_CUR);

            for(int i=0;i<a;i++)
            {   
                fscanf(csv, "%s[^,]", v[i].data);
                fscanf(csv, "%lf[^\n]", &v[i].valor);

            }
        }

        printf("%d\n", v[0].valor);


    fclose(csv);


    return 0;
}

2 个答案:

答案 0 :(得分:1)

您的data字段现在只包含一个char。它需要至少有一个典型值的空间,如02/19/18。

例如,使用char[10](如果您确定它永远不会超过9个字符)。

我认为编译器应该警告你的fscanf电话。

答案 1 :(得分:0)

您的fscanf()来电已关闭:当您拨打此电话时

fscanf(csv, "%s[^,]", v[i].data);

fscanf()将首先解析一串非空白字符,直到找到空白字符(%s转换),这样"02/20/18,11403.7"就会被写入您的数组,而您的缓冲区将会溢出。在那之后,您处于未定义的行为领域,任何事情都可能发生。 在获得UB之前,甚至无法达到[^,]转换。

当然,您可以通过从格式字符串中删除%s来解决此问题,但我认为,您真正想要做的是将所有数字解析为数字:

int month, day, year;
double value;
int conversionCount = fscanf(csv, "%d/%d/%d,%lf\n", &month, &day, &year, &value);
if(conversionCount != 4) {
    handleError();
}

不要忘记检查fscanf()的结果,因为这是了解解析是否成功完成的唯一方法。我在格式字符串的末尾添加了\n,它会吞噬浮点值后面的任何空格,包括换行符。这样,您就可以在一个简单的循环中使用一个fscanf()一次一行地执行转换,而无需调用fseek()。只需保持解析行,直到fscanf()调用返回的内容不是您期望的转换次数。