为什么scanf接受“%f”格式说明符的字符?

时间:2018-11-11 18:15:15

标签: c stdio

我正在为我的课程准备一个简单的程序,发现{ "rules": { "users": { "$uid": { "notes": { ".validate": "newData.isString() && newData.val().length <= 2000" } } } } } 并不像我期望的那么严格:

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;
}

在哪里可以了解其行为?

如果没有整数也没有浮点数,如何使输入严格使用标准函数并引发异常?

P。 S.我在Ubuntu中使用gcc v5。

4 个答案:

答案 0 :(得分:3)

  

我正在为我的课程准备一个简单的程序,发现scanf是   不像我预期的那么严格

不,你没有。

给出此scanf呼叫:

  float alpha;
  float b;

  scanf("%f %f", &alpha, &b);

...以及此输入:

a 0

... scanf在尝试扫描浮点值且尚未扫描任何十进制数字时遇到'a'时,匹配失败。它在该点停止(并将“ a”留在流中以进行后续读取),并且与往常一样,它返回成功扫描的输入字段数(0)。

  

在哪里可以了解其行为?

您可以尝试在命令行(Linux,OSX等)上运行命令man scanf,或输入与Google搜索相同的命令。或谷歌“ scanf文档”或“ scanf手册”或类似。或查找特定C库的官方手册。对于标准库函数,the standard是一个很好的参考,但是您的特定实现可能未在其中记录扩展名,或者有时甚至与标准存在细微差别。

  

如何使用标准函数严格输入并抛出   既没有整数也没有浮点数的例外?

C没有例外。它在大多数情况下通过函数返回值告诉您有关错误的信息,尽管某些第三方库可能会稍微有所不同。但是您必须通过检查返回值并适当地响应来完成您的部分。在这种情况下,必须避免读取alphab的值。因为这些变量没有初始化,并且随后没有分配任何值,所以读取它们的值会产生未定义的行为

答案 1 :(得分:3)

其他答案,尤其是@John Bollinger很好地解释了为什么代码无法达到目标。

注释输入可能会转换为arr = 'a b c d'def morse_code(morse_string) new_elements = [] # iterate over each character in the string, morse_string.split(" ").each do |element| if morse_dict[element] # https://apidock.com/ruby/Array/push new_elements.push( morse_dict[element] ) else # whatever you want to do when there is no match end end # re-create the string again, but with braille # https://apidock.com/ruby/Array/join new_elements.join(' ') end morse_string = 'a b c d' morse_code(morse_string) ,或者两者都不转换。

  

如果没有整数也没有浮点数,如何使输入严格使用标准函数并引发异常?

最好是使用其他工具,例如int来读取输入的并形成 string 以便以后进行测试。

严格测试 有点困难。 float在溢出时具有未定义的行为fgets()具有相似的UB,尤其是当*scanf("%d",...)不支持无穷/非数字时。


测试字符串是否转换为有效的*scanf("%f",...)

float

要测试字符串是否转换为有效的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一样。以后再说-GTG。

答案 2 :(得分:1)

AX可用于读取一行。用fgets解析行。 sscanf将返回成功扫描的项目数。这还将捕获第二个浮点之后的字符。如果不是换行符,则循环将继续,直到扫描两个浮点后跟换行符为止。

sscanf

答案 3 :(得分:0)

正如@John Bollingeranswer)和@chuxanswer)友好地解释了这个问题本身就是错误的,实际上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学位期间编写的简单学习程序!

否则,请检查@chux's答案以获得更类似于生产的解决方案。