【问题标题】:C++: strod() and atof() are not returning double as expectedC++:strod() 和 atof() 没有按预期返回 double
【发布时间】:2020-06-10 11:10:27
【问题描述】:

我正在尝试使用从 .txt 文件中获得的值将字符串转换为双精度值。

我得到的双打没有小数。我相信这是因为,在 .txt 中,数字的小数点用逗号而不是点分隔。但我不知道如何解决。

这是我的代码的简化:

#include <iostream>
#include <fstream> // read text file
#include <stdlib.h> // strtod, atof

int main() {

std::ifstream readWindData("winddata.txt");

// check that document has been opened correctly
if (!readWindData.is_open()) {
    std::cout << "Wind data could not be opened." << std::endl;
    return 1;
}

// skip headers of the table
std::string firstLine;
std::getline(readWindData, firstLine);

int numberOfRows = 0; // variable to count rows of the table

// initialise strings that separate each value
std::string time, string u10st, u40st, u60st, u80st, u100st, 
            u116st, u160st, dir10st, dir60st, dir100st, timeDecst;

// initialise doubles
double u10, u40, u60, u80, u100, u116, u160, dir10, dir60, dir100, timeDec;

std::string nextLine;

// Read strings and turn it into doubles line by line until end
while (readWindData >> time >> u10st >> u40st >> u60st >> u80st >> u100st
        >> u116st >> u160st >> dir10st >> dir60st >> dir100st >> timeDecst) {

    // try two different functions to turn strings into doubles:
    u10 = strtod(u10st.c_str(), NULL);
    u40 = atof(u40st.c_str());

    // ensure numbers are displaying all their decimals
    std::cout.precision(std::numeric_limits<double>::digits10 + 1);

    // see what I am getting
    std::cout << time << " " << u10st << " " << u10 << " " << u40 << "\n";

    std::getline(readWindData, nextLine); // this line skips some crap on the side of some rows

    numberOfRows++; // counts rows
}

std::cout << "Number of rows = " << numberOfRows << "\n";
readWindData.close();

return 0;
}

这是文件的三行:

time (hour) u10(m/s)u40(m/s)u60 (m/s)u80(m/s)u100(m/s)u116(Um/s)u160(m/s)dir10 dir60 dir100         time decimal hours      
00:00       4,25636 7,18414 8,56345 9,75567 10,9667 12,1298 13,8083 110,616 131,652 141,809         0       midnight
00:10       4,54607 7,40763 8,62832 9,91782 11,2024 12,2694 14,1229 114,551 133,624 142,565         0,166666667 

这些是上面代码输出的那些行: (提醒,我 std::cout 时间(字符串),u10st(字符串),u10(双),u40(双))。

00:00 4,25636 4 7
00:10 4,54607 4 7

关于如何将 4,25636 字符串读入双 4.25636 的任何想法?文件太长,无法修改。

【问题讨论】:

  • 看起来是语言环境问题;当语言环境使得小数点分隔符是逗号并且您的语言环境使用句点时,就会发生序列化。研究设置语言环境。
  • @AndyG 我已经研究了一下,看看你看起来是否正确。我看不到如何更改 atof 和 strtod 的功能。我发现的大多数示例都是针对 std::cout、std::cin... 我可以请您提供更多指导来解决这个特定问题吗?
  • @AndyG 似乎atofstrtod 总是使用“C”语言环境(期望点十进制)。来自cppreference形成了使用“C”语言环境的 atof 的有效浮点数...

标签: c++ text ifstream atof strtod


【解决方案1】:

为避免混淆全局语言环境,您可以在调用 strtod() 之前将 , 替换为 .

    std::replace(u10st.begin(), u10st.end(), ',', '.');
    u10 = strtod(u10st.c_str(), nullptr);

但在上面显示的程序中,如果您使用 comma 是小数分隔符的语言环境,您也可以使用运算符 &gt;&gt;ifstream 直接读取到 double

    readWindData.imbue(std::locale("de_DE.UTF-8")); // or fr, nl, ru, etc.

    double u10, u40, u60, u80, u100, u116, u160, dir10, dir60, dir100, timeDec;

    while (readWindData >> time >> u10 >> u40 >> u60 >> u80 >> u100
            >> u116 >> u160 >> dir10 >> dir60 >> dir100 >> timeDec) {

Live demo

【讨论】:

  • 两种解决方案都有效。谢谢! (为简单起见,第二个是最好的)。尽管我必须解决一些问题才能使其正常工作。否则会得到错误:“在抛出 'std::runtime_error' what() 的实例后调用终止:locale::facet::_S_create_c_locale 名称无效。”为避免该错误,请在 Ubuntu 上工作: $ sudo apt-get install locales $ sudo locale-gen de_DE.UTF-8
【解决方案2】:

浮点数使用逗号小数分隔符,您需要句点。

这表明数据是用不同于你的locale locale 序列化的。

要解决这个问题,请在解析数字之前设置您的语言环境(然后再恢复)。

例如,这里有一些代码用默认的句点分隔符解析数字“12,34”,然后我们将语言环境设置为丹麦并重试:

const char* number = "12,34";
double parsed_number = 0;
parsed_number = std::strtod(number, nullptr);
std::cout << "parsed number in default locale: " << parsed_number << std::endl;
std::cout << "Setting locale to Denmark (comma decimal delimiter)" << std::endl;
std::locale::global(std::locale("en_DK.utf8"));
parsed_number = std::strtod(number, nullptr);
std::cout << "parsed number in Denmark locale: " << parsed_number << std::endl;
//restore default locale
std::locale::global(std::locale(""));

输出:

默认语言环境中的解析数字:12
将语言环境设置为丹麦(逗号十进制分隔符)
在丹麦语言环境中解析的数字:12.34

Live Demo

四处打听,看看是谁序列化了这些数据,并获得正确的语言环境。 您可以使用locale -a在 *nix 系统中找到可用的语言环境

在 Windows 上,它似乎是 a little more difficult

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-22
    • 2013-05-17
    • 1970-01-01
    • 1970-01-01
    • 2020-06-28
    • 2013-04-28
    • 1970-01-01
    • 2017-11-08
    相关资源
    最近更新 更多