Program breaks when character is entered instead of integer - c++

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 ;
}

Related

enter Odd, Even, zero and negative numbers and count using for and while loop in C++ without using arrray

I've met some problem during programming. I want to write a program to differentiate even numbers, odd numbers, zero values and negative numbers by using while and for loop.
1st question :
However, when I try to run my program, the last number I've entered will not be counted. I know it occur because of my o++ put at the top of the if condition, how should I solve my problem?
2nd question :
For the for loop parts, actually it may ignored those negative values. How should I solve it to let the negative numbers also count in loop ? May I changed the num>0 to num < 100000 to let the for loop works?
#include<iostream>
using namespace std;
#include<iostream>
using namespace std;
int main ()
{
int num ,numbers = 1 ;
char answer = 'Y' ;
int o=0, e=0, z=0 ,n=0 ;
// o for odd numbers, e for even numbers, z for zero values, n for negative numbers
cout << "Enter number" << numbers << ": " << endl ;
cin >> num ;
for ( num = num ; num >0; num++)
while (answer == 'y' || answer == 'Y')
{
if (num % 2 == 0 && num > 0)
{
e++ ;
cout<< "The number of even numbers is :" << e << endl;
numbers ++ ;
cout<<"Please enter number" << numbers << endl ;
cin >> num ;
cout<<"If you wish to continue, Please enter y or Y to continue this program : "<< endl ;
cin>> answer ;
}
else if (num % 2 == 1 && num > 0)
{
o++;
cout<< "The number of odd numbers is :" << o << endl;
numbers ++ ;
cout<<"Please enter number" << numbers << endl ;
cin >> num;
cout<<"If you wish to continue, Please enter y or Y to continue this program : "<< endl ;
cin>> answer ;
}
else if (num == 0)
{
z ++;
cout<< "The total of 0 is :" << z << endl;
numbers ++ ;
cout<<"Please enter number" << numbers << endl ;
cin >> num;
cout<<"If you wish to continue, Please enter y or Y to continue this program : "<< endl ;
cin>> answer ;
}
}
cout << "The total even numbers is :" << e << endl;
cout << "The total odd numbers is :" << o << endl ;
cout << "The total negative numbers is :" << n << endl ;
cout << "The total zero number is:" << z << endl;
return 0;
}
This line, in main() is really puzzling:
// ...
for ( num = num ; num >0; num++)
while (answer == 'y' || answer == 'Y')
The for(;;) statement is your main loop. The while statement will be executed as long as num is positive.
Let's look at this for() statement in detail:
for (num = num; // num = num ??? this statement does nothing.
num > 0; // the while statement (and the contents of the whule() loop block)
// will only execute if num is > 0.
++num) // if num was > 0 then this loop will run until num overflows...
Removing the for(;;) statement will make your program run a lot better.
Your o++ has nothing do with it.
(Perhaps you have been so convinced about that being the problem that you didn't think of looking elsewhere. It happens to everyone.)
The problem is that your sequence is this:
Check the most recently entered number and print the result
Ask the user for a number, but don't do anything with it
Ask the user whether they want to continue
If they want to continue, repeat from item 1
If they don't, stop counting
And since you stop counting if the user doesn't want to continue, the last number seems to have disappeared.
Fixing it left as an exercise.
(Think more carefully about which order you need to do things in.)
Handling negative numbers requires you to write some code to do that - you handle two cases of positive numbers, and one for zero, but you must have forgotten about the negatives.
Fixing this also left as an exercise.

How to Print the invalid input in a error message? C++

The Idea is to invoke a single function to check the user input and return True || False.
User Input with 0123456789 must return
The Number Entered Correctly
User Input with 0123w456789 must return
Number is not allowed or Contains invalid input such as "w"
User Input with 0123wx456789 must return
Number is not allowed or Contains invalid input such as "wx"
My Code:
#include <iostream>
using namespace std;
int main ( )
{
string i_numvalidation;
cout << "Enter the number: " << '\n';
cin >> i_numvalidation;
bool isNumber = true;
for (int i = 0; i < i_numvalidation.length(); i++)
{
if (!(i_numvalidation[i] >= '0' && i_numvalidation [i] <= '9'))
{
isNumber = false;
}
}
if (isNumber)
cout << " Entered number " << i_numvalidation << " is correct" << '\n';
else
cout << " Entered number " << i_numvalidation << " is not allowed or Contains invalid input such as " << "'\n";
}
Question is Updated to understand it clearly.
You already have almost everything you need to get the desired output. You only need to remember the characters that make the input invalid (ie those for which you set isNumber = false;) in a second string and print that instead of the original input. Really the only ingredient that you are not already using in your code is adding a character to a string and that can be done like this:
std::string x;
char invalid_character = 'w';
char other_invalid_character = 'p';
x += invalid_charater;
x += other_invalid_character;
std::cout << x; // prints wp
The Functions I have Implemented is working for a single value but it is still not printing the complete invalid characters.
If the Input is 0123ab456789 so it will print the error message with "a" instead of "ab". It must print "ab" as input contains "ab".
The Code:
#include <iostream>
using namespace std;
int main ( )
{
string i_numvalidation;
cout << "Enter the Number: " << '\n';
cin >> i_numvalidation;
bool isNumber = true;
int bad_index = 0 ;
if (i_numvalidation [0] == '0')
isNumber = false;
for (int i = 0; i < i_numvalidation.length () && isNumber; i++ )
{
if (!(i_numvalidation [i] >= '0' && i_numvalidation [i] <= '9'))
{
isNumber = false;
bad_index = i ;
break;
}
}
if (isNumber)
{
cout << " The Entered " << i_numvalidation << " number is correct" << '\n';
}
else
cout << " The Entered " << i_numvalidation << " is not allowed or Contains invalid input such as '" << i_numvalidation [ bad_index ] << "'\n";
}
Like:
String err='1';
for(int i=0;i<i_numvalidation.length(); i++)
{
if(i_numvalidation[i]!= '0' || i_numvalidation[i]!= '1' || i_numvalidation[i]!= '2' and so on...)
{
err[err.length()]=i_numvalidation[i];
isNumber=false;
}
}
if(!isNumber)
cout<<"That's not a number bruh"<<err<<endl;
Sorry if I'm not helpful, I tried...
Hope you'll get the answer.

Else component of if/else not executing (C++)

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 ;

Searching the last character of a string for punctuation

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);

