读取浮点数的最小缓冲区长度

时间:2011-09-15 02:30:41

标签: c buffer fgets

我正在编写一个小命令行程序,它从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。

4 个答案:

答案 0 :(得分:5)

这种类型的东西是我实际使用fscanf而不是先读入固定大小的缓冲区的地方。如果您需要确保不跳过换行符或其他有意义的空格,可以使用fgetc逐个字符处理,直到得到数字的开头,然后ungetc致电fscanf

如果你想变懒,只需选择像1000这样的大号......

答案 1 :(得分: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

以零读入。

答案 2 :(得分: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个字符(至少在我的机器上),但我不会让它运行完成所以它可能更多。

答案 3 :(得分: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,使缓冲区大小成为别人的问题