C++: strod()和 atof()没有像预期的那样返回double。

问题描述 投票:0回答:1

我试图用从一个.txt文件中获得的数值将字符串变成双数。

我得到的双倍数没有小数,这是因为在.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 time (string), u10st (string), u10 (double), u40 (double)).

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

有什么办法可以把那个425636的字符串读成双4.25636?文件太长,无法修改。

c++ text ifstream atof strtod
1个回答
1
投票

为了避免在全局环境下的混乱,你可以只用替换掉 ,. 呼叫前 strtod()

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

但在上图所示的程序中,你也可以从下面读出 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) {

现场演示


1
投票

浮点数使用了逗号小数点分隔符,而你期望的是句号。

这表明数据的序列化使用了不同的 地区 而不是你的。

为了解决这个问题,在解析数字之前设置你的locale(之后再还原)。

例如,这里有一些代码,可以用默认的句号分隔符来解析数字 "12,34",然后我们将locale设置为Denmark,再试一次。

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(""));

输出:

在默认的locale中解析出的数字: 12 设置locale为丹麦(逗号十进制分隔符) 在丹麦locale中解析的数字: 12.34

实时演示

问问周围的人,看看是谁把这个数据序列化了,然后得到正确的locale.你可以在*nix系统中找到可用的locale,用 locale -a

在Windows上,它似乎是 稍有难度

© www.soinside.com 2019 - 2024. All rights reserved.