Storing a char into an int variable - c++

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.

Related

isdigit(c) - a char or int type?

I have written the following code to test if the given input is a digit or not.
#include<iostream>
#include<ctype.h>
#include<stdio.h>
using namespace std;
main()
{
char c;
cout<<"Please enter a digit: ";
cin>>c;
if(isdigit(c)) //int isdigit(int c) or char isdigit(char c)
{
cout<<"You entered a digit"<<endl;
}
else
{
cout<<"You entered a non-digit value"<<endl;
}
}
My question is: what should be the input variable type? char or int?
The situation is unfortunately a bit more complex than has been told by the other answers.
First of all: the first part of your code is correct (disregarding multiple-byte encodings); if you want to read a single char with cin, you'll have to use a char variable with >> operator.
Now, about isdigit: why does it take an int instead of a char?
It all comes from C; isdigit and its companion were born to be used along with functions like getchar(), which read a character from the stream and return an int. This in turn was done to provide the character and an error code: getchar() can return EOF (which is defined as some implementation-defined negative constant) through its return code to signify that the input stream has ended.
So, the basic idea is: negative = error code; positive = actual character code.
Unfortunately, this poses interoperability problems with "regular" chars.
Short digression: char ultimately is just an integral type with a very small range, but a particularly stupid one. In most occasions - when working with bytes or character codes - you'd want it to be unsigned by default; OTOH, for coherency reasons with other integral types (int, short, long, ...), you may say that the right thing would be that plain char should be signed. The Standard chose the most stupid way: plain char is either signed or unsigned, depending from whatever the implementor of the compiler decides1.
So, you have to be prepared for char being either signed or unsigned; in most implementations it's signed by default, which poses a problem with the getchar() arrangement above.
If char is used to read bytes and is signed it means that all bytes with the high bit set (AKA bytes that, read with an unsigned 8-bit type would be >127) turn out to be negative values. This obviously isn't compatible with the getchar() using negative values for EOF - there could be overlap between actual "negative" characters and EOF.
So, when C functions talk about receiving/providing characters into int variables the contract is always that the character is assumed to be a char that has been cast to an unsigned char (so that it is always positive, negative values overflowing into the top half of its range) and then put into an int. Which brings us back to the isdigit function, which, along its companion functions, has this contract as well:
The header <ctype.h> declares several functions useful for classifying and mapping characters. In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.
(C99, §7.4, ¶1)
So, long story short: your if should be at the very least:
if(isdigit((unsigned char)c))
The problem is not just a theoretical one: several widespread C library implementations use the provided value straight as an index into a lookup table, so negative values will read into unallocated memory and segfault your program.
Also, you are not taking into account the fact that the stream may be closed, and thus >> returning without touching your variable (which will be at an uninitialized value); to take this into account, you should check if the stream is still in a valid state before working on c.
Of course this is a bit of an unfair rant; as #Pete Becker noted in the comment below, it's not like they were all morons, but just that the standard mostly tried to be compatible with existing implementations, which were probably evenly split between unsigned and signed char. Traces of this split can be found in most modern compilers, which can generally change the signedness of char through command line options (-fsigned-char/-funsigned-char for gcc/clang, /J in VC++).
If you want to read a single character and check whether it is a digit or not then it should be char.
If you set it as int then multiple characters will be read and the result of isDigit will always be true.

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

array of char is equal to int?

I am trying to figure out why an array of char is assigned to a int value, now I am a little confused in using cast operator.
I didn't get what is in do statement, I hope somebody can explain
char *readword()
{
int c,i;
char t[255];
char *p;
//jump over chars who aren't letters
while ((c=getchar())<'A'|| (c>'Z' && c<'a') || c>'z')
if (c==EOF) return 0;
i=0;
do {
t[i++]=c;// shouldn't be like (char)c
} while ((c=getchar())>='A' && c<='Z' || c>='a' && c<='z');
//keep the word in heap memory
if ( c==EOF)
return 0;
t[i++]='\0';
if ((p=(char *)malloc(i))==0)
{
printf(" not enough memory\n");
exit(1);
}
strcpy(p,t);
return p;
}
The getchar() function returns an int type; and it is important to use an int to capture the getchar() return value. This is due to if getchar() fails, it returns an (int)(EOF)(as per chux comment. When it successfully returns, it will return a value that is suitable for a char.
The question code is building a char string or array, one char at a time:
t[i++]=c;
The above line could be written:
t[i++]=(char)c;
Either is suitable due to the compiler automatically converting the first case.
The mixture of char and int is fairly simple: EOF is intended as a file that can be distinguished from any value you could have read from the file.
To support that, you need to initially read the data from the file into something larger than a char, so it can accommodate at least one value that couldn't possibly have come from the file. The type they chose for that purpose was int.
So, you read a character from the file, into an int. You compare that to EOF to see if it's really a character that came from the file or not. If (and only if) you verify that it really came from the file, you save the value into a char, because you now know that's what it really represents.
That said, I'd consider it pretty poor code as it stands right now. Just for one particularly obvious example, instead of the c<'A'|| (c>'Z' && c<'a') || c>'z') type of code, you almost certainly want to use isalpha(c) instead.
It's also a lot easier to do this with scanf instead.
You can assign any int value to a char. Only the lowest 8 bits will be used. A cast would be more "correct" in terms of communicating your intent - people might not otherwise remember that anything larger than an 8-bit value will get truncated and results are likely to be unexpected.
Note that since you didn't say "unsigned char t[255]" that you actually get 7 bits and the most significant (8th) bit will be interpreted as a sign. So for example if you were to say
char t = 0xFF;
then you would in fact get -1 assigned to t.
If you assign numbers > 0xFF then all bits higher than the 8th bit will get stripped. So if you were to say:
char t = 0x101;
Than in fact you'd get the value 1 assigned to t.
The code in question is correct because getchar() returns an int and -1 is an error value so it's important to check it. For non-error cases the return will fit in an 8-bit char.

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.