How do I fix a infinite while loop? - c++

I have a function that uses a while loop to receive multiple inputs in the form.
The function compares
id, C for add or D for remove, and amount to add/remove by
951482 C 5.250
951482 D 15.111
951482 C 29.628
951482 D 10.200
951482 D 3.175
951482 X ‐1
The function compares these lines to an input received somewhere else
id, charge(ignore this), limit of data, and starting data
951482 6.25 50 35.733
changes are preformed on the starting data
Where the last line is the end of my loop
I currently have
void read_and_total (bool& any_errors, double& starting_disk_usage,
double& max_disk_usage, double& end_disk_usage,
int& account_number)
{
int line_account;
double data_change;
char transaction_char;
int line_number = 2;
end_disk_usage = starting_disk_usage;
max_disk_usage = starting_disk_usage;
cin >> line_account >> transaction_char >> data_change;
any_errors = false;
while (account_number != line_account && transaction_char != 'X' && data_change != -1)
{
cout << line_account << ' ' << transaction_char << ' ' << data_change << endl;
if (transaction_char == 'D')
end_disk_usage = end_disk_usage - data_change;
if (transaction_char == 'C')
end_disk_usage = end_disk_usage + data_change;
if (max_disk_usage < end_disk_usage)
max_disk_usage = end_disk_usage;
//Error proccessing
if (transaction_char != 'C' && transaction_char != 'D' &&
transaction_char != 'X')
{
cout << "Error in line #" << line_number << " - "
<< "invalid transaction code" << ' ' << transaction_char
<< ' ' << endl;
any_errors = true;
}
if (data_change < 0)
{
cout << "Error in line #" << line_number << " - "
<< "invalid transaction amount " << data_change << endl;
any_errors = true;
}
if (line_account != account_number) {
cout << "Error in line #" << line_number << " - "
<< " non‐matching account number" << line_account
<< endl;
any_errors = true;
}
cout << "Bottom of function" << endl;
cin >> line_account >> transaction_char >> data_change;
}
return;
}
My while loop is infinitely looping due to the control variable not updating, I don't understand why this is happening because I asking for a new character and new double.
Edit 6:
Ok it actually does not work still however the error in my while statement has been brought to light I want to compare account_number and line_account, this is my fault for using bad variable names.
so when I used one of the solutions
while(account_number != line_account && transaction_char != 'X' && data_change != -1)
it does not enter the loop as it is always false, and skips over the rest of the numbers
my while loops is testing for this line
951482 X ‐1
where the line_account number is the same as my account_number
the character is X
and the value is exactly -1
when I remove the checking for the account_number it works but with it added it always fails to enter the loop.
Edit 4:
I added additional info on the problem at the top
i want my while loop to check for this line at the end of my data
951482 X ‐1
and all three values must be correct,
account number should be the same as the header
the character should be x
and the value MUST be -1 not any other negative value.
Edit 3:
i have now change my while statement to
while (!(account_number == line_number && transaction_char == 'X' && data_change == -1))
I believe this is the source of my problems I am trying to get all three conditions to be true for the loop to end.
Edit 2:
After adding 2 test ouputs the resulting message is a repition of
Bottom of function
951482 X 0.000000
I am not sure why -1 is being set to 0.00000
Edit:
If a include a test statement at the end of the while loop it results in infinitely printing statement. I think I have a problem in my while loop conditions.

How about changing your while() statement to:
while(account_number != line_number && transaction_char != 'X' && data_change != -1))
{
:
:
}

I suspect
while (!(account_number == line_number && transaction_char == 'X' && data_change == -1))
should be
while (account_number != line_number || transaction_char != 'X' || data_change != -1)

Related

Failing Tictactoe in c++

