Reading from a file in C++, one line at a time.

Greetings coders. I humbly request your assistance.

Let’s say I have a text file in the following format:


12
buckaroo
56.3

245
trapeze
17.6

987
california
1.2

I want to load this info in 3 structs (which will become a linked list). I’d like to read the file, one line at a time and store the content in the appropriate struct variable, detect the empty line as a separator, then load the next 3 lines in the next struct, and so on. Something like:



ifstream fileread;
fileread.open("file.txt");
fileread>>Structor->integil;
fileread>>Structor->Stringum;
fileread>>Structor->doubloon;
fileread.close();


Obviously, the code above is wrong and incomplete. I’m just using it to give you some variable names you can use in your examples, To keep things homogeneous and more readable. I’ve perused my textbook, read the online tutorials, but I still don’t know how to do this.

Thank you for your time

/Gozu

Look here.

The C++ way:



std::vector<std::string> > read_lines(const std::string& fname)
{
  std::ifstream str(fname.c_str());
  std::string buffer;
  std::vector<std::string> ret;
  if(!str)
    throw exception("file not found"); // or whatever
  while(!str.eof())
  {
    getline(str, buffer);
    ret.push_back(buffer);
  }
  return ret;
}


This is off the top of my head, but should compile with little modification.

Advantages of using C++'s I/O libraries over C’s I/O libraries.


#include <iostream>
#include <fstream>
using namespace std;

struct info
{
  int integil;
  char stringum[100];
  double doubloon;
};

int main(int argc, char* argv[])
{
  int i=0, SIZE=3;
  char discard;
  info arry[SIZE];

  ifstream fileread("file.txt");

  while(!fileread.eof() && i < SIZE)
    {
      fileread >> arry*.integil;
      fileread >> arry*.stringum;
      fileread >> arry*.doubloon;
      fileread >> discard;
      i++;
    }
}

You’ll of course want to add error checking (see Dominic’s solution) but I think this is close to what you were going for.

Wow. It’s beautiful! So simple, so elegant. It’s poetry made code! Thank you! Using the && to keep cycling and an array of structs. That would’ve never occurred to me. I thought it would be simpler.

Dominic’s code is c++er but it’s scary (why not type using namespace std; and avoid all the std:: that follow?) and I think it stores all the lines in strings whereas I meant to store some of them in ints and doubles as well. But, now that I think about it, can I typecast the resulting strings as ints and doubles without ill effects? What code would do the trick?

Thank you both for your work and thank everybody else for the helpful links they provided!

Well, you can do that. If this code is in a header file for some reason (i.e. it’s made inline or is part of a template definition) then you wouldn’t want to do that, as it brings everything in std into the scope of any source file that includes the header, missing the point of namespaces, slightly.

No, you’ll need a special conversion function. Here’s one:



  template<typename from, typename to>
    to convert(const from& val)
    {
      std::strstream str;
      to temp;
      str << val;
      str >> temp;
      return temp;
    }


Use it like this: convert<std::string, int>(“5”); (evaluates to 5), convert<float, std::string>(0.5f); (evaluates to “0.5”) etc.