Using a function call with the argument cin.get() or .getline() - c++

Is it possible to do a function call with an argument of a string using cin.get() or cin.getline()?
If not, how could i get user input from the console using a function call like this?
void setString(string str);
string stringText;
void setString(string str) {
stringText = str;
}
int main() {
setString(cin.getline());
return 0;
}

There is a free function called getline that takes an input stream and a string as parameter, the second being an out parameter. It returns the stream object that was passed in, not the string.
You could however write your own function that returns a string
std::string getConsoleLine()
{
std::string str;
std::getline( std::cin, str );
return str;
}
Note that, just like any other input stream, cin can be in a failed state from a period read. You could make your function clear any flags and ignore anything left in it first.
std::string getConsoleLine()
{
// as a precaution add this lines
std::cin.clear();
std::cin.ignore( std::numeric_limits<streamsize>::max() );
std::string str;
std::getline( std::cin, str );
return str;
}
Then you could pass it to your function.
setString( getConsoleLine() );

cin.getline() does not return std::string so you cannot pass it directly as a parameter to a function.
You need to store the input in a variable
std::string str;
cin >> str;
Then pass that variable to the function:
setString(str);

Probably you want something like this:
#include <string>
#include <iostream>
int main()
{
std::string stringText;
// puts the input you type into stringText
std::getline(std::cin, stringText);
// Now do what you like with stringText
std::cout << "You typed: " << stringText << '\n';
return 0;
}

Related

Is there a way to turn input string to input stream in c++?

