Just going through some quick exercises in Dr. Stroustrup's book "Principles & Practices..." and I am using code that HE gives for getting user input to fill a vector of integers. I print a simple message and then ask the user for numbers...
He has the following for simply filling vector<int> my_nums below. BUT, when I run this code the compiler has no problems and I fall straight throught this input loop without being able to input ANY integers. Did I miss something about user input using std::cin???
#include <iostream>
#include <vector>
#include <exception>
#include <string>
#include <stdio.h>
usingnamespace std;
/* The program asks for a list of integers from the user and prints them using a function print_nums() after loading into a vector*/
void print_nums(const vector<int>&, const string&); //declare print_nums()
int main()
{
string label; //user's phrase for labeling input numbers
vector<int> my_nums; //user vector of integers
std::cout<<"Please give a units/label for your numbers: ";
std::cin>>label;
std::cout<<"\n\nPlease input your integers followed by RETURN to end: ";
for(int holding; std::cin>>holding;){
my_nums.push_back(holding);
}
//didn't call print_nums() yet because I'm falling through the input above!!
cout<<"Got past the for loop\n"; //simple print statement for checking..
return 0;
} //end main routine
void print_nums(const vector<int>& nums, const string& label){
cout<<label<<"\n\n";
for(unsignedint i=0; i<nums.size(); ++i){
cout<<nums[i]<<"\n";
}
} //end of print_nums function
Does this help to critique a little better? Again, I think I'm just supposed to be reading the input buffer but I am not sure I've redirected stdin in any way or have screwed something else up. But that's why I'm asking you guys! BTW, should I migrate AWAY from codeblocks and just get MS VisStudio or MS VisStudio CODE??
Let me know what you guys think!
And as usual..... thanks for the guidance and instruction for us morons! LOL
It's also worth asking... are you running this through some web application, through a local IDE (e.g. Visual Studio), or through the command-line directly?
I get this "for loop" to read-in integers from pages 122/123 in chapter 4.
NOW, he (the good Dr.) does use his OWN special header named: "std_lib_facilities.h".... so I am not sure if the header has something in in it that makes this all easier? (I am NOT using the header as you can tell from my code above - I simply use the standard headers we all have access to...).
Like JLBorges said.... I think the loop is designed to just stop when you DON'T input an integer..... so I will re-test that again. I will also try some other termination schemes as well. But I thought this would work and have no reason to believe why it shouldn't considering the author....????
Thanks for the help so far..... going to try some of these ideas and see what I get.
Put your call to the function back it will not hurt to call it. It will help you understand what is happening though.
When you have put the function call back run the program an when asked for a label put My_Numbers. When the function is called it will print what it was able to put in the in the variable "label". Then rerun the program and put My Numbers. Then see what the function prints. This should give you an idea of what is happening. If not let me know.
Again, I think I'm just supposed to be reading the input buffer but I am not sure I've redirected stdin in any way or have screwed something else up.
No you have not redirected std in any way that I can see. And Yes you are working from the input buffer as the keyboard does not go directly into the variable. There is a hint in there.
NOW, he (the good Dr.) does use his OWN special header named: "std_lib_facilities.h".... so I am not sure if the header has something in in it that makes this all easier?
No I do not believe it adds anything special just header files that you may not need at this time. But it has been awhile since I looked at that header file to know all of what is in it. I feel that what you are doing is a better learning tool than to use something that is easy just because the person who wrote the book (I mean any book) wants to put off covering a topic until a later time, so they take the easy out. This also applies to the line usingnamespace std; // <--- Best not to use.
The for loop as designed is actually an endless loop as long as you enter a number each time. Pressing "Enter" just goes to the next line and waits for you to enter something more. Trying to enter a blank line does not work.
Ways out would be to press "Ctrl + d" (Unix/Linux) or "Ctrl + z" (Windows). This will signal "eof". Or enter something that is not a number. Understanding how the program works I just enter a letter when I am done to cause "std::cin" to fail and end the for loop. And "std::cin" is never used after the for loop it is not a problem.
should I migrate AWAY from codeblocks and just get MS VisStudio or MS VisStudio CODE??
CodeBlocks is good and many people use it. I use VS Community, the free version, because in the beginning it was the only IDE I knew about, but I find that the free version covers everything I need and has more features than I may ever use.
I would suggest not changing, but adding VS because you will find some differences between the two in the way they work.
A quick example is <iostream>, in VS, will eventually include the header files
1 2 3 4 5
<climits>
<cmath>
<cstdio>
<cstdlib>
<streambuf>
I have not checked the <iostream> in the MinGW compiler to see what they include, but it may be different.
Having two different compilers will allow you to check your programs in two different environments.
It asked for labels, then “please input your integers…..”
Then it took integers, over and over. “Return” doesn’t stop it (it continues even if zero is the evaluation for holding).
I happen to know that consoles “end” input with ctrl-Z, so I entered ctrl-Z.
That ended input, and THEN I got the “Got past the for loop” message.
Probably according to plan, but….
Further, if I enter any letters, the input sequence ends, as @JLBorges states.
I decided to append the “print_nums” function, which prints the list from input.
The “special header” named “std_lib_facilities.h” isn’t really all that special. It would amount to a pre-compiled header collection of simple, standard library includes.
He’s just letting the details of which headers to include for a later chapter (harmless to skip ahead).
I’m not personally familiar with CodeBlocks (heard about it, but not used it). Like @Handy Andy, I use Visual Studio (several versions, some for particular project requirements) on Windows, Xcode on MAC (though I don’t actually like Xcode).
I can recommend Visual Studio. If you decide to try it, select among the options to install the Clang/LLVM compiler. Microsoft’s compiler is ok, but it’s behind relative to C++17 (fairly good up to C++14), but Clang/LLVM is a lot more current. There are also ways to install GCC (though GCC isn’t known for it’s optimizer, it is known to be among the first to implement all the new C++ features).
In my version of this book, Stroustrup does mention how these loops terminate.
He points out that the subject is dealt with in more depth by chapter 10.6, which also covers various error handling in streams.
That is odd then! And what I mean by ODD is that when I run it==>
1.) the use of cin ONLY grabs the first word in my label variable even though I type multiple space separated words and ending with a RETURN ...... NOT the whole phrase!! Is this to be expected if one does NOT use getline() instead?
2.) I do NOT get to input ANY integers! It literally drops right through that "for" loop and I see the final "Got past the for loop" message.
Here's what the output looks like (using an online compiler...) ==>
Please give a units/label for your numbers: The numbers you typed are==>
Please input your integers followed by RETURN to end: The
Got past the for loop
Now my question to you guys is...... WHY are you all able to get this to work and I can not?? This does NOT sound cool at all! Is this a compiler issue?
where S is a string will take input UP TO A SPACE AND STOP.
It will leave any additional WORDS separated by space for the next cin, which is now in your loop expecting integers.
Since the next WORD isn't an integer, it breaks the loop (this is described somewhere in Stroustrup's book)
So...it's working for you too. Just, still not what you're expecting, because "enter units label" is usually something like "ms" or "s" or "in" or "mm"....which, if you enter that, works more like you're expecting.
So, yes, even for us, if we answer the first question with any spaces and additional words, it works as written but does NOT take any integers....and that's by design
#include <iostream>
#include <vector>
#include <string>
// The program asks for a list of integers from the user
// and prints them using a function print_nums() after loading into a vector
void print_nums( const std::vector<int>&, const std::string& );
int main() {
std::string label; //user's phrase for labeling input numbers
std::cout << "Please enter a units/label for your numbers followed by RETURN: ";
// std::getline: read complete line of input (everything up to a new line)
// http://www.cplusplus.com/reference/string/string/getline/
std::getline( std::cin, label );
std::vector<int> my_nums; //user vector of integers
std::cout << "\nPlease input your integers. End input "
<< "by entering any non-numeric character:\n" ;
for( int holding ; std::cin>>holding ; ) my_nums.push_back(holding);
print_nums( my_nums, label ) ;
}
void print_nums( const std::vector<int>& nums, const std::string& label ) {
std::cout << "\n\n--------------\n" << label << "\n--------------\n" ;
// range based loop: for every integer v in vector nums
// http://www.stroustrup.com/C++11FAQ.html#forfor( int v : nums ) std::cout << v << '\n' ;
}
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
usingnamespace std;
void print_nums( const string &str, const vector<int>& V )
{
cout << str << '\n';
for ( int i : V ) cout << i << ' ';
cout << '\n';
}
int main()
{
string label, line;
cout << "Enter a label: ";
getline( cin, label );
cout << "Enter a line of numbers, ended by return: ";
getline( cin, line );
stringstream ss( line );
vector<int> nums;
for ( int i; ss >> i; ) nums.push_back( i );
print_nums( label, nums );
}
Enter a label: Just a demonstration
Enter a line of numbers, ended by return: 3 1 4 1 5 9
Just a demonstration
3 1 4 1 5 9
That way:
(a) you don't need a sentinel to end the input (although you do need all numbers on one line);
(b) you don't need to clear up the stream afterwards, as you would need to do by ending it with non-numeric input should you need any more cin operations afterwards.
I can't see any good reason for putting stdin in a failed state if you don't have to.
This is a rudimentary lesson I'm working on BUT thankfully I am completely following all of your suggestions and totally agree with the advice. I DID end up using "getline()" to get ALL of the user input and that naturally works so thanks for the confirmation that getline is in fact the way to go (as intuition pointed out!) and also re-writing that section with getline.
I am ABOUT to get into streams so Lastchance's suggestion is ALSO very apropos but like Niccolo and JLBorges are hinting at.... I'm trying to do this "by the book's lesson" and the current "level" for each chapter - but I DO agree with you guys that screwing up the input for the rest of the program is not desirable and will be looking forward to I/O streams in the next few chapters.
I'm going to drop JLBorges code VERBATIM into the compiler and see what goes down. I will report back to you guys what it does and HOPEFULLY it works and refuses to vomit. If not, I will let you know what problems I find.
Thanks again everyone for the input and concise advice! Too many times you ask for advice and people give you very convoluted or esoteric instructions (Essentially answering a completely different problem or re-writing it their own wayy) and you're stuck figuring out "what's wrong" on your own after reading a bunch of nonsense.
You guys didn't do that and I am grateful! You realize that me understanding WHY it is wrong is more important than the dumb little program or knowing about something I haven't explored yet! For that I am grateful.
I will have MORE rudimentary questions coming as I fumble through the chapter's exercises - but as you all said I'm learning more screwing it up than I would if I got it right first!! So please bare with me - I intend to get up to speed very quickly since I am getting BACK into C++ after a few years hiatus. Thankfully things are returning fast and I am tracking with you guys.
JLBorges code worked flawlessly on my compiler. As you all stated the initial use of "cin" screwed up the following use of the input buffer and totally messed up the outcome of the program even though the logic was correct from the book.
I dropped the code in verbatim and here is what I got when I put in a phrase and some test numbers==>
Please enter a units/label for your numbers followed by RETURN: Here's your numbers!==>
Please input your integers. End input by entering any non-numeric character:
52 89 56 -158 321 -78945 23 -54 l
BTW, that terminating character is a lower case "L" and NOT a "1" just to put your minds at rest! NOT a good choice in retrospect!
So, thank you all for the advice and as you all aptly stated - it worked for me too..... it screwed up where it was supposed to due to a partially full buffer from before!
In a way, that was Stoustrup's purpose. He uses simple approaches to show what they do, and then explores improvements (by chapter 10, you're dealing with most of the solutions).