Extracting arguments using stringstream - c++

I want to input a phrase and extract each character of the phrase:
int main()
{
int i = 0;
string line, command;
getline(cin, line); //gets the phrase ex: hi my name is andy
stringstream lineStream(line);
lineStream>>command;
while (command[i]!=" ") //while the character isn't a whitespace
{
cout << command[i]; //print out each character
i++;
}
}
however i get the error: cant compare between pointer and integer at the while statement

As your title "Extracting arguments using stringstream" suggests:
I think you're looking for this :
getline(cin, line);
stringstream lineStream(line);
std::vector<std::string> commands; //Can use a vector to store the words
while (lineStream>>command)
{
std::cout <<command<<std::endl;
//commands.push_back(command); // Push the words in vector for later use
}

command is a string, so command[i] is a character. You can't compare characters to string literals, but you can compare them to character literals, like
command[i]!=' '
However, you're not going to get a space in your string, as the input operator >> reads space delimited "words". So you have undefined behavior as the loop will continue out of bounds of the string.
You might want two loops, one outer reading from the string stream, and one inner to get the characters from the current word. Either that, or loop over the string in line instead (which I don't recommend as there are more whitespace characters than just space). Or of course, since the "input" from the string stream already is whitespace separated, just print the string, no need to loop over the characters.
To extract all words from the string stream and into an vector of strings, you can use the following:
std::istringstream is(line);
std::vector<std::string> command_and_args;
std::copy(std::istream_iterator<std::string>(is),
std::istream_iterator<std::string>(),
std::back_inserter(command_and_args));
After the above code, the vector command_and_args contains all whitespace delimited words from the string stream, with command_and_args[0] being the command.
References: std::istream_iterator, std::back_inserter, std::copy.

Related

How can I split a getline() into array in c++

I have an input getline:
man,meal,moon;fat,food,feel;cat,coat,cook;love,leg,lunch
And I want to split this into an array when it sees a ;, it can store all values before the ; in an array.
For example:
array[0]=man,meal,moon
array[1]=fat,food,feel
And so on...
How can I do it? I tried many times but I failed!😒
Can anyone help?
Thanks in advance.
You can use std::stringstream and std::getline.
I also suggest that you use std::vector as it's resizeable.
In the example below, we get input line and store it into a std::string, then we create a std::stringstream to hold that data. And you can use std::getline with ; as delimiter to store the string data between the semicolon into the variable word as seen below, each "word" which is pushed back into a vector:
int main()
{
string line;
string word;
getline(cin, line);
stringstream ss(line);
vector<string> vec;
while (getline(ss, word, ';')) {
vec.emplace_back(word);
}
for (auto i : vec) // Use regular for loop if you can't use c++11/14
cout << i << '\n';
Alternatively, if you can't use std::vector:
string arr[256];
int count = 0;
while (getline(ss, word, ';') && count < 256) {
arr[count++] = word;
}
Live demo
Outputs:
man,meal,moon
fat,food,feel
cat,coat,cook
love,leg,lunch
I don't want to give you some code because you must be new at C++ and you have to learn by yourself but I can give an hint: use substring to store it into a vector of string.

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;

Reading strings until end of line? [duplicate]

This question already has answers here:
taking input of a string word by word
(3 answers)
Closed 8 years ago.
Is there some way to read consecutive words separated by spaces as strings until end of line is found in C++? To be precise, I'm working on an algorithmic problem and the input goes like:
some_word1 some_word2 some_word3 (...) some_wordn
other_data
And the trick is I don't know how many words will there be in the first line, just that I should read them as separate words for further processing. I know I could use getline(), but after that I'd have to work char-by-char to write each word in a new string when space occurs. Not that it's a lot of work, I'm just curious if there's a better way of doing this.
Why would you have to work character by character after using getline?
The usual way of parsing line oriented input is to read line by line,
using getline, and then use an std::istringstream to parse the line
(assuming that is the most appropriate parsing tool, as it is in your
case). So to read the file:
std::string line;
while ( std::getline( input, line ) ) {
std::istringstream parse( line );
// ...
}
You could use sstream and combine it with getline(), which is something you already know.
#include <iostream>
#include <sstream>
int main()
{
std::string fl;
std::getline(std::cin, fl); // get first line
std::istringstream iss(fl);
std::string word;
while(iss >> word) {
std::cout << "|" << word << "|\n";
}
// now parse the other lines
while (std::getline(std::cin, fl)) {
std::cout << fl << "\n";
}
}
Output:
a b
|a|
|b|
a
a
g
g
t
t
You can see that the spaces are not saved.
Here you can see relevant answers:
Split a string in C++
Taking input of a string word by word
I would suggest to read the complete line as a string and split the string into a vector of strings.
Splitting a string can be found from this question Split a string in C++?
string linestr;
cin>>linestr;
string buf; // Have a buffer string
stringstream ss(linestr); // Insert the string into a stream
vector<string> tokens; // Create vector to hold our words
while (ss >> buf)
tokens.push_back(buf);

How to find a string of 2 words in a file?

With the following code, I can find a string of 1 word (in this example I'm looking for "Word"):
ifstream file("file.txt");
string str;
while (file >> str){
if (str.find("Word") != string::npos){
////
}
}
But it doesn't work if I want to find, for example, "Computer screen", which is composed of two words.
Thanks
file >> str reads a parameter (in this case, a string) delimited with whitespace. If you want to read the whole line (or in any case, more than one word at once), you can use getline operator (reads the string which is delimited by newline by default).
ifstream file("file.txt");
string str;
while (std::getline (file,str)){
if (str.find("Computer screen") != string::npos){
////
}
}
If you know there are two words and what they are, all you need is this:
ifstream file("file.txt");
string str;
while (file >> str){
if (str.find("Computer") != string::npos){
file >> str;
if (str.find("screen") != string::npos) {
////
}
}
}
But more likely, you are asking to find a single string that might be two words, or three or more.
Then, can you count on the string being on a single line? In which case, #Ashalynd's solution will work. But if the string might be broken it will fail. You then need to handle that case.
If your file is "small" - i.e. can easily fit in memory, read in the whole thing, remove line breaks and search for the string.
If it is too large, read in lines as pairs.
Something like this:
std::ifstream file("file.txt");
std::string str[2];
int i = 0;
std::getline (file,str[i]);
++i;
while (std::getline (file,str[i]))
{
int next_i = (i+1)%2;
std::string pair = str[next_i] + " " + str[i];
if (pair.find("Computer screen") != std::string::npos)
{
////
}
i = next_i;
}
All this assumes that the possible white space between the words in the string is a single space or a newline. If there is a line break with more white-space of some kind (e.g. tabs, you need either to replace white-space in the search string with a regex for white-space, or implement a more complex state machine.
Also, consider whether you need to manage case, probably by converting all strings to lower case before the match.

Reading from an iostream

Maybe I'm missing something, but I'm having a lot of trouble finding any information on how to how to read from an iostream (std::iostream& stream). Is there a way I can convert it to a string or similar?
For clarification this is (what I'm basically trying to do, for example):
std::stringstream ss("Maybe I'm missing something \n but I'm having a lot of trouble finding any information on how to how to read from an iostream.");
readStream(ss);
void readStream(std::iostream& stream)
{
std::string out;
stream >> out;
// Do some stuff with the string
}
This seems to work, but out will be equal to "Maybe" rather than the full string.
You read from an iostream the same way you would if you were using cin.
stream >> varName;
Crazy syntax yes, but that's what the makers of streams decided to do.
You can also use get and getline if your reading to strings. Get will get the next character or a specified buffer of characters, and getline will go to the next newline.
getline(stringName);
You can read more on this here: http://cplusplus.com/reference/iostream/iostream/
Streams converts automatically for the type they are shifting to.
using namespace std;
int number;
double fraction;
string world;
stream >> number >> fraction >> world;
When shifting to a string, it reads until the first word delimiter, you may wish to use std::getline.
using namespace std;
string line;
getline(stream,line);
Maybe you want to read whole lines. In this case you have to use std::getline, thus having:
void readStream(std::iostream& stream)
{
std::string out;
// while getting lines
while(std::getline(stream, out))
{
// Do some stuff with each line
}
}
You can also choose a line delimiter character, by passing it to std::getline as a third parameter.
The stream operator >> is used to read formatted white space separated text.
int val1;
stream >> val1; // reads a space separated int
float val2;
stream >> val2; // reads a space separated float
std::string val3;
stream >> val3; // reads a space separated word.
Unfortunately std::string (and C-Strings) are not symmetric (input/output do not work in the same way (unlike the other fundamental types)). When you write them they write the full string (up to the null terminator, '\0', of the C-string).
If you want to read a whole line of text use std::getline()
std::string line;
std::getline(stream, line);
But like most languages, you can loop reading the stream until it is finished.
std::string word;
while(stream >> word)
{
// Reads one word at a time until the EOF.
std::cout << "Got a word (" << word << ")\n";
}
Or the same thing one line at a time:
std::string line;
while(std::getline(stream, line))
{
// Reads one word at a time until the EOF.
std::cout << "Got a word (" << word << ")\n";
}
Note 1: I mentioned white space separated above. White space includes space/tab and most importantly new line so using the operator >> above it will read one word at a time until the end of file, but ignore new line.
Note 2: The operator >> is supposed to be used on formatted text. Thus its first action is to drop prefix white space characters. On the first non white space text, parse the input as appropriate for the input type and stop on the first character that does not match that type (this includes white space).