Troubleshooting my c++ programs - c++

I've got these 2 programs for the current chapter in my C++ class that I cant seem to get to work and I dont understand why.
The first project requests
"Create a program that displays the appropriate shipping charge based on the zip code entered by the user. To be valid, the zip code must contain exactly five digits and the first three digits must be either “605” or “606”. The shipping charge for “605” zip codes is $25. The shipping charge for “606” zip codes is $30. Display an appropriate error message if the zip code entered is invalid. Use the sentinel value “X” to end the program."
#include <iostream>
#include <string>
using namespace std;
string zipCode = "";
string zip = "";
int main() {
cout << "ENTER AN X TO STOP ZIP CODE DATA ENTRY." << endl << endl;
cout << "Enter Zip Code: ";
getline(cin, zipCode);
while (zipCode != "x")
{
if (zipCode.length() == 5)
{
if (zipCode.find("605", 0))
{
cout << "Shipping charge is $25" << endl;
}
else if (zipCode.find("606", 0))
{
cout << "Shipping charge is $30" << endl;
}
else
cout << "Invalid Zip Code.";
}
else
{
cout << "Zip code must contain exactly 5 digits." << endl;
}
cout << "Enter Zip Code: ";
getline(cin, zipCode);
}
cout << endl << "End of Program.";
return 0;
}
I tried a similar structure for the second program and cant get it to work properly either.
Create a program that displays the color of the item whose number is entered by the user. All item numbers contain exactly seven characters. All items are available in four colors: blue, green, red, and white. The fourth character in the item number indicates the item number, as follows: a B or b indicates Blue, a G or g indicates Green, a R or r indicates Red, and a W or w indicates White. If the item number is not exactly seven characters display the appropriate error message. If the fourth character is not one of the valid color characters, display the appropriate error message. Use the sentinel value “X” to end the program.
#include <iostream>
#include <string>
using namespace std;
string itemCode = "";
int main() {
cout << "ENTER AN X TO STOP ITEM NUMBER DATA ENTRY." << endl << endl;
cout << "Enter Item Number: ";
getline(cin, itemCode);
while (itemCode != "x")
{
if (itemCode.length() == 7)
{
if (itemCode.find("B", 3) == "B")
{
cout << "Color is blue." << endl;
}
else if (itemCode.find("G", 3) == "G")
{
cout << "Color is green." << endl;
}
else if (itemCode.find("R", 3) == "R")
{
cout << "Color is Red." << endl;
}
else if (itemCode.find("W", 3) == "W")
{
cout << "Color is White." << endl;
}
else
cout << "Invalid color code found in item number.";
}
else
{
cout << "Item number must contain exactly 7 characters." << endl;
}
cout << "Enter Item Number: ";
getline(cin, itemCode);
}
cout << endl << "End of Program.";
return 0;
}

From glancing at your code, two obvious problems come to mind that's likely the source of your issues:
You're not checking if getline successfully grabbed the input.
Your usage of string::find's return value is wrong. You need to check for std::npos to see if there's a match or not. See here if you need more details.
For your first problem, you want something like:
while (getline(cin, zipCode) && zipCode != "x")
// ...
And removing the other getlines.
For the second, your usage should look something like:
if (zipCode.find("605", 0) != string::npos)
// ...
Your current if (zipCode.find("605", 0)) does not work because anything other than 0 or false is considered truthy. std::string::npos is typically defined as -1 which means the expression is true if the zipCode isn't found -- the opposite of your desired behavior.

Related

How can I add numbers before my output here?

I'm working on a C++ program for my class and I'm unsure about a specification. I want to add numbers before the output of string orderCode but am unsure how to do this. For example, output for the input "BF12" would be "12 Black Forest cakes." I am trying to include the number and amount of cakes into one single string variable. Could anyone offer me some pointers? Anything would be very much appreciated.
Here is my code:
#include <iostream>
using namespace std;
int main() {
string orderCode;
string repeat = "y";
while ("y" == repeat) {
cout << "\nWelcome to the Great Cake company!\n";
cout << "\nEnter the cake order code: ";
cin >> orderCode;
int quantity = orderCode.length() - 1;
if (orderCode == "BF2")
{ (cout << orderCode.substr(quantity) << " Black Forest cakes");
}
if (orderCode == "CC")
{ (cout << "Carrot cakes");
}
if (orderCode == "CM")
{ (cout << "Chocolate Mint cakes");
}
if (orderCode == "DF")
{ (cout << "Devil's Food cakes");
}
if (orderCode == "GC")
{ (cout << "German Chocolate cakes");
}
if (orderCode == "PC")
{ (cout << "Pumpkin Cheesecakes");
}
if (orderCode == "RC")
{ (cout << "Rum cakes");
}
if (orderCode == "T")
{ (cout << "Tiramisu cakes");
}
cout << "\nOrder more? (y/n) ";
cin >> repeat;
}
return 0;
}
You want to parse the user input, assuming the digit will always be after the letters and assuming the digit is a decimal (thus not counting ABCDEF as part of the digit).
string orderCode = "BF12";
size_t last_index = orderCode.find_last_not_of("0123456789");
string result = orderCode.substr(last_index + 1);
result += " Black Forest cakes";
cout << result << endl;
Meanwhile for your switch case you still need to erase the digit part of the input.
orderCode.erase(last_index+1);
You can then compare to orderCode
You need to omit BF and exctract the number. Since BF has length of 2, you need to print the rest:
cout << orderCode.substr(2, quantity) << " Black Forest cakes"
Meanwhile, your switch case does not make any sense.

Conditional cin giving stacked cout messages

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.

How to keep track of letters already guessed in Hangman game for C++?

This assignment given to me was to copy a Hangman game from our textbook and modify it to specific instructions in the book. I have spent a lot of hours trying to research this issue and find a reason why I keep getting the same error message that I do. Everywhere I have looked, everyone that have attempted to modify this code have attempted with arrays and have had the same luck that I have. I'm currently doing a chapter in Strings and was planning on doing most of my statement that is requested by the instructions in String.
What I need to modify in this code is to:
Keep track of all letters that are input by the user
Send an error message to the user if they input a letter that is already entered
The main issue I am having is that when I compile this code and put in the same letter that I have already put in, it terminates with the message:
terminate called after throwing an instance of 'std::out of range'
what(): basic_string::substr
#include <iostream>
#include <string>
using namespace std;
int main()
{
//declare variables
string origWord = " ";
string letter = " ";
char dashReplaced = 'N';
char gameOver = 'N';
int numIncorrect = 10;
string displayWord = "-----";
string usedLetter = " ";
string letterNotGuessedYet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int letterPlace = 0;
//get original word
do //begin loop
{
cout << "Enter a 5-letter word in uppercase: ";
getline(cin,origWord);
}while(origWord.length() != 5); //end do loop
//clear the screen
system("cls");
//start guessing
cout <<"Guess this word: " << displayWord << endl;
while(gameOver =='N')
{
cout << "Enter an uppercase letter: ";
cin >> letter;
//This provides the letterPlace value with the possition of the
//input letter by the user within letterNotGuessedYet
letterPlace = letterNotGuessedYet.find(letter,0);
//This statement determines if the letter input by the user is
//still in the letterNotGuessYet string.
if(letterNotGuessedYet.substr(letterPlace,1)== letter)
{
letterNotGuessedYet.replace(letterPlace, 1, "*");
//cout << endl << letterNotGuessedYet; //This tests that a letter is being replaced with an *
}
else
{
cout << "The letter " << letter << " has already been used. Choose another letter." << endl << endl;
}// end if
//search for the letter in the original word
for(int x = 0; x < 5; x++)
{
//if the current character matches
//the letter, replace the corresponding
//dash in the displayWOrd variable and then
//set the dashReplaced variable to 'Y'
if (origWord.substr(x,1) == letter)
{
displayWord.replace(x, 1, letter);
dashReplaced = 'Y';
}//end if
}//end for
//if a dash was replaced, check whether the
//displayWord variable contains any dashes
if (dashReplaced == 'Y')
{
//if the displayWord variable does not
//contain any dashes, the game is over
if (displayWord.find("-",0) == -1)
{
gameOver = 'Y';
cout << endl << "Yes, the word is " << origWord << endl;
cout << "Great guessing!" << endl;
}
else //otherwise, continue guessing
{
cout << endl<< "Guess this word: " << displayWord << endl;
dashReplaced = 'N';
}//end if
}
else //processed when dashReplaced contains 'N'
{
//minus 1 to the number of incorrect gueses left
numIncorrect += 1;
//if the number of incorrect guesses is 10,
//the game is over
if (numIncorrect == 10)
{
gameOver = 'Y';
cout << endl << "Sorry, the word is " << origWord << endl;
}//end if
}//end if
}//end while
//system("pause");
return 0;
}//end of main function
I believe the reason that I'm receiving this error has something to do with the below code:
//This provides the letterPlace value with the possition of the
//input letter by the user within letterNotGuessedYet
letterPlace = letterNotGuessedYet.find(letter,0);
//This statement determines if the letter input by the user is
//still in the letterNotGuessYet string.
if(letterNotGuessedYet.substr(letterPlace,1)== letter)
{
letterNotGuessedYet.replace(letterPlace, 1, "*");
//cout << endl << letterNotGuessedYet; //This tests that a letter is being replaced with an *
}
else
{
cout << "The letter " << letter << " has already been used. Choose another letter." << endl << endl;
}// end if
I am grateful for any assistance that you can bring my way.
The reason you're getting the error is because you are using the "letterPlace" value before you test to see if it was actually found or not. If "string::find" doesn't find anything it will return a value "string::npos". You need to test the letterPlace vairable for this value before trying to use it.
letterPlace = letterNotGuessedYet.find(letter,0);
// Check to see if this letter is still in the "letterNotGuessedYet string
if(letterPlace != string::npos)
{
// At this point the letter is in the letterNotGuessedYet string so let it go
letterNotGuessedYet.replace(letterPlace, 1, "*");
}
else
{
// The letter was not found which means it has already been guessed.
// Show error to the user here
cout << "The letter " << letter << " has already been used. Choose another letter." << endl << endl;
}

Menu Structure and Loops

I have this little program I am creating. In lamens terms, I am wanting to make a menu where a user can input his selection, it takes him to the predetermined area and after he is done it takes him back to the menu where he can make a different selection. I have gotten down where it displays when you press 1 (you will see what i mean with the code). But after it goes through what it is supposed to do, it doesn't go back to the menu it just continues on to the second option. Also say you are at the menu and you want to start with the 2nd option it just starts with the first. Can anyone please help me with this...
#include <iostream>
using namespace std;
int main()
{
int option;
cout << "Hello there...\n\nToday we are going to do a little fun project that I created.\n\n";
cin.get();
cout << "\nAs we progress throughout this program, I will explain the different things\n";
cout << "that we are going to do. We will be covering some basic C++ excersises.";
cout << "\n\nFirst and foremost we will begin by covering what I have learned so far....\n\n";
cin.get();
cout << "The first topic we will cover will include what is known as 'variables'.\n";
cout << "what are variables you ask?";
cin.get();
int var = 1;
int main=1;
do
{
cout << "\n\n\nEnter the number of one of the following and I will explain!\n";
cout << "1.integer 2.boolian 3.floats 4.doubles 5.character";
cout << "\n\n[when you are done type 'done' to continue]\n\n";
cin >> option; //this is where the user puts in his option (1,2,3,4,5,6) I have only 1 and 2 complete
if (option = 1) //starts with this regardless of input
{
cin.ignore();
cout << "\n\n\nInteger is the variable abbreviated as 'int' this allows C++ to only";
cout << "\nread whole and real numbers. C++ takes this number as stores it\n";
cout << "in a user-defined variable (you can make up what that variable is..)\n";
cin.get();
cout << "an example syntax would be:";
cout << "\n\nint var=[whole;real number]";
cin.get();
cout << "\n\nwhat this implies is that you have 'declared' to the system";
cout << "\nthat you are going to use an 'int' that you have named 'var'\n";
cout << "and in this 'var' you are going to store a real and whole number\ninside of it.";
cout << "\n\nPress any key to go back to menu";
cin.get();
}
else if (option = 2); //continues with this without going back to menu.
{
cin.ignore();
cout << "\n\n\nBoolian is the variable abbreviated as 'bool' this allows C++ to only";
cout << "\nread true or false ( 0 or 1 ). C++ takes this number as stores it\n";
cout << "in a user-defined variable (you can make up what that variable is..)\n";
cin.get();
cout << "an example syntax would be:";
cout << "\n\nbool var=[true or false]";
cin.get();
cout << "\n\nwhat this implies is that you have 'declared' to the system";
cout << "\nthat you are going to use an 'bool' variable that you have named 'var'\n";
cout << "and in this 'var' you are going to store a either a true or false\ninside of it.";
cout << "\n\nPress any key to go back to menu";
cin.get();
}
} while (var = 1);
}
The problem lies with the comparison operator
1) if (option = 1) , use if(option == 1)
2) else if (option = 2); , use else if(option == 2) , remove the semicolon
3) while(var = 1) ; , use while(var ==1 );
comparision in C++ is done with the == operator:
e.g.
if (option == 1)
if (option == 2)
while (var == 1);

On finding vowels and capitals char in the beginning of a string?

I've been making a little memory game as an exercise from a textbook I'm doing. It's called Grandma's trunk and it works by in one turn you found an item in the trunk and the next turn you say you found the previous item and the newest item on this turn...I think.
Mostly it's an exercise on using functions, which I think I've gotten down pretty well. But my output is completely wrong. I've believe I've located the problem in one function where I'm supposed to analyze the first character and decided if it needs an AN or A or THE before the string. There might be a problem with the random function I'm using to throw in predefined items from a small database. The int main() function is supposed to be relatively complete, this is just an exercise to master functions...which I, sorta? Would rather call it novice experience.
I thought that perhaps I was running into the getline bug where it couts a blank line, and from my understanding, is fixed by cin.ignore(); but all that did was force me to press enter twice when I enter data. Which...I sort of like. Perhaps I'm using gizmos like isupper and .at() wrong? I tried using find_first_of but it didn't really change anything.
output calling the storage trunk and the owner grandma and just using word1 word2 word3... wordn....as items found leaves me with the output.
In grandma trunk you've found a
and an ord3 word1.
it completely muddles up the output. I'm starting to think that the int main() body I was given wasn't exactly stellar. But I can't be 100% confident in my article function. Any help would just be incredible. I've been struggling using this among many books and advice from a buddy to teach myself a little about programming. It's been a rather huge headache.
program itself
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
using namespace std;
string CorrectArticle(string phrase);
string GetPhrase(void);
bool Continue(void);
string UpperCase(string);
string RandomItem(void);
const string PUNCTUATION = ".";
int main(){
//Variables
int turn;
bool flag;
string phrase,
article,
story, item,
storage, owner;
srand(time(NULL));
cout << "Welcome to Grandmother's Trunk 9000" << endl;
cout << "This is a memory game. Each turn a player" << endl;
cout << "Says an item to place inside a trunk. " << endl;
cout << "And the next player has to say what the " << endl;
cout << "previous player said plus his/her own item." << endl;
cout << "This will go around in revolving turns." << endl;
cout << endl << endl;
cout << "But Grandma's Trunk is a little dry..." << endl;
cout << "Let's change what the storage is and " << endl;
cout << "Who owns it." << endl << endl;
//define storage variable
cout << "What exactly is this storage?" << endl;
getline (cin, storage);
cout << "So the items are stored in " << storage << endl;
cout << endl;
//define owner
cout << "Who owns this " << storage << " ?" << endl;
getline (cin, owner);
cout << "The owner is " << owner << endl;
story = "In "+ owner + " " + storage + " you've found ";
turn = 0;
flag = Continue();
//While flag is true
while (flag) {
if (turn %2 == 0) {
item = GetPhrase();
} else {
item = RandomItem();
}
//set corrected item to article
article = CorrectArticle(item);
//advance the story every item
story = story + "\n and " + article + " " + item;
cout << story << PUNCTUATION << endl;
turn++;
flag = Continue();
}
return (0);
}
//Gives A, AN, and THE to correct words
// An if phrase starts with i,e,i,o,u or y
// A if phrase starts with other lower case letters
// The for phrases that start with an uppercase letter
string CorrectArticle(string phrase){
int i=0;
string correctedString;
string stringAn;
string stringA;
string stringThe;
stringAn= " an ";
stringA = " a ";
stringThe= "The ";
if (GetPhrase().at(i) = "a" or "e" or "i" or "u"){
correctedString = stringAn + GetPhrase();
}else if (isupper(GetPhrase().at(i))){
correctedString = stringThe + GetPhrase();
}else{
correctedString = stringA + GetPhrase();
}
return correctedString;
}
//This function takes no parameters
//and returns the user's input
string GetPhrase(void){
string itemInput;
cout << "\nWhat did you find? \n" << endl;
getline (cin, itemInput);
cout << "\nYou found " << itemInput << endl;
cin.ignore();
return itemInput;
}
//Asks user if they wish to continue
bool Continue(void){
//return false if no, true if yes
string continueString;
cout << "Would you like to continue?";
cout << " Yes or No would suffice" << endl;
getline(cin,continueString);
UpperCase(continueString);
cout << "You picked " << continueString;
if (UpperCase(continueString).find("NO") != string::npos){
return false;
} else if (UpperCase(continueString).find("YES") != string::npos){
return true;
}
}
//Changes the string to uppercase
string UpperCase(string stringUpper){
int i = 0;
while (i<stringUpper.size()){
stringUpper[i] = toupper(stringUpper[i]);
i++;
}
return stringUpper;
}
//Randomizes items found in game
string RandomItem(void){
int randomNumber;
int maxNumberOfItems = 5;
string randomizedItem;
randomNumber= rand() % maxNumberOfItems;
switch (randomNumber){
case 0:
randomizedItem = "Smaug";
break;
case 1:
randomizedItem = "Batman";
break;
case 2:
randomizedItem = "Yoda";
break;
case 3:
randomizedItem = "Paul Atreides";
break;
case 4:
randomizedItem = "Captain Kirk";
break;
default:
cout << "ERRORRRR! PANIC!" << endl;
}
return randomizedItem;
}
Remember that = is assignment, == for compare.
Also remember that you have to compare variable with value, such as:
if ((string == "a") or (string == "e") ...
If the or works for you, all the best. I've only been able to use ||. Must be compiler conformity issues.
Try this:
bool is_vowel(char letter)
{
const std::string vowels("aeiouAEIOU");
return (vowels.find_first(letter) != std::string::npos);
}
In other words, I place all the vowels in a string a search the string. If there is a match, the letter is a vowel.