3

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?

Ch3steR
  • 20,090
  • 4
  • 28
  • 58
r3k0j
  • 91
  • 6
  • Were you planning on using that `is` string stream for anything useful ? – WhozCraig May 07 '22 at 17:54
  • @WhozCraig yes, to pass it to my other functions as argument. – r3k0j May 07 '22 at 17:57
  • Side note - `!getline(std::cin,from_console).eof()` should be `getline(std::cin,from_console)`. Besides that, the entire usage of turning a string to input stream seems to be completely unrelated to the actual question you are asking, which is about the behavior of `Ctrl+D`. It's either that or you've asked two, separate questions as one. – Fureeish May 07 '22 at 17:58
  • @Fureeish yes, I did ask two separate question. Should I ask the other question in another thread? Edit: Btw removing ! from the while loop ends after i enter enter and ends the program. I want it to end after i type Ctrl+D – r3k0j May 07 '22 at 18:00

3 Answers3

5

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
eerorika
  • 232,697
  • 12
  • 197
  • 326
1

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:

  1. 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){
  1. 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"));
}
1

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;
}
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • Thanks, that was what I was looking for. The only problem is that I want the input to end when i specifically type Ctrl+D. How to do that? – r3k0j May 07 '22 at 18:27
  • 1
    @r3k0j Well, assuming your platform's console does, indeed, use Ctrl+D for EOF, then maybe this will offer some advice for changing the loops' conditions: [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/q/5605125/10871073) – Adrian Mole May 07 '22 at 18:37
  • 1
    ... I only really wanted to concentrate on the first (main) part of your question. – Adrian Mole May 07 '22 at 18:38