hex char to decimal and store output as char - c++

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

Related

Issues replacing a char within a c++ string using string.replace()

I am writing a program that uses a substitution cipher.
I am trying to replace each char in a string (that the user entered) with a char from another string (the encryption key string).
But I am having a bunch of issues doing this with the string.replace() function. It does not replace the the char in the userMessage with the correct char. Although this is not an issue when using a string literal as initialization value for letterReplacement. In addition to this, it somehow temporarily increases the size of the userMessage resulting in the loop running for e.g 5 times in a message 3 char long (no matter how letterReplacement was initialized). I would appreciate any information on why this happens.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string userMessage;
std::cout << "\nWelcome to my Military Grade* Encryption Software!" << std::endl;
std::cout << "--------------------------------------------------" << std::endl << std::endl;
std::cout << "Please enter a secret message you would like to encrypt:\n-" << std::endl;
getline(std::cin, userMessage);
std::cout << "-" << std::endl << std::endl;
const std::vector <std::string> encryptionKey {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZT.,<>!?+- '",
"ß?pl ,;0=}okm9)]ijN8([uhb7/{zgv6&ctf%xdrys4$e3w|<2Q>1!+#ä-:*GnB"};
for(size_t i {0}; i < userMessage.size(); ++i) // Here we encrypt the Message
{
char currentCharInUM {userMessage.at(i)};
size_t currentKeyPosition {encryptionKey.at(0).find(currentCharInUM)}; //finds the position that currentChar is at in first encryptionKey String
std::cout << "currentKeyPosition: " << currentKeyPosition << " - " << i << std::endl;
if(currentKeyPosition == std::string::npos) // is letter in userMessage is not in encryptionKey just keep it (skip iteration)
continue;
std::string letterReplacement {encryptionKey.at(1).at(currentKeyPosition)};
userMessage.replace(i,1,letterReplacement);
}
std::cout << userMessage;
return 0;
}
The first character of 2nd element of the vector encryptionKey 'ß' is equal to 2 bytes. So that when you enter 'a' it returns '├' and when you enter b it returns 'ş'. You can try to put another character instead of 'ß'.
If your intention was indeed to store non-ASCII characters, it would have been more advantageous to use a lookup table.
The table could be a std::unordered_map<char, wchar_t> to map the English letters to the encrypted characters:
#include <iostream>
#include <string>
#include <unordered_map>
int main()
{
// Strings
const char encryptionKeyA[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZT.,<>!?+- '";
const wchar_t encryptionKeyW[] = L"ß?pl ,;0=}okm9)]ijN8([uhb7/{zgv6&ctf%xdrys4$e3w|<2Q>1!+#ä-:*GnB";
// Create the lookup table bassed on the above strings
std::unordered_map<char, wchar_t> encryptionMap;
for (int i = 0; i < sizeof(encryptionKeyA); ++i)
encryptionMap[encryptionKeyA[i]] = encryptionKeyW[i];
// Test
std::string userMessage = "abcTest";
// The output string
std::wstring encryptedString;
// Now go through each character of the userMessage
for(auto ch : userMessage)
{
// If the character exists, append the associated encrypted character
auto iter = encryptionMap.find(ch);
if (iter != encryptionMap.end())
encryptedString += iter->second;
else
encryptedString += L' '; // Just append a space if it didn't exist
}
std::wcout << encryptedString;
}
Output:
ss?p1 N8
Note that the output is what is displayed if the locale is English. If the terminal/output were set to German, I would assume that the output would be:
ß?p1 N8
since the first character is the "double-s".
Also note that I am assuming that both the original and encrypted character strings are of the same size (in terms of the number of characters) when building the map. If they're not the same size, then the loop to build the map should be adjusted accordingly.

change ascii code and preappend character to string in C++

I want to pre-append a character to a string after performing some calculations to the character ascii code but doing (somenumber+'0') + s doesn't work and I don't understand why.
the answer I want is "ahello" using the ascii representation of a ('0' + 49)
This is what I have tried:
std::string s = "hello";
s.insert(0, std::to_string('a'));
std::cout << s << std::endl; // 97hello
s = "hello";
s += 'a';
std::cout << s << std::endl; // helloa
s = "hello";
s = 'a' + s;
std::cout << s << std::endl; // ahello
//s = (49+'0') + s;
//std::cout << s << std::endl;
Do you want to append the ASCII code int of the character (97) or do you want to append the ASCII representation ('a') ?
In the later case, you could just use s.insert(0, "a") directly.
If you want to transform the ASCII code int before, you can use the std::string fill constructor, as was already pointed out by Steephen:
// fills the string with n consecutive copies of character c.
std::string(size_t n, char c);
// so you could do this to get a string "f":
std::string(1, 'a'+5);
This will solve the issue:
s.insert(0, string(1,1+'a'));
O/p
bhello
s.insert(0, string(1,0+'a'));
O/P
ahello
Try
s.insert(0, string(1,49+'a'));

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

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.

C++ Confusion. Reading Integer From Text File. Convert to ASCII

I am learning C++ for the first time. I have no previous programming background.
In the book I have I saw this example.
#include <iostream>
using::cout;
using::endl;
int main()
{
int x = 5;
char y = char(x);
cout << x << endl;
cout << y << endl;
return 0;
}
The example makes sense: print an integer and the ASCII representation of it.
Now, I created a text file with these values.
48
49
50
51
55
56
75
I am writing a program to read this text file -- "theFile.txt" -- and want to convert these numbers to the ASCII value.
Here is the code I wrote.
#include <iostream>
#include <fstream>
using std::cout;
using std::endl;
using std::ifstream;
int main()
{
ifstream thestream;
thestream.open("theFile.txt");
char thecharacter;
while (thestream.get(thecharacter))
{
int theinteger = int(thecharacter);
char thechar = char(theinteger);
cout << theinteger << "\t" << thechar << endl;
}
system ("PAUSE");
return 0;
}
This is my understanding about the second program shown.
The compiler does not know the exact data type that is contained in "theFile.txt". As a result, I need to specify it so I choose to read the data as a char.
I read the each digit in the file as a char and converted it to an integer value and stored it in "theinteger".
Since I have an integer in "theinteger" I want to print it out as a character but char thechar = char(theinteger); does not work as intended.
What am I doing incorrect?
You are reading char by char, but you really (I think) want to read each sequence of digits as an integer. Change your loop to:
int theinteger;
while (thestream >> theinteger )
{
char thechar = char(theinteger);
cout << thechar << endl;
}
+1 For a very nicely formatted & expressed first question, BTW!
You are reading one char at a time from the file. Hence, if your file contains:
2424
You will first read the char "2" from the file, convert it to an int, and then back to a char, which will print "2" on cout. Next round will print "4", and so on.
If you want to read the numbers as full numbers, you need to do something like:
int theinteger;
thestream >> theinteger;
cout << char(theinteger) << endl;