Sudoku input program skipping a prompt

I wrote a program for my computer science class that validates and solves sudoku puzzles from .txt files, but I wanted to take it one step further and write a program that made it easy to input and sudoku game. I'm sure you can figure out the format of the files based on this code. My only problem is that the last cin gets skipped, and that option is important to me. Any insight will be appreciated!!
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct s {
s();
~s() {/*zzzz*/}
void show_grid();
void set (int &r, int &c, int &v) {g[r][c] = v;}
private:
int g[9][9];
};
//************************************************************************
void s::show_grid() {
//print game out to check it
cout << " | ------------------------------- |" << endl;
for (int k=0; k<81; k++) {
if (k%3 == 0)
cout << " |";
cout << " " << g[k/9][k%9];
if (k%9 == 8) {
cout << " |" << endl;
if ((k/9)%3 == 2)
cout << " | ------------------------------- |" << endl;
}
}
cout << endl;
}
//************************************************************************
s::s() {
//initialize all elements to zero
for (int i=0; i<9; i++) {
for (int j=0; j<9; j++) {
g[i][j] = 0;
}
}
}
//************************************************************************
void create_name (string &name) {
//append .txt extension LIKE IT OR NOT
string ext = name;
ext.erase(ext.begin(), ext.end() - 4);
if (ext.compare(".txt")!=0)
name.append(".txt");
}
//************************************************************************
int main () {
s g;
string name;
string yon("");
int count = 0;
int row, col, val, rcv;
ofstream os;
cout << "Enter game file name: ";
cin >> name;
create_name(name);
//open and do typical checks
os.open(name.c_str());
if (os.fail()) {
cerr << "Could not create " << name << ". Waaaah waaaaaaaaaah...\n\n";
return 0;
}
//useful output (hopefully)
cout << "Enter grid coordinates and value as a 3-digit number,\n"
<< "from left to right, row by row.\n"
<< "(e.g. 2 in first box would be 112)\n";
//take input as one int, to be user friendly
while (cin >> rcv && count < 81) {
row = (rcv / 100) - 1;
col = ((rcv / 10) % 10) - 1;
val = rcv % 10;
os << row << " " << col << " " << val << endl;
g.set (row, col, val);
count++;
}
os.close();
//From here down is broken, but it still compiles, runs, and works
cout << "Show grid input(y/n)?\n";
cin >> yon;
if (yon.compare("y")==0)
g.show_grid();
else if (yon.compare("n")==0)
cout << "Peace!\n";
return 0;
}
The problem is here:
while (cin >> rcv && count < 81)
Consider what happens when count==81: First, rcv will be input from cin, and only then the condition count < 81 will be evaluated to false. The loop will stop, and the value of rcv will be ignored. So effectively you read one input too many.
You should change the order of evaluation, so that count is checked first:
while (count < 81 && cin >> rcv)
Edit:
According to your comment above you are actually expecting to read less than 81 values. In that case, I recommend having the user input a special value (for example, 0) to terminate the loop. You'd just need to add if (rcv==0) break;. If you just input an invalid value as you are apparently doing, the cin stream will be put in a failed state and further input will not succeed.
Try something like:
//useful output (hopefully)
cout << "Enter grid coordinates and value as a 3-digit number,\n"
<< "from left to right, row by row.\n"
<< "(e.g. 2 in first box would be 112)\n"
<< "or Z to end the loop\n"; // 1
//take input as one int, to be user friendly
while (count < 81 && cin >> rcv ) { // 2
row = (rcv / 100) - 1;
col = ((rcv / 10) % 10) - 1;
val = rcv % 10;
os << row << " " << col << " " << val << endl;
g.set (row, col, val);
count++;
}
if(!std::cin) { // 3
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
1) Let the user know that he can enter in invalid char. It doesn't have to be Z, actually any non-numeric char will work.
2) Fix off-by-one error in the order of the &&.
3) If std::cin is in error state, clear the error and ignore the Z.
cin >> yon
still actually reads in a variable, it just reads in the variable that the while loop found to be false. When the while loop condition returns false rcv is ignored, so the number remains in the input stream waiting for the next cin statement. When yon is called that number meant for rcv is read into yon, giving you some strange errors.
it would be better to use interjay's method:
while (count < 81 && cin >> rcv)