-3

I'm doing an exercise for the college and I have to compare a string added including the header <string>, and a character.

I have a text file with a few lines of data from a census, like

Alabama AL 4849377
Alaska AK 736732
Arizona AZ 6731484

I want to read the state name of each line with a string variable, but the comparison is the only thing that I am asking for, because is where I have the error.

I have this fragment of code:

    struct Census{
    string name;
    int population, code;
};

struct States{
    Census state;
};

typedef States Vector[US_STATES];

void loadCensus(ifstream & census, Vector stats){
    int i=0;
    string readData;
    string line;
    while (getline(census, line)) {
        stringstream linestream(line);
        while (linestream >> readData) {
            if (linestream >> stats[i].state.name >>
                stats[i].state.code >>
                stats[i].state.population)
            {
                std::cerr << "Bad input on line " << i << ": " << line << std::endl;
            }
            stats[i].state.name=readData;
            stats[i].state.code=readData;
            stats[i].state.population=readData;
            i++;
        }
    }
}

How I should convert readData to an integer to assign stats[i].state.population=readData? I get an error in line 17 in the linestream >> readData.

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
  • Please post a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – R Sahu Dec 07 '15 at 22:23
  • You probably want to *index* your string but the code you have provided really isn't sufficient to tell for sure. Please see [*How to create a Minimal, Complete, and Verifiable example*](https://stackoverflow.com/help/mcve). – 5gon12eder Dec 07 '15 at 22:23
  • Did you mean to use the string `"\n"`? – user253751 Dec 07 '15 at 22:24
  • I want to compare if a readString is reaching a break line. That's why i put "\n". – Amat Martinez Dec 07 '15 at 22:36
  • No. You put `'\n'` instead of `"\n"`. Also see [Why is iostream::eof inside a loop condition considered wrong?](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). – Captain Obvlious Dec 07 '15 at 22:48

2 Answers2

1

You want to use the getline() function instead. I think ita a member function of ifstream or either compare the not readData to a string ("\n") - double quotation. Or put the read data into a string and check if the sting contains a '\n'.

0

census >> readData will read the next word (any group of non-whitespace characters) from the input. In order to do this, it will discard all whitespace on its hunt for the next word. '\n' is whitespace, so you will never read it with the >> operator without playing games you probably don't want to play.

Instead of >>, use std::getline to read a line and then use a std::stringstream to break the line up into words.

std::string line;
while (std::getline(census, line)) {
    std::stringgstream linestream(line);
    while (linestream >> readData) {
        statistics.state[i]=readData;
        i++;
    }
}

But...

I do not believe statistics.state[i]=readData; does quite what you want to do. You probably want something more like:

std::string line;
while (std::getline(census, line)) {
    std::stringstream linestream(line);
    if (!(linestream >> statistics.state[i].name >>
                      statistics.state[i].abbreviation >> 
                      statistics.state[i].population))
    {
        std::cerr << "Bad input on line " << i << ": " << line << std::endl;
    }
    i++;
}

In this state becomes an array or vector of objects that probably looks something like

struct statestats
{
    std::string name;
    std::string abbreviation;
    int population;
};

Breaking it down line by line

std::stringstream linestream(line);

Makes a stringstream. A string stream is a stream like cin and cout or a fstream, but it contains a string. The main use is to buffer and build strings with the same syntax you would use on another stream. In this case we are use it to split up the line into words.

if (linestream >> statistics.state[i].name >>
                  statistics.state[i].abbreviation >> 
                  statistics.state[i].population)

Needs to be handled in a few parts in a few parts. Over all it is an abbreviation of

if (linestream >> statistics.state[i].name && 
    linestream >> statistics.state[i].abbreviation &&
    linestream >> statistics.state[i].population)

Each stage of which reads from the linestream into a variable.

Next, the >> operator returns the stream being read, and this is used two ways in the example. The first allows chaining. The output of one >> is used as the input of the next, so if you look at >> as you would a function (and it is a function. See Stream extraction and insertion for more) you can think about it looking something like this:

linestream.read(statistics.state[i].name).read(statistics.state[i].abbreviation).read(statistics.state[i].population)

The >> syntax just makes it easier.

The next advantage you get from returning the stream is the stream can be tested to see if the stream is still good. It has a boolean operator that will return true if the stream is in a good state and can be used.

if(linestream)
{
    good
}
else
{
    bad
}

will enter good if the stream is open, has not reached the end of the stream, and has had no troubles reading or writing data.

Going back to our example

if (linestream >> statistics.state[i].name >>
                  statistics.state[i].abbreviation >> 
                  statistics.state[i].population)

Will enter the body of the if statement if the stream successfully read all three values from the stream. Which is not what we want. Ooops. I've corrected the above code already.

if (!(linestream >> statistics.state[i].name >>
                    statistics.state[i].abbreviation >> 
                    statistics.state[i].population))

will enter the body of the if if at least one value was not read for any reason and print out an error message. Normally when there is an error you will need to clear the error before continuing, but in this case we've use the whole stream and are about to discard it.

Assuming no error occurred all of the data from this line has been read and there is no need to

stats[i].state.name=readData;
stats[i].state.code=readData;
stats[i].state.population=readData;
user4581301
  • 33,082
  • 7
  • 33
  • 54
  • Thank you for the recommendation. Look at the code I've updated please. – Amat Martinez Dec 07 '15 at 23:58
  • And another question only for curiosity, I've seen lot of people typing std:: instead of "using namespace std". Why? – Amat Martinez Dec 08 '15 at 00:00
  • [Good reading on the `using namespace std;` issue.](http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) the TL;DR version is the std namespace is huge and `using namespace std` pulls all of it into the global namespace. Say you make a function `distance`. Which `distance` is going to be used? Your `distance` or `std::distance`? With `using namespace std;` they now both have the same name. `pow` and `std::pow` are subtly different. Which one got called? – user4581301 Dec 08 '15 at 00:47
  • @AmatMartinez Two things: Radically changing the question after it has been answered should only be done with care because it makes the existing answers look odd. The code I am responding to with my answer no longer matches the question. Plus it moves the goal posts on successfully answering the question. – user4581301 Dec 08 '15 at 00:55
  • Second `stream >> a >> b >> c` reads from the stream into `a`, `b`, and `c`, setting the values to whatever was read and returns the stream. If it could not be read, it puts the stream into an error condition and. `if (stream)` makes sure the stream is readable. If it isn't, at least one previous reads failed. Read up on streaming IO. – user4581301 Dec 08 '15 at 00:58
  • The compiler shows me an error with the function linestream(line). What does it do exactly? – Amat Martinez Dec 08 '15 at 00:58
  • Editing the question. Up in a few minutes. – user4581301 Dec 08 '15 at 01:04
  • @AmatMartinez Got haulled away for a while. Just posted. What error did you get for `linestream(line)?` – user4581301 Dec 08 '15 at 01:41
  • Thank you for your help! I changed my algorithm and I found a better way to read the data. I will vote your answer because of your kind help. – Amat Martinez Dec 08 '15 at 18:07