why std::cin doesn't give error on "char" - c++

Here is a small code:
char a;
while(std::cin >> a) {
std::cout << a << " is pressed\n";
}
When I type in "w", i get "w is pressed".
When I type in "www", i get "w is pressed" 3 times in a row.
Can someone please explain why this happens?
Thanks

When you use std::cin to read a char variable it reads one character at a time. That is why you get 3 iterations in the while loop for input www.

There is a queue of inputs. if you entered too much, your input waits in patient...

The first part of the answer is on the first line of your code.
char a;
Variable a is a single char, an 8-bit value typically used to store a code representing a display character. If the display is ASCII, then (value) 0 = no character, (value) 32 = space, value 48 = (character) '0', etc.
std::cin is an instance of class std::istream, it has various members and operator overloads to deal with different types. In the case of a char, you are calling
std::istream::operator(char)
Which reads one char, exactly one, from the input stream and returns.
#include <iostream>
int main()
{
char a, b, c;
std::cin >> a >> b >> c;
std::cout << "a = " << a << ", b = " << b << ", c = " << c << '\n';
return 0;
}

Related

Assigning char type to int to print corresponding ASCII character

The code asks for a positive integer, than the first output shows the corresponding ASCII code, the others are made to convert the integer to decimal, octal and hexadecimal equivalents. I understand the logic of the code, but I don't understand the assignment made on line 10 c=code than the assignment made on line 12 code=c. What happens on background when we 'swap' the two variables.
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
unsigned char c = 0;
unsigned int code = 0;
cout << "\nPlease enter a decimal character code: ";
cin >> code;
c = code;
cout << "\nThe corresponding character: " << c << endl;
code = c;
cout << "\nCharacter codes"
<< "\n decimal: " << setw(3) << dec << code
<< "\n octal: " << setw(3) << oct << code
<< "\n hexadecimal: " << setw(3) << hex << code
<< endl;
return 0;
}
I could be wrong here so maybe someone else can weigh in, but I believe I know the answer.
If you assign a character a number, when you print that char it prints the corresponding character. Since c is of type char, the line c = code converts the integer entered into a character. You can test this yourself by assigning any int to a char variable and printing it out.
The second assignment, code = c, seems to be completely unnecessary.
That's not a swap. c is assigned the same value as code and then this value is assigned back to code. The original value of code is lost.
We can see this because unsigned char c is (usually) much smaller than unsigned int code and some information may be lost stuffing the value in code into c.
For example, code = 257. After c = code; code is still 257 and c, assuming an 8 bit char will be 1. After code = c;, both code and c will be 1. 257 has been lost.
Why is this being done? when given a char, operator<< will print out the character encoded, completely ignoring the request to print as hex, dec, or oct. So
<< "\n decimal: " << setw(3) << dec << c
is wasted. Given an int << will respect the modifiers, but if c and code have different values, you're comparing apples and Sasquatches.

hex char to decimal and store output as char

I am writing a hex to dec conversion function. The input is a single character which is converted to hex and returned back as a char.
Here is the function
char hex2dec(char inp)
{
char out;
cout << "inp:" << inp;
if(inp >= '0' && inp <='9')
{
out = (inp - '0');
cout << " out " << out;
}
else
{
out = (toupper(inp) - 'A' + 10);
cout << " out " << out;
}
return out;
}
When i pass '0' and 'A' to the function, the print i get is
inp:0 out
inp:A out
i.e nothing is printed in out.
I am not able to find the issue..Can anyone help?
What you are actually trying to print is ascii characters with codes [0-15] which are not printable characters ie you want to print 15 but you print "\x0f" etc
use:
cout << (int)out;
and you'll force cout to invoke method printing ints not chars - this will solve your issue.
..or more 'c++++ ish' ;-)
cout << static_cast(out);
..or this which for most looks weird:
cout << int(out);
Use int out instead of char out. cout prints char as a character not an integer. The ASCII values 0-15 are unprintable control characters.
the reason why u got an 'A' from print is that out is char ,and after 'A' - 'A' + 10, out is a character whose ascii value is 10 instead of integer 10. So u will get a character whose ascii value is 10 instead of getting 'A'.After checking the ascii table, that character is null,which can explain why u get nothing in the output.
Simply use std::stringstream for this purpose.
#include <iostream>
#include <sstream>
int main (int argc, char ** argv)
{
// use hex formatting
std::stringstream stream;
stream << std::hex << 'A';
// retrieve value of the hex input character
int value;
stream >> value;
std::cout << value << std::endl; // prints 10
// reset the stream
stream.str ();
stream.clear();
// also works for strings
stream << "0xABC" << std::endl;
stream >> value;
std::cout << value << std::endl; // prints 2748
return 0;
}

cout not printing unsigned char

