why does my code not read or follow the if statements? - c++

Why does my code not read or follow the if statements?
#include<iostream>
using namespace std;
int main (){
int sum = 0;
int integer;
while ((integer != -1) && (sum < 2000)){
int integer;
cout<<"Enter an integer: ";
cin>>integer;
if (integer == -1){
cout<<"Program was terminated.\n"<<"Your total sales are: "<<sum<<endl;
break;
}
else if (sum >= 2000) {
cout<<"Congratulations!"<<"Your total sales are: "<<sum<<endl;
break;
}
sum = sum + integer;
if (sum > 499){
cout<<"You're off to a good start!"<<endl;
}
if (sum > 999){
cout<<"You're halfway through!"<<endl;
}
else if (sum > 1499){
cout<<"You're almost there!"<<endl;
}
}
return 0;
}
Expected:
Input looks like:
Enter an interger: 350, 500,800, 500
Then the out should look like:
Enter an integer 350
" " 500
youre off to a good start
800
youre halfway through
500
Congratualations! Youre total sales are: 2150
Reality:
Enter an integer: 350
Enter an integer: 500
You're off to a good start!
Enter an integer: 800
You're off to a good start!
You're halfway through!
Enter an integer: 500
You're off to a good start!
You're halfway through!

you want only 1 branch to be entered, so you need a if else if chain.
if (sum >= 2000) {
std::cout << "Congratulations!" << "Your total sales are: " << sum << std::endl;
break;
}
else if (sum > 1499) {
std::cout << "You're almost there!" << std::endl;
}
else if (sum > 999) {
std::cout << "You're halfway through!" << std::endl;
}
else if (sum > 499) {
std::cout << "You're off to a good start!" << std::endl;
}
You have to start with the largest number to the smallest one, since if you go from smaller to larger, if a branch is entered it will always be the first branch.
while ((integer != -1) && (sum < 2000)){
this is wrong, as integer is not initialiazed and this is therefore undefined behaviour. In some cases it might never enter the while loop because integer holds some random garbage value that happens to be -1.
You can replace it with a simple while true loop:
while (true) {
since you are calling break; in the final branches anyway (this escapes the while loop). This will also fix the bug, that the loop would terminate before the final print outs.
int integer;
while ((integer != -1) && (sum < 2000)) {
int integer;
you just declared integer twice, the second one is not needed.
Full code:
#include <iostream>
int main() {
int sum = 0;
int integer;
while (true) {
std::cout << "Enter an integer: ";
std::cin >> integer;
if (integer == -1) {
std::cout << "Program was terminated.\n" << "Your total sales are: " << sum << std::endl;
break;
}
sum = sum + integer;
if (sum >= 2000) {
std::cout << "Congratulations!" << "Your total sales are: " << sum << std::endl;
break;
}
else if (sum > 1499) {
std::cout << "You're almost there!" << std::endl;
}
else if (sum > 999) {
std::cout << "You're halfway through!" << std::endl;
}
else if (sum > 499) {
std::cout << "You're off to a good start!" << std::endl;
}
}
}
read Why is "using namespace std;" considered bad practice?

Related

Program to calculate test scores [closed]

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 12 months ago.
Improve this question
I am writing a program to calculate the grade of 3 test scores. The lowest of the first 2 scores is dropped and added to the third test score to make the final grade. The 3 test scores cannot be higer than 50, lower than 0 and cannot be a character or string. So far, I have satisified all those requirment but I need to implement decimal grades to the program like for instance 45.5. Also to round the final grade up or down. For example if final grade is 89.5 round up to an A.
#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;
char getGrade(int num) {
if (num < 60)
return 'F';
if (num < 69)
return 'D';
if (num < 79)
return 'C';
if (num < 89)
return 'B';
return 'A';
}
bool isnumeric(string temp) {
for (char &chr : temp) {
if ((chr >= '0' and chr <= '9') or chr == '-')
continue;
else
return false;
}
return true;
}
int main(int argc, char const *argv[]) {
cout << "Welcome to the grade calculator.You will input three test "
"scores.\nThe highest of the first two grades and the third grade "
"will be\nadded together to determine the numeric grade average for "
"the\ncourse.Each test score has a maximum of 50 points.\n";
int arr[3];
int ctr = 0;
string temp;
int num;
while (ctr < 3) {
cout << "\nPlease enter test score " << (ctr + 1) << ": ";
label1:
cin >> temp;
if (isnumeric(temp)) {
num = atoi(temp.c_str());
if (num > 50) {
cout << "\nTest scores cannot be higher than 50, try again: ";
goto label1;
} else if (num < 0) {
cout << "\nTest scores cannot be negative, try again: ";
goto label1;
} else {
arr[ctr++] = num;
}
} else {
cout << "\nInvalid test score entered, try again: ";
goto label1;
}
}
int average = 0;
average = max(arr[0], arr[1]);
average = average + arr[2];
cout << "\nThe average for the course = " << average << "\n";
cout << "The letter grade = " << getGrade(average);
cout << "\n\n\nThank you for using this program\n";
return 0;
}
Just changed a couple of things to make it work with decimals:
1. Added chr == '.' to the isNumeric() function:
bool isnumeric(string temp) {
for (char& chr : temp) {
if ((chr >= '0' and chr <= '9') or chr == '-' or chr == '.')
continue;
else return false;
}
return true;
}
2. Changed variable types:
double arr[3]{};
int ctr = 0;
std::string temp;
double num;
3. Removed goto: (You can just use continue)
while (ctr < 3) {
std::cout << "\nPlease enter test score " << (ctr + 1) << ": ";
std::cin >> temp;
if (isnumeric(temp)) {
num = atof(temp.c_str());
if (num > 50) {
std::cout << "\nTest scores cannot be higher than 50, try again: ";
continue;
}
else if (num < 0) {
std::cout << "\nTest scores cannot be negative, try again: ";
continue;
}
else {
arr[ctr++] = num;
}
}
else {
std::cout << "\nInvalid test score entered, try again: ";
continue;
}
}
4. For rounding off, you can use std::round() as such:
double average = 0;
average = std::max(arr[0], arr[1]);
average = std::round(average + arr[2]);
You can also change your cout statements:
std::cout << "\nThe average for the course = " << average;
if (std::round(average) != average) std::cout << ", rounded off to = " << std::round(average);
std::cout << ".\nThe letter grade = " << getGrade(average);
std::cout << "\n\n\nThank you for using this program\n";
Just make all these changes and your program will successfully work with decimals.
Also, consider not using the following in your code:
using namespace std;
..as it's considered as a bad practice. For more info on why, look up to Why is using namespace std considered as a bad practice.
Edit: To accomplish your requirement, you can just change the while loop as such:
while (ctr < 3) {
if (temp.size() == 0)
{
std::cout << "\nPlease enter test score " << (ctr + 1) << ": ";
std::cin >> temp;
}
if (isnumeric(temp)) {
num = atof(temp.c_str());
if (num > 50) {
std::cout << "\nTest scores cannot be higher than 50, try again: ";
std::cin >> temp;
continue;
}
else if (num < 0) {
std::cout << "\nTest scores cannot be negative, try again: ";
std::cin >> temp;
continue;
}
else {
arr[ctr++] = num;
temp.clear();
}
}
else {
std::cout << "\nInvalid test score entered, try again: ";
std::cin >> temp;
continue;
}
}
The above code works as you said.

How to find out if string is only numbers, no letters

I have constructed a code that checks if the entered number is a proper divisible of 9 by getting the string length and finding the sum of each digit entered and finding if its perfectly divisible by 9.
The code works well, I just need some error checks and I have two things to try and add to it.
I need to make sure first that the inputted information is only numbers, no letters.
Also I want to find a way to make input limited from 1 to 1000.
I have this bool example that will check if it is in fact a number, but how can I make an if statement for my userNum input to check the boolean?
bool isNumber(const string &line)
{
if (line[0] == '0') return true;
return (atoi(line.c_str()));
}
#include <iostream>
#include <string>
using namespace std;
string userNum;
char userInput;
int sum, i, n;
int main()
{
tryagain:
sum = 0;
cout << "Enter number to test if it is divisible by 9: ";
cin >> userNum;
if (userNum == isNumber) {
cout << "Nah..";
return 0;
// Find sum of digits by seperating
n = userNum.length(); // Gets the sum of the string length in bytes
}
for (i = 0; i < n; i++) // Starting from 0, until num is less than the length of userNum go up one increment
sum = (sum + (userNum[i] - '0'));
if (sum % 9 == 0) {
cout << "Your number, " << userNum << " adds up to " << sum << " which is evenly divisible to 9" << endl << endl;
}
else {
cout << "Your number, " << userNum << " adds up to " << sum << " which IS NOT evenly divisible to 9" << endl << endl;
}
// Restart option begins here.
cout << "Would you like to try another number? (Y/N): ";
cin >> userInput;
if (userInput == 'y' || userInput == 'Y') {
goto tryagain;
cout << endl;
}
else if (userInput == 'n' || userInput == 'N') {
cout << endl;
cout << "Goodbye!" << endl;
}
else {
cout << endl;
cout << "You have entered an unknown input, goodbye!" << endl;
}
system("pause");
return 0;
}
You could do this in 3 ways:
Use a regular expression, with std::regex_match. The regex that you are looking for is ^[0-9]+$ which checks if a string contains only numbers. This is a possible expression but not the absolute one
Use std::stoi which tries to convert a string into an integer. Be sure to surround it with a try-catch statement to ensure that the string can be properly parsed. If you get the exception, then the string is not a number.
As Justin has pointed out in the comments, you could also try using std::isdigit and iterate over the string to check each char.
Rely on std functions and try to avoid writing code by yourself. The second approach is probably what you are looking for because, if the method does not throw an exception, you can check the range of the number.
When you face a problem for which you cannot find a solution, give a look at the list of algorithms on cppreference. Use them as much as you can because they make the code shorter, easier to read and they can give you advantages (some algorithms just need an extra parameter at the end to start a parallel execution of the method!)
for (i = 0; i < n; i++) {
if(userNum[i] < '0' || userNum[i] > '9') {
cout << "Nah..";
return 0;
}
sum = (sum + (userNum[i] - '0'));
}
Given the necessary range-check with the range being 1...1000, you do not gain anything from summing the digits and dividing the sum by 9, instead of just doing the latter on the number itself. So the numerical part could be simple i < 1, i > 1000, i % 9 == 0 checks, where i is the parsed integer.
std::stoi parses a number at the beginning of a string, so while you can use it, it does not replace checking the characters. e.g. 1, 1.2, 1a are all parsed to 1. You need a string which does not start with a number, and only then you get an std::invalid_argument exception. So you will need #Justin's suggestion too, though here I flipped it as "any_of the characters is not a digit:
std::string s;
std::cin >> s;
try {
if (std::any_of(s.begin(), s.end(), [](char c) { return !std::isdigit(c); }))
throw std::invalid_argument(" is not all-digits");
int i = std::stoi(s);
if (i < 1) throw std::invalid_argument(" is less than 1");
if (i > 1000) throw std::invalid_argument(" is more than 1000");
if (i % 9 == 0) std::cout << i << " is divisible by 9" << std::endl;
else std::cout << i << " is not divisible by 9" << std::endl;
}
catch (std::invalid_argument ia) {
std::cout << s << ia.what() << std::endl;
}
catch (std::out_of_range oor) {
std::cout << s << " sure is not between 1 and 1000";
}
(stoi's "own" invalid_argument can not occur here, because of the pre-check for all-digits)
In the case you would want to get a number between 1 and 1010000 inclusive, then yes, you could start doing magics, like checking length of input, various patterns, and summing the digits:
(Example is tuned down to 1010 so it can be tested without getting a headache)
std::string s;
std::cin >> s;
std::string::iterator it = s.begin(), end = s.end();
int len = end - it;
try {
// if(len==0) will not happen because of the cin
if (*it == '0') {
if (len == 1) throw std::invalid_argument(" is less than 1");
throw std::invalid_argument(" starts with 0, multi-digit numbers do not do that");
}
if (len > 11) throw std::invalid_argument(" is too long for not being greater than 10^10");
if (len == 11) {
if (*it != '1'
|| std::any_of(it + 1, end, [](char c) { return c != '0'; }))
throw std::invalid_argument(" is greater than 10^10 or is not all-digits");
// well, here we know that the number is 10^10 (and is not divisible by 9)
// so this could return early
}
int sum = 0;
for (; it != end; ++it) {
if(!std::isdigit(*it)) throw std::invalid_argument(" is not all-digits");
sum += (*it) - '0';
}
if (sum % 9 == 0)std::cout << s << " is divisible by 9" << std::endl;
else std::cout << s << " is not divisible by 9" << std::endl;
}
catch (std::invalid_argument ia) {
std::cout << s << ia.what() << std::endl;
}

How do I make the code not repeat

int main() {
power=1;
while (1 == 1){
tapcost=power*3;
cout << "type upgrade/buy/a" << endl;
cin >> way;
if (way == "upgrade"){
cout << "1. A Power " << "(Costs: " << tapcost << ")" << endl;
cin >> upgr;
if (upgr == 1){
if (0<=money-power*3){
power=power+1;
money=money-power*3;
}
else
cout << "You can't afford that!!!" << endl;
}
}
if (way == "a"){
money=money+power;
}
}
return 0;
}
When I type upgrade and then type anything else other than the variable "1", the code will repeat infinitely.
This is a never-ending problem.
See this question: Infinite loop with cin when typing string while a number is expected
I think your code have some mistakes.
int upgr;
cin >> upgr; // you can type any number you want (-2 147 483 648 / 2 147 483 647)
I suggest you to use getline, cin.getline or fgets instead of cin >> when reading a line.
And just use while(1) or while(true)
You have created an infinite loop by never changing the value of your ‘1’ variable. In some way you need to change that value when iterating through your conditions or else you’ll never get out of your loop.
You could also try out something like that.
char i;
while((std::cin >> i) && i != '1') {
....
}
In your code, while (1 == 1) creates an infinite loop. Since I assume you want this code to keep asking players for their input until they decide to stop, you can add an option exit which breaks out of the loop when the player wants to.
#include <iostream>
int main() {
int power = 1;
int money = 1000;
while (1 == 1) {
int tapcost = power * 3;
std::string way;
std::cout << "type upgrade/buy/a/exit" << std::endl;
std::cin >> way;
if (way == "upgrade") {
std::cout << "1. A Power " << "(Costs: " << tapcost << ")" << std::endl;
int upgr;
std::cin >> upgr;
if (upgr == 1) {
if (0 <= money - power * 3) {
power = power + 1;
money = money - power * 3;
}
else {
std::cout << "You can't afford that!!!" << std::endl;
}
}
}
if (way == "a") {
money = money + power;
}
if (way == "exit") {
break;
}
}
return 0;
}

logic error, need help can't figure out the looping logic

I am a beginner coder and I need a few ideas on how my code can output the right syntax.
If I input number < 25
Outputs and extra(s) ", " because it still runs through and sees that (amount_left > 0).
How would I make it so if there doesn't exist a quarter or dime it does not output the ", "?
#include <cstdio>
#include <iostream>
using namespace std;
void compute_coins(int coin_value, int& number, int& amount_left);
int main(){
int amount_left, number;
while(amount_left > 1 || amount_left < 99){
cout << "Enter number of cents (or zero to quit):" << endl;
cin >> amount_left;
if (amount_left == 0){
break;
}
else{
cout << amount_left << " cents can be given as ";
compute_coins(25, number, amount_left);
if (number == 1){
cout << "1 quarter";
}
else if (number > 0){
cout << number << " quarters";
}
if (amount_left > 0){
cout << ", ";
}
compute_coins(10, number, amount_left);
if (number == 1){
cout << "1 dime";
}
else if (number > 1){
cout << number << " dimes";
}
if (amount_left > 0){
cout << ", ";
}
compute_coins(1, number, amount_left);
if (number == 1){
cout << "1 penny";
}
else if (number > 1){
cout << number << " pennies";
}
std:: cout << ".";
}
cout << endl;
}
return 0;
}
void compute_coins(int coin_value, int& number, int& amount_left){
number = amount_left/coin_value;
amount_left = amount_left - (number * coin_value);
}
The expectation is that a period, and exactly one period must come after all the amounts get printed out.
Therefore, it makes no logical sense to write complicated code that tries to figure out whether it should print a period before the rest of the code, for all the remaining denominations, is done.
Just get rid of that code that prints all those periods, inside all of those awkward if/else statements.
At the very end of everything, simply execute
std::cout << ".";
No ifs, elses, or buts.
Simply focus on the problem of writing out the counts of all the denominations, correctly separated by commas. Forget about the trailing period. Just focus on formatting a comma-separated list of all possible denominations. Put the trailing period out of your mind.
Then, once you get all of that working, simply append
std::cout << ".";
at the end, and call it a day. This is a 100% guaranteed, or your money back, way to end up with exactly one period at the end of your output.

Generating numbers outside of my range C++ (way too large)

I decided for fun to try and make a simple program that "sort of" simulates blackjack in a dumbed down way. It's basically done, except for the fact that the randomly generated numbers are WAY too large. I don't care about the bias srand/rand has (for now) I just want to get it working properly.
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>
using namespace std;
int genRandInt (int low, int high) {
int randnum = low + (rand() % (high - low + 1));
return randnum;
}
int main()
{
srand(time(NULL));
int computerScore;
int score;
int card;
while (int playAgain = 1)
{
cout << "Enter 0 to hold or 1 to hit: ";
int play;
cin >> play;
if (play == 0)
{
computerScore = genRandInt(1, 31);
if (score < computerScore)
{
cout << "Your score is " << score << " and the computer's score is " << computerScore << "! You lose.\n";
}
if (score > 21)
{
cout << "Your score is " << score << " which is greater than 21. Bust!\n";
}
if (score > computerScore && score <= 21)
{
cout << "Your score is " << score << " and the computer's score is " << computerScore << "! You win!\n";
}
cout << "Would you like to play again? 1 for yes, 0 for no. : ";
cin >> playAgain;
}
if (play == 1)
{
card = genRandInt(1, 11);
score = score + card;
cout << "Your score is: " << score << "\n";
}
}
return 0;
}
Any ideas?
You use int score; uninitialized in
if (score < computerScore)
or
score = score + card;
depending on the if(play == 0) or if(play == 1) condition.
It happens to have some junk as its memory content, the compiler does not initializes to zero for you. In fact, it is undefined behaviour to use un-initialized variables. Initialize it before the first usage, preferable in the definition itself,
int score = 0;
Also, compile with warnings on (-Wall -Wextra for g++/clang++), since the compiler will easily warn about these mistakes.
Try running this and seeing if you have the same issues. I just added some print statements to try and debug it, and it stopped showing me really big numbers..
EDIT:
//ADD
int score = 0;
//
if (play == 1)
{
cout << "printing in the PLAY = 1 "<< score << endl;
card = genRandInt(1, 11);
score = score + card;
cout << "Your score is: " << score << "\n";
}