Using C++ (g++-4.7 on Mint 16).
Code is a unrefined (and unfinished) Tic-Tac-Toe game.
#include <iostream>
using namespace std;
int main()
{
//initial data
char turn='A';
char ttt[] = {'1','2','3','4','5','6','7','8','9'};
int move;
int over=0; //0 is no, 1 is yes
int valid=0;
while ( over == 0)
{
//display
cout << "\n" << ttt[0] << "|" << ttt[1] << "|" << ttt[2] <<"\n-----\n";
cout << ttt[3] << "|" << ttt[4] << "|" << ttt[5] <<"\n-----\n";
cout << ttt[6] << "|" << ttt[7] << "|" << ttt[8] <<"\n\n Choose a number (Player " << turn << "):";
//ask enter for play with turn
cin >> move;
cout << "\n";
valid = 0;
while (valid == 0)
{
//check if input is valid
if (((move > 0) and (move < 10)) and
((ttt[move-1] != 'A') and (ttt[move-1] != 'B')) and
(cin))
{
ttt[move-1] = turn;
valid=1;
}
else
{
cout << "Invalid slot. Choose a number (Player " << turn << "):";
cin >> move;
cout << "\n";
}
}
//check if done if no //change turn then goto //display
if (((ttt[0]==ttt[1]) and (ttt[1]==ttt[2])) or
((ttt[3]==ttt[4]) and (ttt[4]==ttt[5])) or
((ttt[6]==ttt[7]) and (ttt[7]==ttt[8])) or
((ttt[0]==ttt[3]) and (ttt[3]==ttt[6])) or
((ttt[1]==ttt[4]) and (ttt[4]==ttt[7])) or
((ttt[2]==ttt[5]) and (ttt[5]==ttt[8])) or
((ttt[0]==ttt[4]) and (ttt[4]==ttt[8]))or
((ttt[2]==ttt[4]) and (ttt[4]==ttt[6])))
{
//display winner or say draw
cout << "Player " << turn << " wins!\n";
over=1;
}
else
{
//change turn
if (turn=='A')
{ turn='B';
}
else
{ turn='A';
}
}
}
return 0;
}
There seem to be a bug on the code. On the part where check if input is valid the and (cin) seem to be failing.
When entering a character, (Instead of a number) it output continuously stacks of:
Invalid slot. Choose a number (Player A or B):
I tested the rest of condition without it, it was all working well. Is there a problem on the code or is this really "cin" problem? I've also tried out !(!cin) but it's the same scenario.
You must clear the fail bit from the cin stream in your else block.
When you enter a character that isn't an integer, the cin stream sets the fail bit, which you correctly check for in your if statement, but you never clear it afterward. This causes your input validity check to be false forever.
#include <limits>
...
else
{
cin.clear(); // Add this line
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // And this one
cout << "Invalid slot. Choose a number (Player " << turn << "):";
cin >> move;
cout << "\n";
}
For additional information, see the documentation for std::basic_ios::clear
Update: see this question and this question for similar problems.
Essentially, you also need to tell cin to ignore whatever is in the stream or it will continually set the fail bit with its bad contents you haven't cleared yet. I modified the above snippet to work.
Related
I've started to learn how to code in C++ on my spare time, using different sites and apps that someone who has also learned C++ online provided me with. By now, I know the most basic commands. I've tried an exercise given by a program, and I'm given the information that someone is going on a vacation, and needs to know how much baggage he can bring with him. The limit to how many baggages he can carry is 45, and I have to display a different output if the baggages are below, above or the same as the limit (45 baggages). I have done some coding, and I ended up with this:
#include <iostream>
using namespace std;
int main()
{
const int limit = 45;
int bag;
cout << "Please type your number here: ";
cin >> bag;
string yn;
int keep = 0;
if (limit < bag)
{
cout << "You passed the limit." << endl;
};
if (limit == bag)
{
cout << "Just enough." << endl;
};
if (limit > bag)
{
cout << "You got space." << endl;
};
++keep;
while(keep > 0)
{
int keep = 0;
cout << "Do you want to try another number?" << endl;
cin >> yn;
cout << endl;
if(yn == "yes")
{
int bag = 0;
cout << "Please type your number here: ";
cin >> bag;
if (limit < bag)
{
cout << "You passed the limit." << endl;
};
if (limit == bag)
{
cout << "Just enough." << endl;
};
if (limit > bag)
{
cout << "You got space." << endl;
};
}
else
{
return 0;
}
}
}
I have developed it more than needed -as you can see-, out of my own interest in the problem. I have copied and pasted the 3 IF commands as seen above, and I believe that there is an easier way, with less code, do solve this. What I have thought of is if I could go back and execute some line of code again, either from a line and below (e.g. from line 45 and below), or specific lines of code (e.g. from line 45 to line 60).
I would appreciate it if you thought of another way to solve this problem and posted your code below.
Thank you for your reply.
We all started writing our first C++ program at some time, so allow me to give you some additional feedback:
First of all, avoid writing using namespace std;
Secondly, naming - what is bag, limit, keep and yn? Wouldn't it be much easier to read and understand if they were called bagSize, maximumPermittedBagSize, inputFromUser (you don't really need the variable keep, see below)?
Finally, here is a (roughly) refactored version your program, with duplication removed and comments added.
#include <iostream>
int main()
{
const int maximumPermittedBagSize = 45;
// Loops forever, the user exits by typing anything except 'yes' laster
while(true)
{
std::cout << "Please type your number here: " << std::endl;
//Declare (and initialize!) variables just before you need them
int bagSize = 0;
std::cin >> bagSize;
if (bagSize > maximumPermittedBagSize)
{
std::cout << "You passed the limit." << std::endl;
}
else if (bagSize == maximumPermittedBagSize )
{
std::cout << "Just enough." << std::endl;
}
else
{
std::cout << "You got space." << std::endl;
}
std::cout << "Do you want to try another number?" << std::endl;
std::string inputFromUser = "";
std::cin >> inputFromUser;
std::cout << std::endl;
//Leave the loop if the user does not answer yes
if(inputFromUser != "yes")
{
return 0;
}
}
}
You can simply run a while loop and do like this:
#include <iostream>
using namespace std;
int main()
{
const int limit = 45;
int bag;
string yn = "yes";
while(yn == "yes")
{
cout << "Please type your number here: ";
cin >> bag;
if (limit < bag)
{
cout << "You passed the limit." << endl;
}
else if (limit == bag)
{
cout << "Just enough." << endl;
}
else if (limit > bag)
{
cout << "You got space." << endl;
}
cout << "Do you want to try another number?" << endl;
cin >> yn;
cout << endl;
}
}
This is a program that grade user inputs for the questions of Driver's License Exam.
I'm having trouble of validating the user input.
I'd like to accept the [ENTER] key as an invalid input and proceed to my validation rather than just go to an empty line and cannot process to the next question. Purpose is to send out error message and that no input is given and [ENTER] key is not valid input and only accept one more chance to enter valid input which are a/A, b/B, c/C, or d/D. So that is why I'm using if statement here instead of loop.
I tried if (testTakerAnswers[ans] == (or =) '\n') {} but still doesn't solve the problem of newline.
I include curses.h in here hope to use getch() statement from the other post but somehow I can't manage to work in my code with an array instead of regular input.
I'm looking for other methods as well rather than getch()
So should I adjust my bool function, or directly validate input in main() function.
#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>
#include <curses.h>
using namespace std;
const unsigned SIZE = 20; // Number of qns in the test
char testTakerAnswers[SIZE]; //Array to hold test taker's answers
bool validateInput(char);
class TestGrader
{
private:
char answers[SIZE]; // Holds the correct answers // Answer is array
int getNumWrong (char[]);
void missedQuestions (char[]);
public:
void setKey(string); // Initialize object with standard keys
void grade(char[]); // Grades the answers from tester
};
void TestGrader::setKey(string key){
if (key.length()!=SIZE){
cout << "Error in key data.\n";
return;
}
for (unsigned pos = 0; pos < SIZE ; pos ++)
answers [pos] = key [pos];
}
void TestGrader::grade(char test[])
{
int numWrong = getNumWrong(test);
if (numWrong <= 5)
cout << "Congratulations. You passed the exam.\n";
else
cout << "You did not pass the exam. \n";
cout << "You got " << (SIZE-numWrong) << " questions correct. \n";
if (numWrong > 0){
cout << "You missed the following " << numWrong << " questions: \n";
missedQuestions(test);
}
}
int TestGrader::getNumWrong(char test[])
{
int counter = 0;
for (int i = 0; i < SIZE; i++){
if (answers[i] != toupper(testTakerAnswers[i])){
counter++;
}
}
return counter;
}
void TestGrader::missedQuestions(char test[])
{
// cout << testTakerAnswers[i]; This is to print taker's answers
int counter = 0;
for (int i = 0; i < SIZE; i++){
if (answers[i] != toupper(testTakerAnswers[i])){
cout << "\n" << i + 1 << ". Correct answers: " << answers[i];
counter++;
}
}
}
bool validateInput(char ans){ // Only A, B, C, D valid input
if (toupper(ans)!='A' && toupper(ans)!= 'B' && toupper(ans)!='C' && toupper(ans)!= 'D'){
cout << "\n********************WARNING*******************\n";
cout << "Invalid input! Enter only a/A, b/B, c/C, or d/D\n";
return false;
}
if (testTakerAnswers[ans] == '\n'){
return false;
}
return true;
}
int main()
{
const int NUM_QUESTIONS = 20;
string name; //Test taker's name
char doAnother; //Control variable for main processing loop
TestGrader DMVexam; //Create a TestGrader object
DMVexam.setKey("BDAACABACDBCDADCCBDA");
do {
cout << "Applicant Name: ";
getline(cin,name);
cout << "Enter answer for " << name << ".\n";
cout << "Use only letters a/A, b/B, c/C, and d/D. \n\n";
for (int i = 0; i < NUM_QUESTIONS; i++){
// Input and validate it
do{
cout << "Q" << i+1 << ": ";
cin >> testTakerAnswers[i];
if (!validateInput(testTakerAnswers[i])){
cout << "You get one more chance to correct.\nOtherwise, it count as wrong answer.";
cout << "\n*********************************************";
cout << "\nRe-enter: ";
cin >> testTakerAnswers[i];
cout << '\n';
break;
}
}while(!validateInput(testTakerAnswers[i]));
}
//Call class function to grade the exam
cout << "Results for " << name << '\n';
DMVexam.grade(testTakerAnswers);
cout << "\nGrade another exam (Y/N)? ";
cin >> doAnother;
while (doAnother != 'Y' && doAnother != 'N' && doAnother != 'y' && doAnother != 'n'){
cout << doAnother << " is not a valid option. Try Again y/Y or n/N" << endl;
cin >> doAnother;}
cout << endl;
cin.ignore();
}while(doAnother != 'N' && doAnother != 'n');
return 0;
}
Your issue is cin >> testTakerAnswers[i]; cin is whitespace delimited, that means that any whitespace (including '\n') will be discarded. So testTakerAnswers[i] can never be '\n'.
I'm not sure exactly what you want to do, but possibly try
getline(cin,input_string);
then
input_string == "A" | input_string == "B" | ...
So if only the enter key is pressed, input_string will become "".
I'm trying to learn C++, my first idea was to make simple win/lost ratio calculator, but it's not working well.
This is my code:
#include<iostream>
#include<conio.h>
using namespace std;
int match=0;
int win=0;
int lose=0;
int ratioo=1;
int total=0;
void lost()
{
if (match=='L');
lose=lose+1;
}
void won()
{
if (match=='W');
win=win+1;
}
int main() {
cout << "Welcome to winratio calculator!" << endl;
cout << "Pressing W adds one win point" << endl;
cout << "Pressing L adds one lose point" << endl;
cout << "Press ENTER to start" << endl;
cout << "Press ESC to close" << endl;
getch();
while(1)
{
cout << "Last game score: ";
cin >> match;
total++;
won();
lost();
ratioo=(win/total)*100;
cout << "Games won: " << win << endl;
cout << "Games lost: " << lose << endl;
cout << "Ratio: " << ratioo <<"%" << endl;
break;
}
return 0;
}
And now my problems:
1)After pressing ANY key there is +1 to win and lose same time
2)I got no idea how to start whole calculator with ENTER and stop it by ESC by getch();, tried few ways but always some errors on the way(it should add points all the time until ESC is pressed
Explanations are very welcome!
Okay, so it looks like we've got a couple of errors in your program as it is now. Let's take a look!
First thing's first. Notice that you have Semicolons at the end of your if statements.
void lost()
{
if (match=='L'); //NOTE: This is a useless if statement
lose=lose+1; //As is, this line will ALWAYS RUN regardless of what character is pressed.
}
void won()
{
if (match=='W'); //Same as Above ^^^^^
win=win+1;
}
Remember that in C, the if statement will execute the next statement conditionally. Remember also that a ; in C is a statement. So, by adding a semicolon after an if statement, you're nullifying the if conditional because the if statement will run the semicolon conditionally, and not your lose = lose + 1;.
Consider writing this instead:
void lost()
{
if (match == 'L')
{
lose = lose + 1;
}
}
void won()
{
if (match == 'W')
{
win = win + 1;
}
}
Furthermore, I noticed that you've inserted a break command to avoid an infinite while(1) loop. To avoid this problem. Consider using match = _getch() instead of cin << match.
match = _getch();
In addition, your Ratioo variable is not receiving anything but 0 due to truncation. To get the percentage you're looking for, you must cast your win/total to double as follows:
ratioo = ((double)win / (double)total) * 100;
So, Now we get to detecting the ESC And ENTER Keys! This is exciting. So, in order to read in these invisible characters, you have to understand that to the computer, these keys are just numbers. The ESC Key is number 27, and the ENTER Key is number 13 (Look Up the ASCII Table for a full list). So To detect them you need to do the following:
match = _getch();
if (match == 27) //27 is the ASCII Code for the Escape Key
{
break;
}
OR Just Substitute 13 if you're looking for the Enter key. By adding A while(1) Loop around it, you can pause a program until that key is pressed (AND ignore all other input).
My Final Version of your Code can be viewed below:
#include<iostream>
#include<conio.h>
using namespace std;
int match = 0;
int win = 0;
int lose = 0;
int ratioo = 1;
int total = 0;
void lost()
{
if (match == 'L')
{
lose = lose + 1;
}
}
void won()
{
if (match == 'W')
{
win = win + 1;
}
}
int main() {
cout << "Welcome to winratio calculator!" << endl;
cout << "Pressing W adds one win point" << endl;
cout << "Pressing L adds one lose point" << endl;
cout << "Press ENTER to start" << endl;
cout << "Press ESC to close" << endl;
while (1)
{
match = _getch();
if (match == 13) //13 is the ASCII Code for the Enter Key
{
break;
}
}
while (1)
{
cout << "Last game score: ";
match = _getch();
if (match == 27) //27 is the ASCII Code for the Escape Key
{
break;
}
total++;
won();
lost();
ratioo = ((double)win / (double)total) * 100;
cout << "Games won: " << win << endl;
cout << "Games lost: " << lose << endl;
cout << "Ratio: " << ratioo << "%" << endl;
}
return 0;
}
Enjoy! And I wish you well towards learning C!
I apologize if this is in the wrong place. I didn't really see an area where to post specific code problems.
I'm tasked by my professor to create a program that allows a user to insert, edit and print out a database of clients. I'm having a problem with one of my functions, it doesn't seem to be comparing something well. The function is the EditClient function on line 85, the logic problem I'm having is on line 93. I included a few tests in the code that makes me certain it is line 93, for example in the else statement on line 99 I have it printing out the same arguments being used in the comparison. Which works! I'm clueless as to why it's not understanding the comparison.
#include <iostream>
#include <iomanip>
using namespace std;
struct ClientInfo{ // the structure template for the client info
char name[40]; //client name
char state[40]; //client state
char city[40];
int PhoneNumber;
long double AccountBalance; //accounts balance
char PaymentDate; //payment date
};
ClientInfo ClientList[10]; //intializes an array with the data type clientinfo
void MainMenu();
void NewClient(ClientInfo List[]); // prototypes
void ViewClient(ClientInfo List[]);
void EditClient(ClientInfo List[]);
int main(){
MainMenu();
system("pause");
}
void MainMenu(){ //this function is the main menu function
char choice = 4;
bool loop = true;
while (loop){
cout << "Welcome to the client database, enter 1 to view the clients, 2 to edit a client , and 3 to enter an entire new client. 0 to quit" << endl; //main menu prompt
cin >> choice;
if (choice == '1'){
ViewClient(ClientList);
}
else if (choice == '2'){
EditClient(ClientList);
}
else if (choice == '3'){
NewClient(ClientList);
}
else if (choice == '0'){
cout << "thank you for using the client database, closing out now" << endl;
loop = false;
}
else{
cout << "invalid number" << endl;
}
}
}
void NewClient(ClientInfo List[]){//function that goes through cins to insert client data
int desiredTimes = 0; // the number of clients the person wish to enter
cout << "how many clients are you entering ?, your list current has "<<endl;
cin >> desiredTimes;
cout << "entering new client function..." << endl;
for (int cnt = 0; cnt < desiredTimes; cnt++){ // runs the program exactly the amount of times the person wished.
cout << "please enter client name" << endl;
cin.ignore();
cin.getline(List[cnt].name, 40);
cout << "please enter client state" << endl; // the getline is used here because there may be spacings within these first 3 catagories
cin.getline(List[cnt].state, 40);
cout << "please enter client city" << endl;
cin.getline(List[cnt].city, 40);
cout << "please enter client Phone Number" << endl;
cin.ignore(); // this is used to prevent the getline from causing issues with the cin
cin >> List[cnt].PhoneNumber;
cout << "please enter client Account Balance" << endl;
cin >> List[cnt].AccountBalance;
cout << "please enter client Payment Date" << endl;
cin >> List[cnt].PaymentDate;
}
}
void EditClient(ClientInfo List[]){ // function to search for a name requested and display the info
char name[40];
cout << "what is the name of the client you wish to view (be specific)?";
cin >> name;
bool loop = true; // boolean for the loop
int cnt = 0; // position in the array
while (loop){
if (cnt < 11){
if (name == List[cnt].name){ //if true, prints out the client's info
cout << "true";
/*NewClient(List[cnt]);*/
loop = false; // ends the loop
}
else{
cout << name << " " << List[cnt].name << endl;
cnt++;
}
}
else{
cout << "your client isn't in the database M8" << endl;
loop = false;
}
}
}
void ViewClient(ClientInfo List[]){//this function goes through the client list and displays a particular client
cout << "the following is a huge overrun of all the data inside this list, prepare your self." << endl;
for (int cnt = 0; cnt <= 10; cnt++){//goes through until the counter is greater than the size of the list in the parameter
cout << endl;
cout << List[cnt].name;
cout << List[cnt].state;
cout << List[cnt].city;
cout << List[cnt].PhoneNumber;
cout << List[cnt].AccountBalance;
cout << List[cnt].PaymentDate;
}
}
this is the specific line, where i'm having a comparision error.
if (name == List[cnt].name){ //if true, prints out the client's info
if (name == List[cnt].name) is doing a pointer comparison, not a string comparison. This will only be true if name and List[cnt].name point to the same memory location, which they never will. You should probably be using std::string instead of char[], but if you need to use char[] for some reason, you'll need to use the strcmp() function to compare them.
instead of the if statement you are using, trying using this statement,
if (strcmp(name,List[cnt].name)==0){
It should work properly :)
#include <iostream>
using namespace std;
int main()
{
char num[10];
int a;
cout << "Odd or Even"<< endl;
for(;;)
{
cout << "Enter Number:" ;
cin >> num;
cout << endl;
for(a=9;a>=0;a--)
{
if(num[a]!='\0 && num[a]!=' ')
break;
}
if(num[a]==1 || num[a]==3 || num[a]==5 || num[a]==7 || num[a]==9)
cout << "Odd" << endl;
else
cout << "Even" << endl;
}
}
I am a rookie of C++,and I wrote a program to discriminate if a number is even or odd,
but no matter what number I enter, it only outputs "Even".
So I added these to find out when did the loop breaks:
cout << a << endl;
cout << "\"" << num[a] << "\"" << endl;
Result:
Enter Number:11
9
" "
Even
the for loop beraks when num[9]=' '? Which will lead to else and always output "Even".
You are confused about the character '1' and the number 1. They are different.
Instead of
if(num[a]==1 || num[a]==3 || num[a]==5 || num[a]==7 || num[a]==9)
you need
if(num[a]=='1' || num[a]=='3' || num[a]=='5' || num[a]=='7' || num[a]=='9')
Update
There is one more problems that is probably tripping you up.
num is not initialized. Zero-initialize it. Remember 0 is not the same as the character '0'.
char num[10] = {0};
Move the initialization of num inside the for loop. That will eliminate the problem of data from a previous execution of the loop from affecting the current execution of the loop.
Here's a version that works for me.
#include <iostream>
using namespace std;
int main()
{
cout << "Odd or Even"<< endl;
for(;;)
{
char num[10] = {0};
int a;
cout << "Enter Number:" ;
cin >> num;
cout << endl;
for(a=9;a>=0;a--)
{
if(num[a]!='\0' && num[a]!=' ')
break;
}
cout << num[a] << endl;
if(num[a]=='1' || num[a]=='3' || num[a]=='5' || num[a]=='7' || num[a]=='9')
cout << "Odd" << endl;
else
cout << "Even" << endl;
}
}
PS
You can replace the line
if(num[a]!='\0' && num[a]!=' ')
by
if(isdigit(num[a]))
That makes more sense to me.
If you are doing this with c++ there are much easier ways! Consider the following:
while (!done) {
string inputline;
getline(cin, inputline); //Now we have a string with the users input!
stringstream ss; // stringstreams help us parse data in strings!
int num; // We have a number we want to put it into.
ss >> num; // We can use the string stream to parse this number.
// You can even add error checking!
// Now to check for odd even, what do we know about even numbers? divisable by 2!
if (num % 2 == 0) // No remainder from /2
cout << Even << '\n'
else
cout << Odd << '\n'
}
see how you go with that!
Warning Untested code
You did a mistake (typo) here in this line..
if(num[a]!='\0 && num[a]!=' ')
it should be
if(num[a]!='\0' && num[a]!=' ')