Creating an array using a Do While loop (with input validation) - c++

I am making a C++ code where you will create an array using a do while loop.
Here is the full code:
const int size = 10;
double *pt1;
//executable
pt1=new double[size];
int i = 0;
do{
cout <<"mile" << "[" << i << "]" << setw(3);
if(*(pt1+i) >= 100 && *(pt1+i) <= 250)
{
cin >> *(pt1+i);
i++;
}
else if( *(pt1+i) > 100 && *(pt1+i) < 250)
{
cout << "100-250 only";
continue;
}
}while(i < 10);
There is an input validation where the numbers that will be accepted are only numbers from 100 to 250 but it keeps on looping. I can't find where the problem is. Any help would be greatly appreciated!

The first error is that you are testing the value of the input before you actually get the input. That makes no sense, you need to switch the order around. So this
if(*(pt1+i) >= 100 && *(pt1+i) <= 250)
{
cin >> *(pt1+i);
...
}
else if( *(pt1+i) > 100 && *(pt1+i) < 250)
{
...
}
should be this
cin >> *(pt1+i);
if(*(pt1+i) >= 100 && *(pt1+i) <= 250)
{
...
}
else if( *(pt1+i) > 100 && *(pt1+i) < 250)
{
...
}
Secondly I think you meant
else if( *(pt1+i) < 100 || *(pt1+i) > 250)
Or better you could have just said
else
Then there is no chance of getting the logic wrong. When you have only two choices, you just need to test for the first choice and use else for the second choice. There's no need to test for the opposite of the first choice, using a plain else will do that automatically.
Also continue at the end of a loop is not necessary, loops continue automatically.
Finally pt1[i] is much easier to read than *(pt1+i).

Related

C++ Darts Game: Loop does not exit second time round

