I wrote a console program to help me test a function library I coded. Part of it is this piece of code:
char insertChoice[2] = {'9'};
while (insertChoice[0] != '0')
{
cout << "\nEnter a string:\n";
char insertStringInput[256];
cin.getline(insertStringInput, 255);
char insertChoice[2];
insertChoice[0] = '9';
cout << "\nWhere would you like to insert the substring?\n\n
1) At the beginning of the string\n
2) At the end of the string\n\nInput: ";
cin >> insertChoice;
cin.ignore();
while (insertChoice[0] != '1' && insertChoice[0] != '2')
{
cout << "\nInvalid input.\nWhere would you like to insert the substring?\n\n
1) At the beginning of the string\n
2) At the end of the string\n\nInput: ";
cin >> insertChoice;
cin.ignore();
}
cout << "\nEnter the substring you would like to insert: ";
char insertSubstring[256];
cin.getline(insertSubstring, 255);
std::string used = "", substr = "";
used += insertStringInput;
substr += insertSubstring;
char insertOutputChoice[2];
insertOutputChoice[0] = '1';
if (insertChoice[0] == '1')
insertOutput(insertInBeginning(used, substr));
else
insertOutput(insertInEnd(used, substr));
cin >> insertOutputChoice;
cin.ignore();
if (insertOutputChoice[0] == '1')
{
ofstream outfile("logfile.txt", ios::app);
outfile << "Test type: Insert Substring\n";
outfile << "Test carried out on: " << __DATE__ << "; " << __TIME__ <<"\n";
outfile << "PARAMETERS:\n";
outfile << "usedString: \"" << insertStringInput << "\"\n";
outfile << "insertString: \"" << insertSubstring << "\"\n";
outfile << "function used: "
<< (insertChoice[0]=='1'?"insertInBeginning":"insertInEnd")
<< "\nOUTPUT:\n";
outfile << "\""
<< (insertChoice[0]=='1'?insertInBeginning(used, substr):insertInEnd(used, substr))
<< "\"\n\n";
outfile.close();
cout << "\nWould you like to do another string insertion test? [y/n]: ";
char insertConfirm[2];
insertConfirm[0] = ' ';
while (tolower(insertConfirm[0]) != 'y'
&& tolower(insertConfirm[0] != 'n'))
{
cin >> insertConfirm;
cin.ignore();
if (tolower(insertConfirm[0]) != 'y'
&& tolower(insertConfirm[0] != 'n'))
cout << "\nInvalid input.
Would you like to do another string insertion test? [y/n]: ";
}
if (insertConfirm[0] == 'n')
insertChoice[0] = '0';
}
}
However, the while (insertChoice[0] != '0') loop does not exit when the user types in insertOutputChoice as 1, regardless of whether the user types in insertConfirm as y or n even though it is supposed to exit when insertConfirm is typed in as n.
insertOutput looks as looks as follows:
void insertOutput(std::string substrOut)
{
cout << "\nThe new string generated is:\n";
cout << substrOut;
cout << "\n\n1) Generate a log file of this test\n";
cout << "2) Insert another substring into a string\n\n";
cout << "0) Finish testing string insertion\n\n\n";
cout << "Input: ";
}
Please excuse the messy, unoptimized code. My first priority is to get this done, and I usually leave optimization until last.
Inside the while loop you create a new insertChoice array. And it hides external one. So when you modify values in this array, external one remains unmodified.
I think there may also be an issue with the if statement at the end of the code. Have you tried this while inputting in both upper and lower case? When checking for a valid input you are converting to lowercase to check but not when checking if the response is 'n'.
Remove line 9:
char insertChoice[2];
There are a lot of errors in your code, are you sure it's compiling correctly?
First, there are 2 insertChoice declarations
char insertChoice[2] = {'9'}; // <------- 1ˢᵗ
and in the while loop:
char insertChoice[2]; // <------- 2ⁿᵈ
insertChoice[0] = '9';
The compiler should warn you about that. If not you must enable warnings with the appropriate options of your compiler (/W3 for cl, -Wall -Wpedantic for gcc...). Never compile without warnings
Second, the following string has syntax error
cout << "\nWhere would you like to insert the substring?\n\n
1) At the beginning of the string\n
2) At the end of the string\n\nInput: ";
If you want a line break in the string you must use an escape right before the new line character
cout << "\nWhere would you like to insert the substring?\n\n\
1) At the beginning of the string\n\
2) At the end of the string\n\nInput: ";
or use multiple string literals like this
cout << "\nWhere would you like to insert the substring?\n\n"
"1) At the beginning of the string\n"
"2) At the end of the string\n\nInput: ";
Consecutive literals will be automatically combined into one by the compiler
In C++-0x life is a lot easier with raw string literals where embedded quotes or newlines are possible
cout << R"(
Where would you like to insert the substring?
1) At the beginning of the string
2) At the end of the string
Input: )";
Related
I'm trying to create a command menu where the user will be able to perform as many commands as he/she wants until pressing "q" which will end the loop. I think I have everything I need to do this except I realized mid-way that my professor asked to use string. When I included string into the program, I began to get error messages saying "could not convert string to bool" wherever there was a while or if statement. What can I do to fix this problem and get my program working. Thanks in advance.
#include <iostream>
#include <string>
using namespace std;
int main()
{
char option;
char number=0;
string s;
string n;
string p;
string q;
char number2;
cout << " Please enter a number: "<< endl;
cin >> number;
do {
cout << " Please enter a command: " << endl;
cout << " s- square the number " << endl;
cout << " n- add the number and (number +1) " << endl;
cout << " p- add the number and (number -1) " << endl;
cout << " q- quit" << endl;
cin >> option;
if (option=s) {
s= number*number;
cout << "Square of this number is : " << s;
}
else if ( option=n){
number2= number+1;
n= number+number2;
cout << "Sum of" << number << "+" << number2 << "is: " << n;
}
else if (option=p) {
number2= number-1;
p= number+number2;
cout << "Sum of" << number << "+" << number2 << "is" << p;
}
else if (option=q)
cout << "Terminating Program";
} while(option);
return 0;
}
you're assigning in the if and else if rather than comparing.
if (option=s) {
should be
if (option=='s') {
note the double =
Also, you need to put single quotes (') around the character choice.
It's a common mistake that even experienced developers make.
These declarations
char number=0;
string s;
string n;
string p;
string q;
char number2;
should all be int
int number=0;
int s;
int n;
int p;
int q;
int number2;
Let me answer as if I were who will evaluate your homework. You have several issues here:
You are asked to use string. Avoid the use of char and string together.
char option; // professor asked to use string: (-1) point
string option; // ok
When you use a single =, like in option="a", you are assigning the value "a" to the variable option. But in the if-else statements you want to compare, so you should use the == comparison operator. Also, you can't compare a char with a string.
if(option = "a") // error: expression must have bool type: (-2) points
if(option == 'a') // error: no operator "==" matches std::string == char; (-2) points
if(option == "a") // ok
You use while(option), but option is declared as a char, not as a bool. Replace this line to while(option!="q") to finish when you enter q.
while(option); // error: expression must have bool type; (-2) points
while(option != "q"); // GOOD!
Also, your program will finish when you scape from the while-statement; so, try to put the "Terminating Program" message after this.
You do not need to declare such many variables (s, n, p, q, number2). Try to use temporary variables inside each scope, for example:
if (option=="s")
{
cout << "Square of this number is : " << number*number << endl;
}
else if ( option=="n")
{
int number2= number+1;
cout << "Sum of " << number << "+" << number2 << " is : " << number+number2 << endl;
}
In the form you write this code, every time you type a new option you will obtain an output like:
Sum of 10+11 is : 21 Please enter a command:
This is ugly to me (-1 point). Try to put a newline (<< endl;) after every cout lines.
Finally, what if I type any other letter not listed in the menu? I would expect a message like Enter a valid option (-1 point).
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.
Look, i have been writing this guessing game for a day and a half now. I keep getting errors related to using cin and getline together, and using a lot of advice I received from Stackoverflow, I thought I fixed all the bugs. Also, I realize it's best not to use >> and getline together, but to be honest, I don't know any other way, and I am afraid I will lose points if I use features of the language that our professor hasn't specifically taught us. So please just help me out, I have been ocd-ing like a maniac.
The game works correctly, and the game repeats, (I also know that using goto is evil, but this is just a very basic guessing game. I pinky promise not to ever use it in real life)
The problem arises when the game repeats a second time. After the game prompts the user to enter Y to continue, and they do, it will goto the start of my do-while loop, as it should. Stack unwinding be damned.
Next, it will read in the user input, ignoring white space at the stare of cin. But somehow, white space hops in at the end of my word after a few runs? I am baffled by this, as I thought that my loop which tests each index using the isalpha function would prevent this?
I could really use some concrete code to fix this, I have been up all night. Suggestions are fine but I don;t fully understand them and I am not allowed to use a good chunk of this languages features. Yes, I realize that is ridiculous, but I'm not my professor.
Here is a screenshot of the logical error:
Here is my code so far: You can read some of my comments to see the different paths this beast has been down:
#include<iostream>
#include<string>
#include <algorithm>
#include <iostream>
#include <string>
#include <functional>
#include <ctype.h>
using namespace std;
int main() {
string secretWord;
string secretWordClean = "";
string guessedLetters; //to be loaded with _ characters equal to length of secretWord
string incorrectlyGuessedChars = "";
char individualCharGuess;
char playAgain;
size_t countOfLetters = 0; //begine count at 0
size_t guessesRemaining;
int guessedUsed;
begin_game://label which we can use to bring us back to the start of the do-while loop at any time
//do{//start of the game
cout << "Please enter a secret word: ";
std::cin >> std::ws;
getline(std::cin, secretWord);
secretWord.erase(std::remove_if(secretWord.begin(), secretWord.end(), std::not1(std::ptr_fun(isalnum))), secretWord.end());
//std::cout << secretWord << "\n";
for(int i = 0; i < secretWord.length(); i++){
if (isalpha(secretWord[i])){
secretWordClean += secretWord[i];
}
}
secretWord = secretWordClean; //assign all alpha secret word string back to original variable for better readability
guessesRemaining = secretWord.length() * 2;
//cout << "Please enter a secret word: ";
//cin >> secretWord;
do{//start of the guessing portion of game
for(int i = 0; i < secretWord.length(); i++){
guessedLetters += "_"; //fills guessedLetters with blanks equal to the length of the secretWord
}
cout << "Please guess a letter, you have " << guessesRemaining << " guesses remaining!" << endl;
cin >> individualCharGuess;
for(int i = 0; i < secretWord.length(); i++){ //every complete iteration of this for loop = one single guess
if(secretWord[i] == individualCharGuess){
guessedLetters[i] = individualCharGuess; //will replace the spaces with the correct character, if guessed
countOfLetters++; //if any letter is guessed correctly, this indicator will be incrimented above 0
continue;
}
if(secretWord.find(individualCharGuess) == string::npos){
if(incorrectlyGuessedChars.find(individualCharGuess) == string::npos){
incorrectlyGuessedChars += individualCharGuess;
}
}
}
if(secretWord.compare(guessedLetters) == 0){
cout << "You win! The word was: " << secretWord << endl;
guessedUsed = ((secretWord.length() * 2) - guessesRemaining) + 1 ;
cout << "You used " << guessedUsed << " guesses." << endl;
cout << "Play again? Enter Y for Yes, or anything else to exit: ";
cin >> playAgain;
if(playAgain != 'Y'){
break; //exit the loop if user guesses all the letters and doesn't want to play again
}
else {
incorrectlyGuessedChars = "";
secretWordClean = "";
//continue;
goto begin_game;
}
}
guessesRemaining--; //we decriment our total guesses remaining if the user does not win the game or run out of guesses
if(countOfLetters > 0){
cout << "You have correctly guessed a letter!" << endl;
cout << "Here are the letters you have guessed correctly so far: ";
cout << guessedLetters << endl;
cout << "Here are the letters you have guessed incorrectly so far: ";
cout << incorrectlyGuessedChars << endl;
countOfLetters = 0; //reset the counter to prepare for next iteration of do-while loop
}
else if (guessesRemaining <= 0) {
cout << "You have run out of guesses!" << endl;
cout << "Here are the letters that you guessed correctly: ";
cout << guessedLetters << endl;
cout << "Here are the letters you guessed incorrectly: ";
cout << incorrectlyGuessedChars << endl;
cout << "The secret word was: " << secretWord << endl;
cout << "Play again? Enter Y for Yes, or anything else to exit: ";
cin >> playAgain;
if(playAgain != 'Y'){
break; //exit the loop if user guesses all the letters and doesn't want to play again
}
else {
secretWordClean = "";
incorrectlyGuessedChars = "";
//continue;
goto begin_game;
}
}
else {
cout << "You guessed wrong! Keep trying, " << guessesRemaining << " guesses to go!" << endl;
cout << "Here are the letters you have guessed correctly so far: ";
cout << guessedLetters << endl;
cout << "Here are the letters you have guessed incorrectly so far: ";
cout << incorrectlyGuessedChars << endl;
}
}while (secretWord.compare(guessedLetters) != 0 || guessesRemaining != 0); //use to repeat the request for a single char guess
return 0;
}
You should initialize with blanks (the _ character) the string before the loop starts, not at the beginning of every iteration, change your code to:
for (int i = 0; i < secretWord.length(); i++) {
guessedLetters += "_"; //fills guessedLetters with blanks equal to the length of the secretWord
}
do{ //start of the guessing portion of game
... rest of the code ...
if you don't, at every iteration of your game the guessedLetters variable is going to have more _ characters appended at the end of it, spoiling your final string comparison.
You should also clear the guessedLetters if you plan to play again:
else {
incorrectlyGuessedChars = "";
secretWordClean = "";
guessedLetters = ""; // Cleanup
//continue;
goto begin_game;
}
as a sidenote: gotos are a terrible programming practice and can render the code very unreadable/unmaintainable. I suggest redesigning your application without using gotos in a future revision.
Just to make clear, I am very new to C++.
But I wrote I very small program to test my skill with arrays and ran into a problem with cin.
If the user enters number, like the program expects them to, all is well. But if a string gets entered, all input is skipped and the program ends.
I set up all of my inputs like this: cin >> x;cin.clear();cin.ignore();
So what is awry??
Here is the full code:
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
system("cls");
int create = 1;
int entry;
int x;
string chc;
cout << "How long should the array be?" << endl;
cout << ":";
cin >> x;cin.clear();cin.ignore();
if(x<1){x=1;}
int myArray[x];
string askcontinue;
for(int x=0;x<sizeof(myArray)/sizeof(myArray[0]);x++){
system("cls");
cout << "Enter value #" << x+1 << endl;
cout << ":";
cin >> entry;cin.clear();cin.ignore();
myArray[x]=entry;
}
system("cls");
cout << "Index - Value" << endl;
for(int x=0;x<sizeof(myArray)/sizeof(myArray[0]);x++){
cout << x << " ------ " << myArray[x] <<endl;
}
system("cls");
cout << "Restart? [Y/N]" << endl;
cout << ":";
cin >> chc;cin.clear();cin.ignore();
if(chc=="y" || chc=="Y"){main();}
}
cin >> x;cin.clear();cin.ignore();
This thing that you're doing throughout your program is part of the problem. If the user enters something that doesn't meet the formatting requirements for an integer, the stream goes into a failure state. Directly after that happens you clear the stream and discard the next character. If the user entered in more than one character as part of the invalid input, the ignore() call is simply discarding the next character, but not all of the invalid input.
You need to check if the input did not succeed, and then discard the input using the overload of ignore() that takes the number of characters you wish to discard. Do the following if you wish to consistently ask the user for input if he does not provide valid characters:
while (!(std::cin >> x)) {
std::cout << "How long should the array be?" << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
But judging from your code, it doesn't look like you want to repeatedly ask the user for input. In that case, you should check for valid input instead and do nothing in the invalid case:
if (std::cin >> x) {
...
}
Also, VLAs (or variable-length arrays) are a non-standard feature of C++, provided as extentions in some compilers. Don't use them. Instead, allocate dynamically by using std::vector:
std::vector<int> myArray(x);
NOTE: you should also change the fact that you defining the variable 'x' three times
the problem you are having, is that c input does not type checking, so it does not care what was entered, so this is up to you. You should input everything as a string, and then make sure that the string contains nothing but numbers, THEN you can use std::stoi, or whatever the appropriate conversion method is. if they DO NOT enter a valid number, then you can just say INVALID, and tell the user to enter a valid number, and go back to the input, you could use something such as:
system("cls");
cout << "Enter value #" << x + 1 << endl;
cout << ":";
cin >> entry; cin.clear(); cin.ignore();
while(!is_valid_integer(entry))
{
system("cls");
cout << "INVALID NUMBER \n Enter value #" << x + 1 << endl;
cout << ":";
cin >> entry; cin.clear(); cin.ignore();
}
myArray[x] = std::stoi(entry);
And then entry is a string.
is_valid_integerwould be defined as:
bool is_valid_integer(std::string str)
{
for(auto it : str)
{
if(!(ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || ch == '8' || ch == '9'))
return false;
//OR: this is more efficient, but is reliant on using ascii codes (which in this case we are)
//if(!(ch >=48 && ch <= 57)) return false;
}
return true;//all numbers
}
I'm required to find a character entered by the user in a for loop. I'd usually do
if (sentence[i] == 'e')
but since here, 'e' will be a one letter char variable, I don't know how to get that value to be compared. I can't just enter
if (sentence[i] == thechar)
but I also can't create a variable to contain the character in between quotation marks like
char2 = "\'" + thechar + "\'";
So how do I do it in this context? I'm not allowed to use other, more effective, more advanced methods. This is a basics course. Please help!
string word;
char letter;
cout << "Enter a word\n";
cin >> word;
cout << "What letter would you like to search for?\n";
cin >> letter;
for (int i = 0; i < word.length(); i++)
{
if (word[i] == letter)
{
cout << letter << " is the " << i + 1 << "character of " << word << endl;
}
}
You can create a variable where you ask for the letter the user wants, and use that variable to compare.
To find position of chosen letter you can use std::string.find(...)
std::string str = "My house is white.";
std::size_t pos = str.find('s');
std::cout << "Position: " << pos << std::endl;
Output:
Position: 6
For more informations go to http://www.cplusplus.com/reference/string/string/find/ page.