我正在编写一个小命令行程序,它从stdin中读取两个浮点数,一个int和一个小字符串(最多4个字符串)。我试图找出我应该创建的缓冲区大小并传递给fgets。我想我可以根据float
和int
的最大值分别包含多少位数来计算出来,如下所示:
#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。
答案 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
,使缓冲区大小成为别人的问题