I am currently coding a simulator for a game (or multiple games) of 501 darts in C++ and have run into a problem in my code.
The purpose of this region is to simulate 10,000 matches of world championship final darts between two players. One match consists of two players playing the best of 13 sets (first to 7), a set being the best of 5 games (first to 3). In each game both players start at a score of 501 and try to reduce their score to 0 before the other player. I am simulating 10,000 of these matches in order to gain the frequency of each possible result between the two players.
My players are declared in a class with their skill attributes and score count etc, with a method throw_quick_set(); which simulates the player throwing a set of 3 darts for their turn before the other player steps up to do the same.
My problem is, after the first match is won (the program sees a player with 7 sets) - the second match goes on forever with a player winning an infinite amount of sets. I see this because of the output phrases I included when a player wins a game or set when I noticed something was going wrong.
Perhaps someone can help me spot the error in my code, I've been staring at it so long I probably wouldn't notice it even if it was staring me in the face.
Thanks for your time!
int results[14] = {0}; //Stores counters for each of 14 possible outcomes
for (int gameNum = 0; gameNum < 10000; gameNum++)
{
// Calculate results of 10,000 full world championship finals.
// Final is thirteen sets - each set is a best of 5 games.
int sidSetWins = 0, joeSetWins = 0;
int sidGWins = 0, joeGWins = 0;
do
{ // Play best of 13 sets
do
{ // Play best of 5 games
do
{ // Play single game
if (currTurn == sid)
{
Sid.throw_quick_set(); // Throws a set of three
currTurn = joe;
}
else if (currTurn == joe)
{
Joe.throw_quick_set(); // Throws a set of three
currTurn = sid;
}
}
while ((Sid.score != 0) && (Joe.score != 0));
if (Sid.score == 0)
{
sidGWins++;
cout << "Sid wins game" << endl;
Sid.score = 501;
Joe.score = 501;
}
else if (Joe.score == 0)
{
joeGWins++;
cout << "Joe wins game" << endl;
Sid.score = 501;
Joe.score = 501;
}
Sleep(1000);
}
while ((joeGWins < 3) && (sidGWins < 3));
if (joeGWins == 3)
{
joeSetWins++;
cout << "Joe wins set" << endl;
sidGWins = 0;
joeGWins = 0; // Reset for each set
}
else if (sidGWins == 3)
{
sidSetWins++;
cout << "Sid wins set" << endl;
sidGWins = 0;
joeGWins = 0; // Reset for each set
}
Sleep(1000);
}
while ((sidSetWins < 7) && (joeSetWins < 7));
if ((gameNum%1000) == 0)
{
cout << "SidSets " << sidSetWins << endl;
cout << "JoeSets " << joeSetWins << endl;
sidSetWins = 0;
joeSetWins = 0; // Reset for each match
}
EDIT: Here's the class method throw_live_set(); also, if that helps you.
int Darts_501::throw_quick_set()
{ // Used for quick games with no commentary - for average calculations
darts = 0;
int startScore = score;
quickGame = true; // Disable commentary
do
{
if (score>=100)
curr_state = fast;
else if (score > 50)
curr_state = slow;
else if ((score <= 50) && (score > 1))
curr_state = focus;
else if ((score == 1) || (score < 0))
curr_state = bust;
else
curr_state = out;
switch (curr_state)
{
case fast:
score -= throw_treble(20, trebPerc);
break;
case slow:
score -= throw_single(20);
break;
case focus:
if (score == 50)
score -= throw_bull(bullPerc);
else if ((score != 0) && (score%2 == 0))
score -= throw_double(score/2); // If score is even, look to hit the double of half that value
else if ((score != 0) && (score%2 != 0))
score -= throw_setup(score); // If odd, look to set-up a good double score (strategic)
break;
case bust:
score = startScore;
break;
case out: score = 0;;
}
darts++;
} while ((darts < 3) &&
(curr_state != out) &&
(curr_state != bust));
return 0;
}

Is there a simpler way to write this?

Hi I'm learning the basic of C++ and I'm in the process of doing an assignment. I'm asking if there is a simpler way to write this part.
if ( 100 >= projectgrade && 0<= projectgrade ) {}
else
{
cout<<endl<<"invalid data, please retry again.";
cin.ignore();
cin.get();
return EXIT_SUCCESS;
}
if ( 100 >= midtermgrade && 0<= midtermgrade ) {}
else
{
cout<<endl<<"invalid data, please retry again.";
cin.ignore();
cin.get();
return EXIT_SUCCESS;
}
if ( 100 >= finalexamgrade && 0<= finalexamgrade ) {}
else
{
cout<<endl<<"invalid data, please retry again.";
cin.ignore();
cin.get();
return EXIT_SUCCESS;
}
Is it possible to write all those restriction in one bracket of if? I try numerous time but I can't figure it out. Ty for helping out!
Well, if you examine your logic it's if any of the grades is less then 0 or greater then 100, so something like this -
if ( projectgrade < 0 || projectgrade > 100 ||
midtermgrade < 0 || midtermgrade > 100 ||
finalexamgrade < 0 || finalexamgrade > 100
) {
cout<<endl<<"invalid data, please retry again.";
cin.ignore();
cin.get();
return EXIT_SUCCESS;
}
Edit
and we could always add a #define like
#define range(x) x < 0 || x > 100
then that if could be shortened to
if (range(projectgrade) || range(midtermgrade) || range(finalexamgrade))
if ( (projectgrade <0) || (projectgrade > 100) || (midtermgrade <0) || (midtermgrade > 100) || (finalexamgrade < 0) || (finalexamgrade > 100))
{
cout<<endl<<"invalid data, please retry again.";
cin.ignore();
cin.get();
return EXIT_SUCCESS;
}
In C++11 you can write:
auto failure = [](){
cout << "invalid data, please try again" << endl;
cin.ignore();
cin.get();
return 0;
};
and then use it when failures happen:
if ( !(100 >= projectgrade && 0<= projectgrade) )
return failure();
// do more stuff
if ( !(100 >= midtermgrade && 0<= midtermgrade) )
return failure();
Note, doing endl after your text instead of before it is preferable; return 0; always indicates success, and cin.ignore() just ignores a single character (in general, you may want to ignore the rest of the line).
First you may add a function for the test
bool is_valid_grade(int grade)
{
return 0 <= grade && grade <= 100;
}
or
bool is_valid_grade(unsigned int grade)
{
return grade <= 100; // unsigned cannot be negative
}
then use it like:
if (is_valid_grade(projectgrade)
&& is_valid_grade(midtermgrade)
&& is_valid_grade(finalexamgrade))
{
// Valid code
}
else
{
return failure(); // your previous code into a function
}

My program run and returns 0, but it doesn't display the cout data ive given it

When I Build and run my code it instantly returns 0 saying programing was successful, however i want it to display all the numbers from 100 to 200 that are divisible by 4.
Here's my code...
#include <iostream>
using namespace std;
int main()
{
int num = 200;
int snum;
cout<<"The following numbers are all divisble by 4 and are inbetween 100 and 200\n";
while(num<99)
{
snum = (num % 4) ;
cout<<snum<<endl;
cout<<num<<endl;
if(snum = 0)
{
cout<< num << endl;
}
else
{
}
num--;
}
return 0;
}
The while condition should be while (num > 99) instead of while(num<99)(false at the beginning)
The if condition should be if (snum == 0) instead of if(snum = 0)(= is assignment, not equal operator)
The else part has nothing, you may delete it. I added some other notes in the comments below.
while (num > 99)
{
snum = num % 4 ; // no need for the parenthesizes
if (snum == 0)
{
std::cout<< num << std::endl;
}
--num; //pre-increment is preferred, although doesn't matter in this case
}
Your loop never executes because the condition
(num<99)
is already false from the start. You probably meant
(num>99)
Also, the if statement condition
(snum = 0)
sets snum to zero, always returning zero, so you probably meant
(snum == 0)
You set num to be 200:
int num = 200;
Then you only run the loop if and when the number is less than 99:
while(num<99)
What do you expect will happen?
This is not how you do an equals-test in C:
if(snum = 0)
In C, equality is checked with ==:
if(snum == 0)
In fact, what you have (if (snum = 0)) will NEVER be true, so your if-statement will NEVER be executed.

If statements in c++ doubles

#include <iostream>
#include <windows.h>
#include <cstdlib>
#include <stdlib.h>
using namespace std;
int main()
{
int x,y,z;
cout<<"welcome to guessing game\nplayer one pick your number: ";
cin>>x;
if (x < 0)(x > 100);
{
cout<<"out of number range";
}
Sleep(2000);
system("cls");
cout<<"ok player 2 pick the guess";
cin>>y;
if (x == y){
cout<<"congrats you got it right";
}
else{
if (x < y){
cout<<"Go lower";}
else {
if (x > y){
cout<<"higher";}}
}
system("pause>nul");
return 0;
}
i cant see the get the initial if statement to work no matter what number i type in it would auto display the out of number range. also am i allowed to place the conditions like that soo close like if (x < 0)(x > 100);. also how do i make it soo it returns to the start of the program?
There is an error:
if (x < 0)(x > 100);
{
cout<<"out of number range";
}
Should be:
if (x < 0 || x > 100)
{
cout<<"out of number range";
}
You also need to work on your indentation; those if/else statements towards the bottom look dodgy (I cannot really tell due to the indentation).
Aside from writing if (x < 0 || x > 100) (and dropping the semicolon), you should be wary of comparing equality on floating point. I would red flag your line if (x == y){ if reviewing your code.
See Floating point comparison
nobody else is actually answering your second question: how to loop it, here you go:
int x;
cout << "Welcome to the guessing game\n";
do {
cout << "Please enter a number from 0 to 100: ";
cin >> x;
} while (x < 0 || x > 100);
You have written
if (x < 0)(x > 100);
{
cout<<"out of number range";
}
First remove the semi colon.
Second did you mean
if ((x < 0) || (x > 100))
{
cout<<"out of number range";
}
try this:
/*
if (x < 0)(x > 100);
{
cout<<"out of number range";
}
*/
if (x < 0 || x > 100)
{
cout<<"out of number range";
}
There are a few notable syntax errors:
if (x < 0)(x > 100);
{
cout<<"out of number range";
}
First of all, you can't just put two conditions side by side like that in C++ that I know of. You'd have to separate them with || for OR, or && for AND (in most cases - there are some others).
Also, you had a ; at the end of your if statement. I believe that doing this in C++ will result in some problems too.
Your final code should look like:
if ((x < 0) || (x > 100))
{
cout << "out of number range" << endl;
}
The << endl; part is optional. This adds a new line to your output, for more readability next time you write something.
Also, to loop your entire game repeatedly, I would use a do-while loop. You can learn about them here.

How do I create a check for this code?

I'm trying to make it so that the code checks if the user input is between (and including) 10 and 100.
Being so used to just single inputs, I'm having trouble since it's an array...
int main()
{
int numlist[20];
for(int i = 0; i < 20; i++)
{
cout << "Enter # " << i + 1 << " : ";
// here is where I am going wrong...
if ((numlist[i] <= 100) && (numlist[i] >= 10))
{
cin >> numlist[i];
}
}
}
Shouldn't you put the input statement cin >> numlist[i] before the test if ((numlist[i] <= 100) && (numlist[i] >= 10)) ?
it looks like you want to do something like this:
int temp = 0;
for (int i = 0; i < 20; i++)
{
cin >> temp;
if ((temp <= 100) && (temp >= 10))
numlist[i] = temp;
}
Just to give a slightly different way you could do this, you might consider a vector instead of an array, and read the data with an istream_iterator along with a standard algorithm:
std::vector<int> numlist;
std::remove_copy_if(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
std::back_inserter(numlist),
[](int i)->bool { return i<10 || i > 100; });
Edit: I guess since I'm using C++11 lambda, I could also use the C++11 copy_if, which expresses the intent a bit more directly:
std::copy_if(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
std::back_inserter(numlist),
[](int i)->bool { return i>=10 && i<=100; });
As far as "clever" goes, that's not the intent at all -- rather, what's desired is a simple, direct expression of the original intent: to copy (filtered) data from standard input to a container. It does take a bit to get used to the idea of treating files as containers (especially ones like std::cin, which is normally interactive), but ultimately a file is a sequence, and istream_iterator/ostream_iterator just let you treat them like other sequences.
As others have noted, you can't check a value that you haven't even read (from the user).
To constraint the input you must check the input after cin inside a do while loop, as long as it doesn't satisfy the constraint.
do
{
//you might cout here
cin >> numlist[i];
}
while ((numlist[i] > 100) || (numlist[i] < 10));