首页 > 解决方案 > 如何在 C 中通过 atof() 正确转换扫描的字符串?

问题描述

我需要验证通过 scanf() 传递的字符串只是数字和“。” 和“,”也应该可以接受,“-”作为负数表示。我写了这段代码:

int main(void)
{
   char cFloatNum[100];
   float fNum;

   scanf("%[[+-]?[0-9]*[.,]?[0-9]+]", &cFloatNum);

   fNum = atof(cFloatNum);

   printf("%f", fNum);

   return EXIT_SUCCESS;
}

0.000000我不知道为什么,但无论我写什么数字,我的输出似乎总是如此。我尝试在各种正则表达式网站上测试我的正则表达式,它完美匹配。

向控制台写入内容后,如果有效,则应通过 printf 在控制台上打印。对于从字符串到浮点数的转换,我需要使用atof()函数。

有效数字的示例是:

-44.276
44,546
56,657675
-77.2435235

标签: c

解决方案


只有数字和“。” 和“,”也应该可以接受,“-”作为负数表示

所以就这么写吧。例如:

#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>

int check_your_condition(float *result) {
   int ret = 0;
   *result = 0;
   bool seen_minus = false;
   bool first_character = true;
   bool seen_dot = false;
   float div = 10;
   for (int c; (c = getchar()) != EOF; first_character = false) {
       if (first_character == true && seen_minus == false && c == '-') {
             seen_minus = true;
             continue;
       }
       if (seen_dot == false && (c == '.' || c == ',')) {
             seen_dot = true;
             continue;
       }
       if (!isdigit((unsigned char)c)) {
             ret = -1;
             // TODO handle error properly
             break;
       }
       const short num = c - '0';
       if (seen_dot == false) {
            *result *= 10;
            *result += num;
       } else {
            const float numf = num / div;
            div *= 10;
            *result += numf;
       }
   }
   if (seen_minus) {
       *result *= -1;
   }
   return ret;
}

int main() {
    float a;
    check_your_condition(&a);
    printf("%f\n", a);
}

这不是一个“即用型”(TM) 程序,因为多行上的换行符仍然只是在输入流中“忽略”(即isdigit(c)会失败)。一个适当的解决方案应该ungetc在那里调用,并包括正确的逻辑来处理其余的输入。

scanf("%[[+-]?[0-9]*[.,]?[0-9]+]"

是完全错误的。Noscanf不支持正则表达式。

对于从 String 到 Float 的转换,我需要使用 atof() 函数。

很可能会要求您将输入作为单行读取,然后atof在结果上应用函数:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main() {
        char buf[200];
        if (fgets(buf, sizeof(buf), stdin) == NULL) abort();
        errno = 0;
        const float a = atof(buf);
        if (errno) abort();
        printf("%f\n", a);
}

在这样的解决方案中,如果.,将被理解为小数分隔符取决于语言环境。并且字符串后面的输入字符串部分将被忽略。


推荐阅读