Splitting string by spaces difficulty - c++

My code is working except for one problem, when I run it it doesn't seem to return the first string.
string text;
cin >> text;
getline(cin ,text);
istringstream iss(text);
copy(istream_iterator<string>(iss),
istream_iterator<string>(),
ostream_iterator<string>(cout, "\n"));
So if my input was, bf "ing" filename, it will only output:
"ing"
filename
I want it so it can output the whole line like so:
bf
"ing"
filename

Assuming you want to have the entire line printed from parsing the string passed to std::istringstream you should remove first reading a separate word, i.e., remove the line
cin >> text;

Get rid of
cin >> text; .
That one consumes the first word of your input, reads it into text, and then you discard it by overwriting text in the next line.

Related

C++: Why won't getline() print the last word of the input string?

i'm trying to get my program to read a string and then output each word on an individual line. When I call this function it is not printing the last word of the sentence. I have not been able to find an answer to this problem.
For example:
Input:
Hello there my friend
Output:
Hello
there
my
Here is my code:
istream& operator >> (istream& in, FlexString& input) {
std::string content;
while (std::getline (in,content,' ')) {
cout << content << endl;
}
return in;
}
I'm new to C++ so this may be dumb, but I tried adding another cout call to print content on the next line after the while loop but it won't print it for some reason.
getline didn't skip the last word. It's still waiting for you to finish it. You selected the space character (' ') as the delimiter, so getline is going to read until if finds a space (not a tab or a newline), or until the input stream ends. Your loop isn't going to stop at the end of the line either, like you seem to be expecting. It is going to keep reading until the stream ends.
If you want to read a single line, and then separate the line word by word, then just call getline once, with the \n delimiter (which is the default). Then use an istringstream to separate the resulting string word by word.
std::string line;
std::getline(in, line);
std::istringstreaam iss(line);
std::string content;
while (iss >> content)
std::cout << content << std::endl;

StringStream input with comma delimited string - know columns apriori

I have a csv that I'd like to tokenize line by line with StringStream. The key is that I know apriori what the columns would look like. For example, say I know the file looks like the following
StrHeader,IntHeader
abc,123
xyz,456
I know ahead of time it is a string column, followed by an int column.
Common approach is to read the file line by line
std::string line;
stringstream lineStream;
while (getline(infile, line)) // read line by line
{
cout << "line " << line << endl;
lineStream << line;
string token;
while(getline(lineStream, token, ',')) // push into vector? this is not ideal
{
}
I know I can have 2 loops, and have inner loop tokenizes the string based on commas. Lots of sample code on stackoverflow would store the result into a vector<string>.
I don't want to do create a new vector every line. Since I know apriori what columns the file would have, can I somehow read directly into a string and int variable? Like this
std::string line;
stringstream lineStream;
while (getline(infile, line)) // read line by line
{
cout << "line " << line << endl;
lineStream << line; // DOESNT WORK - tell lineStream we have comma delimited string
string strValue;
int intValue;
lineStream >> strValue >> intValue; // SO MUCH CLEANER
// call foo(strValue, intValue);
}
The problem above is this line
lineStream << line; // DOESNT WORK - tell lineStream we have comma delimited string
From what I could tell, the above code works if the input line is space delimited, not comma delimited.
I have no control over the input. So, simply replacing the "spaces" with "commas" in the original string is not an ideal solution since I don't know if the input already has spaces.
Any ideas? thanks
You could try to only read to the delimiter with std::getline() and then put that in a string stream for conversion.
while (!infile.eof()){
std::getline(infile, strValue, ',');
std::getline(infile, line);
strstr.str(line);
strstr.clear();
int intValue;
strstr >> intValue;
foo(strValue, intValue);
}

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;

Issue with getline() delimiter

I am trying to read through a file and get specific strings on each line. The end of the string that i need is marked by a semicolon. I have no problems doing this, but I am noticing that getline() with the delimiter is automatically attaching a new line to my string.
filename.open(FileName);
while(filename)
{
getline(filename, name[counter], ';');
filename >> amount[counter] >> unit[counter] >> calories[counter];
counter++;
}
So when i would go to print out the name array there would be 1 extra line break that I had not put there myself as if there was an extra '\n' being picked up along the way. Does anyone have a solution? An example of the file format that I am reading from is below.
Dave Jones; 24 Tall
Jillian Jones; 34 Short
etc...
After running
filename >> amount[counter] >> unit[counter] >> calories[counter];
the newline is still in the buffer. This normally isn't a problem when you are using only ">>"; it just ignores newlines. But when you mix getline and ">>" you need to ignore the newlines that ">>" leaves behind. Try something like this:
filename >> amount[counter] >> unit[counter] >> calories[counter];
// Ignore first character or everything up to the next newline,
// whichever comes first
filename.ignore(1, '\n');
This is a bit redundant, but it's easy to read.
Better way would be to read file line by line into a buffer and then split strings by ';':
while(true) {
std::string line;
std::getline( in, line );
if( !in ) break;
std::istringstream iline( line );
while(true) {
std::string str;
std::getline( iline, str, ';' );
if( !iline ) break;
// you get string by string in str here
}
}
A simpler way to swallow the whitespace:
filename >> amount[counter] >> unit[counter] >> calories[counter] >> std::ws;

c++ string manipulation reversal

I am currently doing c++ and am going through how to take in an sentence through a string and reverse the words (This is a word......word a is This etc)
I have looked at this method:
static string reverseWords(string const& instr)
{
istringstream iss(instr);
string outstr;
string word;
iss >> outstr;
while (iss >> word)
{
outstr = word + ' ' + outstr;
}
return outstr;
}
int main()
{
string s;
cout << "Enter sentence: ";
getline(cin, s);
string sret = reverseWords(s);
cout << reverseWords(s) << endl;
return 0;
}
I have gone through the function and kind of understand but I am a bit confused as to EXACTLY what is going on at
iss >> outstr;
while (iss >> word)
{
outstr = word + ' ' + outstr;
}
return outstr;
Can anybody explain to me the exact process that is happening that enables the words to get reversed?
Thank you very much
iss is an istringstream, and istringstreams are istreams.
As an istream, iss has the operator>>, which reads into strings from its string buffer in a whitespace delimeted manner. That is to say, it reads one whitespace separated token at a time.
So, given the string "This is a word", the first thing it would read is "This". The next thing it would read would be "is", then "a", then "word". Then it would fail. If it fails, that puts iss into a state such that, if you test it as a bool, it evaluates as false.
So the while loop will read one word at a time. If the read succeeds, then the body of the loop appends the word to the beginning of outstr. If it fails, the loop ends.
iss is a stream, and the >> is the extraction operator. If you look upon the stream as a continuous line of data, the extraction operator removes some data from this stream.
The while loop keep extracting words from the stream until it is empty (or as long as the stream is good one might say). The inside of the loop is used to add the newly extracted word to the end of the outstr
Look up information about c++ streams to learn more.
The instruction:
istringstream iss(instr);
allows instr to be parsed when the operator>> is used, separating words thourgh a whitespace character. Each time the operator >> is used it makes iss point to the next word of the phrase stored by instr.
iss >> outstr; // gets the very first word of the phrase
while (iss >> word) // loop to get the rest of the words, one by one
{
outstr = word + ' ' + outstr; // and store the most recent word before the previous one, therefore reversing the string!
}
return outstr;
So the first word retrieved in the phrase is actually stored in the last position of the output string. And then all the subsequent words read from the original string will be put before the previous word read.