Input hexadecimal floating point number using scanf() and conversion specifier “%a”

huangapple go评论51阅读模式
英文:

Input hexadecimal floating point number using scanf() and conversion specifier "%a"

问题

我正在测试printf()scanf()函数的转换说明符。对于在printf()函数中使用的浮点十六进制数的%a格式说明符,我没有遇到问题。它显示了我预期的结果。但是当我尝试使用以下代码输入十六进制浮点数时,遇到了问题:

printf("Enter variable:\n");
scanf("%a", &var);
printf("var = %f\n", var);
printf("var = %e\n", var);
printf("var = %a\n", var);

当我输入一个示例值,例如0x1.205b0cp-11,它给我以下结果:

Enter variable:
0x1.205bc0p-11
var = 0.000000
var = 0.000000e+000
var = 0x0.000000p+0

无论我输入什么数字,它总是给我0。这个问题的原因或解决方案是什么?我不知道我做错了什么。

英文:

I'm testing conversion specifiers both for printf() and scanf() function. I hadn't problem with %a format specifier for floating point hexadecimal number used in printf() function. It displayed what I expected. But I encountered problem when I wanted to input hexadecimal float using

scanf("%a", &var);

I'm using the following code:

#include <stdio.h>

int main()
{
	float var;

	printf("Enter variable:\n");
	scanf("%a", &var);
	printf("var = %f\n", var);
	printf("var = %e\n", var);
	printf("var = %a\n", var);

	return 0;
}

When I enter a sample value, e.g. 0x1.205b0cp-11 that is 5.5e-4 it gives me that result:

Enter variable:
0x1.205bc0p-11

var = 0.000000
var = 0.000000e+000
var = 0x0.000000p+0

Whatever number I enter it always gives me 0. What's the reason or solution for that problem. I have no idea what I'm making wrong.

答案1

得分: 1

那段代码在我的系统上运行得很好(a),产生了预期的结果:

pax> ./prog
Enter variable: 0x1.205bc0p-11
var = 0.000550
var = 5.500000e-04
var = 0x1.205bcp-11

请注意,十六进制浮点常数(以及%a转换说明符)是在C99中引入的,因此您应该确保您使用的编译器支持它。大多数现代编译器都会支持,但某些人可能会受限于特定级别,如果供应商不积极跟进的话(b)

请记住,scanf系列函数,以及转换说明符aegf(以及它们的大写变体)都是相同的 - 它们都处理strtod处理的每种格式。它们都存在的(很可能)原因是为了与printf的转换说明符相对应,在某些情况下,它们会影响值的输出方式。

值得考虑的是,首先测试一些比十六进制浮点数更简单的输入,然后逐步增加复杂度。例如,可以尝试以下序列:{ 0, 3, 3.1, 3.14159, 9e2, 6e-2, ... }。这至少能让您知道输入在何处失败。

此外,测试转换以确保它有效是个好主意(这对于所有可能会对将来的程序行为产生不利影响的调用都适用)。换句话说,您可以使用以下代码替代您的scanf语句:

if (scanf("%a", &var) != 1) {
    fprintf(stderr, "出现严重错误!\n");
    return 1;
}

(a) 顺便提一下,我的系统是gcc 9.4.0(通过gcc --version获得)运行在Ubuntu 20.04.2上(通过cat /etc/lsb_release获得)。通常,在提问时包含这种信息是个好主意,因为它可以帮助我们更快地解决问题。

(b) 也许有考虑更改供应商的充分理由,当然,这取决于正常的成本效益分析。

英文:

That code works on my system<sup>(a)</sup>, producing the expected result:

pax&gt; ./prog
Enter variable: 0x1.205bc0p-11
var = 0.000550
var = 5.500000e-04
var = 0x1.205bcp-11

Keep in mind that hexadecimal floating point constants (and the %a conversion specifier) were introduced in C99, so you should make sure you're using a compiler that handles that. Most modern ones will, but some people may be locked in to a certain level if the vendor isn't keen on keeping up to date<sup>(b)</sup>.

Keep in mind that the scanf family, conversion specifiers a, e, g, and f (and their upper-case variants) are all the same - they each handle every format that strtod handles. The (likely) reason that they all exist is to mirror the printf conversion specifiers where it makes a difference to how the value is output.

It's possibly worth testing with a variety of inputs less advanced than hex floating point, and work your way up to there. For example, the sequence { 0, 3, 3.1, 3.14159. 9e2, 6e-2, ... }. That would at least let you know where the input is failing.

Also, it's a good idea to test the conversion to ensure it works (this is true of all calls where failure can adversely affect future program behaviour). In other words, something like this in place of your scanf statement:

if (scanf(&quot;%a&quot;, &amp;var) != 1) {
    fprintf(stderr, &quot;Something went horribly wrong!\n&quot;);
    return 1;
}

<sup>(a)</sup> My system, by the way, is gcc 9.4.0 (from gcc --version) running on Ubuntu 20.04.2 (from cat /etc/lsb_release). It's often a good idea to include that sort of information in questions, it can help us figure out issues more quickly.

<sup>(b)</sup> Possibly a good reason to consider changing vendors though, of course, subject to normal cost/benefit analysis.

答案2

得分: 0

尝试类似于使用 printf("var = %e\n", var/7.0 + var *var); 这样的方式来计算。有时,即使不进行数学运算,仅使用简单的代码也可能需要链接数学库,该库是 printf() 所需的。

英文:

Try computing somehow like with printf(&quot;var = %e\n&quot;, var/7.0 + var *var);. Sometimes simple code without doing any math does not link in the math library needed by printf().

huangapple
  • 本文由 发表于 2023年2月10日 05:35:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75404647.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定