I am currently learning C++ and I have been asked to make a program which will calculate the interest that would be paid on a deposit of a given size. One of the requirements is that we display an error message when non-integer data is entered.
I however cannot work out how to detect if non-integer data has been entered. If anyone could provide an example of how this problem is solved it would be much appreciated!
You don't have to check yourself. The expression (std::cin >> YourInteger) evaluates to a bool, whcih is true if and only if YourInteger was succesfully read. This leads to the idiom
int YourInteger;
if (std::cin >> YourInteger) {
std::cout << YourInteger << std::endl;
} else {
std::cout << "Not an integer\n";
}
this should be a clear enough starting point.
char* GetInt(char* str, int& n)
{
n = 0;
// skip over all non-digit characters
while(*str && !isdigit(*str) )
++str;
// convert all digits to an integer
while( *str && isdigit(*str) )
{
n = (n * 10) + *str - '0';
++str;
}
return str;
}
You need to find out if the input value contains non numeric characters. That is, anything other than 0-9.
You have to first take input as string and then verify if every digit is indeed numeric.
You can iterate the string and test if each character is a valid digit using the built in function isdigit() defined in <cctype>. You might also want to allow for a single comma if you're working with decimal numbers.
Related
so I'm pretty new to C++ and I'm doing an assignment for my class. I ran into a problem when trying to check if an input is a string or a double/int. So I made a basic program to test it
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
string hi;
double hello;
cin >> hello;
if (!cin)
{
//Strings go here
cin.clear();
cin >> hi;
cout << hi << endl;
}
else
{
cout << hello << endl;
}
cout << "Done!" << endl;
}
So it works for basically when inputting a letter (such as "j" or "a") or a number but when inputting "+" or "-" it waits for the next input then forces it through the string block, even if it is a number. However "*" or "/" are read as strings and don't cause that issue (I'm assuming since they aren't explicitly operators)
I assume I am probably missing something. Thank you
Edit: I am testing with single types at a time (such as 123, 1 , d, +) without mixing types, so there won't be any inputs that have a double and a string
As per user4581301's suggestion, I'll put in some examples input and outputs
Inputs:Outputs
"Hello":"Hello"
123:123
"/":"/"
"+" (Input after: 2):"2"
The problem
Your programme does not work exactly as intended, because it doesn't take into consideration potentially consumed but lost characters.
Here are different cases that work as expected:
abc: the first char read is not numeric, so it's not consumed and cin fails fast. The second reading reads every chars present as a string.
123abc456: the first 123 is read. When a is encountered, it is not consumed since it's not valid numeric. Further reading is stopped, but a numeric value could be read.
/123: the first char read is not numeric, so it's not consumed and cin fails. the second reading reads every char present as string.
-123 or +123: the first char is considered as a valid numeric char and is read, and then the remainder is read, still as a numeric value. Works as expected if you consider that a double ora an int can be signed. Depending on output formatting, the + might not appear with your output.
Here are the cases that do not work: if the first char is + or - but it is not followed by a valid numeric char. In this case the first char is consumed, but the next char makes the numeric input fail. The remaining chars are then read as string (except the first sign that was already consumed and is lost). Examples:
++123
+ 123 (the space ends the axtraction of the double that fails, the remainder is read as a string).
Online demo
The solution
The easiest solution is to read the input as a string, then try to convert the string.
For example:
size_t processed;
string hi;
double hello;
cin >> hi;
try {
hello = stod(hi,&processed);
cout<<"number:" <<hello;
if (processed<hi.size())
cout << " (followed by something)";
cout <<endl;
}
catch (...) // should be more precise in catching, but it's for the proof of concept
{
cout <<"string: "<< hi << endl;
}
Online demo
If you want to consider + and - as alphanumeric, it'd be easy to check if hi is non empty and hi[0] a digit before trying to do the conversion.
Alternatively, you could also do a regex check of the string to see if it matches a numeric format.
I've created a guessing game where you have to guess randomly generated number in range from 1 to 100. I also managed to restrict a user if they enter a number that is out of the range, and requires new input. The problem is when you accidentally enter letters or symbols. Then it enters an infinite loop. I tried:
while(x<1 || x>100 || cin.fail())//1. tried to test if input failed (AFAIU it checks if input is expected type and if it is not it fails)
while(x<1 || x>100 || x>='a' && x<='z' || x>='A' && <='Z') // 2. tried to test for letters at least
while(x<1 || x>100 x!=(int)x)//3. to test if it is not integer
{ cout<<"Out of range";
cin>>x;
}
For one solution, you could try and use isdigit. This checks to see if input is actually a number. So you can do something like:
if(!(isdigit(x))){
cout << "That is not an acceptable entry. \n";
continue;
}
EDIT: I should say, that after researching this, I realized that for isdigit to work, the entry needs to be a char. However, this can still work if you convert the char into an int after it discovers that it's an int. Example:
if(!(isdigit(x))){
cout << "That is not an acceptable entry. \n";
continue;
}
else{
int y = x - '0';
}
That int y = x - '0' might seem odd; but it's there because you have to convert the char to an int, and according to the ASCII coding, to do so, you subtract the character '0' from the desired number. You can see that here: Convert char to int in C and C++
I have a little "blackjack" program coded in C++. The thing is that the program asks questions like "Would you like... (y/n)?" where user needs to type y/n. I want to check if the value returned is actually the type that I want. So function that should return int, returns int and function that should return char, returns char, before it actually returns something.
I would need some suggestions guys. I think it's not that difficult, I just can't find any solution. Thank you.
Code:
char pickCard(){
char aCard;
std::cout << "Would you like another card?";
std::cin >> aCard;
if (aCard is a char){
return aChar;
} else {
std::cout << "Not a char!";
}
}
I think you have a misconception of exactly how std::istream's formatted input works. In your example, aCard must be a char, because you've declared it as such. If the use enters more than one character, one character will be put into aCard, and std::cin will hold onto the other characters and give them to you the next time you call operator>> (or any other input function); if the user enters a number, aCard will be the character representation of the first digit of that number.
Keep in mind that operator>> knows what type of variable you've given it, and it will ensure that the user's input is valid for that type. If you give it an int, it will make sure the users input is convertible to an int or give you 0 if it isn't. A variable can never be anything but the type you declared it to be.
If you're interested in chars in particular, there's a whole bunch of character classification functions you can use to tell what sort of character (letter, digit, whitespace, etc.) you're working with, but keep in mind that char foo('4') is entirely different than int foo(4).
I guess you just want to know if the input string is in number format. >> will set the istream's failbit if it cannot convert the input string to int.
int num;
if (cin >> num) { // input is "123abc", num == 123
cout << "yes, input is a number. At least start with some figures. "
cout << "num == " << num;
} else { // input is "abc" , error
cout << "no, input is not a number or there is some kind of IO error."
}
If you want to force y or n as only allowed characters you can do:
char pickCard(){
std::string response;
std::cout << "Would you like another card?";
std::cin >> response;
if (response=="y" || response=="n"){
return response[0]; //or anything useful
} else {
std::cout << "Not a char!";
//... more code here
}
//... more code here
}
you can use length() property of std::string to find its length. a string of length one is a char in most cases.
I am trying to write a console program, which gets a number from the input and puts it into an array. The read in lasts as long as the user does not hit the "space" button. I have tried several things, but my program won't compare the input with the ASCII code of "space". Thanks in advance!
#include <iostream>
using namespace std;
int main()
{
int fabcd[25],number_of_items = 0;
cout << "The read in loop lasts while you don't hit space:\n";
while((char)cin.get() != 32)
{
cin >> fabcd[number_of_items];
number_of_items++;
}
return 0;
}
There are several problems with your code. The most fundamental
is that you do two inputs each time through the loop, the first
in the while, and the second using >> in the loop. Note too
that the second will skip any spaces, then convert the input to
an integer. If the input cannot be legally converted to an
integer (e.g. the next character is an 'a'), the input goes
into an error state, and cin.get() will always return EOF.
And of course, if you are entering numbers, you can easily
enter more than 25, and overrun the buffer.
If you just want to enter a sequence of numbers, then:
std::vector<int> fabcd;
int tmp;
while ( std::cin >> tmp ) {
fabcd.push_back( tmp );
}
is all you need. (The numbers must be separated by white
space.) If you want to enter the digits, up until you
encounter a white space, something like the following should
work:
std::vector<int> digits;
int tmp = std::cin.get();
while ( tmp != EOF && ! std::isspace( tmp ) ) {
digits.push_back( tmp /* or tmp - '0' */ );
tmp = std::cin.get();
}
Notice that the results of std::cin.get() are assigned to an
int, not a char. This function returns an int
intentionally, because it must be able to return the out of band
value EOF. There are a couple of variants on this: if you use
std::cin::peek(), instead of std::cin::get(), you'll not
actually extract the character (which you'll have to do in the
loop); and there is also std::get( char& ), which extract the
character into the given char, provided it isn't at EOF.
Using this function, the loop would be:
std::vector<int> digits;
char tmp;
while ( std::get( tmp ) && ! std::isspace( tmp ) ) {
digits.push_back( tmp );
}
(You might also want to use std::isdigit, instead of !
std::ispace to control the loop.)
EDIT:
One last point: the actual numeric code for a space or whatever
depends on the implementation, and is not necessarily 32.
Also, you'll want to handle tabs and newlines similarly. You
should always use the isspace, etc. functions. Or if you
really do want to check for a space, and only a space, compare
with ' ', and not 32.
(char)13 ist the carriage return not the space.
isn't the point that you would do:
((char)cin.Get()) !=' '
The acii code for space is 32. So you should substitute 64 or 13, which is carraiage return to 32:
while((char)cin.get() != 32)
However the problem might be that cin may stop on some characters for example whitespace: You can disable this behaviour by setting: cin.unsetf(ios::skipws);
according to C++, user input check for '\0' stops at spaces?
try this :
#include <iostream>
#include <conio.h >
using namespace std;
int main()
{
int fabcd[25],number_of_items = 0;
cout << "The read in loop lasts while you don't hit space:\n";
while( _kbhit() != 32 )
{
char ch =getche();
if (ch != 32 )
{
cin >> fabcd[number_of_items];
number_of_items++;
}
else
break;
}
cout << "\nnumber of items:"<<number_of_items;
cin.get();
cin.get();
return 0;
}
Here is the answer:
int fabcd[25],number_of_items = 0;
cout << "The read in loop lasts while you don't hit space:\n";
char a;
while((a=cin.get()) != ' ')
{
fabcd[number_of_items]=a;
number_of_items++;
}
return 0;
This may be a total beginner's question, but I have yet to find an answer that works for me.
Currently, I'm writing a program for a class that takes in a user's input (which can be one or more numbers separated by spaces), then determines whether the number is prime, perfect, or neither. If the number is perfect, then it will display the divisors.
Thus far, I've already written the code for the prime, perfect, and listing the divisors. I'm stuck on the input portion of my program. I don't know how to get the input that's separated by spaces to go through my loops one at a time.
This is my current program:
cout<<"Enter a number, or numbers separated by a space, between 1 and 1000."<<endl;
cin>>num;
while (divisor<=num)
if(num%divisor==0)
{
cout<<divisor<<endl;
total=total+divisor;
divisor++;
}
else divisor++;
if(total==num*2)
cout<<"The number you entered is perfect!"<<endl;
else cout<<"The number you entered is not perfect!"<<endl;
if(num==2||num==3||num==5||num==7)
cout<<"The number you entered is prime!"<<endl;
else if(num%2==0||num%3==0||num%5==0||num%7==0)
cout<<"The number you entered is not prime!"<<endl;
else cout<<"The number you entered is prime!"<<endl;
return 0;
It works, but only for a single number. If anyone could help me to get it to be able to read multiple inputs separated by spaces, it'd be greatly appreciated. Also, just a side note, I do not know how many numbers will be entered, so I can't just make a variable for each one. It will be a random amount of numbers.
Thanks!
By default, cin reads from the input discarding any spaces. So, all you have to do is to use a do while loop to read the input more than one time:
do {
cout<<"Enter a number, or numbers separated by a space, between 1 and 1000."<<endl;
cin >> num;
// reset your variables
// your function stuff (calculations)
}
while (true); // or some condition
I would recommend reading in the line into a string, then splitting it based on the spaces. For this, you can use the getline(...) function. The trick is having a dynamic sized data structure to hold the strings once it's split. Probably the easiest to use would be a vector.
#include <string>
#include <vector>
...
string rawInput;
vector<String> numbers;
while( getline( cin, rawInput, ' ' ) )
{
numbers.push_back(rawInput);
}
So say the input looks like this:
Enter a number, or numbers separated by a space, between 1 and 1000.
10 5 20 1 200 7
You will now have a vector, numbers, that contains the elements: {"10","5","20","1","200","7"}.
Note that these are still strings, so not useful in arithmetic. To convert them to integers, we use a combination of the STL function, atoi(...), and because atoi requires a c-string instead of a c++ style string, we use the string class' c_str() member function.
while(!numbers.empty())
{
string temp = numbers.pop_back();//removes the last element from the string
num = atoi( temp.c_str() ); //re-used your 'num' variable from your code
...//do stuff
}
Now there's some problems with this code. Yes, it runs, but it is kind of clunky, and it puts the numbers out in reverse order. Lets re-write it so that it is a little more compact:
#include <string>
...
string rawInput;
cout << "Enter a number, or numbers separated by a space, between 1 and 1000." << endl;
while( getline( cin, rawInput, ' ') )
{
num = atoi( rawInput.c_str() );
...//do your stuff
}
There's still lots of room for improvement with error handling (right now if you enter a non-number the program will crash), and there's infinitely more ways to actually handle the input to get it in a usable number form (the joys of programming!), but that should give you a comprehensive start. :)
Note: I had the reference pages as links, but I cannot post more than two since I have less than 15 posts :/
Edit:
I was a little bit wrong about the atoi behavior; I confused it with Java's string->Integer conversions which throw a Not-A-Number exception when given a string that isn't a number, and then crashes the program if the exception isn't handled. atoi(), on the other hand, returns 0, which is not as helpful because what if 0 is the number they entered? Let's make use of the isdigit(...) function. An important thing to note here is that c++ style strings can be accessed like an array, meaning rawInput[0] is the first character in the string all the way up to rawInput[length - 1].
#include <string>
#include <ctype.h>
...
string rawInput;
cout << "Enter a number, or numbers separated by a space, between 1 and 1000." << endl;
while( getline( cin, rawInput, ' ') )
{
bool isNum = true;
for(int i = 0; i < rawInput.length() && isNum; ++i)
{
isNum = isdigit( rawInput[i]);
}
if(isNum)
{
num = atoi( rawInput.c_str() );
...//do your stuff
}
else
cout << rawInput << " is not a number!" << endl;
}
The boolean (true/false or 1/0 respectively) is used as a flag for the for-loop, which steps through each character in the string and checks to see if it is a 0-9 digit. If any character in the string is not a digit, the loop will break during it's next execution when it gets to the condition "&& isNum" (assuming you've covered loops already). Then after the loop, isNum is used to determine whether to do your stuff, or to print the error message.
You'll want to:
Read in an entire line from the console
Tokenize the line, splitting along spaces.
Place those split pieces into an array or list
Step through that array/list, performing your prime/perfect/etc tests.
What has your class covered along these lines so far?
int main() {
int sum = 0;
cout << "enter number" << endl;
int i = 0;
while (true) {
cin >> i;
sum += i;
//cout << i << endl;
if (cin.peek() == '\n') {
break;
}
}
cout << "result: " << sum << endl;
return 0;
}
I think this code works, you may enter any int numbers and spaces, it will calculate the sum of input ints
std::vector<int> num{};
int buf;
do{
std::cin >> buf;
num.push_back(buf);
}while(std::cin.peek() == ' ');
In C language you can to it using scanf like this:
scanf('%d %d',&a,&b);