c++ weird problem converting a char to int - c++

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.

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.

C++ char array value assignment

I'm trying to keep the alphabet in a char array. But 4 letters show absurd charachters.
I run the program step by step using F11 button. Wrote the alphabet and after 'Q', until 'V' whatever I write, it shows ...PQÿÿÿÿVWXYZ this character: 'ÿ'
int main()
{
cout << "ALPHABET:";
char alf[] = "";
cin >> alf;
system("PAUSE");
}
I expect: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Actual result: ABCDEFGHIJKLMNOPQÿÿÿÿVWXYZ
Problem is with this line:
char alf[] = "";
you declare char array with size 1 which can only hold empty strings (null terminator). Note that std::istream::operator>> with char * does not validate size of array (it cannot) so you are getting Undefined Behavior writing into array with out of bounds. Solution is to use std::string instead which will grow as needed.
int main()
{
std::cout << "ALPHABET:";
std::string alf;
std::cin >> alf;
std::cout << alf << std::endl;
}

The last characters in my C-style string are odd values when I

for our assignment we have to work with C-style strings in C++, and reverse an input, however when I have a string of 6 or more characters it outputs the reversed string as well as some garbage values. Any help for fixing this is appreciated.
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
const int SIZE = 11;
char name[SIZE];
cout << "Please enter a name of 10 characters or less ";
cin.getline(name, SIZE);
char *stringStart, *stringEnd;
stringStart = name;
stringEnd = &name[strlen(name)-1];
char backwardsName[SIZE];
int i = 0;
// Appending each element to backwardsName starting with last character from name and decrementing.
while (stringEnd >= stringStart)
{
backwardsName[i] = *stringEnd;
++i;
--stringEnd;
}
cout << backwardsName << endl;
return 0;
}
I have tried using pointers to even ending the backwardsName string with a NULL character '\0' to no avail. The pointers did the same thing. The NULL character did help, but it started to break down when strings were 8 or more characters (I think).
The issue is with NUL termination. You did not put a \0 after reversing backwardsName.
backwardsName[i] = '\0';
cout << backwardsName << endl;

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

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;
}

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;
}