I'm a beginner in c++, i'm trying to make a tictactoe. My program fails at the part acfter i enter input. When I enter an input, there is no next action from the program like i expected it to ("unvalid", check if win or loose, ask for input again). It only shows blank. like below: after I enter "1", nothing happens, and I can keep enter more input.
terminal example photo
I know it is a simple activity but I just ca't figure it out ToT. Thank you for helping!
//tictactoe
#include <iostream>
#include <vector>
using namespace std;
//declared variables
vector<char> out = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
int in = 2;
char player_out;
bool loose = false;
char x;
bool filled = false;
bool end(){ //won yet?
bool loose = false;
//horizontal
if (out[1] == out[2] && out[3] == out[2]){
loose = true;
}
else if (out[4] == out[5] && out[6] == out[5]){
loose = true;
}
else if (out[7] == out[8] && out[9] == out[8]){
loose = true;
}
//vertical
else if (out[1] == out[4] && out[7] == out[1]){
loose = true;
}
else if (out[2] == out[5] && out[8] == out[2]){
loose = true;
}
else if (out[3] == out[6] && out[9] == out[3]){
loose = true;
}
else if (out[1] == out[5] && out[9] == out[5]){
loose = true;
}
else if (out[3] == out[5] && out[7] == out[5]){
loose = true;
}
else{
loose = false;
}
return loose;
}
void game_start_display(){ //display the board
cout << "TIC TAC TOE\n";
cout << " | | \n";
cout << " " << out[1] << " | " << out[2] << " | " << out[3] << " \n";
cout << "______|______|______\n";
cout << " | | \n";
cout << " " << out[4] << " | " << out[5] << " | " << out[6] << " \n";
cout << "______|______|______\n";
cout << " | | \n";
cout << " " << out[7] << " | " << out[8] << " | " << out[9] << " \n";
cout << " | | \n\n";
}
int change_player(){ //take turn 1st and 2nd player
if (in == 1){
in++;
}
else{
in--;
}
return in;
}
bool filled_f() { //check if the spot is filled
if (out[x] != 'X' and out[x] != 'O'){
filled = true;
out[x] = player_out; //fill the input into the spot
}
else if (out[x] == 'X' or out[x] == 'O')
cout << "The square has already been used!\n";
filled = false;
return filled;
}
char player_out_f(){ //change output sign for each players (X, O)
if (in == 1){
player_out = 'X';
}
else if (in == 2){
player_out = 'O';
}
return player_out;
}
void c_player_display(){ //tell players to enter a number
cout << "Player " << in << "'s turn, please enter a number:\n";
}
int main(){
//intro
int loose = false;
game_start_display();
while(loose == false){ //when the game is still happening
change_player(); //change player (player start is set 2 so this comes first and change it to 1)
player_out_f(); //change player output sign (X, O)
c_player_display(); //print the line to ask for input
while(filled == false){ //when the there is no input yet (the spot is not filled)
cin >> x; // input
if (x > 0 && x < 10){ //check if input is in range 1-9
filled_f(); //check if the spot is occupied
}
else if(x < 0 && x > 10) { //if input is out of range
cout << "Invalid! Enter again!\n";
filled = false; //repeat the asking input circle (the while)
}
}
game_start_display(); //output the board again with new char (X or O)
end(); //check if anyone's won yet, if no, repeat the circle
}
cout << "Player " << in << " won! GG";
}
You have infinite loop at while (filled == false) { ... }, because filled_f always sets filled to false (and the else if branch of the condition inside this loop as well does so). It's because you most likely missed figure brackets when writing else if block in filled_f. Your indentation hints that you wanted 2 statements to be in that block, but as of now, only the first is executed conditionally, and the second (filled = false;) is executed after the branch. In other words, with intuitive indentation this function looks like this:
bool filled_f() { //check if the spot is filled
if (out[x] != 'X' and out[x] != 'O') {
filled = true;
out[x] = player_out; //fill the input into the spot
}
else if (out[x] == 'X' or out[x] == 'O')
cout << "The square has already been used!\n";
filled = false;
return filled;
}
It sets filled = false; in any case, since if/else execute (depending on condition) the statement immediately following one of them (see here), and indentation is ignored (unlike in, e.g., Python, where indentation alone determines boundaries of conditions, loops, function etc), so only cout << ... is conditionally executed. To do what you want put figure brackets around appropriate statements the same way you already did for the first if branch to create compound statement (block) from them, which is a statement itself and does what you want - groups several other statements within it, executed in sequence:
bool filled_f() { //check if the spot is filled
if (out[x] != 'X' and out[x] != 'O') {
filled = true;
out[x] = player_out; //fill the input into the spot
}
else if (out[x] == 'X' or out[x] == 'O') {
cout << "The square has already been used!\n";
filled = false;
}
return filled;
}
Additional remarks
Note that logically it's not needed to have if condition in else since if the first if condition is dissatisfied, else if condition is definitely satisfied (look De Morgan's Laws) and you can just write else:
// ...
else {
cout << "The square has already been used!\n";
filled = false;
}
// ...
Also in your main loop, you use this:
if (x > 0 && x < 10){ //check if input is in range 1-9
filled_f(); //check if the spot is occupied
}
else if(x < 0 && x > 10) { //if input is out of range
cout << "Invalid! Enter again!\n";
filled = false; //repeat the asking input circle (the while)
}
to test whether x is within range, but your condition in else if is wrong (should be x <= 0 || x >= 10 instead of x < 0 && x > 10) and can be omitted altogether (again see De Morgan's Laws) by using just else.

C++ while loop insight request

basically I am having weird trouble with my while loop near the beginning of the program which checks for user validation on their choice of activity. When they choose the first activity and complete it, it works fine, but when they complete the second activity, it will go into runtime and keep requesting the user to input a valid choice, even though they haven't even gotten the chance to input a choice. Any tips?
#include <iostream>
using namespace std;
int main()
{
const int DIGITS_CHOICE = 1, IDENTIFIER_CHOICE = 2, DOUBLE_CHOICE = 3, EXIT_CHOICE = 4;
int choice;
int userNumber, storedNumber, factor = 10, digitCounter = 0, subtractor;
char ch;
do
{
cout << "\n\n\t\tPlease choose an option:\n\n"
<< "1. How many digits?\n"
<< "2. Is this a valid C++ Identifer?\n"
<< "3. Is this a double letter word?\n"
<< "4. Exit\n";
cout << endl << "Choice: ";
cin >> choice;
while (choice < DIGITS_CHOICE || choice > EXIT_CHOICE)
{
cout << endl << "Please enter a valid menu option: ";
cin >> choice;
}
if (choice != EXIT_CHOICE)
{
switch (choice)
{
case DIGITS_CHOICE:
cout << "Please enter an integer: ";
cin >> userNumber;
storedNumber = userNumber;
if (userNumber < 10)
{
digitCounter = 1;
}
else
{
while (userNumber != 0)
{
subtractor = userNumber % factor;
if (subtractor > 0)
{
userNumber = userNumber - subtractor;
factor *= 10;
digitCounter++;
}
else
{
userNumber = 0;
}
}
}
cout << storedNumber << " has " << digitCounter << " digit(s)." << endl;
factor = 10;
digitCounter = 0;
break;
case IDENTIFIER_CHOICE:
cout << "Please enter an identifier and press [Enter] immediately after. ";
cin >> ch;
if (ch >= 0 || ch <= 9 || ch <= 'a' || ch >= 'z' || ch <= 'A' || ch >= 'Z' || ch != '_')
{
if (ch >= 0 || ch <= 9)
{
cout << "Not a valid identifier." << endl;
cout << "Identifiers cannot start with a digit." << endl;
ch = '\n';
}
else
{
cout << "Not a valid identifier." << endl;
cout << "Inavlid character." << endl;
ch = '\n';
}
}
while (ch != '\n')
{
if (ch >= 'a' || ch <= 'z' || ch >= 'A' || ch <= 'Z')
{
cin.get(ch);
}
}
break;
case DOUBLE_CHOICE:
break;
}
}
} while (choice != EXIT_CHOICE);
return 0;
}
Also the program isn't complete yet. the third option has nothing and the 2nd option is almost complete. the first activity though is complete :)
Your check for valid characters is too broad, and doesn't really make sense:
if (ch >= 0 || ch <= 9 || ch <= 'a' || ch >= 'z' || ch <= 'A' || ch >= 'Z' || ch != '_')
Every possible value of ch is going to be greater than or equal to zero, so this expression is equivalent to (true || a || b || c || ... || z) and it's always going to resolve to true.
Instead, see if it's below 'A', between 'Z' and 'a' or beyond 'z' and if so, it's invalid.
Also, when checking if it's a digit, you need to check if it's ≥ '0' and ≤ '9' as characters. It's important that you compare it to the character representation of 0 and 9 because the value of the character '0' not actually 0 (it turns out it's actually 48) and likewise with '9':
if ( ch < 'A'
|| (ch > 'Z' && ch < 'a')
|| ch > 'z')
{
if (ch >= '0' && ch <= '9')
{
cout << "Not a valid identifier." << endl;
cout << "Identifiers cannot start with a digit." << endl;
ch = '\n';
}
else
{
cout << "Not a valid identifier." << endl;
cout << "Invalid character." << endl;
ch = '\n';
}
}
It's not really clear what the check after that is meant to do? Is it only meant to allow letters? That seems strange after saying "Identifiers cannot start with a digit." anyway:
if (ch >= 'a' || ch <= 'z' || ch >= 'A' || ch <= 'Z')
This has essentially the same issue where every character is going to be either above 'a' or below 'z' or both, so this will always resolve to true. Instead, use && to check for being within a range:
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
Hopefully that addresses your question.
The logic is not great; i is valid, but your code says it's not. It at least goes back to the menu just fine. Your code is also behaving like it will respond immediately as letters are being typed. That is not the case. It won't print anything until the user presses Enter.
It seems the issue is your variable ch being a char. If I type anything that's longer than a single character, what will happen is that the single character gets evaluated, and the remaining characters I typed remain in the input stream. It looks like you are attempting to handle that, but it's not working. I am not going to spend time delving into the why, partly because it's complex, partly because I don't know the full intricacies of istream behavior.
What I will say is that if you want to handle a multi-character input, use cin.get() everywhere and not just sometimes. You can do processing of each character, but again, nothing will go to the screen until the user presses Enter.
But here's code that appears to work:
#include <cctype> // isalpha() and isalnum()
#include <string> // ch is now a std::string
// ...
case IDENTIFIER_CHOICE:
cout << "Please enter an identifier and press [Enter] immediately after. ";
std::cin.ignore(256, '\n'); // needed because of getline behavior
std::getline(std::cin, ch);
if (!(isalpha(ch[0]) || ch[0] == '_')) {
cout << "Not valid.\n";
break;
}
for (int i = 1; i < ch.size(); ++i) {
if (!isalnum(ch[i])) {
cout << "Not valid.\n";
break;
}
}
cout << "Valid.\n";
break;
// ...
With cin, when you press Enter, that keystroke is saved in the input stream. getline() doesn't behave the way we expect because while cin will typically ignore that keystroke, getline does not. So I just tell cin to ignore an arbitrary (but sufficient in this case) amount of characters in the stream up to and including the Enter keystroke (Mac and Linux, should still behave for Windows (I think)).
This is still far from bulletproof input validation (that's impossible), but I think it suffices for what you're working on.

How to prevent C++ buffer overflow if the user enters two or more strings separated by white spaces?

I'm a student, and I am currently working on C++ Classes. I am making a program which is supposed to ask a user to input a float point number not greater that 99.99 as a price of fuel at a gas station. I have created code that saves the user input in to a char array, and created limits so that the user can't input more than 2 dots, for example (2..2). The maximum number of characters is 5 including one dot. Now, everything works fine except for if the user enters two sets of strings before hitting enter. I have a problem because the second string messes up with other cin statements in the loop.
The code will also take the finalized char array input, and than covert it to a float variable so that the further calculations can be computed easily.
I am working on a Windows system, and Visual Studio 2017 C++.
I have tried detecting the single white space in an if/else statement, but it seems that white space is not detected as a single char array member, like this ex. else if (str[count] == ' ') , and than asking to re enter the correct input without the white space. getline() function could not work on a char array, so I couldn't discard the characters entered after including and after the white space in this way. I have tried changing the char array to a string, but still if the user inputs two or more strings separated by white space, my program keeps reading it in to cin over again.
int main()
{
int count = 0;
int lenFlag = 0, mainFlag = 0;
float result = 0;
int len;
char str[6] = "00000";
//string str ="00000";
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
//This part will ask the user to set the price of fuel
//for the gas pump program. The programming project segment
//is from a book by Walter Savitch "Absolute C++".
while (mainFlag == 0)
{
cout << "Please enter the fuel price in dollars $";
cin >> str;
len = strlen(str);
cout << "strlen is = " << len << endl;
while (len <= 5 && mainFlag == 0)
{
count = 0, lenFlag = 0;
while (count < len && lenFlag == 0)
{
if (count == 0 && (str[count] < 48 || str[count] > 57))
{
cout << "The first input member must be a number."
"You must use a number between 0-9.\n"
"Try again: ";
cin >> str;
len = strlen(str);
lenFlag = 1;
}
else if (count > 0 && (str[count] < 48 || str[count] > 57)
&& str[count] != '.')
{
cout << "You must enter number between 0-9, or a decimal delimiter.\n"
"Try again, : ";
cin >> str;
len = strlen(str);
lenFlag = 1;
}
else if (count > 0 && (str[0] == '.' && str[1] == '.') || (str[0] == '.' && str[2] == '.') ||
(str[0] == '.' && str[3] == '.') || (str[0] == '.' && str[4] == '.') ||
(str[1] == '.' && str[2] == '.') || (str[1] == '.' && str[3] == '.') ||
(str[1] == '.' && str[4] == '.') || (str[2] == '.' && str[3] == '.') ||
(str[2] == '.' && str[4] == '.') || (str[3] == '.' && str[4] == '.'))
{
cout << "You have entered more than 1 decimal delimiter, try again: ";
cin >> str;
len = strlen(str);
lenFlag = 1;
}
else if (count > 1 && str[0] > 48 && str[0] < 58 && str[1]>47
&& str[1] < 58 && str[2]>47 && str[2] < 58)
{
cout << "Maximum number is 99.99, try again:\n";
cin >> str;
len = strlen(str);
lenFlag = 1;
}
else if (str[count] == ' ')
{
cout << "Typing whitspace is not an option!!" << endl;
cout << "Try again!!" << endl;
cin >> str;
len = strlen(str);
lenFlag = 1;
}
else if (count == len - 1 && lenFlag == 0)
{
//cout << "Main flag switches to 1!!" << endl;
mainFlag = 1;
}
count++;
}
} //while(lenCopy <= 5) loop end
if (len > 5)
{
cout << "Either non-numbers were entered, or a negative
number, or an incorrect " << endl;
cout << "number size. Enter a maximum size of 5
including a .dot for decimal number" << endl;
cout << "Maximum number is 99.99." << endl;
mainFlag = 0;
}
}//mainflag loop ends
int dotpos = 0;
for (int n = 0; n < len; n++)
{
if (str[n] == '.')
{
//dotpos = n + 1;
dotpos = len - n - 1;
cout << "dotpos = " << dotpos << endl;
}
else
{
result = result * 10 + (str[n] - '0');
//Line above is a float and character mix as a math equation.
cout << "result " << n << " = " << result << endl;
}
}
if (dotpos > 0)
result = result / (power(10, dotpos));
cout << "You have set the cost at $" << result << " per gallon." << endl;
system("pause");
return 0;
}
Occasional stack around str variable has been corrupted, and that happens when I heavily try to mess with the user input just to check if the program can crash. That's why I need to know how to clear the input after the white space. I solved the stack corruption problem by changing the char array to string, but still not the excess characters that potential users might throw down at the program.
If you must use character arrays, I highly recommend restricting the amount of characters read from the console.
The std::istream::getline() is well suited for this:
const unsigned int LIMIT = 10;
char number_as_text[LIMIT];
std::cout << "Enter a floating point number, less than 10 characters: ";
std::cin.getline(number_as_text, LIMIT);
You can then use a function like strtod to convert the string to floating point variable.
I have found one good way to solve a problem of the string buffer overflow. It uses
cin>>ws; followed by getline() function. The two need to be used in conjunction, and
than the read will be only the first string of characters and everything after the whitespace will be trashed.
cout << "Do you want to set cost in gallons or liters? "
"\nPress G for gallons or L for liters: ";
cin >> ws;
getline(cin, chooseSetCost);
while (chooseSetCost != "G" && chooseSetCost != "g" && chooseSetCost != "L" && chooseSetCost != "l")
{
cout << "Incorrect input. Try again: ";
cin >> ws;
getline(cin, chooseSetCost);
cout << "choose cost is = " << chooseSetCost << endl;
}

Multiple 'if' statements without an 'else'

The code I have to write is basically a mini bank. It asks for an initial amount, the type of action, and a second operator for that action.
I'm not allowed to use else, but am allowed to use if statements (I don't understand why), nor am I allowed to use a loop or an array.
This is the code I have so far:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int operand1;
int operand2;
float output;
char action;
int main()
{
cout << fixed << showpoint << setprecision(2);
cout << "Enter the initial balance [1-1000]: " << endl;
cin >> operand1;
cout << "Enter an action (D, W, I or C):" << endl;
cin >> action;
cout << "Enter the second operand:" << endl;
cin >> operand2;
if ((action != 'D' && action != 'W' && action != 'I' && action != 'C') || (operand1 > 1000 || operand1 < 1) ||
(action == 'I' && operand2 > 15 || operand2 < 1) || (action == 'C' && operand2 != 20 && operand2 != 10 && operand2 != 5) ||
(operand2 > 1000 || operand2 < 1))
{
cout << "Input out of range" << endl;
return 0;
}
if (action == 'D')
{
output = (operand1 + operand2);
cout << "The new account balance is " << output << endl;
}
if (action == 'W')
{
output = (operand1 - operand2);
if (output<0)
{
cout << "Input out of range" << endl;
return 0;
}
cout << "The new account balance is " << output << endl;
}
if (action == 'I')
{
output = ((float)operand1 + (((float)operand2 / 100) * (float)operand1));
cout << "The new account balance is " << output << endl;
}
if (action == 'C')
{
output = operand1 % operand2;
cout << operand1 / operand2 << " bills dispensed plus " << output << endl;
}
cin.get();
cin.get();
return 0;
}
On certain instances, I get multiple errors instead of just one. For example:
Enter the initial balance [1-1000]: 1030
Enter an action (D, W, I or C): D
Enter the second operand: 40
Input out of range
However, it seems to just move on when it sees the error anyway, and I get this output:
Enter the initial balance [1-1000]:
1030
Input out of range
Enter an action (D, W, I or C):
D
Enter the second operand:
40
The new account balance is 1070.00
I can't seem to figure out how to have only one output, and for it to just display the error with no balance, without using an else statement.
Use switch (action):
https://en.cppreference.com/w/cpp/language/switch
After the cases it can have a default.
Also lots of conventions forbid else, but not forbid elseif - are you sure elseif is forbidden in your case?
But even if elseif is allowed - switch is better to read and is a more elegant solution.
You can use switch by taking all the commands as different cases. This is what others have already said.
My contribution would be that you could put your first if statement i.e. the error case under the default case.
And before using switch statements, could you check if it is ever explicitly stated that you can't use 'else if' statements. If not, you should use that. It is not the same as an 'else' statement.
&& has a higher precedence than ||
if (
(action != 'D' && action != 'W' && action != 'I' && action != 'C') ||
(operand1 > 1000 || operand1 < 1) ||
// (action == 'I' && operand2 > 15 || operand2 < 1) ||
(action == 'I' && (operand2 > 15 || operand2 < 1)) ||
(action == 'C' && operand2 != 20 && operand2 != 10 && operand2 != 5) ||
(operand2 > 1000 || operand2 < 1))
{
cout << "Input out of range" << endl;
return 0;
}
To have more traceability, on what the code does, it would be worth the effort to do:
if (action != 'D' && action != 'W' && action != 'I' && action != 'C')
{
cout << "Input out of range; action " << action << endl;
return 0;
}
if (operand1 > 1000 || operand1 < 1)
{
cout << "Input out of range; 1st operand: " << operand1 << endl;
return 0;
}
...

