Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have only really been coding for a few days, though I've reading the textbook for my Intro to C++ class for two weeks. I'm having an issue with an assignment, and I feel like I'm missing something super simple, but I can't understand what I've done wrong.
The exercise calls for you to 'write a program that reads numbers from cin, and then sums them, stopping when 0 has been entered.'
The professor told us we could write it with a for loop, a while loop, or a do-while loop. I am trying to write it with a for loop.
The program compiles successfully, it allows me to enter multiple values, and it sums it correctly. It also stops on no successfully. The only thing that's wrong with it is when I enter 0, it does not stop the program. I have tried using different commands inside the for loop, such as goto, and trying to direct it to go to break; when the value entered is zero, but my knowledge is shoddy, to say the least. I've read the textbook but I don't have enough experience yet, and I don't remember everything, and I can't figure out what I'm doing wrong.
This is what the program looks like:
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
char indicator{ 'n' };
double value{};
double sum{};
for (;;)
{
cout << endl
<< "Enter a value here: ";
cin >> value;
sum += value;
cout << endl
<< "Do you want to enter another value (enter y or n)? ";
cin >> indicator;
if (('n' == indicator) || ('N' == indicator))
break;
}
cout << endl
<< "The sum of the values you entered is " << sum << "."
<< endl;
return 0;
}
Please point out my stupid mistake, I'd be grateful to learn. Thank you!
There is no sense to ask the user each time whether he wants to continue.
So I would write the loop the following way
cout << "Enter a sequence of real numbers (0 - exit): ";
for (;;)
{
if ( !( cin >> value ) || ( value == 0.0 ) ) break;
sum += value;
}
Also as the variable value is used only in the body of the loop it should be declared there. So the loop can look like
cout << "Enter a sequence of real numbers (0 - exit): ";
for (;;)
{
double value;
if ( !( cin >> value ) || ( value == 0.0 ) ) break;
sum += value;
}
An alternative for this for loop is while loop of the following form
cout << "Enter a sequence of real numbers (0 - exit): ";
while ( true )
{
double value;
if ( !( cin >> value ) || ( value == 0.0 ) ) break;
sum += value;
}
Just compare value to zero after it is inputted:
for (;;)
{
cout << endl
<< "Enter a value here; enter 0 to stop: ";
cin >> value;
if(value==0.0) break;
sum += value;
}
I would like to make a few suggestions to you which you may find helpful.
To begin, any of the loops you mentioned (for, while, do while) may be used in solving this problem. But I believe that the do while lends itself best to this particular problem.
The use of a for is especially bad for this exercise as for loops are typically employed while performing iterations over a set of values or some sort of finite counting. Being asked to perform an action an indefinite number of times is better suited for a while or do while.
Just look at your for declaration:
for(;;)
{
// ...
}
What benefit does using for have in this situation if you make use of none of it's functionality.
Second, the use of double is for your value and sum is not recommended either. This is because of something called floating-point precision. You can not reliably compare a double value using ==. See: What is the most effective way for float and double comparison?
Instead, unless specified by the problem statement, I would opt to use an integer value type. Either int or unsigned int.
Third, you are not correctly initializing your variables. Instead, it should be done as:
int value = 0;
int sum = 0;
Improper variable initialization can lead to countless bugs and is a very common source of problems.
Finally, I would recommend against the use of using namespace. This is used commonly by beginner developers who then are taught better practices and then have to unlearn the behavior. See: Why is "using namespace std" considered bad practice?
Taking this advice into consideration would lead to a solution such as:
#include <iostream>
int main(int argc, char** argv)
{
int sum = 0;
int value = 0;
do
{
sum += value;
std::cout << "Please enter a value: ";
std::cin >> value;
} while(value != 0);
std::cout << "The sum of all values entered is: " << sum;
return 0;
}
ITNOA
You can just change
cout << endl
<< "Do you want to enter another value (enter y or n)? ";
cin >> indicator;
if (('n' == indicator) || ('N' == indicator))
break;
with
cout << endl
<< "Do you want to enter another value (enter 0 for exit or not zero to continue)? ";
int indicator = -1;
cin >> indicator;
if (indicator == 0)
break;
If you do not want to ask user to continue enter new value in every time #Govind Parmar and #Vlad from Moscow write cleaner code than you write.
Related
I'm just getting started with programming and this is my first post on this site, hopefully the start of a long and productive journey!
I'm studying C++ from the Deitel's book and one of the exercises of the control flow 1 (chapter 4 - if, if...else, while) is asking me, among other things, to input a number and check that it's no smaller than 1 and no greater than 20 (in this case an error message has to be displayed to the user until a valid number is entered). In order to make it work I had to use the || operator as follows:
while (number < 1 || number > 20)
{
cout << "Wrong number, insert a valid number";
cin >> number;
}
Problem is, the book has yet to introduce boolean operators (||, && ...)!
So my question is, is it possible to operate such a control on a value without using the "or" operator and only using the if, if...else and while, nested if necessary? Thank you in advance.
On approach would be nested ifs.
bool ok = false;
if (number >= 1) {
if (number <= 20) {
ok = true;
}
}
if (!ok) {
// print error
}
So you assume the number is bad. If it's < 1 then it skips the first if and the number stays bad. If the number is > 1 then it tries the second condition and only sets ok to true is that is true i.e. both conditions are true.
You can wrap this in the necessary while look yourself:
bool ok = false;
while(!ok)
{
// input number
// check number
// optional error
}
You could possibly use arithmetic for this. But then it is a trick
do
{
cout << "Insert a valid number";
cin >> number;
}
while ( (number-1)*(20-number)<0 );
Another approach is to test in separate
while ( true )
{
cout << "Insert a valid number";
cin >> number;
if ( number < 1 ) continue;
if ( number > 20 ) continue;
break;
}
Well, you could always use std::clamp()
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int low = 10, high = 20;
int number;
while ( true )
{
cout << "Enter a number between " << low << " and " << high << " inclusive : ";
cin >> number;
if ( clamp( number, low, high ) == number ) break;
cout << "Invalid number\n\n";
}
}
You can write a function already (see main function) so write one which checks if the number is within an interval and returns 1 if it is and 0 otherwise. This can be done with using only if and return statements in a function. And put a function call in while statement.
Thank you all for your help.
The solution to the issue that was bothering me is the little expression that Peter wrote in the comments, as it is the only thing suggested that's already been explained in the few chapters that i've read (the implicit boolean operators with 0 as "false" and 1 or greater as "true").
I'm sorry I couldn't be more specific with my question but english isn't my first language. That's also the reason why I started studying on the Deitel book: being programming a complex subject I thought it'd be better to begin with something in italian before moving to an english text.
I'm trying to only allow integer values into my program, so I've made the following function. The function is similar to other ones I've seen online, and mine seems to work just fine up until I add an ! in front of it to check if something is not an int.
Function to check if input is an integer:
bool isInteger(std::string s)
{
for (int i = 0; i < s.length(); i++)
{
if (isdigit(s[i]) == false)
{
return false;
}
return true;
}
}
Function being put to use:
int getLevel()
{
int level;
std::cout << "Level One\n";
std::cout << "Level Two\n";
std::cout << "Level Three\n";
std::cout << "Level Four\n";
std::cout << "Level Five\n";
std::cout << "Enter your level (1-5): ";
std::cin >> level;
while (!isInteger(std::to_string(level)) || level < 1 || level > 5)
{
std::cout << "Enter an integer value between 1-5 inclusive: ";
std::cin >> level;
}
clrscr();
return level;;
}
I believe the function works just fine until I put the ! in front of it. I am trying to only allow integer input into my program, and when I enter a double or string, the console becomes flooded with the message "Enter an integer value between 1-5 inclusive: " and doesn't give any time to enter an input. I am fairly new to c++ programming and could use some advice. Thank you!
std::cin >> level;
will try to read an integer and it will never read anything other than an integer. If this fails std::cin's failbit is set and further input operations (like std::cin >> level; inside the loop) are skipped.
You need to check if the reading succeeded and ignore the current input if not. Like this for example:
std::cout << "Enter your level (1-5): ";
while(!(std::cin >> level) || level < 1 || level > 5) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Enter an integer value between 1-5 inclusive: ";
}
As little semi-related hint: level will always be an integer. Converting it to a string will always be the string-representation of an integer, so isInteger(std::to_string(level)) will always be true, unless level is negative, because you don't check for the sign.
Also that return true; in isInteger must be outside the loop, else you only check the first character.
Thanks to all the replies and clarification, I've managed to come up with a solution of my own.
New isInteger function that now checks for everything that is needed including inputs like "0004" that a user suggested above:
bool errorCheck(std::string s)
{
int intLevel;
std::stringstream tempLvl(s);
tempLvl >> intLevel;
for (int i = 0; i < s.length(); i++)
{
if (isdigit(s[i]) == false || s[0] == '0' || intLevel < 1 || intLevel > 5)
{
return false;
}
}
return true;
}
The method in action:
std::cout << "Enter your level (1-5): ";
std::cin >> stringLevel;
while (!errorCheck(stringLevel))
{
std::cout << "Enter an integer value between 1-5 inclusive: ";
std::cin >> stringLevel;
}
std::stringstream lvl(stringLevel);
lvl >> level;
clrscr();
return level;
}
Please let me know if you spot any problems with the code or have any easier solutions. Thanks for all the help!
ok i am gonna tell u the fact that console input extracts the input from console so if u ever tried to do something like that
i.e read string in place of integer the cin is going to be in bad state you can check this fact by putting an if like this
if(!cin>>level) break;
and u will find it working actually stream takes input from the console and convert it to boolean value so u can always check it's state bad state return false else true...... ..
SO,finally the bug is in cin>>level...
I hope u understood.... also check out that return true statement..
i am gonna put u reference link for more answer on this bug...
user enters String instead of Int
Assignment:
The program should ask the user to enter a positive number and display all numbers from 1 to the input value. If the number is not positive, an error message should show up asking the user to re - enter the number.
My specific problem:
For my program, if the user enters an incorrect number and then re - enters a positive number, it does not display all the numbers from 1 to the input value. The program just ends.
#include <iostream>
using namespace std;
int main()
{
int userChoice;
int i = 1;
cout << "Enter a positive integer" << endl;
cin >> userChoice;
if (userChoice > 0)
{
for (i = 1; i <= userChoice; i++)
{
cout << "Loop 1:" << endl;
cout << i << endl;
}
}
else if (userChoice < 0)
cout << "Please re - enter" << endl;
cin >> userChoice;
system("pause");
return 0;
}
You need some sort of loop at the top of your program, that keeps asking for input until the user provides something valid. It looks like a homework assignment, so I will provide pseudo-code, not something exact:
std::cout << "Enter a number:\n";
std::cin >> choice;
while (choice wasn't valid) { // 1
tell the user something went wrong // 2
ask again for input in basically the same way as above // 3
}
// after this, go ahead with your for loop
It is actually possible to avoid the duplication here for step 3, but I worry that might be a little confusing for you, so one duplicated line really isn't such a big problem.
As an aside, you may wish to reconsider your use of what are often considered bad practices: using namespace std; and endl. (Disclaimer - these are opinions, not hard facts).
When the condition is true or false, how can I make it return back and ask the question again, making the user re-enter the value?
Here is what I want to implement:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int n;
cout<<"Enter numbers. Press 5 to stop: ";
cin>>n;
bool tr=true;
while(tr)
{
if(n!=5)
cout<<"You entered "<<n; //How to make it return again, since its false? I keep getting infinite loops :( ;
else
tr=false;
}
return 0;
}
You need to prompt the user in the while loop, so that it occurs in each iteration:
int n;
bool tr = true;
while(tr)
{
cout << "Enter numbers. Press 5 to stop: ";
cin >> n;
if(n!=5) {
cout << "You entered " << n;
} else {
tr = false;
}
}
Just put all your code (except 'n' and 'tr' definition) in while loop as follow:
int main()
{
int n;
bool tr=true;
while(tr)
{
cout<<"Enter numbers. Press 5 to stop: ";
cin>>n;
if(n!=5)
cout<<"You entered "<<n;
else
tr=false;
}
return 0;
}
The other answers all work, and there is something to be learned about improving program flow from them, but I believe the trick you're asking for is the continue keyword, which skips the remainder of this iteration of the loop.
bool tr = true;
int n;
while (tr)
{
cout << "Enter numbers...";
cin >> n;
if (n != 5)
continue;
else
tr = false;
}
EDIT Part 1: On the continue keyword.
You want to make your code as readable as possible. In this example, its use is unnecessary (as the other posters have shown); but it is the answer to the question "How do I skip the rest of processing in this iteration of my loop and continue to the next iteration?". Usually, such flow-breaking directives actually make code harder to read; but sometimes the opposite is true. Anything (or, at least, almost anything) that can be accomplished with continue or break, can be accomplished without them, so if you're going to use them, you want to have a definite reason for doing so. Usually, when I use continue, it's because I'm looping through a collection of inputs and I want to skip processing the loop whenever the input isn't in the format I'm expecting. Something like this (pseudo-code)...
foreach (Input i in ReceivedInputs)
{
if (i.isBad())
{
cout << "Bad input";
continue;
}
// Do massive block of calculating here.
}
is easier to read than this...
foreach (Input i in ReceivedInputs)
{
if (i.isBad())
cout << "Bad input";
else
{
// Do massive block of calculating here.
}
}
because the second version makes it harder to track what scope you're in, if you're looking toward the end of the massive block of calculating. In this case, I gain code readability by continue, so I use it. But simple code probably shouldn't use it. The break keyword is similar, though it's a lot easier to come up with examples where break is beneficial.
EDIT Part 2: On multiple iterations
This is just an issue of setting up the loop; there are no magic keywords here. The shortest way I can come up with, is probably something like this:
int n = 0;
int numberToTake = 10;
for ( int numbersTaken = 0; numbersTaken < numberToTake; ++numbersTaken)
{
cout << "Enter numbers...";
int n = 0;
for (cin >> n; n != 5; cin >> n)
cout << "Try again.";
// Do whatever processing on n you want to do here.
}
Though I should point out that, doing it this way, the only value you will ever get from the user will be 5, and if he inputs anything that doesn't fit in an integer, you will get unexpected behavior.
EDIT 3: After reading the comment more thoroughly, I think you're just looking for is the more traditional use of the for loop.
No need for the exra bool variable.
The idiom can be: Infinitely loop until the user enters 5:
for(;;) { // Loops infinitely
cout << "Enter numbers. Press 5 to stop: ";
cin >> n;
if(n == 5)
break; // Exits the loop
cout << "You entered " << n; // Before the if if you want to print 5 as well
}
I need to implement a loop where I have to ask the user, and then check the validity of the input (in this case it is necessary to print that is an invalid number). What is the better way to implement it?
Our programming professor does not let us use break, and for(;;) since, as he says, it is a bad practice. Is that correct?
Example 1:
int i = 0;
while(i == 0) {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
}
Example 2:
int i = 0;
do {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
} while (i == 0) // Better while(true) and use break ?
Example 3:
int i = 0;
for ( ;; ) {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
else
break;
}
In your case the second construct (do..while) is the most intuititve for the reader to look at what the code does, and this is important.
The first one isn't so bad, the last one is poor a "for" construct is usually used where there are a limited number of iterations with the limit set in advance. It doesn't have to be, but intuitively that is how a for loop is used.
(Incidentally if the user entered a string that isn't a number you would have to clear the fail flag on cin, but that is not really the question being asked here).
Don't you need to accept zero as an integer? It's good practice to not rely on input numbers having a special meaning.
If the meaning of the loop is to loop infinitely until the task is done there's nothing wrong with clearly saying while(true). I would probably do something more like this (requires C++11): (or use boost lexical_cast)
#include <iostream>
#include <string>
#include <stdexcept>
int infini_asker(){
while (true) {
std::cout << "...: ";
std::string tmp;
std::cin >> tmp;
int i;
try{
i=std::stoi(tmp);
}catch(std::invalid_argument){
continue;
}catch(std::out_of_range){
continue;
}
return i;
}
}
int main(){
int num=infini_asker();
std::cout << " got:" <<num << std::endl;
}
A modification of Example 1 looks to be the best form:
while(true) {
cout << "...: ";
cin >> i;
/*... other stuff ...*/
// Do your input validation here:
// Note that it's much better to whitelist what is
// acceptable input as opposed to checking all of the
// possible cases of invalid input
if (...) { // where .. is the condition for valid input
break
}
}
do-while loops should be reserved for special cases where you want to get the point across that the nested logic should be executed at least once. Anything you can do with do-while, you can do with while(...)
for(;;) is less familiar syntax for a lot of programmers (I didn't know what it meant a year ago), whereas while(true) is much more obvious.
They all work. Like Shmiddty says a for(;;) is not a good programming habit. I would do it like example 2, but I am not a professional programmer.