Filtering out negative numbers using scanf - c++

my aim is to scan for some positive-only a, if negative number is entered, the function should print error:
if ( scanf("%u %lf", &a, &b) != 2 ) {
//error
}
Now the theory is that scanf returns successful writing attempts, so if I enter a negative number, scanf shouldn't return 2. My theory seems to be incorrect, why?
Obviously I could simply scanf %d and then check whether %d is negative but right now I'm curious why my initial theory is incorrect. So is there a way without scanning and then comparing?

Your theory doesn't work because scanf doesn't fail or doesn't refuse to copy the user input to the memory address specified even if a signed number is entered when an unsigned number is expected. Therefore, as per the scanf documentation, scanf will return the number of items copied to the provided memory address.

My theory seems to be incorrect, why?
When %u is used as the format spefifier, scanf expects (from http://en.cppreference.com/w/cpp/io/c/fscanf):
The format of the number is the same as expected by strtoul() with the value 10 for the base argument.
strtoul documentation says this about negative numbeers:
If the minus sign was part of the input sequence, the numeric value calculated from the sequence of digits is negated as if by unary minus in the result type, which applies unsigned integer wraparound rules.
Hence %u does not fail even when you enter a negative number.

scanf() still succeeds (and increments the return value) if the input is not the right type of number.
For example, if scanf("%u", &my_unsigned_int); reads the text "-1", it will return 1 and my_unsigned_int will be written to like my_unsigned_int = (unsigned int) -1;
This will also be the case if they enter a decimal value - it will be assigned to your int field with a type cast. It doesn't look like you rule out floats, so you probably just want to scanf("%f", &some_float); and then check the value of some_float.

Related

Storing a char into an int variable

I am learning about implicit conversions in C++. And i read the following example:
char a;
std::cin>>a; //I can enter an integer like 56 here
std::cout<<a<<std::endl; //for the input 56 it will display 5 because of its ASCII value
I understood the above example by reading about it in different books and posts on SO. For example, if i provide the input J, then the program successfully prints J on the console. Similarly if i provide the input say 56 then the output will be 5 because of its ASCII value.
But then i tried the opposite as shown below:
int a;
std::cin>>a;//if i provide the input as the character J then why is the output 0 instead of the corresponding code point of `J`
std::cout<<a<<std::endl;
For the above snippet, if i provide the input 56 then the output is correctly printed as 56. But if i provide the input as J then the output is 0.
So my question is in the above 2nd snippet why the code point corresponding to the character J is not printed and instead we get 0 printed on the console. I mean, a is an integer variable so it is able to store the code point corresponding to the character J and then when we do cout<<a; we should be getting that code point as the output instead of 0. What is happening here. Is this related to implicit conversion like a char can be promoted to an int or something else.
The << operator works different depending on what is on the right hand side. In the first example it reads the char ‘5’ with a ASCII value of 53 and throws the ‘6’ away. In the second case it reads the int fifty-six. When you enter “J” that’s not an int, so trying to read an Int gets a result of 0.
And the >> operator does the same thing: When you output ‘5’ it’s written, it is written as a char, and the int 56 is written as an Int.
When istream operator<< expects something but gets something else, its failbit is set and in this state, the stream will not do anything.
So if there is a chain, it is stopped when a wrong input is met.
About handling this here.
But something else is also happening.
Since C++11, if extraction fails, zero is written to its value.
int a; // default-initializing fundamental type (no init / garbage value)
std::cin >> a;
If a char is encountered, a will become 0.
And also for integers, if the entered value is more or less than the type can hold, failbit is set and it will become std::numeric_limits<T>::max/min() or max() if T is unsigned.

Why won't auto assign values of type long long?

Using auto, I have created a variable number and used cin.get to get the value. I used this code to do so:
auto number = cin.get();
cout << typeid(number).name() << endl;
It seems that even if I enter a number that is over 2147483647, the value still gets assigned type int. Why is this? Shouldn't auto be assigning a value of type long if the number exceeds the max 32 bit int value?
auto is resolved at compile-time, and decided based on the return type of cin.get() (which happens to be int by definition).
In addition, the expression typeid(number).name() is also evaluated at compile-time, meaning that the compiler resolves this to a constant value (e.g., "i" for my system) and stores that in the executable.
auto is resolved on compile-time. The compiler deduced that number is of type int because std::istream::get returns an int.
If this is a problem, use long long explicitly here.
So auto doesn't change anything. And neither istream::get() nor istream::getline() actually parses the input to see if it is a number.
But let's look at some options:
cin.get()
This returns an int that represents one character of the input stream. But it represents a character, not a number.
cin.getline()
This is an error.
There's no overload of istream::getline() that expects no arguments.
char s[100]; cin.getline(s, 100);
This will store a line of the input (or 100 characters if it is too long) and store it in the string s.
In addition to what's already been said about auto…
It is impossible to "enter a number that is over 2147483647" here. cin.get() is unformatted input. You are reading bytes, and bytes (assuming CHAR_BIT==8) only go up to 255. That is why cin.get() returns an int: it will never any higher value. Ever.

Different results for long long int in c and c++?

I am trying to solve a this problem-> Candy3
We are supposed to use long long to solve this problem. But when I'm using cin to take inputs that are larger than 10^19 (i know it is the limit of long long but the there is limit constraint specified and we are supposed to output the right answer) it is giving random outputs. Whereas, when I'm using scanf() it is printing the correct answer.
This is really weird. What is the difference b/w scanf and cin.
My code
#include<iostream>
#include<stdio.h>
using namespace std;
int main(){
int t,n;
cin>>t;
while(t--){
long long sum=0,sweet;
cin>>n;
for(int i=0; i<n; i++){
//cin>>sweet; printing yes no randomly
scanf("%lld", &sweet); // working correctly
sum = (sum + sweet)%n;
}
if(sum)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
return 0;
}
EDIT: This is a weird question and it is not specified in the question that what should be the size of input. Here is the input specification -
"The first line of the input file contains an integer T specifying the
number of test cases. Each test case is preceded by a blank line. Each
test case looks as follows: The first line contains N : the number of
children. Each of the next N lines contains the number of candies one
child brought."
As many people have noted, you're attempting to read integers which will overflow a long long.
The difference between scanf and cin.operator>>() with respect to integer overflow is that scanf does not (necessarily) test for integer overflow; if the number read is too big, the result is undefined behaviour. It's common that you'll just find an incorrect value in the corresponding argument, but there are no guarantees.
cin.operator>>(), on the other hand, does check for integer overflow, and if it finds integer overflow, it stores the largest possible integer of the indicated type and puts the cin stream into failure state. Once the stream is in failure state, it stays there until the state is cleared; furthermore, any subsequent use of cin.operator>>() will do nothing if the stream is in failure state.
Consequently, once you attempt to read an integer which is too large with cin.operator>>(), your code will find sweet to be the largest possible long long on every subsequent read.
So when using C++ formatted input, you need to always check for failure, and do something appropriate.
You say you're entering values bigger than 1019. That will probably overflow a long long.
Type long long is guaranteed to be at least 64 bits wide, and on every compiler I've seen it's exactly 64 bits wide. That means the maximum possible value of a long long is 263-1, or 9,223,372,036,854,775,807, which is approximately 9 * 1018.
If you enter a value of 1019, or 10,000,000,000,000,000, it will overflow. If cin << ... encounters a numeric overflow, it will fail; you haven't checked for that.
I don't believe that using scanf will solve this problem. scanf has undefined behavior if it reads a number outside the range of the specified type; storing a garbage value is a likely outcome. I can only guess that you're happen to be entering a smaller number with the scanf version of your program than with the cin >> ... version, and didn't notice that you were doing so.
You can use somewhat larger values (at the cost of not being able to store negative values) by using type unsigned long long, which has a minimum value of 0 and a maximum of at least 264-1, or 18,446,744,073,709,551,615, approximately 1.8 * 1019.
If you need even larger numbers, you might consider using floating-point, which gives you a much larger range at the expense of losing precision for large values.
Did you try to test small numbers such as 5, for example ? If it's working it's probably something in the number you enter which is probably out of the maximum that long long int can contain. Just try doing this on your system:
#include <iostream>
#include <stdio.h>
#include <limits>
using namespace std;
int main()
{
std::cout << std::numeric_limits<long long int>::max() << std::endl;
return 0;
}
and check if the value you entered is bigger than the one printed. If so, just declare a variable with enough space for the value, if the value printed is above the value you entered and there's STILL an error, comment on this post.
    I have also encountered this problem, and you can get an ac by scanf and get an error by cin because of the example is special. In fact, if there is an overflowing, using these two input methods will also be wrong.
    For long long type, for question I encountered at "A+B and C (64bit)", if we use the example data "9223372036854775808 -9223372036854775808 0" to A B C, we can get the error answer by the cin and get the correct answer by scanf;However, if we use the example data "9223372036854775808 -9223372036854775808 -1" to A B C, we can get the correct answer by cin and get the error answer by scanf.
    So we should use another method to solve the problem.(or the input data is in ( 2-63, 263 ), and the input data will be legal.)

C++ How to block negative numbers being passed as argument where unsigned is expected

I already saw this thread, however the situation is totally different and I can't apply that solution to my problem.
I have the following constructor:
Fan::Fan(Id id, std::string name, Age age);
Where Id and Age are typedef'ed unsigned int and unsigned short.
This is given to me, so I know that I must use them, as most likely the tester of the assignment will try to use numbers bigger than int (in range of unsigned int / short).
Obviously, a Fan's id and age cannot be negative numbers.
In the example code (to compile against), a fan is created with numbers for id and age. I cannot use string there and check for a minus sign.
I thought it wouldn't compile when I entered negative age / id in my unit testing. However, it turned out it did compile, and it gave random values (most likely due to overflow reasons).
So to conclude - it is possible to call the constructor with negative values for the age and id, but in the constructor their values get 'thrashed' and random numbers appear, and it causes unintended behavior.
For example, this:
Fan* fan = new Fan(-1, "Name", 9);
Compiles, and at run-time the id of the fan gets some unrelated value. So I must be able to detect the negative number in the constructor.
How do I "block" the negative numbers in the constructor?
Thanks for your time! I hope my question is clear.
I created a small function template that checks whether the input lies within the range of the output data type, and throws an exception otherwise. It requires that the input and output data types are integral, and that the size of the input data type is larger than the output data type.
template<typename DestType, typename SrcType>
DestType range_check_and_convert(SrcType const& src)
{
static_assert(sizeof(SrcType) > sizeof(DestType),
"SrcType must be larger than DestType");
static_assert(std::is_integral<SrcType>::value &&
std::is_integral<DestType>::value, "integral types only");
if(src > static_cast<SrcType>(std::numeric_limits<DestType>::max())) {
throw std::out_of_range("input too big");
} else if(src < static_cast<SrcType>(std::numeric_limits<DestType>::min())) {
throw std::out_of_range("input too small");
}
return static_cast<DestType>(src);
}
Live demo
By declaring the contructor to only take unsigned values you basically already "block" that negative numbers can be passed as parameters.
You can still write that you pass -1 to the function, but what the function then sees is the unsigned interpretation of that negative number, see this question.
For example in a 32-bit windows application passing -1 would result in an Id of 0xffffffff or 4294967295. Now you have to decide, whether this is a valid input for your application, but it probably is, because it's still a positive number. On the other hand an age of -1 is probably an invalid input, because it is unlikely to be 4294967295 years old. As you noticed, you can't check your unsigned value for -1. You have to check if age is bigger than for example 200, because -1 is effectively a large number when given as an unsigned parameter.

Non-Integer numbers in an String and using atoi

If there are non-number characters in a string and you call atoi [I'm assuming wtoi will do the same]. How will atoi treat the string?
Lets say for an example I have the following strings:
"20234543"
"232B"
"B"
I'm sure that 1 will return the integer 20234543. What I'm curious is if 2 will return "232." [Thats what I need to solve my problem]. Also 3 should not return a value. Are these beliefs false? Also... if 2 does act as I believe, how does it handle the e character at the end of the string? [Thats typically used in exponential notation]
You can test this sort of thing yourself. I copied the code from the Cplusplus reference site. It looks like your intuition about the first two examples are correct, but the third example returns '0'. 'E' and 'e' are treated just like 'B' is in the second example also.
So the rules are
On success, the function returns the converted integral number as an int value.
If no valid conversion could be performed, a zero value is returned.
If the correct value is out of the range of representable values, INT_MAX or INT_MIN is returned.
According to the standard, "The functions atof, atoi, atol, and atoll need not affect the value of the integer expression errno on an error. If the value of the result cannot be represented, the behavior is undefined." (7.20.1, Numeric conversion functions in C99).
So, technically, anything could happen. Even for the first case, since INT_MAX is guaranteed to be at least 32767, and since 20234543 is greater than that, it could fail as well.
For better error checking, use strtol:
const char *s = "232B";
char *eptr;
long value = strtol(s, &eptr, 10); /* 10 is the base */
/* now, value is 232, eptr points to "B" */
s = "20234543";
value = strtol(s, &eptr, 10);
s = "123456789012345";
value = strtol(s, &eptr, 10);
/* If there was no overflow, value will contain 123456789012345,
otherwise, value will contain LONG_MAX and errno will be ERANGE */
If you need to parse numbers with "e" in them (exponential notation), then you should use strtod. Of course, such numbers are floating-point, and strtod returns double. If you want to make an integer out of it, you can do a conversion after checking for the correct range.
atoi reads digits from the buffer until it can't any more. It stops when it encounters any character that isn't a digit, except whitespace (which it skips) or a '+' or a '-' before it has seen any digits (which it uses to select the appropriate sign for the result). It returns 0 if it saw no digits.
So to answer your specific questions: 1 returns 20234543. 2 returns 232. 3 returns 0. The character 'e' is not whitespace, a digit, '+' or '-' so atoi stops and returns if it encounters that character.
See also here.
If atoi encounters a non-number character, it returns the number formed up until that point.
I tried using atoi() in a project, but it wouldn't work if there were any non-digit characters in the mix and they came before the digit characters - it'll return zero. It seems to not mind if they come after the digits, for whatever reason.
Here's a pretty bare bones string to int converter I wrote up that doesn't seem to have that problem (bare bones in that it doesn't work with negative numbers and it doesn't incorporate any error handling, but it might be helpful in specific instances). Hopefully it might be helpful.
int stringToInt(std::string newIntString)
{
unsigned int dataElement = 0;
unsigned int i = 0;
while ( i < newIntString.length())
{
if (newIntString[i]>=48 && newIntString[i]<=57)
{
dataElement += static_cast<unsigned int>(newIntString[i]-'0')*(pow(10,newIntString.length()-(i+1)));
}
i++;
}
return dataElement;
}
I blamed myself up to this atoi-function behaviour when I was learning-approached coding program with function calculating integer factorial result given input parameter by launching command line parameter.
atoi-function returns 0 if value is something else than numeral value and "3asdf" returns 3. C -language handles command line input parameters in char -array pointer variable as we all already know.
I was told that down at the book "Linux Hater's Handbook" there's some discussion appealing for computer geeks doesn't really like atoi-function, it's kind of foolish in reason that there's no way to check validity of given input type.
Some guy asked me why I don't brother to use strtol -function located on stdlib.h -library and he gave me an example attached to my factorial-calculating recursive method but I don't care about factorial result is bigger than integer primary type value -range, out of ranged (too large base number). It will result in negative values in my program.
I solved my problem with atoi-function first checking if given user's input parameter is truly numerical value and if that matches, after then I calculate the factorial value.
Using isdigit() -function located on chtype.h -library is following:
int checkInput(char *str[]) {
for (int x = 0; x < strlen(*str); ++x)
{
if (!isdigit(*str[x])) return 1;
}
return 0;
}
My forum-pal down in other Linux programming forum told me that if I would use strtol I could handle the situations with out of ranged values or even parse signed int to unsigned long -type meaning -0 and other negative values are not accepted.
It's important upper on my code check if charachter is not numerical value. Negotation way to check this one the function returns failed results when first numerical value comes next to check in string. (or char array in C)
Writing simple code and looking to see what it does is magical and illuminating.
On point #3, it won't return "nothing." It can't. It'll return something, but that something won't be useful to you.
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
On success, the function returns the converted integral number as an int value.
If no valid conversion could be performed, a zero value is returned.
If the correct value is out of the range of representable values, INT_MAX or INT_MIN is returned.