使用 sscanf 定位错误的来源
Locate the source of a bug with sscanf
我已经为此苦苦挣扎了太久。
假设我有这个最少的代码:
test.cxx
#include <iostream>
#include <cstdio>
int main (int argc, char *argv[])
{
const char *text = "1.01 foo";
float value = 0;
char other[8];
int code = sscanf(text, "%f %7s", &value, other);
std::cout << code << " | " << text << " | => | " << value << " | " << other << " | " << std::endl;
return 0;
}
$ g++ test.cxx; ./a.out
按预期生成此输出:
$ 2 | 1.01 foo | => | 1.01 | foo |
现在我将这 5 行嵌入到一个项目中,该项目有几千行,并且包含很多...
正在编译,运行,现在的输出是:
$ 2 | 1.01 foo | => | 1 | .01 |
我可以使用什么策略来定位这种不一致的根源?
编辑:
export LC_ALL=C (or LC_NUMERIC=C); ./a.out
似乎解决了我的问题
这可能是由于您的测试和目标应用程序中的语言环境不同所致。我能够在 coliru 上重现它:
通过使用:
setlocale(LC_ALL, "cs_CZ.utf8");
http://coliru.stacked-crooked.com/a/5a8f2ea7ac330d66
您可以在此 SO 中找到一些解决方案:
sscanf() and locales. How does one really parse things like "3.14"?
[编辑]
使用 uselocale
的解决方案,但是既然你用 C++ 标记了这个问题,那么为什么不使用 std::stringstream 并为其注入适当的语言环境(参见上面的 link 到 SO)。
http://coliru.stacked-crooked.com/a/dc0fac7d2533d95c
const char *text = "1.01 foo";
float value = 0;
char other[8];
// set for testing, sscanf will assume floating point numbers use comma instead of dots
setlocale(LC_ALL, "cs_CZ.utf8");
// Temporarily use C locale (uses dot in floats) on current thread
locale_t locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
locale_t old_locale = uselocale(locale);
int code = sscanf(text, "%f %7s", &value, other);
std::cout << code << " | " << text << " | => | " << value << " | " << other << " | " << std::endl;
// Go back to original locale
uselocale(old_locale);
freelocale(locale);
我已经为此苦苦挣扎了太久。
假设我有这个最少的代码:
test.cxx
#include <iostream>
#include <cstdio>
int main (int argc, char *argv[])
{
const char *text = "1.01 foo";
float value = 0;
char other[8];
int code = sscanf(text, "%f %7s", &value, other);
std::cout << code << " | " << text << " | => | " << value << " | " << other << " | " << std::endl;
return 0;
}
$ g++ test.cxx; ./a.out
按预期生成此输出:
$ 2 | 1.01 foo | => | 1.01 | foo |
现在我将这 5 行嵌入到一个项目中,该项目有几千行,并且包含很多...
正在编译,运行,现在的输出是:
$ 2 | 1.01 foo | => | 1 | .01 |
我可以使用什么策略来定位这种不一致的根源?
编辑:
export LC_ALL=C (or LC_NUMERIC=C); ./a.out
似乎解决了我的问题
这可能是由于您的测试和目标应用程序中的语言环境不同所致。我能够在 coliru 上重现它:
通过使用:
setlocale(LC_ALL, "cs_CZ.utf8");
http://coliru.stacked-crooked.com/a/5a8f2ea7ac330d66
您可以在此 SO 中找到一些解决方案:
sscanf() and locales. How does one really parse things like "3.14"?
[编辑]
使用 uselocale
的解决方案,但是既然你用 C++ 标记了这个问题,那么为什么不使用 std::stringstream 并为其注入适当的语言环境(参见上面的 link 到 SO)。
http://coliru.stacked-crooked.com/a/dc0fac7d2533d95c
const char *text = "1.01 foo";
float value = 0;
char other[8];
// set for testing, sscanf will assume floating point numbers use comma instead of dots
setlocale(LC_ALL, "cs_CZ.utf8");
// Temporarily use C locale (uses dot in floats) on current thread
locale_t locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
locale_t old_locale = uselocale(locale);
int code = sscanf(text, "%f %7s", &value, other);
std::cout << code << " | " << text << " | => | " << value << " | " << other << " | " << std::endl;
// Go back to original locale
uselocale(old_locale);
freelocale(locale);