2

I can get getline() to work with cin (getline(cin,line)), but when I open a stream, it won't read the line from the file. The file contains a list of elements from the periodic table.

for Example:
H
He
O
etc...

EDIT:

However, when I try to cout the newly read line, it doesn't put it into var symbol at the line:
cout << "symbol: " << symbol << endl;

It doesn't give me anything out, but it should return the first element (H).

#include <fstream>
#include <iostream>
#include <vector>
#include <string>

using namespace std;

void print(vector <string> x)
{
    cout << "list of elements:" << endl;
    for (int i = 0; i < x.size(); ++i)
    {
        cout << x[i] << endl;
    }
}

int main(int argc, char** argv) 
{
    string symbol;
    vector <string> elementlist;
    ifstream readin;

    readin.open("Elements.txt");
    getline(readin,symbol);
    cout << "symbol: " << symbol << endl;
    while (!readin.good())
    {
        elementlist.push_back(symbol);
        getline(readin,symbol);
    }
    print (elementlist);
    return 0;
}
Daniel Heilper
  • 1,182
  • 2
  • 17
  • 34

2 Answers2

2

I'd do it something like this:

#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>

class line {
    std::string data;
public:
    friend std::istream &operator>>(std::istream &is, line &l) {
        std::getline(is, l.data);
        return is;
    }
    operator std::string() const { return data; }    
};

int main() {
    std::ifstream readin("Elements.txt");

    // Initialize vector from data in stream:
    //
    std::vector<std::string> 
        element_list((std::istream_iterator<line>(readin)),
                      std::istream_iterator<line>());

    // write data from vector to cout:
    //
    std::copy(element_list.begin(), element_list.end(),
             std::ostream_iterator<std::string>(std::cout, "\n"));

    return 0;
}                              
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Don't you wish `std::istream_iterator` could be used with a custom delimiter? :-( – obataku Aug 30 '12 at 04:56
  • @veer: Yes, sometimes. And with [some effort](http://stackoverflow.com/a/10060244/179910), it can. At least for this, the `line` class is easier though. – Jerry Coffin Aug 30 '12 at 04:57
1

As I stated in my comment, your loop condition is wrong.

while (!readin.good())
{
    elementlist.push_back(symbol);
    getline(readin,symbol);
}

As it turns out, you want to loop using the condition readin.good(). Since !readin.good() will evaluate to false, you never actually enter the loop.

Community
  • 1
  • 1
obataku
  • 29,212
  • 3
  • 44
  • 57
  • 1
    You generally do *not* want to use `while (x.good())` either. Some time ago, I posted a [blog entry](http://coderscentral.blogspot.com/2011/03/reading-files.html) about how to do this that might be helpful. – Jerry Coffin Aug 30 '12 at 04:24
  • @JerryCoffin right. In the example I originally used I demonstrated `while (std::getline(std::cin, line) && std::cin.good()) { ... }`. Is there anything wrong with that? PS `std::getline` will never short-circuit. – obataku Aug 30 '12 at 04:27
  • 3
    Yes, `while (std::getline(...))` is normally a good way to do things. – Jerry Coffin Aug 30 '12 at 04:32
  • @JerryCoffin ah, I see now. I overlooked `ios::operator void*` :-) – obataku Aug 30 '12 at 04:52