I'm trying to write a c++ program that tests each input integer, and stops if the input is invalid.
Here is my code, without the testing part:
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int i;
do
{
cout << "\nPlease enter an integer: ";
cin >> i;
cout << endl << i << endl;
} while(i != 0);
system("Pause");
return 0;
}
How can I test the input for validity?
The easiest is to use std::getline to read a whole line of input into a std::string, and then test whether that string is a valid integer specification.
It's also possible to do this by testing the failure state of cin, and clearing it, but that way lies an assortment of complications that you don't want.
In order to test the string you can use a high level std::istringstream (just read from it and test its failure state after) or, more efficient but a little more complicated, strtol from the C library (the latter is what a C++ stream uses internally).
You need to test whether a string is an integer without crashing.
You can do this with strtol(). It converts the string to an integer, and reports on the first character that is not a legal char for a number. No invalid characters means the entire string was an integer.
There is a good description and example of how to use it here:
http://www.tutorialspoint.com/c_standard_library/c_function_strtol.htm
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int i;
do
{
cout << "\nPlease enter an integer: ";
while(!(cin >> i))
{
cin.clear();
cin.ignore();
cout << "\nInput was invalid, please re-enter: ";
}
cout << endl << "The integer is: " << i << endl;
} while(i != 0);
system("Pause");
return 0;
}
Related
I have this while loop, just to check if the entered number is 2. If the user entered by accident a letter instead of a number the loop goes to infinity even though I've added isdigit, but didn't fix the loop from going crazy if the input is a character. This is code:
int num1;
bool cond {false};
while(!cond){
cout<<"enter 2:";
cin>>num1;
if (!isdigit(num1)){
cout<<"not a digit:";
cin>>num1;
}
//
if(num1 == 2)
cond = true;
}
I would suggest trying something a little more straightforward instead of your current code:
#include <iostream>
#include <limits>
using namespace std;
int main()
{
int num1;
cout << "Please enter the number 2:";
cin >> num1;
while (num1 != 2)
{
cin.clear(); //Clears the error flag on cin.
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "You did not enter the number 2, Please try again:";
cin >> num1;
}
return 0;
}
Now, cin.ignore(numeric_limits<streamsize>::max(), '\n'); is when it ignores up until '\n' or EOF \n is the delimiter meaning that, that is the character at which cin will stop ignoring.
Furthermore, numeric_limits<streamsize>::max() is basically saying there is no limit to the number of characters to ignore.
You need to use the header file #include<limits> to use this.
I recommend separating the reading of input data from converting it to a number. A good method for this is to use stringstream. Here's a working example:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int num1;
string input;
bool cond{ false };
cout << "enter 2:";
while (!cond) {
getline(cin, input);
stringstream ss(input);
ss >> num1;
if( ss.fail() ){
cout << "not a digit:";
continue;
}
//
if (num1 == 2)
cond = true;
else
cout << "enter 2:";
}
return 0;
}
int num1;
bool cond {false};
do{
cout<<"enter 2:";
cin>>num1;
if (cin.good()) {
cond = true;
}else {
cin.clear();
cin.ignore();
cout << "Invalid, please enter 2." << endl;
}
}while(!cond);
While false, execute statements. Also, if you want the user to re-enter a number, cin must be flushed.
Try declaring the variable num1 as char because isdigit(ch) works for char and not for int.
I hope this solves your problem
Why does the loop iterate infinitely?
Let's take this example
int a;
std::cin >> a;
std::cout << "Entered: " << a;
Now let's test it with different inputs
with int
5
Entered: 5
10
Entered: 10
Yes just as we would expect, but what happens when you enter a char?
with char
r
Entered: 0
f
Entered: 0
Why does this happen?
When you declare the variable int, and then do std::cin >> , you are telling the input method that the user will enter an integer, but when it doesn't get what it expected, it will fail. C++ will not implicitly convert the value of char into int. Hence, you get strange results.
How to solve this?
As I have mentioned earlier, it fails. When this fails you can catch it this way
if (!(std::cin >> a))
{
std::cout << "Invalid input ! \n";
}
We're saying, if the input fails, show the message.
let's test this new code.
int a;
if (!(std::cin >> a))
{
std::cout << "Invalid input !\n";
}
else
{
std::cout << "Entered: " << a;
}
5
Entered: 5
r
Invalid input !
How to print char value of the int?
If you want to just print the ASCII value of the entered number, you need to cast the value into char.
You can do
int num = 48;
char character_value = num;
Here C++ will implicitly convert char into int.
But if you need a safer type of conversion, prefer using static_cast<>.
The syntax looks like this
int a = 5;
char character_value = static_cast<char>(a);
Static cast in C++
Type casting in C++
Dealing with invalid input in C++
I need help in c++. I want to compare char array. So, I did some coding. Unfortunately, it always comes out an error. I can't run it. Here I attached the code. Please help me fix this code. I want to check if the conclusion equal to sentence 1 then it is invalid but if it's not equal sentence 1 then it is valid. Help me, please. Thank you.
int number;
char sentence[number];
char rules[50];
char statement[50];
char premis1[100];
char premis2[100];
char conclusion[100];
cout<<"How many sentence you want to insert:";
cin>>number;
cout<<endl;
for(int i=0; i<number; i++)
{
cout<<"Enter sentence ";
cout<<i+1;
cout<<":";
cin>>sentence[i];
cin.ignore();
}
cout<<"Enter premis 1:";
cin.getline(premis1,100);
cin.ignore();
cout<<"Enter premis 2:";
cin.getline(premis2,100);
cin.ignore();
cout<<"Enter conclusion:";
cin.getline(conclusion,100);
cin.ignore();
for(int i=0;i<number;i++)
{
if(strcmp(conclusion,sentence[0],)==0)
{
cout<<"Statement is invalid."<<endl;
cout<<endl;
}
else if(strcmp(conclusion,sentence[0])!=0)
{
cout<<"Statement is valid."<<endl;
}
else
cout<<"exit"<<endl;
}
Your mistakes you've made in the program:
You never initialized number but used in sentence[], still it's invalid even after number's declaration, that's because the compiler must know the exact value of the array length to be defined.
You've defined sentence as a char array but from your code, it seems like you wanted to store a full sentence into each element of array, which is impossible. Use std::string here.
You're doing strcmp() with the first character of char array, not the sentence with conclusion.
Aside: Please don't forget to include the important header files which are common to the code and we must assume your program is incomplete, because it has a lack of main() and statement(s), such as strcmp(...,...',' - incomplete).
Redesigned the program (notice that using namespace std statement is used here because it's just a small program to demonstrate and for sake of simplicity and getting rid of std:: prefixes everywhere):
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(void) {
int number = 0;
vector<string> sentence;
string tempSentence;
string conclusion;
cout << endl;
cout << "How many sentences you want to insert? ";
cin >> number;
for (int i = 0; i < number; i++) {
fflush(stdin);
cout << "Enter sentence " << (i + 1) << ": ";
getline(cin, tempSentence);
sentence.push_back(tempSentence);
}
cout << "Enter conclusion: ";
getline(cin, conclusion);
if (conclusion == sentence[0])
cout << "The statement is invalid." << endl;
else if (conclusion != sentence[0])
cout << "The statement is valid." << endl;
else
cout << "EXIT" << endl;
return 0;
}
I've taken std::vector<> of std::string here to insert a single string in defined number of sentences given in a dynamic way in each iteration (from #include <vector>) and used std::string rather than char arr[], it's easy to compare strings here.
Sample Output:
$ g++ -o prog prog.cpp; ./prog
How many sentences you want to insert? 3 // --- INPUT
Enter sentence 1: This is the first sentence.
Enter sentence 2: This is the second sentence.
Enter sentence 3: This is the third sentence.
Enter conclusion: This is NOT the first sentence.
The statement is valid. // first sentence != conclusion // --- OUTPUT
I've picked up a book on C++ and I'm basically at the very beginning of it (just started). For some of the problems I had to solve within the book I used the input stream cin the following way -->
cin >> insterVariableNameHere;
But then I did some research and found out the cin can cause a lot of problems, and so found out about the function getline() within the header file sstream.
I'm just having some trouble trying to wrap my head around what's happening in the following code. I don't see anything that uses the extraction operator (>>) to store the number value in. Its (my problem) further explained in the comments I left.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
// Program that allows a user to change the value stored in an element in an array
int main()
{
string input = "";
const int ARRAY_LENGTH = 5;
int MyNumbers[ARRAY_LENGTH] = { 0 };
// WHERE THE CONFUSION STARTS
cout << "Enter index of the element to be changed: ";
int nElementIndex = 0;
while (true) {
getline(cin, input); // Okay so here its extracting data from the input stream cin and storing it in input
stringstream myStream(input); // I have no idea whats happening here, probably where it converts string to number
if (myStream >> nElementIndex) // In no preceding line does it actually extract anything from input and store it in nElementIndex ?
break; // Stops the loop
cout << "Invalid number, try again" << endl;
}
// WHERE THE CONFUSION ENDS
cout << "Enter new value for element " << nElementIndex + 1 << " at index " << nElementIndex << ":";
cin >> MyNumbers[nElementIndex];
cout << "\nThe new value for element " << nElementIndex + 1 << " is " << MyNumbers[nElementIndex] << "\n";
cin.get();
return 0;
}
stringstream myStream(input): Creates a new stream that uses the string in input as "input stream" so to speak.
if(myStream >> nElementIndex) {...): Extracts number from the stringstream created using the line above into nElementIndex and executes ... because the expression returns myStream, which should be non-zero.
You were probably confused by using the extraction as the condition in the if statement. The above should be equivalent to:
myStream>>nElementIndex; // extract nElement Index from myStream
if(myStream)
{
....
}
What you probably wanted was
myStream>>nElementIndex; // extract nElement Index from myStream
if(nElementIndex)
{
....
}
So recently, I came across using isdigit as a way to check to see if an entered value for an int is actually an integer, rather than a string or a char.
However, when I wrote a short program to play around with that, the program failed to execute from that point on.
EDIT: I also in the program wanted to take the invalid data and convert it to a different data type.
Here is the code:
#include <iostream>
#include <sstream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
int enterCFN;
char revisit;
int review(0);
cout << "Enter a digit: ";
cin >> enterCFN;
bool y = isdigit(enterCFN);
if (y == false)
{
// This is the data conversion section
revisit = enterCFN;
revisit = review;
cout << review << "\n";
}
else
{
cout << enterCFN << "\n";
}
return 0;
}
Is there anyone who can correct my error and show me what I'm doing wrong?
enterCFN is an int. It stores a number. isdigit() checks if a character represents a number. These are not the same thing: for example 32 is a number but char(32) means ' ' (space).
What you want instead is this:
if (cin >> enterCFN)
That will take the input from the user and check if it is valid all at once. No need for isdigit().
isdigit() checks if a given character is one of 0-9
For validating integer do something like following:
std::cout << "Enter a digit: ";
std::cin >> enterCFN ;
while (1)
{ if ( std::cin >> enterCFN )
{
// good input
break ;
}
else
{
std::cout << "Enter a digit: ";
// clear stream flags set due to bad input
std::cin.clear();
// get rid of the bad input.
// ignore the rest of the line
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
In the following code, if the user inputs something that is not an int, the program goes into an infinite loop. Why does this happen, and what should I do to fix it?
#include <iostream>
#include <string>
using namespace std;
int main()
{
int i;
char str[100];
while (!(cin >> i))
{
gets(str);
cout << "failure read!" << endl;
}
cout << "successful read!" << endl;
return 0;
}
Clear the error state:
int main()
{
int i;
char str[100];
while (!(cin >> i))
{
cin.clear();
cin.getline(str,100);
cout << "failure read!" << endl;
}
cout << "successful read!" << endl;
return 0;
}
I think that you want to replace the while loop with an if statement, with this loop, you'll continuously read from cin while an error occurs. However, cin is structured so that after an error occurs, you must manually clear the error state, and since you're not doing that here this will go into an infinite loop. Using an if statement tries to read a value and then let's you know whether or not it succeeded.
Additionally, this really isn't a good way to read from cin. It's brittle and any invalid input can totally take down your program, since gets is inherently unsafe. For a discussion of a safer and more robust way to get input in C++, check out http://www.stanford.edu/class/cs106l/course-reader/Ch3_Streams.pdf