iostream - reading string with embedded blanks - c++

I have a file with records that looks like this
123 Tag Now is the time for all good men to come to the aid
There always a number and some tag followed by a series of words. I want to extract the number as integer, tag as string, and sentence as string. I've done this using getline and scan plus some substring foolishness.
Is there any way to do this ala...
ispringstream iss ("123 Tag Now is the time for all good men to come to the");
integer i;
string tag, sentence;
iss >> i >> tag >> ws >> ???? >> sentence;
I.e. It would be nice if there were some way to turnoff white space as a terminator.

You should be able to do it in two steps:
istringstream iss ("123 Tag Now is the time for all good men to come to the");
int i;
std::string tag, sentence;
iss >> i >> tag >> ws;
std::getline(iss, sentence);

If there will be no line breaks,
iss >> i >> tag;
getline(iss, sentence);

Related

How can I cin a char with multiple words?

I tried looking on the internet but I've not seen an answer.
So I have to cin a char with multiple words, like "Cars have four wheels." And I need to take every word and cout him. I learned at school that you can do this:
char a[100][20];
cin.getline(a, 100);
But it doesn't work. What's the proper way to cin a char with multiple words separate by a space;
You can try using std::istringstream for parsing the words.
std::vector<std::string> word_database;
std::string text_line;
while (std::getline(std::cin, text_line))
{
std::string word;
std::istringstream text_stream(text_line);
while (text_stream >> word)
{
word_database.push_back(word);
}
}
In the above code, one line of text is input to the text_line variable.
An istringstream is created using the line of text. The "words" are extracted from the text stream using operator>>. The words are appended to the database.

Split string by commas using istringstream

I tried this code which can split the string by comma:
string spa ="12,233,434,2";
istringstream iss(spa + ",");
int val;
char dot =',';
while(iss >> val >> dot){
cout << val << endl;
}
But I have no idea how it works. It seems to extract the value firstly, then right-shifts?
iss >> val >> dot reads an int and a char, which happens to match the format of the input.
Their values prior to reading doesn't matter at all.
The while tests if the read was successful, and stops when the input fails.

Simple casting conversion on C++

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.
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'.
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;

Splitting string from inputstream with whitespace delimiter

I can't seem to split my string with the whitespace delimiter.
I tried using the getline(cin, myString).
I input the string as "10 20 30", when I print the string onto the output stream, I get "20 30", but not the 10.
I also tried the while(cin >> string). It works here, but the while loops never terminates.
Any help is appreciated.
You can use istringstream:
string str;
getline(cin, str);
istringstream ss(str);
for(string word; ss >> word; )
cout << word << endl;
Your while(cin >> str); doesn't stop unless:
Something fails in >> which is hard in your case.
EOF occurs (You can use Ctrl+Z, Ctrl+D, F6 It depends on your system)
A user defined condition: if(str.find('\n')) break;

getline delimiter using stringstream

It seems that it's not separating the word within the space.
Trying to separate the words in between, and stored it in first and second.
cin >> name; //input name
stringstream file (name);
getline(file,first, ' '); //seperate the name with the first name and last name using space
getline(file,second, ' ');
Replace
cin >> name;
with
getline(cin, name); //input name
cin >> reads only upto the first space. You would have realized this if you done a cout << name; to check what's getting read - this is the first step of debugging.
When you read the initial input with cin >> name; that only reads up to the first white space character.
You then try to break that into two pieces at white space, which it doesn't contain.
Easy way:
cin >> first >> second;
Alternatively, if you start with std::getline(cin, name); instead of cin >> name;, then the rest should work correctly.