Converting method

If we've got a vector of hex chars, how do we print the actual English characters?

I wrote this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>

 int main() {
 std::vector<char> vHex{ '4','8','6','5','6','C','6','C', '6','F' };

    std::vector<size_t> hexBits_vec;
    std::vector<size_t> allBits_vec;
    int decVal{ 0 };

    for (auto a : vHex) {
        switch (a) {
        case 'a':
        case'A':
            decVal = 10; break;
        case 'b':
        case'B':
            decVal = 11; break;
        case 'c':
        case'C':
            decVal = 12; break;
        case 'd':
        case'D':
            decVal = 13; break;
        case 'e':
        case'E':
            decVal = 14; break;
        case 'f':
        case'F':
            decVal = 15; break;

        default: decVal = static_cast<int>(a - '0'); break;
        }

        while (decVal > 0) {   // compute binary values for each hex char
            hexBits_vec.push_back(decVal % 2);
            decVal /= 2;
        }

        while (hexBits_vec.size() < 4)  // fill up 4 bits for each hex value
            hexBits_vec.push_back(0);

        std::reverse(hexBits_vec.begin(), hexBits_vec.end());  // put to right order 

        for (auto i : hexBits_vec)  
            allBits_vec.push_back(i);

        hexBits_vec.clear();  // ready for next hex char
    }

    decVal = 0;
    int byte_count{ 0 }, pw{ 7 }; // pw is the power of each bit in a byte, from right to left {7, 6, ..., 0}
    std::vector<bool> bin_to_char_vec;

    for (auto a : allBits_vec) {
        bin_to_char_vec.push_back(a);

        if (++byte_count % 8 == 0) {
            for (auto bit : bin_to_char_vec)
                decVal += bit * pow(2, pw--);
            std::cout << static_cast<char> (decVal);

            // Set defaults
            pw = 7;
            decVal = 0;
            bin_to_char_vec.clear();
        }
    }

    std::cout << '\n';
    return 0;
}


1) How good is this code to you?
2) If not good, please give some tip(s) for making it better.
Last edited on
That's probably one of the least efficient ways to do the conversion.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int hex2value(char c){
    return c >= '0' && c <= '9' ? c - '0' : tolower(c) - 'a' + 10;
}

template <typename T>
std::string hex2string(const T &hex){
    std::string ret;
    for (size_t i = 0; i < hex.size(); i += 2){
        auto c = hex2value(hex[i]) << 4;
        c |= hex2value(hex[i + 1]);
        ret += (char)c;
    }
    return ret;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <string_view>
#include <string>
#include <cctype>

using namespace std::string_view_literals;

std::string hex2string(std::string_view hex) {
	const auto h2v {[](unsigned char c) -> unsigned char {
		return c >= '0' && c <= '9' ? c - '0' : static_cast<unsigned char>(std::toupper(c)) + 10 - 'A';
	}};

	std::string ret;

	for (size_t i {}; i < hex.size(); i += 2)
		ret += static_cast<char>(h2v(hex[i]) << 4 | h2v(hex[i + 1]));

	return ret;
}

int main() {
	std::cout << hex2string("353637"sv) << '\n';
}



567


1
2
3
int main() {
	std::cout << hex2string("48656c6c6f"sv) << '\n';
}



Hello

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>
#include <cctype>
using namespace std;

int digit( char c ){ return '0' <= c && c <= '9' ? c - '0' : tolower( c ) - 'a' + 10; }
   
string converter( const string &vHex )
{
   string result;
   for ( auto it = vHex.begin(); it != vHex.end(); it += 2 ) result += ( 16 * digit(*it) + digit(*(it+1)) );   // Surprised this works
   return result;
}

int main()
{
   cout << converter( "48656c6C6f" ) << '\n';
}
If vHex size isn't exactly a multiple of 2, then the terminating condition will always be false.
If vHex size isn't exactly a multiple of 2, then hex[i] doesn't need shifting and hex[i+1] will either not work or will be reliant on null termination.
Thank you for you codes. One thing I'd like to ask is that how you knew that if we shift the first hex character four bits to left then add the second character to it by bitwise or, the binary result of the two hex characters will be at hand, please? Is there any rule in this case to read?
Cause hex is base 16 which is 2 to power 4 - hence 4 bits required for each of the 2 parts of a hex code. So get the first part, shift by 4 bits and then or in the next 4 bits. A char (8 bits) (as unsigned) has a range 0 - 255 (ie 256 value) which is 2 to power 8 which is 8 bits - or 0 - 0xff in hex ie 2 groups of 4 bits.
Base 16 is represented using 16 symbols, while base 256 (the base used by any octet-based storage format) is represented using 256 symbols.
256 = 2^8 = 2^(4*2) = (2^4)^2 = 16^2
Thus a single octet fits exactly into two base 16 digits.

Compare octal:
256 = 2^8 < 2^(3*3) = (2^3)^3 = 8^3
So three octal digits are slightly too big for an octet, but two octal digits are not big enough to store an octet.
However, 8 octal digits neatly fit 3 octets:
256^3 = (2^8)^3 = 2^(8*3) = 2^(3*8) = (2^3)^8 = 8^8
What's with the x-or's ?? :) :) :)
Yes, exactly. Honestly I found it a little after posting the question here and before getting back to see your answers. Yet, I appreciate your time and hep.
Topic archived. No new replies allowed.