2011-09-15 75 views
1

我在寫一個小型命令行程序,它從stdin中讀取兩個浮點數,一個int和一個小字符串(最多4個字符)。我試圖找出我應該創建並傳遞給fgets的緩衝區大小。我想我可以基於有多少位應該分別,像這樣列入floatint最大值計算這個讀取浮點的最小緩衝區長度

#include <float.h> 
#include <limits.h> 

... 

int fmax = log10(FLOAT_MAX) + 2;  // Digits plus - and . 
int imax = log10(INT_MAX) + 1;  // Digits plus - 
int buflen = 4 + 2*fmax + imax + 4; // 4 chars, 2 floats, 1 int, 3 spaces and \n 

... 

fgets(inbuf, buflen + 1, stdin); 

但它發生,我認爲這可能實際上並不正確。 imax最終在我的系統上是10,這似乎有點低,而fmax如果40.(我認爲這有點高,因爲較長的值可能用e符號表示。)

所以我的問題是:這是解決這個問題的最好方法嗎?這甚至是必要的嗎?它比分配256的緩衝區感覺更優雅,並且假設它足夠了。稱它爲驕傲的問題; P。

+1

請問您的問題時,請在C和C++之間進行選擇。根據您使用的語言,答案會有所不同。 –

+0

你爲什麼要爲int和浮點數使用不同的緩衝區?無論如何,你必須一個接一個地閱讀它們,所以要採用一個足夠大的緩衝區來容納浮動塊並完成它。 – arne

+1

另請參見INT_MAX,看看它在base-10表示中真的只有十位數。然後考慮雙倍(64位,53位尾數),你可能會看到40位數字聽起來是正確的。 – arne

回答

5

這種類型的東西是我實際使用fscanf而不是首先讀入固定大小緩衝區的地方。如果您需要確保不跳過換行符或其他有意義的空格,則可以使用fgetc逐字符處理,直到獲得數字的開頭,然後調用fscanf之前的ungetc

如果你想偷懶,雖然,隨便挑一個很大的數字,如1000 ...

+1

理智+1。 – Perception

0

我敢肯定有確定的浮動字符串算法的最大長度的好辦法,但是,這是什麼好玩的?讓我們通過蠻力來解決吧!

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

int main(int, char **) 
{ 
    float f; 
    unsigned int i = -1; 
    if (sizeof(f) != sizeof(i)) 
    { 
     printf("Oops, wrong size! Change i to a long or whatnot so the sizes match.\n"); 
     return 0; 
    } 
    printf("sizeof(float)=%li\n", sizeof(float)); 

    char maxBuf[256] = ""; 
    int maxChars = 0; 
    while(i != 0) 
    { 
     char buf[256]; 
     memcpy(&f, &i, sizeof(f)); 
     sprintf(buf, "%f", f); 
     if ((i%1000000)==0) printf("Calclating @ %u: buf=[%s] maxChars=%i (maxBuf=[%s])\n", i, buf, maxChars, maxBuf); 
     int numChars = strlen(buf); 
     if (numChars > maxChars) 
     { 
     maxChars = numChars; 
     strcpy(maxBuf, buf); 
     } 
     i--; 
    } 
    printf("Max string length was [%s] at %i chars!\n", maxBuf, maxChars); 
} 

看起來,答案可能是每浮動(至少在我的機器上)47個字符,但我不會讓它運行到完成所以它可能更多。

+0

看起來像多線程的工作! –

2

這是爲了底座10浮點數(#include <float.h>std::numeric_limits<float_type>等效構件)之一定義:

FLT_MAX_10_EXP // for float 
DBL_MAX_10_EXP // for double 
LDBL_MAX_10_EXP // for long double 

由於是最大精度爲小數在基座10:

FLT_DIG // for float 
DBL_DIG // for double 
LDBL_DIG // for long double 

雖然它真的取決於你定義的是一個有效的浮點數。你可以想象有人期待:

00000000000000000000000000000000000000000000000000.00000000000000000000 

被讀入爲零。

+0

公平點。我從來沒有想到,我可以解釋每一個技術上正確的輸入,儘管我認爲儘可能多地輸入儘可能多的合理輸入是可能的,這可能會減少緩衝區大小。 –

0

根據@MSN的回答,您無法真正瞭解您的緩衝區是否足夠大。

考慮:

const int size = 4096; 
char buf[size] = "1."; 
buf[size -1 ] = '\0'; 
for(int i = 2; i != size - 1; ++i) 
    buf[i] = '0'; 
double val = atof(buf); 
std::cout << buf << std::endl; 
std::cout << val << std::endl; 

這裏atof()手柄(因爲它應該)的1千個字符表示。

所以真的,你可以做一個或多個:

  • 處理不具有大的情況下足夠的緩衝區
  • 具有對輸入文件
  • 使用更好的控制fscanf直接,使緩衝區大小別人的問題