2012-06-29 3 views
4

Может ли кто-нибудь посоветовать простой способ преобразования строки csv в массив float в 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

Вы можете использовать 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()' splatters nulls в середине вашей строки ... –

2

Используйте петлю while(), которая считывает только одно поплавок за раз с sscanf(). Как только sscanf() вернет 0, вы знаете, что находитесь в конце списка.

+0

как вы получите sscanf продвигаться вдоль струны, то есть двигаться вперед через каждый CSV-файл? – bph

+0

Извините, не подумал об этом. Работает, как и ожидалось, с помощью scanf, fscanf .. – ypnos

+1

Вы используете спецификатор преобразования% n для поиска числа прочитанных символов. Вы должны быть немного осторожны; с какой стороны запятая идет? Или вы обрабатываете запятые вне 'sscanf()'? Вероятно, последнее. Итак: 'size_t offset = 0; int позиция; while (sscanf (buffer + offset, "% lf% n", & my_array [i], & position) == 1) {offset + = position; if (buffer [offset] == ​​',') position ++; } 'будет приближением к тому, что необходимо. –

3

Там в библиотеке, вы можете использовать - LibCSV

Из их описания:

libcsv небольшая, простая и быстрая CSV библиотека, написанная на чистом ANSI C89, который может считывать и записывать данные в формате CSV. Она обеспечивает прямой вперед интерфейс с использованием функции обратного вызова для обработки разобранных полей и строк и может анализировать неправильно отформатированные CSV файлы

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) 
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; 
} 
+0

спасибо за ответ, но это своего рода C безумие, которое я пытаюсь избежать - было надеясь, что будет простой один или два лайнера, которые кто-то знал о – bph

+1

@Hiett - функция одного лайнера, как вы ищите, отсутствует в стандартной библиотеке языка C. – BLUEPIXY

+0

Разделение должно использовать strtok_r – BLUEPIXY

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; 
} 
Смежные вопросы