I am working on below code:
#include<iostream>
#include<stdio.h>
using namespace std;
main() {
unsigned char a;
a=1;
printf("%d", a);
cout<<a;
}
It is printing 1 and some garbage.
Why cout is behaving so?
cout << a is printing a value which appears to be garbage to you. It is not garbage actually. It is just a non-printable ASCII character which is getting printed anyway. Note that ASCII character corresponding to 1 is non-printable. You can check whether a is printable or not using, std::isprint as:
std::cout << std::isprint(a) << std::endl;
It will print 0 (read: false) indicating the character is non-printable
--
Anyway, if you want your cout to print 1 also, then cast a to this:
cout << static_cast<unsigned>(a) << std::endl;
I had a similar issue here that I've long forgotten about. The resolution to this problem with iostream's cout can be done like this:
#include<iostream>
#include<stdio.h>
main() {
unsigned char a;
a=1;
printf("%d", a);
std::cout<< +a << std::endl;
return 0;
}
instead of casting it back to another type if you want cout to print the unsigned char value as opposed to the ascii character. You need to promote it.
If you noticed all I did was add a + before the unsigned char. This is unary addition that will promote the unsigned char to give you the actual number representation.
User Baum mit Augen is responsible for reminding me of this solution.
You need to typecast a as integer as cout<< (int)(a);. With this you will observe 1 on the output. With cout << a;, the print will be SOH (Start of Heading) corresponding to ascii value of 1 which can't be printed and hence, some special character is observed.
EDIT:
To be more accurate, the cout statement should be cout << static_cast<unsigned>(a) as Nawaz has mentioned.
The C compiler has its own way of defining the type of the printed output, because you can specify the type of the output.
Ex:
uint8_t c = 100;
printf("%d",c);
so you can also print c as an int by %d, or char %c, string %s or a hex value %x.
Where C++ has its own way too, the cout prints the 8-bit values as a char by default. So, you have to use specifiers with the output argument.
You can either use:
a + before the name of the output argument
uint8_t data_byte = 100;
cout << "val: " << +data_byte << endl;
use a function cast unsigned(var); like,
uint8_t data_byte = 100;
cout << "val: " << unsigned(data_byte) << endl;
printf("%u",a);
its so simple try it

c++ weird problem converting a char to int

I'm a total newbie to C++ and I was trying to do one of the problems from Project Euler when I had a very weird problem. I reduced the error to the following.
Consider the following simple code:
#include <iostream>
using namespace std;
int main() {
int numdigits;
cout << "digits: ";
cin >> numdigits;
char tmpchar;
cin >> tmpchar;
cout << atoi(&tmpchar) << endl;
return 0;
}
Basically if the first input (numdigits) is below 48 everything works fine but if the input is 48 or greater if have a very weird behaviour:
air:programming santi$ ./lol
digits: 30
3
3 <--- OK
air:programming santi$ ./lol
digits: 48
3
30 <--- Not OK
air:programming santi$ ./lol
digits: 49
3
31 <--- Not OK
air:programming santi$ ./lol
digits: 50
3
32 <--- Not OK
What is going on? I got mad trying to find the error in the algorithm until I found out that the error was in that part of the code where I didn't bother to look at first.
Thanks in advance!
The problem is here:
char tmpchar;
cin >> tmpchar;
cout << atoi(&tmpchar) << endl;
atoi expects a NUL-terminated string, which isn't what you're giving it (there's no NUL character except that you may be sometimes getting one by chance).
A possible (ugly) fix is:
char tmpchar[2] = {0};
cin >> tmpchar[0];
cout << atoi(tmpchar) << endl;
If you're dealing with multiple-character strings, then using std::string would be the way to go:
std::string str;
cin >> str;
cout << atoi(str.c_str()) << endl;
atoi(&tmpchar)
I think this would simply invoke undefined behaviour. Because the type of &tmpchar is char* which is correct c-string type, but its not null-teminated string.
Why don't you simply do this:
int i = tmpchar - '0';
cout << i << endl; //prints whatever single-digit you enter for tmpchar
Or if you want to print the ASCII value of tmpchar, then do this:
int i = tmpchar;
cout << i << endl; //prints the ASCII value of tmpchar
Or even simpler:
cout << (int) tmpchar << endl; //prints the ASCII value of tmpchar
atoi() takes a NUL ('\0') terminated character pointer. You're pointing it at the first character, but there is no guarantee that the second character is NUL. Try the following.
#include <iostream>
using namespace std;
int main() {
int numdigits;
cout << "digits: ";
cin >> numdigits;
char tmpchar[2];
cin >> tmpchar[0];
tmpchar[1] = '\0';
cout << atoi(tmpchar) << endl;
return 0;
}
atoi takes a null-terminated string as an argument. That is an array of characters with a null character ('\0') at the end.
+---+---+---+
|'1'|'0'|\0 | = "10"
+---+---+---+
You are passing the address of a single character. But there is no terminating null character!
+---+---+---+
|'3'| ? | ? | = ?
+---+---+---+
This is undefined behaviour, and that's why you get weird results.
You can obtain a number from a single digit character in a safe manner like this:
int number = digit - '0';
The argument to atoi must be a null-terminated array of characters, not just a pointer to one character.
char tmpchar[2] = {0};
cin >> tmpchar[0];
cout << atoi(&tmpchar) << endl;
Here {0} sets all array elements to 0, cin reads the first one, the second character remains null, so &tmpchar makes a pointer to a character array that is terminated with null character.

why it always give zero output?

int i;
cin>>i;
cout<<i
when we entered Character i.e 'A' why it gives Zero output ?
Because A is not a numeric value suitable for storing in an integer, so it will leave your integer alone, as shown here:
#include <iostream>
int main (void) {
int i = 12345;
std::cin >> i;
std::cout << i << std::endl;
return 0;
}
When you run that code and enter A, it outputs 12345 as the value doesn't change.
If you want truly robust input, it's usually better to input lines as strings then convert them yourself.
"Mickey-mouse" programs or those where you have total control over the input can use the sort of input methods you're using, serious code should use more suitable methods.
If your intent is to convert an input character into its integer code, you can use something like:
#include <iostream>
int main (void) {
char c;
std::cin >> c;
std::cout << (int)c << std::endl;
return 0;
}
You should always check if the operation succeeded before continuing.
int i;
if (cin >> i)
cout << i;
else
cout << "Not a valid number!";
because the value 'A' is not stored in the variable i since it is a integer variable. i believe that is the reason the initial value 12345 is printed on the screen...