2009-12-07 82 views
1

我有一個C中的字符串,我從某個算法中獲得。它具有這樣將字符串中的值轉換爲浮點數組

0.100 
0.840 
0.030 
0.460 
0.760 
-0.090 

以及格式數值等

在需要這些數值存儲到一個浮陣列,用於數字處理。我是C新手,發現C中的字符串處理很複雜。任何人都可以告訴我如何實現這一點。

回答

1

所有的值都是單個字符串,比如「0.100 0.840 0.030 ...」,還是你有一堆單獨的字符串,比如「0.100」,「0.840」,「0.030」等。如果它們在單個字符串中,它們是否被空格(製表符,空格,換行符)或打印字符(逗號,分號)隔開?你知道你有多少價值(即,你的float數組需要多大)?

要轉換代表一個浮點值翻一番字符串,請使用strtod()如下:

char valueText[] = "123.45"; 
char *unconverted; 
double value; 

value = strtod(valueText, &unconverted); 
if (!isspace(*unconverted) && *unconverted!= 0) 
{ 
    /** 
    * Input string contains a character that's not valid 
    * in a floating point constant 
    */ 
} 

閱讀上strtod()瞭解詳情。 unconverted將指向未被strtod()轉換的字符串中的第一個字符;如果它不是空白或0,那麼你的字符串沒有被正確格式化爲浮點值,應該被拒絕。

如果所有的值都在一個字符串中,您將不得不將該字符串拆分爲不同的標記。最簡單的(如果有點不安全)的方式來做到這一點是使用strtok()

char input[] = "1.2 2.3 3.4 4.5 5.6 6.7 7.8"; 
char *delim = " "; // input separated by spaces 
char *token = NULL; 

for (token = strtok(input, delim); token != NULL; token = strtok(NULL, delim)) 
{ 
    char *unconverted; 
    double value = strtod(token, &unconverted); 
    if (!isspace(*unconverted) && *unconverted != 0) 
    { 
    /** 
    * Input string contains a character that's not valid 
    * in a floating point constant 
    */ 
    } 
} 

閱讀上strtok()瞭解詳情。

如果你不知道你有多少值,你需要做一些內存管理。您可以動態地分配使用浮動或malloc()一些realloc()初始大小的數組,然後定期用realloc()擴展它:

#define INITIAL_EXTENT 10 

double *array = NULL; 
size_t arraySize = 0; 
size_t arrayIdx = 0; 

char input[] = ...; // some long input string 
char *delim = ...; // whatever the delimiter set is 
char *token; 

/** 
* Create the float array at some initial size 
*/ 
array = malloc(sizeof *array * INITIAL_EXTENT)); 
if (array) 
{ 
    arraySize = INITIAL_EXTENT; 
} 
/** 
* Loop through your input string 
*/ 
for (token = strtok(input, delim); token != NULL; token = strtok(NULL, delim)) 
{ 
    double val; 
    char *unconverted; 
    if (arrayIdx == arraySize) 
    { 
    /** 
    * We've reached the end of the array, so we need to extend it. 
    * A popular approach is to double the array size instead of 
    * using a fixed extent; that way we minimize the number 
    * of calls to realloc(), which is relatively expensive. 
    * 
    * Use a temporary variable to receive the result; that way, 
    * if the realloc operation fails, we don't lose our 
    * original pointer. 
    */ 
    double *tmp = realloc(array, sizeof *array * (arraySize * 2)); 
    if (tmp != NULL) 
    { 
     array = tmp; 
     arraySize *= 2; 
    } 
    else 
    { 
     /** 
     * Memory allocation failed; for this example, we just exit the loop 
     */ 
     fprintf(stderr, "Memory allocation failed; exiting loop\n"); 
     break; 
    } 
    } 
    /** 
    * Convert the next token to a float value 
    */ 
    val = strtod(token, &unconverted); 
    if (!isspace(*unconverted) && *unconverted != 0) 
    { 
    /** 
    * Bad input string. Again, we just bail. 
    */ 
    fprintf(stderr, "\"%s\" is not a valid floating-point number\n", token); 
    break; 
    } 
    else 
    { 
    array[arrayIdx++] = val; 
    } 
} 

當你用它做不要忘記free()陣列。

+0

我試圖實現這一點,但我每次都得到分段錯誤錯誤。看着它。你有什麼想法可能導致它? – sfactor

+0

段錯在哪裏發生?在閱讀令牌?轉換令牌?擴展數組?分配值?我把這些代碼扔掉了我的頭頂,所以如果有錯誤,我不會感到驚訝,但它有助於確切知道它在哪裏死去。如果你可以通過調試器運行它來找到確切的線路,那會很有幫助。 –

0

你想要的功能被稱爲fscanf

/* fscanf example */ 
/* Stolen from cplusplus.com 
    Modified by C Ross */ 
#include <stdio.h> 

int main() 
{ 
    char str [80]; 
    float f; 
    FILE * pFile; 

    pFile = fopen ("myfile.txt","r"); 
    /* Loop over this and add to an array, linked list, whatever */ 
    fscanf (pFile, "%f", &f); 
    fclose (pFile); 
    printf ("I have read: %f \n",f); 
    return 0; 
} 
0

假設您的字符串是

char *str; 

使用類似:

double d[<enter array size here>]; 
double *pd = d; 

for(char *p = str; p = strchr(p, '\n'); p++, pd++) 
{ 
    *p = 0; 
    *pd = atof(p); 
    *p = '\n'; 
} 
0

如果它是一個字符串,首先你需要把它拆分在新行字符(S?)然後你可以使用「atof」stdlib函數從它們中創建浮動數字。像這樣:

2

使用strtod()。與atof()不同,它可以檢測輸入字符串中的錯誤。

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

int main(void) { 
    char buf[] = "0.100\n0.8foo40\n0.030\n\n\n\n0.460\n0.760bar\n-0.090trash"; 
    char *err, *p = buf; 
    double val; 
    while (*p) { 
    val = strtod(p, &err); 
    if (p == err) p++; 
    else if ((err == NULL) || (*err == 0)) { printf("Value: %f\n", val); break; } 
    else { printf("Value: %f\n", val); p = err + 1; } 
    } 
    return 0; 
} 

strtod()返回讀取的值,除非出現錯誤。

如果err指向傳入的字符串,則不能使用字符串,因此在上面的代碼片段中,我增加p以繼續從下一個位置讀取。

如果err爲NULL或指向一個空字符串,沒有錯誤,所以,在我的片段中,我打印該值並停止循環。

如果err點某處的字符串(不p本身,前測試),這是在我的代碼片段,其中的錯誤,字符以上,我知道的東西被讀取,所以我打印出來,集合P一個過去的錯誤和循環。


編輯爲了完整起見,我應該提到的錯誤還沒有的情況下。它可能發生strtod()讀取一個字符序列(雖然有效)不能用double表示。在這種情況下,errno被設置爲ERANGE,並且該值本身是「無意義的」。您應在撥打strtod()之前將errno設置爲0,然後在使用返回值之前進行檢查。對於非常小的輸入值(例如「1E-42000」),設置errno是實現定義的,但返回0(或幾乎爲0)。

相關問題