【问题标题】:Using both commas and dots to represent decimal numbers使用逗号和点来表示十进制数
【发布时间】:2018-09-22 18:33:00
【问题描述】:

我遇到了一个非常具体的问题,但在其他地方没有找到解决方案。我正在做一个小项目,我想通过允许用户使用逗号或点输入价格来使其更加健壮。所以我做了一个小功能,让我可以做到这一点:

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

int main () {
    setlocale(LC_ALL, "Portuguese");
    float val;
    char str[20];

    scanf("%s", str);
    for (int i = 0; str[i] != '\0'; ++i)
        if (str[i] == ',') 
            str[i] = '.';
        val = atof(str);
    printf("String value = %s, Float value = %f\n", str, val);
    return(0);
}

如果我不是葡萄牙人,这将按预期工作。由于我们主要在十进制数字中使用逗号,因此使用 atof 函数不起作用,因为它会转换为带点的浮点数,然后当我尝试使用 printf 浮点数时,它将显示 0.0 但如果您删除该行setlocale(LC_ALL, "Portuguese"); 它会工作得很好。有什么想法吗?

【问题讨论】:

标签: c localization comma


【解决方案1】:

有两个问题:

  • 如果您遇到不适合当前语言环境的小数点,那么只有这样,才能更改它。
  • 您正在使用atof,这是一个不应该使用的不安全函数 - 它没有错误处理。请改用strtof

您可以使用标准函数localeconv 获取有关当前语言环境的各种有用信息。

例子:

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

int main (void) 
{
  setlocale(LC_ALL, "Portuguese");
  char ok_decimal_point  = localeconv()->decimal_point[0];
  char bad_decimal_point = (ok_decimal_point=='.') ? ',' : '.';

  float val;
  char str[20] = "123.456";

  for (int i = 0; str[i] != '\0'; ++i)
  {
    if (str[i] == bad_decimal_point)
    {
      str[i] = ok_decimal_point;
    }
  }

  val = strtof(str, NULL);
  printf("String value = %s, Float value = %f\n", str, val);
  return(0);
}

(尽管来自另一个使用, 的国家/地区,但我更喜欢教育用户使用. 表单,因为这更像是一个国际标准。世界各地有两种不同的小数点标准是没有帮助人类。那些使用最少的版本应该适应。)

【讨论】:

  • 这确实有效。但出于好奇,为什么atof 不安全?例如,如果它收到一个无法转换的字符串,它只是返回 0.0,还是还有其他问题?
  • @Real 如果接收到无法转换的字符串,则行为未定义。它可能会返回 0,也可能会返回其他内容,也可能会使程序崩溃。 strto... 函数没有这个问题,所以它们总是首选。
【解决方案2】:

您的代码按预期工作:

for 循环将所有, 转换为.,因此atof 无法转换以. 作为小数点的数字,因为您事先调用了setlocale(LC_ALL, "Portuguese");

你需要这个:

if (str[i] == '.') str[i] = ',';

而不是这个:

if (str[i] == ',') str[i] = '.';

这个例子很清楚:

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

int main() {

  float val;

  // converting with default locale
  char str[20] = "1.234";
  val = atof(str);
  printf("Default locale: String value = %s, Float value = %f\n", str, val);

  // converting with Portugese locale    
  setlocale(LC_ALL, "Portuguese");

  char strport[20] = "1,234";
  val = atof(strport);
  printf("Portugese locale: String value = %s, Float value = %f\n", strport, val);
  return(0);
}

【讨论】:

  • 我现在真的觉得很笨,基本上只是在转换后将 setlocale 移到它的工作原理......哎呀,有道理。谢谢大佬帮忙,我正要扯掉一些头发
  • "if (str[i] == '.') str[i] = ',';" 直到再次更改区域设置。最好编写完全可移植的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多