I have a relatively large program and not all of it is relating to my question, but this particular bit is stumping me.
Below is my int main:
int main ()
{
int caseNumber ;
string clientName, clientEmail, subject, path, fileName, firstTime ;
//creates string for path of files created and where the Python project is stored (with the .exe)
path = _pgmptr ;
fileName = "EmailGenerator.exe" ;
fileName.length() ;
path.erase(path.length() - fileName.length()) ;
//checks first time use for customizing
cout << "Welcome to the Ticket Email Generator.\n\n"
<< "If this is your first time using this program,\nplease enter Y to customize some personal details.\n"
<< "If not, enter any other character.\n" ;
cin >> firstTime ;
cin.ignore() ;
if (firstTime == "Y" || firstTime == "y")
{
//save sender email (defaults to morgan_wallace#cable.comcast.com - creator)
setSender (path) ;
//Verifies signature file is as desired (to be saved for the future)
char ready = 'n' ;
while (!(ready == 'y' || ready == 'Y'))
{
std::cout << "\nPlease modify the signature.txt file located in " + path << endl
<< "Enter Y when done.\n" ;
cin >> ready ;
cin.ignore() ;
}
}
//Email "To" field:
setTo (path) ;
//Email "Subject" field:
setSubject (path) ;
//Email "Body" field:
std::cout << "\nPlease provide the following information for the body of the email:" << endl ;
//create standard time-based greeting at top of message
setToName (path) ;
//select message type & compose body of message
ofstream scriptfout (path + "script.txt") ;
std::cout << "\nPlease select from case type menu:" << endl << endl ;
caseTypeMenu(scriptfout) ;
scriptfout.close() ;
//compose full body and add signature
setBody (path) ;
std::cout << "Would you like to review your email before sending? Y/N " ;
char reviewChar ;
cin >> reviewChar ;
cin.ignore() ;
if (reviewChar == 'y' || reviewChar == 'Y')
{
review (path) ;
}
else if (reviewChar == 'N' || reviewChar == 'n')
{
//run email sender (python program)
string pythonPathString = path + "EmailProj/EmailProj/EmailProj.py" ;
string pythonString = "C:/Python27/python.exe " + pythonPathString + " " + path ;
system(pythonString.c_str()) ;
//Exit program
string anything ;
std::cout << "Enter anything to exit\n" ;
cin >> anything ;
cin.ignore() ;
}
else
{
cout << "Invalid entry review: " + reviewChar << endl ;
//Exit program
string anything ;
std::cout << "Enter anything to exit\n" ;
cin >> anything ;
cin.ignore() ;
}
return 0 ;
}
My specific issue my last if/else (everything else executes as expected):
std::cout << "Would you like to review your email before sending? Y/N " ;
char reviewChar ;
cin >> reviewChar ;
cin.ignore() ;
if (reviewChar == 'y' || reviewChar == 'Y')
{
review (path) ;
}
else if (reviewChar == 'N' || reviewChar == 'n')
{
//run email sender (python program)
string pythonPathString = path + "EmailProj/EmailProj/EmailProj.py" ;
string pythonString = "C:/Python27/python.exe " + pythonPathString + " " + path ;
system(pythonString.c_str()) ;
//Exit program
string anything ;
std::cout << "Enter anything to exit\n" ;
cin >> anything ;
cin.ignore() ;
}
else
{
cout << "Invalid entry review: " + reviewChar << endl ;
//Exit program
string anything ;
std::cout << "Enter anything to exit\n" ;
cin >> anything ;
cin.ignore() ;
}
If you input an 'h', or some character not Y, y, N, or n, it does not print the error script with the inappropriate answer. It prints a line of my code (something that is printed to screen with cout in an earlier portion of the code) and then "Enter anything to exit" and waits for input. If you input 'g', it just skips the error message altogether and prints the "Enter anything to exit line" and waits for input.
The point of this last if/else is to allow the user to view their message, and then decide whether to send it, edit portions of it, or just disregard it completely. For purposes of error checking, I would like to handle inputs that are not Y, y, N, and n, even though theoretically there should be no other inputs.
Your problem is here:
cout << "Invalid entry review: " + reviewChar << endl ;
When you use the plus sign you are actually adding the value of an integer to a pointer, not concatenating strings.
Try with this:
cout << "Invalid entry review: " << reviewChar << endl ;
Related
I'm new to C++ and am finding it difficult to find information on the cin feature. This is my first program ever so it's very simple. It determines if the entered number is a prime number or composite whilst filtering out bad values such as negative numbers and decimals. The program also will time-out after 10 failed entries.
The last feature I want to add to this program is the ability to filter out character inputs but I'm having no luck with trying different solutions. I tried converting the character to a float/double/int but to no avail. I just need help with cin, if the user inputs the letter 'K' or any other invalid character i'd like the program to recognize this and then produce the "invalid value" cout message + new entry try x number of times.
Currently when a character is entered the program crashes and goes through all 10 try attempts at once leaving the output results in the terminal very sloppy.
#include <iostream>
#include <cmath>
using namespace std ;
int main (void)
{
//Declare variables
int y, c, i1 ;
double i ;
//Ask for user input
cout << endl << endl << "Please enter a number: " ;
cin >> i ;
//Eliminate bad user input values
i1 = i ;
//Detect when a decimal number is entered for the first attempt
for ( c = 1 ; int(i1) != i ; c ++ )
{
cout << endl << "This value is invalid. Please retry: " ;
cin >> i ;
i1 = i ;
//Terminate program after so many failed attempts
if ( 8 < c )
{
cout << endl << "This value is invalid. Try again next time! \n\n" ;
return 0 ;
}
//Detect if a '0' is entered on the latter attempts
for ( c ; i < 1 ; c ++ )
{
cout << endl << "This value is invalid. Please retry: " ;
cin >> i ;
i1 = i ;
//Terminate program after so many failed attempts
if ( 8 < c )
{
cout << endl << "This value is invalid. Try again next time! \n\n" ;
return 0 ;
}
}
}
//Detect when '0' is entered on the first attempt
for ( c = 1 ; i < 1 ; c ++ )
{
cout << endl << "This value is invalid. Please retry: " ;
cin >> i ;
i1 = i ;
//Terminate program after so many failed attempts
if ( 8 < c )
{
cout << endl << "This value is invalid. Try again next time! \n\n" ;
return 0 ;
}
//Detect if a decimal number is entered on the latter attempts
for ( c ; int(i1) != i ; c ++ )
{
cout << endl << "This value is invalid. Please retry: " ;
cin >> i ;
i1 = i ;
//Terminate program after so many failed attempts
if ( 8 < c )
{
cout << endl << "This value is invalid. Try again next time! \n\n" ;
return 0 ;
}
}
}
//Find prime numbers
for ( y = 1 ; y <= i ; y ++ )
{
//Give instant result if user input is no. 1
if ( i == 1 )
{
cout << endl << "The number: " << i << " is a composite number.\n\n" ;
break ;
}
//Eliminate no. 1 from prime number search
if ( y == 1 )
continue ;
//Search for a whole number division using modulus
if ( fmod(i, y) == 0 )
{
if ( i == y )
cout << endl << "The number: " << i << " is a prime number.\n\n" ;
else if ( i != y )
{
cout << endl << "The number: " << i << " is a composite number.\n\n" ;
break ;
}
}
}
return 0 ;
}
If the input is an integer, I want to set it equal to an integer variable.
If the input is a string, I will want to set it to a string variable, and later check if the string is "quit".
I don't know how to check it. I've looked for a built in function and found nothing.
while (true) {
int numberEntered;
string stringEntered;
cout << "enter a number to see if it is greater than 5: \n or enter \'quit\' to exit the program";
//I don't know what to do below here
cin >> ;
if (stringEntered == "quit") {
break;
}
if (numberEntered > 5) {
cout << "that number is greater than 5" << endl;
}
else {
cout << "not greater than 5" << endl;
}
}
cin >> numberEntered;
if (!cin.fail())
{
...
It may be more idiomatic to use:
if (cin >> numberEntered)
David S.'s answer is good. If you want to tidily handle garbage being entered after the line, here is another option (this is more complicated for your situation, but if you later want to expand your program to handle a lot of different input, then this way may come out to be simpler).
while( true )
{
string stringEntered;
cout << "enter a number to see if it is greater than 5: \n or enter \'quit\' to exit the program: " << flush;
// read the whole line, this ensures no garbage remains in the input stream
getline(cin, stringEntered);
if ( stringEntered == "quit" )
break;
// this checks that a number was entered and nothing else
istringstream iss(stringEntered);
int numberEntered;
char ch;
if ( !(iss >> numberEntered) || (iss >> ch) )
{
cout << "please try again. ";
continue;
}
// process the number
cout << "that number is " << (numberEntered > 5 ? "" : "not ")
<< "greater than 5." << endl;
}
You may need #include <sstream>.
I'm currently working on making a little word processor and I've come across an issue. I'm trying to make the program so that when you press enter, the program will put a full stop on your input and then a space (I'll sort out paragraphs later). The issue is that I can't get the program to search the last character for punctuation and then branch on the result. The compiler gives me the following error: ISO C++ forbids comparison between pointer and integer. The code I currently have is:
#include <fstream>
#include <string>
#include <iostream>
#include <cstring>
#include <limits>
using namespace std ;
int main()
{
int i = 0;
string text ;
string text2 ;
string title ;
string usertitle ;
string filelocation = "C:/Users/" ;
string user ;
string punctuation = ". : ! ? "
cout << "Input a title for your file: " ;
getline(cin , title) ;
title.insert(title.length() , ".txt" ) ;
cout << "Your title is: " << title << endl ;
cout << endl << "Input the username associated with your computer: " ;
getline(cin , user) ;
filelocation.append( user ) ;
filelocation.append("/Documents/") ;
filelocation.append(title) ;
cout << "Your chosen file name and location is: " << filelocation << endl ;
for ( i = 1 ; i > 0 ; i++ )
{
if (text == "")
{
cout << "There are a few instructions that you need to follow in order to use this system effectively: " << endl ;
cout << "The first being that if you want to use it, you actually have to use a directory that exists. " << endl ;
cout << "The second being that when you want to exit the program you press enter with nothing typed" << endl ;
cout << "The third being NOT TO USE FULL STOPS, THE PROGRAM WILL PUT THEM IN FOR YOU" << endl ;
cout << "Please begin writing: " << endl ;
getline(cin,text) ;
}
if (text!="")
{
text2.append(text) ; //<===HERE IS WHERE I AM HAVING TROUBLE
if ((text.at(text.size() -1 ) != "!" ) && (text.at(text.size() -1 ) != "?") && (text.at(text.size() -1 ) != ":" ))
{
text2.append(". ") ;
getline(cin, text) ;
}
else
{
getline(cin, text) ;
}
if (text == "")
{
cout << "End of session" << endl ; break ;
}
}
}
ofstream writer( filelocation.c_str() ) ;
if(! writer)
{
cout << "Error opening file for output: " << strerror(errno) << endl ;
return -1 ;
}
else
{
writer << text2 << endl ;
writer.close() ;
}
return 0 ;
}
Thanks for your help in advance!
"!" is a string, you want to compare against a character: '!'.
You can't compare "!" and '!'.
I suggest using rbegin() to address the last character:
text2.append(text.begin(), text.end());
switch(*text.rbegin())
{
case '!':
case '?':
case ':': text2.append(". "); break;
}
getline(cin, text);
if(text.empty())
{
cout << "End of session" << endl;
break;
}
if ((text.at(text.size() -1 ) != "!" ) && (text.at(text.size() -1 ) != "?") && (text.at(text.size() -1 ) != ":" ))
That is both inefficient and is not doing what you think. text.at(text.size() -1 ) returns the last character. To get what you want:
char lastChar = text[text.size() - 1]; // or char lastChar = *text.rbegin();
if (!(lastChar == '.' || lastChar == '?' || lastChar == '!')) // note the single quotes
{
text2.append(". ");
}
getline(cin, text);
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: )";
The bug starts at cin.getline ( string, 25, '\n' ); or the line below it (strtod). If I use cin, it works, except I cannot quit out. If I type anything that's not a double, an infinite loop runs. Need help. Basically, the first iteration runs, does not ask for input, so the user gets the math questions wrong. The second iteration works fine. And the next is fine, too. If I back out, using q, I get dumped back to the mode-chooser. After choosing a mode, the bug reappears for the first iteration. Next iterations it's gone.
int main()
{
char choice, name[25], string[25], op;
int operator_number, average, difference, first_operand, second_operand, input, answer, total_questions = 0, total_correct = 0;
double dfirst_operand, dsecond_operand, dinput, danswer, percentage;
bool rounding = false;
srand ( time(NULL) );
cout << "What's your name?\n";
cin.getline ( name, 25, '\n' );
cout << '\n' << "Hi, " << name << ".";
do {
do {
cout << "\nWhich math operations do you want to practice?\n 1. Addition\n 2. Subtraction\n 3. Multiplication\n 4. Division\n 5. Mixed\n 6. Difference of squares multiplication.\nChoose a number (q to quit).\n";
cin >> choice;
} while( choice < '1' || choice > '6' && choice!= 'q');
cout << "\n";
switch(choice) {
case '1':
while( string[0]!= 'q') {
dfirst_operand = rand() % 15 + 1;
dsecond_operand = rand() % 15 + 1;
danswer = dfirst_operand + dsecond_operand;
cout << dfirst_operand << " + " << dsecond_operand << " equals?\nEnter q to quit.\n";
cin.getline ( string, 25, '\n' );
dinput = strtod( string,NULL);
//cin >> dinput;
if(string[0]!='q') {
++total_questions;
if(dinput==danswer) {
++total_correct;
cout << "Correct. " << total_correct << " correct out of " << total_questions << ".";
} else {
cout << "Wrong. " << dfirst_operand << " + " << dsecond_operand << " equals " << danswer << ".\n" << total_correct << " correct out of " << total_questions << ".";
};
percentage = floor(10000 * (float) total_correct / total_questions)/100;
cout << ' ' << percentage << "%.\n\n";
}
}
break;
}
} while(choice!='q');
return 0;
}
The problem is this line:
cin >> choice;
This line parses the input buffer for character input that can be converted to an integer. So if you enter:
2<newline>
The string "2" is converted, and <newline> remains in the input buffer; so the subsequent cin.getline() is satisfied immediately.
This is also why JonH's suggestion does not work, you need to purge the input buffer after the cin << choice input. An alternative is to use cin.getline() for all input (or better; use ::getline() which operates on std::string rather than C-strings), and then parse that input using a std::istringstream object when you need formatted input scanning.
However if you must use cin.ignore() to solve this problem, you should do it thus:
cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ) ;
where std::numeric_limits is defined in the header. Your solution trusts the user not to enter more than 25 characters. That is not a very safe assumption.
Try to throw a cin.ignore() right after or before the cin.getline().