将CSV字符串转换为浮点数数组

4
有没有简单的方法可以在C语言中将一个csv字符串转换为浮点数数组?例如:
char my_string[] = "1.0,2.0,3.0";

收件人:

my_array = [1.0, 2.0, 3.0]

其中 my_array 是类型为 float[] 的数组

我会使用 sscanf 作为快速且简易的解决方案,但事先我不知道字符串中包含多少个值

是否有一些现成的库函数可以做到这一点,而不用我去循环遍历每个 char 寻找“,”呢?

6个回答

6
你可以使用 strtok() 函数来实现:
float my_array[N]; // if you don't know how many there are, use the heap
int i = 0;

char *tok = strtok(my_string, ",");
while (tok != NULL) {
    my_array[i++] = atof(tok);
    tok = strtok(NULL, ",");
}   

3
如果你不介意 strtok() 在字符串中间插入空字符的事实的话。 - Jonathan Leffler

3

有一个库可以使用 - LibCSV

根据他们的描述:

libcsv是一个小型、简单且快速的CSV库,使用纯ANSI C89编写,可以读取和写入CSV数据。它提供了一个直观的接口,使用回调函数处理解析后的字段和行,并可以解析格式不正确的CSV文件。


2
使用sscanf()while()循环,每次读取一个浮点数。当sscanf()返回0时,表示已经到达列表的末尾。保留HTML标签。

你如何让sscanf沿着字符串前进,即向前移动每个csv? - bph
1
你可以使用%n转换说明符来查找读取的字符数。 你必须要小心一点; 逗号在哪一边?还是在sscanf()之外处理逗号?可能是后者。所以:size_t offset = 0; int position; while (sscanf(buffer + offset, "%lf%n", &my_array[i], &position) == 1) { offset += position; if (buffer[offset] == ',') position++; } 这段代码大致上就是所需的。 - Jonathan Leffler
1
根据@JonathanLeffler所说,需要增加i的值,并检查以确保它不会导致my_array缓冲区溢出。 - Brian Swift

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

char** split(const char *str, const char *delimiter, size_t *len){
    char *text, *p, *first, **array;
    int c;
    char** ret;

    *len = 0;
    text=strdup(str);
    if(text==NULL) return NULL;
    for(c=0,p=text;NULL!=(p=strtok(p, delimiter));p=NULL, c++)//count item
        if(c==0) first=p; //first token top

    ret=(char**)malloc(sizeof(char*)*c+1);//+1 for NULL
    if(ret==NULL){
        free(text);
        return NULL;
    }
    strcpy(text, str+(first-text));//skip until top token
    array=ret;

    for(p=text;NULL!=(p=strtok(p, delimiter));p=NULL){
        *array++=strdup(p);
    }
    *array=NULL;
    *len=c;
    free(text);
    return ret;
}

void free4split(char** sa){
    char **array=sa;

    if(sa!=NULL){
        while(*sa)
            free(*sa++);//for string
        free(array);    //for array
    }
}

int main(){
    char my_string[] = "1.0,2.0,3.0";
    float *my_array;
    char **strs;
    size_t count;

    strs=split(my_string, ", \t", &count);
    my_array=(float*)malloc(sizeof(float)*count);
    {   //convert
        int i;
        for(i=0;i<count;++i)
            my_array[i]=(float)atof(strs[i]);
        free4split(strs);

    }
    {   //test print
        int i;
        for(i=0;i<count;++i)
            printf("%f\n", my_array[i]);
    }
    return 0;
}

谢谢回复,但这种 C 语言的疯狂是我想避免的 - 希望有人知道一个简单的一两行代码。 - bph
1
@Hiett - 类似您所寻找的一行代码函数在C语言的标准库中不存在。 - BLUEPIXY
分割应使用strtok_r函数。 - BLUEPIXY
@Hiett:我认为你不会找到一个“简单”的两行代码来解决这个‘C’语言问题。你需要使用像Radu建议的那样的方法,使用诸如LibCSV之类的库,或者使用另一种编程语言。 - Chimera

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

char* getToken(char **p, const char delimiter){
    char *word, *top=*p;
    int len;

    if(*p == NULL || **p == '\0') return NULL;
    while(**p && **p != delimiter)
        ++(*p);
    if(**p != delimiter) return strdup(top);
    len = *p - top;
    ++(*p);
    word=(char*)malloc(sizeof(char)*(len+1));
    strncpy(word, top, len);
    word[len]='\0';
    return word;
}

int main(){
    char my_string[] = "1.0,2.0,3.0";
    float *my_array=NULL;
    char *word, *p=my_string;
    int count=0;

    while(NULL!=(word=getToken(&p, ','))){
        my_array=(float*)realloc(my_array, sizeof(float)*(++count));
        my_array[count-1]=(float)atof(word);
        free(word);
    }
    {   //test print
        int i;
        for(i=0;i<count;++i)
            printf("%f\n", my_array[i]);
    }
    return 0;
}

0
你可能需要查看使用 strchr 函数族。
STRCHR(3)           Linux Programmer's Manual           STRCHR(3)

NAME
       strchr, strrchr - locate character in string

SYNOPSIS
       #include <string.h>

       char *strchr(const char *s, int c);

       char *strrchr(const char *s, int c);

DESCRIPTION
       The  strchr()  function  returns  a  pointer  to the first
       occurrence of the character c in the string s.

       The strrchr() function  returns  a  pointer  to  the  last
       occurrence of the character c in the string s.

RETURN VALUE
       The  strchr()  and strrchr() functions return a pointer to
       the matched character or NULL  if  the  character  is  not
       found.

CONFORMING TO
       SVID 3, POSIX, BSD 4.3, ISO 9899

SEE ALSO
       index(3),  memchr(3),  rindex(3),  strpbrk(3),  strsep(3),
       strspn(3), strstr(3), strtok(3)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接