C++ - Getting Byte from Console - c++

I am new to C++ and coming from a C# / Java background I feel like I am kind of spoilt.
What I am trying to achieve here is to get the data input by the user as byte (unsigned char) using cin.
#include <iostream>
using namespace std;
typedef unsigned char byte;
int main()
{
byte num = 0;
char exitKey = '0';
cout << "Type in a number between 0 and 255.\n";
cin >> num;
cout << "\nYour number multiplied by 2 is:\n" << (num * 2);
cin >> exitKey;
return 0;
}
The value returned is the ASCII decimal value of the character I typed in. How can I get the actual value, treating the value as a number?
Help is appreciated. Thanks.

It doesn't matter what type-aliases you use, when reading using cin >> a character is always a character, and will be read as a character.
The value you are getting is the ASCII code for the character '1'.
If you want to read it as a number, then use a proper numeric datatype, like int.

Since you are using char datatype here. The 1 value entered here is considered as character and ASCII value of 1 (49) is getting stored and 49 * 2 = 98 is getting printed.
Instead of char use int as datatype.

Related

Taking user input of an integer that can only be limited 1 digit

i'm currently learning c++ and have a project that I'm currently working on. My program in its entirety is to randomize 3 numbers from values 0-9 or set them myself. I was able to get the randomize numbers to work but not the setting of numbers myself. The issue being that when i tried to have the numbers as the int data type it produced 3 numbers for one input. It should be that x = 1, y = 2, z =3.... vales are: 123. To counter this issue I made the data type a character instead but it bugs me that random numbers are int values and my set numbers are char values. This is my current code below:
if ( userInput == 's') {
cout << "Enter three distinct digits each in the range 0..9 (e.g. 354)";
char num1 = ' ';
char num2 = ' ';
char num3 = ' ';
cin >> num1 >> num2 >> num3;
cout << endl << "Values to guess are: " << num1 << num2 << num3;
This might help you understand better what you're looking for.
Consider for example using:
int x;
cin >> x; // read an integer from the standard input stream (ignoring initial white space)
This will read a single integer from standard in, while
char c;
cin >> c; // read a character from standard input stream (ignoring initial white space)
read a single character from standard in (generally an ASCII character value).
If you have the following in standard input:
354
the first will finish with x = 354 and the second with c = '3' // = 51.
From my understanding you want to read 3 digits from standard in and store them in 3 separate numeric data types. You can do this using the following code:
uint8_t get_digit() {
char c;
cin >> c; // read a single non-whitespace character
if (! is_digit(c) ) return -1; // Error did not read a digit return bogus number
return (uint8_t)(c - '0'); // convert ascii digit to number and return value
}
This code will read a single character and check if it was a digit, if not it returns a bogus result (-1) othewise it returns the numeric value of the digit.

Manually converting a char to an int - Strange behaviour

I've wrote a small program to convert a char to an int. The program reads in chars of the form '1234' and then outputs the int 1234:
#include <iostream>
using namespace std;
int main(){
cout << "Enter a number with as many digits as you like: ";
char digit_char = cin.get(); // Read in the first char
int number = digit_char - '0';
digit_char = cin.get(); // Read in the next number
while(digit_char != ' '){ // While there is another number
// Shift the number to the left one place, add new number
number = number * 10 + (digit_char - '0');
digit_char = cin.get(); // Read the next number
}
cout << "Number entered: " << number << endl;
return 0;
}
This works fine with small chars, but if I try a big char (length 11 and above) like 12345678901 the program returns the wrong result, -539222987.
What's going on?
12345678901 in binary is 34 bits. As a result, you overflowed the integer value and set the sign bit.
Type int is not wide enough to store such big numbers. Try to use unsigned long long int instead of the type int.
You can check what maximum number can be represented in the given integer type. For example
#include <iostream>
#include <limits>
int main()
{
std::cout << std::numeric_limits<unsigned long long int>::max() << std::endl;
}
In C you can use constant ULLONG_MAX defined in header <limits.h>
Instead of using int, try to use unsigned long long int for your variable number.
That should solve your problem.
Overflowed integer. Use unsigned long long int.

C++ stringstream, if word is numeric, divide by two

I am fairly new to programming and have to create a program which reads the prompt: "I have 8 dollars to spend." It then needs to print out with each word on a separate line, and then if any of the strings is numeric, it needs to be divided by 2. Therefore it should end up printing out as:
I
have
4
dollars
to
spend.
I have managed to do everything, except finding the numeric value and dividing it by 2. So far I have this:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
string prompt;
string word;
cout << "Prompt: ";
getline(cin, prompt);
stringstream ss;
ss.str(prompt);
while (ss >> word)
{
cout << word << endl;
}
return 0;
}
After looking through various other posts, I cannot manage to get this to work. I'm assuming its an if/else statement within the while loop along the lines of, if numeric, set int num to num / 2 then cout << num << endl;, else cout << word << endl;, but I can't figure it out.
Thanks in advance.
You can use the stringstream class, which handles conversions between strings and other data types, to attempt to convert a given string to a number. If the attempt is successful, you know
The stringstream object allows you to treat a string as though it is a stream similar to cin or cout.
Incorporate this into your while loop, like so:
while (ss >> word)
{
int value = 0;
stringstream convert(word); //create a _stringstream_ from a string
//if *word* (and therefore *convert*) contains a numeric value,
//it can be read into an _int_
if(convert >> value) { //this will be false if the data in *convert* is not numeric
cout << value / 2 << endl;
}
else
cout << word << endl;
}
The strtol (C++11 version that works on std::string directly: std::stol) function is really good for testing whether a string holds a number, and if so, what the numeric value is.
Or you could continue using iostreams like you have been... try extracting a number (int or double variable), and if that fails, clear the error bit and read a string.
I dont have 50 rep so I cant comment, thats why I'm writing it as answer.
I think you can check it character by character, using Ascii value of each char, & if there are ascii values representing numbers between two spaces(two \n in this case as you've already seperated each word), then you have to divide the number by 2.

Take two hex characters from file and store as a char with associated hex value

I'd like to take the next two hex characters from a stream and store them as the associated associated hex->decimal numeric value in a char.
So if an input file contains 2a3123, I'd like to grab 2a, and store the numeric value (decimal 42) in a char.
I've tried
char c;
instream >> std::setw(2) >> std::hex >> c;
but this gives me garbage (if I replace c with an int, I get the maximum value for signed int).
Any help would be greatly appreciated! Thanks!
edit: I should note that the characters are guaranteed to be within the proper range for chars and that the file is valid hexadecimal.
OK I think dealing with ASCII decoding is a bad idea at all and does not really answer the question.
I think your code does not work because setw() or istream::width() works only when you read to std::string or char*. I guess it from here
How ever you can use the goodness of standard c++ iostream converters. I came up with idea that uses stringstream class and string as buffer. The thing is to read n chars into buffer and then use stringstream as a converter facility.
I am not sure if this is the most optimal version. Probably not.
Code:
#include <iostream>
#include <sstream>
int main(void){
int c;
std::string buff;
std::stringstream ss_buff;
std::cin.width(2);
std::cin >> buff;
ss_buff << buff;
ss_buff >> std::hex >> c;
std::cout << "read val: " << c << '\n';
}
Result:
luk32#genaker:~/projects/tmp$ ./a.out
0a10
read val: 10
luk32#genaker:~/projects/tmp$ ./a.out
10a2
read val: 16
luk32#genaker:~/projects/tmp$ ./a.out
bv00
read val: 11
luk32#genaker:~/projects/tmp$ ./a.out
bc01
read val: 188
luk32#genaker:~/projects/tmp$ ./a.out
01bc
read val: 1
And as you can see not very error resistant. Nonetheless, works for the given conditions, can be expanded into a loop and most importantly uses the iostream converting facilities so no ASCII magic from your side. C/ASCII would probably be way faster though.
PS. Improved version. Uses simple char[2] buffer and uses non-formatted write/read to move data thorough the buffer (get/write as opposed to operator<</operator>>). The rationale is pretty simple. We do not need any fanciness to move 2 bytes of data. We ,however, use formatted extractor to make the conversion. I made it a loop version for the convenience. It was not super simple though. It took me good 40 minutes of fooling around to figure out very important lines. With out them the extraction works for 1st 2 characters.
#include <iostream>
#include <sstream>
int main(void){
int c;
char* buff = new char[3];
std::stringstream ss_buff;
std::cout << "read vals: ";
std::string tmp;
while( std::cin.get(buff, 3).gcount() == 2 ){
std::cout << '(' << buff << ") ";
ss_buff.seekp(0); //VERY important lines
ss_buff.seekg(0); //VERY important lines
ss_buff.write(buff, 2);
if( ss_buff.fail() ){ std::cout << "error\n"; break;}
std::cout << ss_buff.str() << ' ';
ss_buff >> std::hex >> c;
std::cout << c << '\n';
}
std::cout << '\n';
delete [] buff;
}
Sample output:
luk32#genaker:~/projects/tmp$ ./a.out
read vals: 0aabffc
(0a) 0a 10
(ab) ab 171
(ff) ff 255
Please note, the c was not read as intended.
I found everything needed here http://www.cplusplus.com/reference/iostream/
You can cast a Char to an int and the int will hold the ascii value of the char. For example, '0' will be 48, '5' will be 53. The letters occur higher up so 'a' will be cast to 97, 'b' to 98 etc. So knowing this you can take the int value and subtract 48, if the result is greater than 9, subtract another 39. Then char 0 will have been turned to int 0, char 1 to int 1 all the way up to char a being set to int 10, char b to int 11 etc.
Next you will need to multiply the value of the first by 16 and add it to the second to account for the bit shift. Using your example of 2a.
char 2 casts to int 50. Subtract 48 and get 2. Multiply by 16 and get 32.
char a casts to int 97. Subtract 48 and get 49, this is higher than 9 so subtract another 39 and get 10. Add this to the end result of the last one (32) and you get 42.
Here is the code:
int HexToInt(char hi, char low)
{
int retVal = 0;
int hiBits = (int)hi;
int loBits = (int)low;
retVal = Convert(hiBits) * 16 + Convert(loBits);
return retVal;
}
int Convert(int in)
{
int retVal = in - 48;
//If it was not a digit
if(retVal > 10)
retVal = retVal - 7;
//if it was not an upper case hex didgit
if(retVal > 15)
retVal = retVal - 32;
return retVal;
}
The first function can actually be written as one line thus:
int HexToInt(char hi, char low)
{
return Convert((int)hi) * 16 + Convert((int)low);
}
NOTE: This only accounts for lower case letters and only works on systems that uses ASCII, i.e. Not IBM ebcdic based systems.

Reading character by character to see if it is a digit

I need help with this if statement. Im trying to read each character to see if it is a number. If it is not a digit then say it is not a number if it is continue reading on to the next character. for example if the user inputs 54gr 21 gr42 134 3f3. the only thing that would cout is 21 and 134.
#include <iostream> // libraries
#include <iomanip>
#include <string>
using namespace std;
int main()
{
char string[80];
// char num[80];
// char good[80];
cout << "enter a string "; // prompting user
cin.getline(string,80); // geting line
// int i = 0;
// int j = 0;
int count = 0;
{
while(string[count] != '\0') {
if(string[count] >= '0' && string[count] <= '9' )
cout << count << endl;
}
++ count;
}
}
I would not try to do this character by character. The problem is that you don't now that 5 is really part of a number until you've read to the end of the string of non-space characters to verify that all the contents are legitimately part of a number.
As such, I think you need/want to break the input up into "words", then check whether each complete word can be converted entirely to a number. You can read "words" with just some_stream >> some_string;
Once you have a "word" you check whether you can convert it entirely to a number. Assuming you want integers, you use strtol to (try to) convert it to a number. That will give you a pointer to the first character it couldn't convert as a number. If that's not the end of the string, then that "word" wasn't a number (even if it started with/contained one or more digits).