What I want to do is get user input from the terminal and use this input in other functions in my program. Since my functions only take input streams as arguments I want to convert the input string into an input stream.
int main(int argc, char** argv)
{
std::vector<std::string> args(argv, argv + argc);
if(args.size() == 1){ //if no arguments are passed in the console
std::string from_console;
std::istringstream is;
std::vector<std::string> input;
while(!getline(std::cin,from_console).eof()){
input.emplace_back(from_console);
}
for(std::string str : input){
std::cout << "\n" << str;
}
}
Another questions that arose when I was trying this code, was that when I ended the console input with a bunch of characters and not with a new line(pressing enter then ctrl+d) the line was ignored and didn't get printed out.
Example:
When I typed the following:
aaa bbb
ccc ctrl+d
I got only the first line(aaa bbb) and not ccc printed out.
But:
aaa bbb
ccc
ctrl+d
prints out ccc as well, but it does ignore the new line. So why is this happening?
Is there a way to turn input string to input stream in c++?
Yes, it is possible. This is what std::istringstream is for. Example:
std::string input = some_input;
std::istringstream istream(input); // this is an input stream
The std::istringstream class has a constructor that takes a std::string as an argument, which uses a copy of the string passed as the initial content of the stream.
So, rather than use a std::vector to store all your input lines from the console, just keep adding those to a single (different) std::string object, remembering to add the newlines after each, then construct your std::istringstream from that.
Here is a trivial example that shows how you can use std::getline (which, like your functions, takes an input stream as its first argument) equally well on std::cin and a std::istringstream object created like that:
#include <iostream>
#include <sstream>
int main()
{
std::string buffer; // Create an empty buffer to start with
std::string input;
// Fill buffer with input ...
do {
getline(std::cin, input);
buffer += input;
buffer += '\n';
} while (!input.empty()); // ... until we enter a blank line
// Create stringstream from buffer ...
std::istringstream iss{ buffer };
// Feed input back:
do {
getline(iss, input);
std::cout << input << "\n";
} while (!input.empty());
return 0;
}
When the eof is in the same line as the last line of content, getline(std::cin,from_console) will reach it and .eof() will return true, thus the last line is read into string from_console but not push into the vector.
There are two ways:
Modify your code by pushing the last line into the vector manually:
while(!getline(std::cin,from_console).eof()){
input.emplace_back(from_console);
}
input.emplace_back(from_console); // add one line
for(std::string str : input){
iterator can be an elegant way:
#include <iterator>
// ...
if (args.size() == 1) { // if no arguments are passed in the console
copy(std::istream_iterator<std::string>(std::cin), {},
std::ostream_iterator<std::string>(std::cout, "\n"));
}

Why do I need clear() stringstream after reading from it in a function?

Why should I write ss.clear() in function Read() to be able to write to stringstream ss again?
#include <iostream>
#include <sstream>
using namespace std;
void Read(istream& ss, string& s)
{
while(getline(ss, s)){
cout << s << endl;
}
ss.clear();
}
int main()
{
stringstream ss;
string s;
ss << "A\nB\n";
Read(ss, s);
ss << "C\n";
Read(ss, s);
}
If ss.clear() is commented, the third line is not written to cout.
When you call
ss << "A\nB\n";
Read(ss, s);
The first call to getline extracts A, the second extracts B, and it is important to understand that you can only know that you are at the end of the stream after getline has been called once more. The third call to getline fails, there is no 3rd line in the stream, and the loop stops. From cppreference:
If no characters were extracted for whatever reason (not even the discarded delimiter), getline sets failbit and returns.
Once the failbit is set, the stream cant be used to extract more. Calling clear resets the error bits so you can continue using the stream.

Difference between std::cin and scanf() applied to string

I am trying to get the first character of a string written to a variable of type char. With std::cin (commented out) it works fine, but with scanf() I get runtime error. It crushes when I enter "LLUUUR". Why is it so? Using MinGW.
#include <cstdio>
#include <string>
#include <iostream>
int main() {
std::string s;
scanf("%s", &s);
//std::cin >> s;
char c = s[0];
}
scanf knows nothing about std::string. If you want to read into the underlying character array you must write scanf("%s", s.data());. But do make sure that the string's underlying buffer is large enough by using std::string::resize(number)!
Generally: don't use scanf with std::string.
Another alternative if you want to use scanf and std::string
int main()
{
char myText[64];
scanf("%s", myText);
std::string newString(myText);
std::cout << newString << '\n';
return 0;
}
Construct the string after reading.
Now for the way directly on the string:
int main()
{
std::string newString;
newString.resize(100); // Or whatever size
scanf("%s", newString.data());
std::cout << newString << '\n';
return 0;
}
Although this will of course only read until the next space. So if you want to read a whole line, you would be better off with:
std::string s;
std::getline(std::cin, s);

Scoping issue with a helper method to manipulate a string

I want to use a helper method to perform an operation on a string. I would like the method to have two parameters: input and output. I think there is a scoping problem with how I want to solve the problem because when I try to display the output, it is blank. I've minimized my code so you can see the approach I am taking.
#include <iostream>
#include <string>
using namespace std;
void example_method(string in, string out);
int main(){
string input;
string output;
cin >> input;
example_method(input, output);
cout << "The result is: " << output << endl;
return 0;
}
void example_method(string in, string out){
out = in;
}
This minimization compiles and runs, but no matter what string I enter, the result is always blank.
What would be a better way to approach this problem?
You're passing the output variable to the function, which means a copy of it is being pushed onto the stack, and then the stack variable is being altered and never returned back to the original variable. What you want to do is pass a reference to the variable, Like so:
#include <iostream>
#include <string>
using namespace std;
void example_method(string in, string &out);
int main() {
string input = "";
string output = "";
cin >> input;
example_method(input, output);
cout << "The result is: " << output << endl;
return 0;
}
void example_method(string in, string &out) {
out = in;
}
Solution One: The string output will always be blank, with your code in its present form. This is because output is only being copied to another string instance when it is passed as an argument to example_method. out is the other string instance which takes the value of output. In other words what this means is that string out=output and nothing else. The code line out = in; only copies the value of in to out.
So, actually the value of output is not being acted upon at all.
In order to effect the value of output you have to pass its value by reference or in other words, you have to pass the address of output to example_method and that address is to be taken by a pointer. This way what ever changes are made via the pointer also effect the value of the output string outside the scope of the example_method.
The following code segment illustrates my point:
#include <iostream>
#include <string>
using namespace std;
void example_method(string another_string, string *pointer_to_output);
int main()
{
string input="I am a test string";
string output="";
//cout<<"Enter input string"<<endl;
//cin>>input;
example_method(input,&output);
cout<<"The result is: "<<output<<endl;
return 0;
}
void example_method(string another_string, string *pointer_to_output)
{
*pointer_to_output=another_string;
}
Solution two:
Why not simply change the return type of the example_method from void to std::string? By this approach void example_method(string in, string out); changes to string example_method(string in, string out); in the declaration above the main.
And the returned output string is put out on the screen using cout<<example_method(input, output);
This way you can simply return your output to the screen using cout.
This way your code works, it achieves what you are trying to do and there is no real need of using pointers.
THE MODIFIED CODE:
#include <string>
using namespace std;
string example_method(string in, string out);
int main(){
string input;
string output;
cin >> input;
cout<<example_method(input, output);
// cout << "The result is: " << output << endl;
return 0;
}
string example_method(string in, string out){
out = in;
return out;
}
Hope this helps!
When you pass a argument to a function, the value is copied into the parameter.
In your case, the function will operate on the copied value, and leave the original value untouched (in this case: empty).
This can be changed by declaring the parameter as a 'reference parameter'. This is done by adding a & to the type, like this: string& out. Then no local copy will be made, so the original value will be updated.
Full example:
#include <iostream>
#include <string>
void example_method(std::string in, std::string& out); // note the additional &
int main(){
std::string input;
std::string output;
std::cin >> input;
example_method(input, output);
std::cout << "The result is: " << output << std::endl;
return 0;
}
void example_method(std::string in, std::string& out){ // Note the additional &
out = in;
}
A different approach is to specify a return value for the function.
Your function is returning nothing (void), so you could return the resulting string instead. In that case, the output parameter is no longer required, but you'll have to assign the returned value to the output variable at the calling site.
A complete example:
#include <iostream>
#include <string>
std::string example_method(std::string in); // note that 'output' is gone
int main(){
std::string input;
std::cin >> input;
std::string output = example_method(input);
std::cout << "The result is: " << output << std::endl;
return 0;
}
std::string example_method(std::string in){
return in; // use 'return' to return a value.
}

Is it possible to accept from the user (standard input) to the string stream directly?

Here is a sample program that uses stringstream. The goal is to accept lines from the user(standard input) and print each word in a separate line.
int main()
{
std::istringstream currentline;
std::string eachword;
std::string line;
// Accept line from the standard input till EOF is reached
while ( std::getline(std::cin,line) )
{
currentline.str(line); // Convert the input to stringstream
while ( currentline >> eachword ) // Convert from the entire line to individual word
{
std::cout << eachword << std::endl;
}
currentline.clear();
}
return 0;
}
I'm wondering, is there a way , I can avoid the intermediate string variable(object), line and directly store the user input to the currentline (istringstream object).
Note:
I know, the following solution already.
while ( std::cin >> eachword)
{
std::cout << eachword << std::endl;
}
std::getline needs a string reference argument, and that's where it places the line it has obtained, so of course you can't avoid passing such an argument (and still use that function). You could elegantly encapsulate the construct, if you need it often -- e.g.:
bool getline(std::istream& i, std::istringstream& current)
{
std::string line;
if ( std::getline(i, line) ) {
current.str(line);
return true;
}
return false;
}
If you want to simplify the first solution,
while ( currentline(line) >> eachword )
I assume you want to not use an intermediate object to prevent unnecessary copying?
You can achieve the same affect by explicitly setting the stream buffers buffer area.
int main()
{
std::string line;
std::istringstream currentline;
std::string eachword;
// Accept line from the standard input till EOF is reached
while ( std::getline(std::cin,line) )
{
// Set the buffer without copying.
currentline.clear();
currentline.rdbuf()->pubsetbuf(&line[0], line.length() );
while ( currentline >> eachword )
{
std::cout << eachword << std::endl;
}
}
return 0;
}
Because of the order of destruction. You just need to make sure the istringstream is destroyed before the object you are using as a buffer. So you need to re-arrange the declarations at the top of main() to make sure that line is created first and thus will be destroyed last (otherwise the destructor of the istringstream has the potential for accessing the memory of a free'ed object.