C++将文本文件写入字符串并转换为double,会得到null char或0

C++ Writing text file to string and converting to double either gives null char or 0

本文关键字:double null char 转换 文件 文本 串并 字符串 字符 C++      更新时间:2023-10-16

我已经尝试了所有建议的方法,从单列文本文件中读取值。它们是正和负浮点值。我尝试过boost、.atof()、.strtod()、get、getline、.push_back()等等。我当前的代码将0指定给cels。我尝试的几乎所有其他函数都只给了字符串"\0",并陷入while循环。

如果你看一下这个程序的底部,我已经启动了svg来创建一个条形图。我需要能够找到最大值和最小值来创建一个比例因子,然后通过svg提供每个值。

我希望使用.atof或getline,因为它们看起来最有效。据我所知,变量类型不匹配是一个问题。我为此付出了巨大的努力,并重写了无数次。我想我很清楚我需要做什么,以及它应该如何运作,但我似乎无法把所有这些都放在一起。我真的很感激任何帮助!

#include <iostream>
#include <fstream>
#include <sstream>
#include <istream>
#include <cstdlib>
#include <string>
#include <vector>
#include <cctype>
#include <cstdio>
using namespace std;
string html_start() { return("<!DOCTYPE html>n<html>n<body>nn"); }
string html_end()   { return("n</body>n</html>nn"); }
string svg_start()  { return("<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1024 768" preserveAspectRatio="xMinYMid meet" >n"); }
string svg_end()    { return("</svg>n"); }

int main ()
{
    ifstream infile ("parsableTemps.txt");
    ofstream fout ("graph.html", std::ofstream::out);
    double cels, fahr, maxnum = -50, minnum = 150;
    int column = 10, width = 5;
    string number;
    //char c;
    infile.open("parsableTemps.txt");
    infile.is_open();
    if (infile.is_open())
    {
    while (! infile.eof())
    {
        std::getline (infile,number);
        //while (! isspace(c))
        //{
        //    infile >> number;
        //}

        //cels = atof(number.c_str());
        char *end;
        //std::getline(infile, number);
        //cout << number;
        cels = strtod(number.c_str(), &end);
        fahr = (9/5 * cels) + 32;
        if (fahr > maxnum)
        {
            maxnum = fahr;
        }
    if (fahr < minnum)
    {
        minnum = fahr;
    }

    fout.open("graph.html");
    fout << html_start();
    fout << "<h1> AVERAGE TEMPERATURE </h1>n";
    fout << svg_start();
    fout << "   <rect x="" << column << "" y="" << maxnum - fahr << "" width="" << width << "" height="" << fahr << "" style="fill:rgb(255,0,0);stroke-width:1;stroke:rgb(0,0,0)"/>n";
    column += width;
}
}
else
{
    cout << "error";
}
//cout << maxnum << " " << minnum;
fout << svg_end();
fout << html_end();
fout.close();
infile.close();
return 0;
}

我怀疑这个问题措辞不当。在你做任何其他事情之前,停止打开输入文件两次:

ifstream infile ("parsableTemps.txt");
//...
infile.open("parsableTemps.txt");//<- Why twice?

这就足够了:

ifstream infile ("parsableTemps.txt");
//...

其次,不要在循环过程中不断地重新打开输出文件。打开一次,循环外:

ofstream fout ("graph.html", std::ofstream::out); //moved...
fout << html_start();                             //moved...
fout << "<h1> AVERAGE TEMPERATURE </h1>n";       //moved...
fout << svg_start();                              //moved...
if (infile.is_open())
{
    while (! infile.eof())
    {

张贴的代码显示

   while (! infile.eof())
    {
        std::getline (infile,number);
        //...
        fout.open("graph.html");
        //...
        fout << "   <rect x="" << column << "" y="" << maxnum - fahr << "" width="" << width << "" height="" << fahr << "" style="fill:rgb(255,0,0);stroke-width:1;stroke:rgb(0,0,0)"/>n";

这将一遍又一遍地重写上一个文件。此外,在完成循环之前,你还没有找到总的最小值和最大值,所以也许你应该在之后写?

就输入而言,它在我的机器上工作。

使用strtod()很麻烦:我也遇到了很多麻烦(因为指针应该总是在正确的位置,等等)

最简单的解决方案是使用一个更宽松的自定义动作模板(可以在StackOverflow上找到):

template <typename T>
T StringToNumber(const std::string &Text, const T defValue = T()) {
    std::stringstream ss;
    for(const char i : Text)  // C++11; can be replaced by an iterator
        if(isdigit(i) || i == 'e' || i == '-' || i == '+' || i == '.')
            ss << i;
    T result;
    return ss >> result ? result : defValue;
}

main()函数中:

std::getline(infile,number);
cels = StringToNumber(number, 0.0);

对于每行有一个以上数字的文件,我使用std::vector<std::string>来分隔不同的"单词"(我指的是用空格或新行分隔的字符序列):

std::vector<std::string> WordsToVectorOfWords(const std::string &Text) {
    std::vector<std::string> VectorOfWords;
    std::string word;
    for(const char i : Text) {  // C++11; can be replaced by an iterator
        if(i == ' ' || i == 't' || i == 'n') {
            VectorOfWords.push_back(word);
            word = "";
            continue;
        }
        word += i;
    {
    return VectorOfWords;
}

并且在main()函数中:

std::getline(infile,number);
std::vector<std::string> VectorOfWords = WordsToVectorOfWords(number);
for(const srd::string Words : VectorOfWords) {  // C++11; can be replaced by an iterator
    cels = StringToNumber(Words, 0.0);
    ...
    }

好吧,现在它对我有效

你的while循环:

while ( !infile.eof() )
{
    char *end;
   infile>>number; // Just read a number as string
    cels = strtod(number.c_str(), &end); // Can use other method too
    fahr = (9/5 * cels) + 32;
    if (fahr > maxnum)
    {
        maxnum = fahr;
    }
    if (fahr < minnum)
    {
        minnum = fahr;
    }
    //fout.open("graph.html"); // Don't reopen
    fout << html_start();
    fout << "<h1> AVERAGE TEMPERATURE </h1>n";
    fout << svg_start();
    fout << "   <rect x="" << column << "" y="" << maxnum - fahr << "" width="" << width << "" height="" << fahr << "" style="fill:rgb(255,0,0);stroke-width:1;stroke:rgb(0,0,0)"/>n";
    column += width;
}

将单个数字作为字符串读取,然后在其上应用strtod,即读取整行。此外,不要重新打开打开的文件以写入和读取

不确定你是否得到了正确的graph.html,但它会根据输入的数量和你的算法来写行。