1

So I wrote this very simple program:

#include <iostream>
#include <string>
using namespace std;

int main()
{
string input;

cin >> input;
cout<< input<<endl;
cin >> input;
cout<< input<<endl;
cin >> input;
cout<< input<<endl;
return 0;
}

I type in 'word1 word2 word3' on one line and the output as expected is

word1
word2
word3

now of course, I could've gotten the same output as for (int i=0; i <3; i++){cin>>input; cout << input<<endl;}.

Which brings me to my question. As soon as cin runs out of things to read from stdin, it will query the user (stdin).

I a way to detect whether cin will read something from the stdin buffer or query the user.

I know its a simple question, but its for homework... and I'm in a massive work-induced time cruch, so kudos to whoever shares the power!

user1833028
  • 865
  • 1
  • 9
  • 18
  • 2
    If I understand your question right, you want `while (std::cin >> input) std::cout << input << '\n';`... – Tony Delroy Feb 19 '13 at 04:16
  • How is what you want different from what you are getting? – Vaughn Cato Feb 19 '13 at 04:20
  • I evidently didn't word this very well.... I need to read all of the arguments between the whitespaces from the initial input, then stop reading after all the arguments are read - when *I don't know the number of arguments I will get.* Thanks though! – user1833028 Feb 19 '13 at 04:24
  • Well how would you know when to stop if the user may enter an arbitrary amount of arguments? Unless, of course, you are talking about taking input via a pipe or redirection into stdin (rather than keyboard), in which case @TonyD 's solution works great since you'll get an EOF from your input when it's done. – us2012 Feb 19 '13 at 04:34
  • Otherwise, you can define a special keyword and do `while ((std::cin >> input) && (input != "stop"))` . – us2012 Feb 19 '13 at 04:36
  • Well, simply put, if their is another argument in the buffer, cin will read that argument. If not, it will go back to get more input - in this case, asking the user. I just need to keep doing 'cin >> input'; *until* it *would* go query the user. Then I stop doing 'cin >> input'. – user1833028 Feb 19 '13 at 04:39
  • I'm still not sure what you mean, but it sounds like you want to `cin.getline(mystring);`, then construct a `stringstream` from `mystring` and read your arguments from there with a `while` construction like the one Tony provided - this will stop as the `stringstream` runs out of buffer and there's no additional querying of the user as you now operate on the `stringstream` instead of `cin`. – us2012 Feb 19 '13 at 04:43
  • That will at least work.. thanks... even if it would still be nice to do it with the buffered input method, if possible... hmm... would one or the other be any more efficient? – user1833028 Feb 19 '13 at 04:51
  • `while( !cin.eof() ) { cin >> input; cout << "/"< – user1833028 Feb 19 '13 at 04:54
  • @user `while (!cin.eof())` is BAD. `while (cin >> input)` does the **same** thing, but it does it right. The `eof` can't be magically thrown, you need the user to input it or some other control sequence (stopword, or as in my getline solution, Enter.) – us2012 Feb 19 '13 at 04:55
  • That was the problem I had with it.... – user1833028 Feb 19 '13 at 04:58
  • I mean, user2012 has posted a working methodology... been a while since I've used that one/taken a programming class, lol ... still be nice to satisfy my curiosity... is there really no way to do this (is the question now clear?)? – user1833028 Feb 19 '13 at 05:00
  • No, it's not clear! How do you expect the program to know when the user is done with his inputs? Read his brainwaves? – us2012 Feb 19 '13 at 05:21
  • Oh sorry. No, just when he presses enter. Ie... take input... he presses enter... it cycles through *all* the argument.. then stops short of asking for more arguments. And thanks.... – user1833028 Feb 19 '13 at 05:24
  • I mean, I *could* just use getline(..) and seperate the whitespaces... but for some reason I think it'd be awesome to do it the cin way.... – user1833028 Feb 19 '13 at 05:26
  • http://stackoverflow.com/questions/236129/splitting-a-string-in-c this is really close .. the first answer. – user1833028 Feb 19 '13 at 05:28
  • Can I be so bold as to ask why you're looking for a solution that you think would be extra-awesome when this is for a school project with a critical deadline ;) ? And: No, I don't think you can reasonably do that with `cin >> ...` as the delimiters for that are fairly hardcoded. The question in your link does it my way (stringstream), the first answer uses `istream_iterator`s, which is fancy but still needs everything in a stringstream first. You can't read that from `cin` with `operator >>` as, (hint hint) the delimiter is pretty much hardcoded for that. – us2012 Feb 19 '13 at 05:31
  • @us2012, if you convert what you've said into an answer I'll hit accept on it. Yes, you may be so bold, but the probes of curiosity can only be enlightening! If you survive. (Thanks for your time.) – user1833028 Feb 19 '13 at 05:38

1 Answers1

2

What you're trying to do can't be done with operator>> only because it doesn't distinguish between different kinds of whitespace. Look at the implementation in your favorite C++ standard library, the following is from gcc 4.7.2's (bits/basic_string.tcc):

 995   // 21.3.7.9 basic_string::getline and operators
 996   template<typename _CharT, typename _Traits, typename _Alloc>
 997     basic_istream<_CharT, _Traits>&
 998     operator>>(basic_istream<_CharT, _Traits>& __in,
 999            basic_string<_CharT, _Traits, _Alloc>& __str)
1000     {
...
1027           while (__extracted < __n
1028              && !_Traits::eq_int_type(__c, __eof)
1029              && !__ct.is(__ctype_base::space,
1030                  _Traits::to_char_type(__c)))
1031         {

As you can see, (line 1029) this stops on all whitespace encountered ( see http://en.cppreference.com/w/cpp/locale/ctype_base for ctype_base::space).

What you want to do is therefore to use getline (which stops when it encounters a newline) and extract via a stringstream:

getline(cin,mystring);
stringstream str(mystring);
while (str >> token) {
  cout << token << '\n';
}
us2012
  • 16,083
  • 3
  • 46
  • 62
  • This is an effective solution as elegant as I was hoping for. Thank you. The curious may wish the examine this: http://stackoverflow.com/questions/236129/splitting-a-string-in-c – user1833028 Feb 19 '13 at 05:57