2011-09-15 48 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直接,使缓冲区大小别人的问题