简体   繁体   中英

istringstream not storing anything in variables

I'm having an issue with istringstream not storing the values it reads. Here is what I have:

      if(inputFile.good()){                                         //Make sure file is open before trying to work with it
                                                                    //Begin Working with information
        cout << "\tIn File:  " << input << endl;
        cout << "------------------------------------" << endl;
        int number_of_lines = 0;
        std::string line;
        while (std::getline(inputFile, line)){
            ++number_of_lines;
        }
        Time times[number_of_lines];
        double math[number_of_lines];
        std::string input;
        int hh, mm;
        for(int loop=0;loop<number_of_lines;loop++){
            std::getline(inputFile, input);
            std::istringstream(input) >> mm >> hh >> math[loop];
            cout << "hours = " << hh << endl;
            times[loop].setTimeHours(hh);
            times[loop].setTimeMinutes(mm);
            times[loop].show();
            cout << "*" << math[loop] << endl;
        }
        std::cout << "Number of lines in text file: " << number_of_lines << "\n" << endl;
    }else{
        cout << "Could not open file!!!" << endl;
    }

The file I'm reading looks like this:

90 1 3.0
1 1 100.0
2 34 5.1

And the output when I run:

  In File:  data04.txt
 ------------------------------------
 hours = 0
 Operation To Be Done = 0:2336552*1.15384e-317
 hours = 0
 Operation To Be Done = 0:2336552*1.58101e-322
 hours = 0
 Operation To Be Done = 0:2336552*1.15397e-317
 Number of lines in text file: 3

Anyone know why its not storing the values?

There are several key problems in this code

  1. It doesn't check if inputs are successful. You always need to make sure you verify that the input operations worked before you process the data you read. Failing so will cause random data to be processed.
  2. You first read to the end of the stream and then hope that the stream magically restarted. That won't work. Read the stream just once and keep appending to a std::vector<Time> (or similar container). Aside from only traversing the file once, on UNIXes the file size can change while reading.
  3. C++ doesn't have variable sized arrays although some compiler may offer an extension similar to C's variable sized array. In C++ you'd use a std::vector<Time> instead.

First and foremost, your program is wrong. After the while loop ends, there is nothing more to read in the file (unless you seekg() back to the beginning), so the std::getline() call in the for loop body basically does nothing.

A second problem is that concerns are not properly separated.

Here is how I would have implemented this program:

struct line_data
{
  Time   t;
  double x;
};

// This handles reading a single Time value.
std::istream & operator >> (std::istream & is, Time & t)
{
  int hh, mm;
  if (is >> hh >> mm)
  {
    // Not happy with the following two lines, too Java-like. :-(
    t.setTimeHours(hh);
    t.setTimeMinutes(mm);
  }
  return is;
}

// This handles reading a single line of data.
std::istream & operator >> (std::istream & is, line_data & ld)
{
  std::string s;
  if (std::getline(is, s))
  {
    std::istringstream iss(s);
    // Ensure errors are propagated from iss to is.
    if (!(iss >> ld.t >> ld.x))
      is.setstate(std::ios::failbit);
  }
  return is;
};

// This handles processing a single line of data.
struct line_manip // satisfies concept OutputIterator<line_data>
{
  std::back_insert_iterator<std::vector<Time>>   ti;
  std::back_insert_iterator<std::vector<double>> xi;

  line_manip(std::vector<Time> & ts, std::vector<double> & xs)
    : ti(std::back_inserter(ts))
    , xi(std::back_inserter(xs))
  {
  }

  line_manip & operator = (const line_data & ld)
  {
    ti = ld.t;
    xi = ld.x;
    return *this;
  }

  line_manip & operator *  ()    { return *this; }
  line_manip & operator ++ ()    { return *this; }
  line_manip & operator ++ (int) { return *this; }
};

int main()
{
  std::ifstream ifs("input.txt");
  std::vector<Time>   ts;
  std::vector<double> xs;
  std::copy(std::istream_iterator<line_data>(ifs),
            std::istream_iterator<line_data>(),
            line_manip(ts, xs));
  // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM