I have a String stored as "word" (from another method) and want to compare it to the user input stored as String "guess". The progam prints out as needed and lets the user input but it doesn't read the input it seems. When the correct word is entered it still contiunes to go to the default on the switch case until the "i" value reaches 0 then it prints that case. I understand this may be a simple fix but I have Spent all night on this and would appreciate any help.
String word = chooseRandomWord(words);
int i = scrambledWord.length();
Scanner input = new Scanner(System.in);
System.out.println(i + " Points: What is your guess?");
String guess;
guess = input.next();
if (guess.equals(word)) {
System.out.println("Congragulitions! your score is " + i + " points");
System.out.println("the word was " + word);
System.exit(0);
}
if (!guess.equals(word)) {
while (i >= 0) {
switch (i) {
case 0:
System.out.println("sorry the word was " + word);
System.exit(0);
default:
i--;
System.out.println(i + " Points: what is your guess?");
guess = input.next();
}
}
}
else {
System.exit(0);
}
}
For each execution of
guess = input.next();
in the switch/case block, there's no checking whether the correct word was entered. As it is now, even if the correct word was entered the program just keeps looping until variable i reaches zero, all the while doing nothing with the received guesses.
Related
using namespace std;
int main(){
// Variable declarations
string hours = "";
double empHours = 0;
bool cont = true;
do{
// Get input of how much employee worked in a week.
cout << "Enter hours worked in a week: " ;
getline(cin, hours);
// Convert the input using string stream for easier validation.
stringstream hours_input(hours);
for(int i = 0; i <= hours[i]; i++)
// Check if input contains any alphabets e.g 90abc, if yes than repeat loop and ask user for input again.
if(isalpha(hours[i]))
cont = true;
// If the input successfully converts to double type
else if(hours_input >> empHours)
// Check if values are values >= 0, if yes than exit the loop
if(empHours >= 0){
hours_input >> empHours; // Assign value to empHours and exit loop
cont = false;
}
// Check if input contains special characters or any other form of bad input, if yes than repeat loop and ask user for input again.
else
cont = true;
}while(cont);
cout << "Value is: " << empHours << endl;
return 0;
}
This is what I have got so far. I am just not sure on how to display the error "That is not a valid option, please try again." and ask for input again. The code works however instead displaying the error mentioned, it displays "Enter hours worked in a week: ".
Simply, keep looping the error "That is not a valid option, please try again." and asking for input, until a valid input is provided.
The valid input should be any integer or float number >= 0.
Invalid inputs are any special characters, alphabets and any form of negative numbers.
You could just use a while loop.
It could go something like this:
while(true){
cin>>foo;
if(check if foo is a valid input){
break; //if the input is valid
}
cout<<"error, try again";
}
Currently, your code doesn't contain anything to print your error message. You already seem to be handling the error scenario though, so adding it isn't that hard.
If you change the else case in your for loop like this, it should work:
for(int i = 0; i <= hours[i]; i++)
// Check if input contains any alphabets e.g 90abc, if yes than repeat loop and ask user for input again.
if(isalpha(hours[i]))
{
cout << "That is not a valid option, please try again." << endl;
cont = true;
}
// If the input successfully converts to double type
else if(hours_input >> empHours)
// Check if values are values >= 0, if yes than exit the loop
if(empHours >= 0){
hours_input >> empHours; // Assign value to empHours and exit loop
cont = false;
}
// Check if input contains special characters or any other form of bad input, if yes than repeat loop and ask user for input again.
else
{
cout << "That is not a valid option, please try again." << endl;
cont = true;
}
You should however consider refactoring your code a bit to prevent some duplication. If you validate the input in a separate function for example, you can have one clear place of error handling instead of the duplication you have now.
I'm quite new to C++, having started learning over the summer.
For an assignment I am supposed to write a program that will extract records from an input text file.
However, the for loop I am using to display the contents of a vector never executes. I believe this is because the loop condition determines that the vector has zero elements, but I do not know why.
The program is designed to start off with a vector of length zero and populate it with "flightRecord" class objects as the program reads through the text file.
The vector is declared outside of main, and should thus be global, right? My impression is that any elements placed inside a global vector would remain until explicitly removed, or the vector goes out of scope.
If anyone can help me resolve this, it would be much appreciated!
Summarised code below:
fileOpener >> word;
while (fileOpener.good()) //As long as end of file not reached and the file is open
{
//std::cout << word << " "; //Put spaces between each word
fileOpener >> word; //Read the contents of the stream into char array word
if (fileOpener.get() != '\n') //if the current char is not equal to a newline
{
infoString.append(word);
std::cout << "infoString contains: " << infoString << std::endl;
}
else
{
std::cout << "Current char is a endline char." << std::endl; //For debug
}
}
//EOF Notification
if (fileOpener.eof() == true) //If the end of file has been reached
{
std::cout << "End of file reached." << std::endl; //Tell the user the EOF has been reached
}
// --------------------------------------------
// Text Processing
//while the end of file has not been reached
unsigned int i = 0; //Used for traversing the input string - unsigned to make compiler happy
while (i < infoString.size()) //While less than the total size of string - ERROR
{
if (infoString.at(i) == ',' || infoString.at(i) == '\n') //If the individual element of the string is a comma OR a newline (to delimit the last piece of info)
{
commaCounter += 1; //Add one to the current value when a comma is located
switch (commaCounter) //Test the value of the comma counter - corresponds to the different string variables in class
{
case 1:
tempFlightNum = infoString.substr(commaLocation, (i - commaLocation)); //Comma location is the starting point for the search --- (i-(commaLocation)) is the length of the substring
commaLocation = i; //Store the location of the comma while i continues to increase
break;
case 2:
//Subtracting one from i makes the substr shorter, thus exluding the last comma -- Also begin the substr at one past the comma location to exlude the first comma
tempOriginAirport = infoString.substr(commaLocation + 1, ((i - 1) - commaLocation));
commaLocation = i; //Update the comma location
break;
case 3:
tempDestAirport = infoString.substr(commaLocation + 1, ((i - 1) - commaLocation));
commaLocation = i; //Update the comma location
break;
case 4:
tempNumPassengers = infoString.substr(commaLocation + 1, ((i - 1) - commaLocation));
commaLocation = i; //Update the comma location
break;
case 5:
std::cout << "Comma counter currently 5" << std::endl; //Debugging notice
tempAvgPrice = infoString.substr(commaLocation + 1, ((i - 1) - commaLocation));
commaLocation = i; //Update the comma location
commaCounter = 0; //reset the comma counter to the starting position
break;
}
// When the end of the line is reached, append the temp variables to the appropriate member functions in the class instance
if (infoString.at(i) == '\n') //If a newline is encountered...
{
//Append the data to a new flightRecord instance in a vector
//Issue is that populating the vector is dependent on
// Problem - vector is out of scope after while loop is exited ****
flightVector.push_back(new flightRecord(tempFlightNum, tempOriginAirport, tempDestAirport, tempNumPassengers, tempAvgPrice)); //Need to delete at end to clear memory
std::cout << "testing - i is currently == to \n" << std::endl;
}
}
i++; //Increase the search index, whether comma or not
}
//Display
// --------------------------------------------
char continue_record = NULL; //If the user wants to display the next record
for (unsigned int i = 0; i < flightVector.size(); i++)
{
// Processing here - This loop does not execute
}
system("PAUSE");
return 0;
}
The vector code is fine, only the push_back is not getting called. When you are appending the values to infostring, '\n' is skipped.
I need help changing my current program so that it displays the letters already entered by the user, and displays the letters again immediately before prompting the user to enter another letter. what I have so far is below.
int main()
{
char another = 'Y';
string message = "";
while (toupper(another) == 'Y')
{
cout << "Enter a message: ";
getline(cin, message);
for (int x = 0; x < message.length(); x += 1)
cout << message.substr(x) << endl;
cout << endl << "Another message (Y/N)? ";
cin >> another;
cin.ignore(100, '\n');
}
system("pause");
return 0;
}
If you want all the characters (you entered at any time) printed, you can do the following:
Start off with two empty strings. One is a buffer, that stores the string that's currently added and the other holds all of the strings already added, like so:
string buf = "";
string messages = "";
Read your characters into your buffer, via:
getline(cin, buf);
Append the string to the other messages, already entered:
messages.append(buf);
Append a string delimiter to your messages, so you know which sequence of characters (including whitespaces) belong to the message you entered:
messages.append(";");
(BTW: Using "-quotes here is really important, to let the compiler know you are comparing strings, not characters, as there is no string::append(char s)-method defined, only string::append(string s).)
Iterate through your messages-string, and check if the character at position x is equal to ';' (Using '-quotes here is also important, because string::operator[] return a character not a string!!!). For instance you might code:
for (int x = 0; x < messages.length(); x++) {
//Test if string delimiter is reached, if so, jump to next line.
if(messages[x] == ';') {
std::cout << "\n";
}
//Else just print the string:
else {
std::cout << messages[x];
}
}
Test if another message should be entered.
OR you create a linked list of strings. Adding new strings to the list, every time you enter a new string. This might be the more elegant way to do this, however it is slightly more involved. (I'm assuming you're fairly new to programming, if not I apologize!). Check Wikipedia or cplusplus.com for more info on linked lists!
Hope I could answer your question,
lindebear
I have been trying to fix this program for the past two days and it is proving to be quite troublesome. It is an assignment for my intro to C++ course and has given me nothing but trouble. I have searched this board, posted on Cplusplus.com and spent hours on Google, looking for some assistance.
Here is my problem. I have been given a program and need to add a few features to it:
I have to save the users entries.
I have to display an error message if the user enters the same entry twice.
Seems simple? Not for a beginner such as myself. Here is the code, with what I have attempted to add to it in order to meet the problem's requirements.
int main()
{
//declare variables
string origWord = "";
string letter = "";
char dashReplaced = 'N';
char gameOver = 'N';
int numIncorrect = 0;
string displayWord = "-----";
string letterGuess[26];
//get original word
do //begin loop
{
cout << "Enter a 5-letter word in uppercase: ";
getline(cin, origWord);
} while (origWord.length() != 5);
//clear the screen
system("cls");
//start guessing
cout << "Guess this word: " <<
displayWord << endl;
while (gameOver == 'N')
{
cout << "Enter an uppercase letter: ";
cin >> letter;
//Entry Storage and Error Message. This is my problem.
for (int x = 0; x < 26; x++)
{
letterGuess[x] = letter;
for (int i = x; i < 26; i++)
{
if (i != x)
{
if (letterGuess[x] == letterGuess[i])
{
cout << "Letter already entered. Choose another letter."
<< endl;
}
}
}
}
//search for the letter in the original word
for (int x = 0; x < 5; x += 1)
{
//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'
{
//add 1 to the number of incorrect guesses
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
My only edit to the program is directly under the header of Entry Storage and Error Message. I have tried a single for loop, but that simply displayed the error message for every letter entered. Not only that but it displayed it 26 times. Adding a Break command fixed that and it only displayed once. However, it still displayed on every entry.
A member of Cplusplus, pointed out that I was incorrectly testing the same variable against the array in the same location. That is why it displayed the error on every entry. Now with this loop, the error only displays when an entry is entered twice. However, the error message displays all 26 times once more. On top of that, it will only error if the letters are entered one after another.
For example, if I enter A then X then A again, no error is shown. If I enter, A then A again, the error is displayed 26 times. Something is clearly wrong with how the letter variable is being entered into the array on top of the whatever is causing the error message to display multiple times.
Any amount of assistance would be greatly appreciated.
Edit: My professor has gotten back to me and suggested using the following instead of what I have been tinkering with:
for (int x=0; x<5; x++)
if (origWord[x] == letterEntered)
origWord[x] = '-';
Is it just me, or does this miss the mark completely? I haven't tried converting it into my program as a simple copy and paste job produces compile errors. However, I don't see how that does anything with what I'm trying to do.
This set's all entries of your letterGuess array to the most recently guessed letter.
letterGuess[x] = letter;
This isn't what you want.
You need to think about the actual algorithm you need to implement:
The user enters a guess
Check to see if they've already guessed that letter
If they have, display an error message, return to 1.
If they have not, save that guess, continue with the game logic.
If you have already learned about standard containers, this can be trivially done with a std::set, or a std::vector that has been sorted.
You need to compare each element in the array to the guessed word. Best use a for loop for this. No more needs to be said if this is an assignment.
Also don't use system("cls") in your program, it is a massive security flaw and may lose you marks.
This is just a basic palindrome tester for my C++ class, and there appears to be issues.
I already know that I have two separate flaws in here somewhere. At least one, I strongly suspect, is a logic issue. The first problem is that it runs fine the first time through, but when the loop initiates, it doesn't ask for user input to put in a new line to test as a palindrome, it simply retests the old one. The second issue is, I assume, that it is testing spaces, which I base off the fact that it's giving 'hannah' back as good, but 'never even or odd' comes back bad. This one I just don't know how to fix.
#include <iostream>
#include <string>
using namespace std;
int main()
{
bool repeater = true;
do
{
string palindroneCheck;
bool palindronity = true;
cout << "Please enter a line to test for palindromity.\n";
getline(cin, palindroneCheck);
int stringSize = palindroneCheck.size();
int cutOff = stringSize/2;
for (int palindroneLength = 0; palindroneLength < cutOff; palindroneLength++)
{
if (palindroneCheck[palindroneLength] != palindroneCheck[stringSize - palindroneLength -1])
{palindronity = false;
break;}
}
if(palindronity == true)
cout << "Congratulations! This line is a palindrone!\n\n";
else
cout << "Sorry, but this is not a palindrone.\n\n";
palindroneCheck.clear();
char repeat;
cout << "Would you like to try another line? Y/N\n";
cin >> repeat;
if (repeat == "n" || repeat == "N")
repeater = false;
} while (repeater == true);
}
OK, you are right about the spaces. Your code will demand that spaces are in the same location like every other character.
The other bug seems more subtle: it's where you ask to repeat or not.
Why? Because it asks, you enter 'n' and then 'enter'
The cin >> repeat only reads the 'n', but not the 'enter'
so the next time you do `readline(cin,PalindromCheck)' it will read an empty string.
Try to write palindromCheck just after reading it. You'll see.
The reading issue of getline is solved by comments. For the whitespaces, you can tackle it by removing all the spaces inside string palindroneCheck,
std::string::iterator new_end = std::remove(palindroneCheck.begin(), palindroneCheck.end(), ' ');
std::string palindroneCheckWithoutSpaces(palindroneCheck.begin(), new_end);
Then you use palindroneCheckWithoutSpaces to do the Palindrone test.
int stringSize = palindroneCheckWithoutSpaces.size();
int cutOff = stringSize/2;
for (int palindroneLength = 0; palindroneLength < cutOff; palindroneLength++)
{
if (palindroneCheckWithoutSpaces[palindroneLength] != palindroneCheck[stringSize - palindroneLength -1])
{palindronity = false;
break;}
}
if(palindronity == true)
cout << "Congratulations! This line is a palindrone!\n\n";
else
cout << "Sorry, but this is not a palindrone.\n\n";
(you need header algorithm to use remove)
Update:
std::remove remove an element from the input range (this is defined by begin and end here) based on the value you passed in , here is the whitespace ' '. Then it return the new end of the changed range (since you delete something, the range becomes smaller). The new range starts with begin and ends with the returned value.
So the second line you create a new string based on the new range.