Program to calculate difference between two times for "time travel"

I am writing a "time travel" program which is supposed to ask the user for the current time, their target travel time, relay those values to be converted into minutes in a function and then based on if the time difference is too high it will not allow the time travel or if it is allowed it will print if they are in the future or the past. My issue right now is that the current time, which is only supposed to be relevant the first iteration, or the first "jump" of the program is not being updated after the jump occurs, and the program defaults to it instead of the target time, which is supposed to be the technical "current time" after the jump has occurred. I have been trying to figure this out for hours and I can't, so I am hoping someone could help me out.
Thank you for your time
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int compute_time_difference(int c_hrs, int c_mins, bool c_am, int t_hrs, int t_mins, bool t_am);
void print_future();
void print_past();
void print_SecurityProtocol();
int main()
{
int c_hrs, c_mins;
int t_hrs, t_mins;
int system_time2;
int time_difference2;
bool c_am = 0;
bool t_am = 0;
char c, c2, Y, N, y, n, jumpAgain;
string am_or_pm_current, am_or_pm_target;
bool g_stop = true;
cout << "Welcome to Po Sled" << endl;
cout << "\tSystem booting..." << endl;
for (int i = 0; i<1; i++) //for loop to run once
{
cout << "\n\tEnter current time below: " << endl;
cout << "\t>Enter hour: "; //User inputs current time in hours
cin >> c_hrs;
while (c_hrs > 12 || c_hrs < 1)
{
cout << "Error: Please enter an hour in the range [1, 12]: ";
cin >> c_hrs;
}
cout << "\t>Enter minutes: "; //User inputs current time in minutes
cin >> c_mins;
while (c_mins > 59 || c_mins < 0) {
cout << "Error: Please enter minutes in the range [0, 59]: ";
cin >> c_mins;
}
cout << "\t>Is it AM or PM?: "; //Classifying if current time is AM or PM
cin >> am_or_pm_current;
while (am_or_pm_current != "am" && am_or_pm_current != "AM" && am_or_pm_current != "pm" && am_or_pm_current != "PM") { //Checks if valid input, if not repeats message until valid
cout << "\tError: Please enter AM/am or PM/pm: ";
cin >> am_or_pm_current;
}
if ((am_or_pm_current == "am") || (am_or_pm_current == "AM"))
{
c_am = 1;
}
else if ((am_or_pm_current == "pm") || (am_or_pm_current == "PM"))
{
c_am = 0;
}
cout << "\n\tCurrent system time set to " << c_hrs << ":" << setw(2) << setfill('0') << c_mins << am_or_pm_current << endl;
cout << "\n\t\tIs this time correct (Y or N)? ";
cin >> c;
while (c != 'Y' && c != 'y' && c != 'n' && c != 'N')
{
cout << "\t\t\tError: Please enter Y/y or N/n: ";
cin >> c;
}
if (c == 'N' || c == 'n')
{
continue;
}
else
{
cout << "\n\tSystem initializing and TARDIS unit warming...." << endl;
cout << "\tThe Po Sled is engaged and ready for input." << endl;
}
}
do {
//Starts a loop for target jump
cout << "\n\tEnter target time below: " << endl; //Enters target time of jump
cout << "\t>Enter Hour: ";
cin >> t_hrs;
while (t_hrs > 12 || t_hrs < 1) {
cout << "Error: Please enter an hour in the range [1, 12]: ";
cin >> t_hrs;
}
cout << "\t>Enter minutes: ";
cin >> t_mins;
while (t_mins > 59 || t_mins < 0) {
cout << "\tError: Please enter minutes in the range [0, 59]: ";
cin >> t_mins;
}
cout << "\n\tIs it AM or PM?: ";
cin >> am_or_pm_target; //Classifying if target time is AM or PM
while (am_or_pm_current != "am" && am_or_pm_current != "AM" && am_or_pm_current != "pm" && am_or_pm_current != "PM")
{ //Validates input is AM or PM
cout << "\tError: Please enter AM/am or PM/pm: ";
cin >> am_or_pm_target;
}
if ((am_or_pm_target == "am") || (am_or_pm_target == "AM"))
{
t_am = 1;
}
else if ((am_or_pm_target == "pm") || (am_or_pm_target == "PM"))
{
t_am = 0;
}
cout << "\tTarget time set to " << t_hrs << ":" << setw(2) << setfill('0') << t_mins << am_or_pm_target; //Sets target time
cout << "\n\t\tIs this time correct (Y or N)? "; //Validates if target time entered is correct
cin >> c2;
while (c2 != 'Y' && c2 != 'y' && c2 != 'n' && c2 != 'N')
{
cout << "\t\t\tError: Please enter Y/y or N/n: ";
cin >> c2;
}
time_difference2 = compute_time_difference(c_hrs, c_mins, c_am, t_hrs, t_mins, t_am);
if (time_difference2 > 360) //If time difference is greater than 6 hours prints error function
{
print_SecurityProtocol();
continue;
}
if (c2 == 'N' || c2 == 'n')
{
continue;
}
cout << "\tJump was made, the current time is " << t_hrs << ":" << setw(2) << setfill('0') << t_mins << am_or_pm_target << endl;
if (time_difference2 < 0 && time_difference2 > -360) //If time difference is less than 0 prints past function
{
print_past();
}
else if (time_difference2 >= 0 && time_difference2 <= 360) //If time difference is ahead of current time prints future function
{
print_future();
}
cout << "\tWould you like to jump again (Y/N)? ";
cin >> jumpAgain;
while (jumpAgain != 'Y' && jumpAgain != 'y' && jumpAgain != 'n' && jumpAgain != 'N') //Input validation
{
cout << "\t\t\tError: Please enter Y/y or N/n: ";
cin >> jumpAgain;
}
if (jumpAgain == 'n' || jumpAgain == 'N') //User exiting program
{
if (time_difference2 < 0)
{
cout << "\t\tSystem shutting down; enjoy the past.\n" << endl;
}
else if (time_difference2 >= 0 && time_difference2 < 360)
{
cout << "\t\tSystem shutting down; enjoy the future.\n" << endl;
}
}
if (jumpAgain == 'Y' || jumpAgain == 'y')
{
continue;
}
} while (jumpAgain != 'n' && jumpAgain != 'N');
return 0;
}
int compute_time_difference(int c_hrs, int c_mins, bool c_am, int t_hrs, int t_mins, bool t_am) //Computes time differences.
{
int currentTime_hours, currentTime_minutes, targetTime_hours, targetTime_minutes, currentTime, targetTime;
int time_difference;
if (c_am == 1) //if c_am is true and it is morning
{
if (c_hrs == 12)
{
currentTime_hours = c_hrs * 0;
}
else if (c_hrs != 12)
{
currentTime_hours = (c_hrs * 60);
currentTime_minutes = c_mins;
currentTime = currentTime_hours + currentTime_minutes; //Sets the value of the current time
}
}
else if (c_am == 0) //if c_am is false and it is afternoon time
{
if (currentTime_hours == 12)
{
c_hrs = c_hrs * 60;
}
else if (currentTime_hours != 12)
{
currentTime_hours = ((c_hrs + 12) * 60);
currentTime_minutes = c_mins;
currentTime = currentTime_hours + currentTime_minutes; //Sets the value of the current time
}
}
if (t_am == 1) //if t_am is true and it is morning time
{
if (targetTime_hours == 12) //if target hours equal to 12 special math
{
targetTime_hours = t_hrs*0;
}
else if (targetTime_hours != 12) //else do this math
{
targetTime_hours = ((t_hrs) * 60);
targetTime_minutes = t_mins;
targetTime = targetTime_hours + targetTime_minutes;
}
}
else if (t_am == 0) //if target time equal to pm then do this math
{
if (targetTime_hours == 12)
{
targetTime_hours = t_hrs * 60;
}
else if (targetTime_hours != 12) //else if target time not equal to 12 then do normal pm math
{
targetTime_hours = ((t_hrs + 12) * 60);
targetTime_minutes = t_mins;
targetTime = targetTime_hours + targetTime_minutes;
}
}
time_difference = targetTime - currentTime;
cout << "the difference computed is " << time_difference;
return time_difference;
}
void print_SecurityProtocol() //Function which prints security protocol error message
{
cout << "\tSecurity Protocols Engaging" << endl;
cout << "\t\tError: The time difference is greater than 6 hours." << endl;
cout << "\t\t\tPlease re-enter target time." << endl;
}
void print_past() //Function that prints when a user is in the past
{
cout << "\tHold onto your lower posterior regions" << endl;
cout << "\n\t\tYou are now in the relative past" << endl;
}
void print_future() //Function that prints when a user is in the future
{
cout << "\tHold onto your lower posterior regions" << endl;
cout << "\n\t\tYou are now in the relative future " << endl;
}
Why do you not use a system time call, instead of getting user input for the 'current time'? Also, use a 24-hour clock instead of a 12-hour and you have removed the need to cater for am/pm within your process.
AM n ot much of a coder but c_hrs*60 would be (at least) 60 hours and (at most) 24*60 which, with the exception of a drive across Europe, Russia, Australia or the Northern US would be excessive time recording. Do you not mean to refer to MINUTES instead of hours (c_mins*60)?