为什么 scanf 接受“%f”格式说明符的字符?
Why scanf accepts chars for "%f" format specifier?
我正在为我的 类 准备一个简单的程序,发现 scanf
并不像我预期的那么严格:
int main()
{
// Define variables
float alpha;
float b;
float result;
// Get user input
printf("Type alpha and b. Space separated float numbers only.\n");
scanf("%f %f", &alpha, &b);
printf("%f %f\n", alpha, b);
return 0;
}
Returns:
Type alpha and b. Space separated float numbers only.
a 0
-29768832.000000 0.000000
我在哪里可以了解它的行为?
如果既没有整数也没有浮点数,我如何使标准函数的输入严格并抛出异常?
P. S. 我在 Ubuntu.
中使用 gcc v5
I'm preparing a simple program for my classes and found that scanf is
not as strict as I expected
不,你没有。
鉴于此 scanf
调用:
float alpha;
float b;
scanf("%f %f", &alpha, &b);
... 并且此输入:
a 0
... scanf
在尝试扫描浮点值且尚未扫描任何十进制数字时遇到 'a' 时匹配失败。它在该点停止(并在流中留下 'a' 以供后续读取),并且一如既往,它 return 是成功扫描的输入字段数 (0)。
Where I can read about its behavior?
您可以在命令行(Linux、OSX、...)尝试 运行 命令 man scanf
,或输入与 Google 搜索。或者 google "scanf docs" 或 "scanf manual" 或类似的。或者查找您的特定 C 库的官方手册。对于标准库函数,the standard 是一个很好的参考,但您的特定实现可能有扩展,那里没有记录,或者有时甚至可能在细微的方面与标准不同。
How can I make input strict with standard functions and throw an
exception if there was neither ints nor floats?
C 没有例外。大多数情况下,它通过函数 return 值告诉您有关错误的信息,尽管某些第三方库的做法可能略有不同。但是您必须通过检查 return 值并适当地响应来完成 您的 部分。在这种特殊情况下,您必须避免读取 alpha
和 b
的值。因为这些变量没有被初始化并且随后没有分配任何值,读取它们的值会产生 未定义的行为.
其他答案,特别是很好地解释了为什么代码无法达到目标。
注意输入可能会转换为 int
、float
,两者都不是,或两者都是。
How can I make input strict with standard functions and throw an exception if there was neither ints nor floats?
最好是使用其他工具如fgets()
读取行输入并形成字符串以备后用测试。
严格测试有点难。 *scanf("%d",...)
在溢出时有 未定义的行为 。 *scanf("%f",...)
有类似的UB,尤其是当float
不支持infinity/not-a-number时。
测试字符串是否转换为有效的int
bool my_isint(const char *s) {
// Add to dis-allow leading white-space
if (isspace((unsigned char) *s)) return false;
char *endptr;
base = 0; // use base = 0 to only allow base 10 input
errno = 0;
long val = strtol(s, &endptr, base);
if (s == endptr) return false; // no conversion
if (errno == ERANGE) return false; // too big for long
if (val > INT_MAX || val < INT_MIN) return false; // too big for int
// Add to allow trailing white-space
while (isspace((unsigned char) *endptr)) endptr++;
// Add to dis-allow trailing junk
while (*endptr) return false; // trailing junk
return true;
}
测试字符串是否转换为有效的 float
就像在 float
支持 infinity/non-a-number 时测试 double
。稍后- GTG.
As @John Bollinger () and @chux () 请解释问题本身是错误的,实际上 scanf
不接受字符而不是浮点数,而是忽略了它。为了捕获此行为,我按以下方式修改了代码:
+ #include <errno.h> // Error codes constants
int main()
{
// Define variables
float alpha;
float b;
+ int matches;
float result;
// Get user input
printf("Type alpha and b. Space separated float numbers only.\n");
± matches = scanf("%f %f", &alpha, &b);
+ if (matches != 2) {
+ printf("ERROR: Space separated float numbers only expected.\n");
+ return EINVAL;
+ }
printf("%f %f\n", alpha, b);
return 0;
}
仅适用于您在 CS 学位期间编写的简单学习程序!
否则,请检查 答案以获得更类似于生产的解决方案。
我正在为我的 类 准备一个简单的程序,发现 scanf
并不像我预期的那么严格:
int main()
{
// Define variables
float alpha;
float b;
float result;
// Get user input
printf("Type alpha and b. Space separated float numbers only.\n");
scanf("%f %f", &alpha, &b);
printf("%f %f\n", alpha, b);
return 0;
}
Returns:
Type alpha and b. Space separated float numbers only.
a 0
-29768832.000000 0.000000
我在哪里可以了解它的行为?
如果既没有整数也没有浮点数,我如何使标准函数的输入严格并抛出异常?
P. S. 我在 Ubuntu.
中使用 gcc v5I'm preparing a simple program for my classes and found that scanf is not as strict as I expected
不,你没有。
鉴于此 scanf
调用:
float alpha; float b; scanf("%f %f", &alpha, &b);
... 并且此输入:
a 0
... scanf
在尝试扫描浮点值且尚未扫描任何十进制数字时遇到 'a' 时匹配失败。它在该点停止(并在流中留下 'a' 以供后续读取),并且一如既往,它 return 是成功扫描的输入字段数 (0)。
Where I can read about its behavior?
您可以在命令行(Linux、OSX、...)尝试 运行 命令 man scanf
,或输入与 Google 搜索。或者 google "scanf docs" 或 "scanf manual" 或类似的。或者查找您的特定 C 库的官方手册。对于标准库函数,the standard 是一个很好的参考,但您的特定实现可能有扩展,那里没有记录,或者有时甚至可能在细微的方面与标准不同。
How can I make input strict with standard functions and throw an exception if there was neither ints nor floats?
C 没有例外。大多数情况下,它通过函数 return 值告诉您有关错误的信息,尽管某些第三方库的做法可能略有不同。但是您必须通过检查 return 值并适当地响应来完成 您的 部分。在这种特殊情况下,您必须避免读取 alpha
和 b
的值。因为这些变量没有被初始化并且随后没有分配任何值,读取它们的值会产生 未定义的行为.
其他答案,特别是
注意输入可能会转换为 int
、float
,两者都不是,或两者都是。
How can I make input strict with standard functions and throw an exception if there was neither ints nor floats?
最好是使用其他工具如fgets()
读取行输入并形成字符串以备后用测试。
严格测试有点难。 *scanf("%d",...)
在溢出时有 未定义的行为 。 *scanf("%f",...)
有类似的UB,尤其是当float
不支持infinity/not-a-number时。
测试字符串是否转换为有效的int
bool my_isint(const char *s) {
// Add to dis-allow leading white-space
if (isspace((unsigned char) *s)) return false;
char *endptr;
base = 0; // use base = 0 to only allow base 10 input
errno = 0;
long val = strtol(s, &endptr, base);
if (s == endptr) return false; // no conversion
if (errno == ERANGE) return false; // too big for long
if (val > INT_MAX || val < INT_MIN) return false; // too big for int
// Add to allow trailing white-space
while (isspace((unsigned char) *endptr)) endptr++;
// Add to dis-allow trailing junk
while (*endptr) return false; // trailing junk
return true;
}
测试字符串是否转换为有效的 float
就像在 float
支持 infinity/non-a-number 时测试 double
。稍后- GTG.
As @John Bollinger (scanf
不接受字符而不是浮点数,而是忽略了它。为了捕获此行为,我按以下方式修改了代码:
+ #include <errno.h> // Error codes constants
int main()
{
// Define variables
float alpha;
float b;
+ int matches;
float result;
// Get user input
printf("Type alpha and b. Space separated float numbers only.\n");
± matches = scanf("%f %f", &alpha, &b);
+ if (matches != 2) {
+ printf("ERROR: Space separated float numbers only expected.\n");
+ return EINVAL;
+ }
printf("%f %f\n", alpha, b);
return 0;
}
仅适用于您在 CS 学位期间编写的简单学习程序!
否则,请检查