C ++将文本文件写入字符串并转换为double,或者给出null char或0

时间:2013-08-06 11:39:41

标签: c++ string svg ifstream

我尝试过各种建议听到从单个列文本文件中读取值的方法。它们是pos和neg浮动值。我尝试过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>\n\n"); }
string html_end()   { return("\n</body>\n</html>\n\n"); }
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;
}

3 个答案:

答案 0 :(得分:2)

我怀疑这个问题措辞严厉。 在您执行任何其他操作之前,请停止打开输入文件两次:

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

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

就输入而言,它适用于我的机器。

答案 1 :(得分:0)

使用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);
    ...
    }

答案 2 :(得分: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,但它根据输入数量和算法编写了该行。