Converting method

Feb 24, 2022 at 5:36am
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 Feb 24, 2022 at 5:37am
Feb 24, 2022 at 5:57am
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;
}
Feb 24, 2022 at 10:03am
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 Feb 24, 2022 at 10:50am
Feb 24, 2022 at 11:52am
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';
}
Feb 24, 2022 at 12:09pm
If vHex size isn't exactly a multiple of 2, then the terminating condition will always be false.
Feb 24, 2022 at 12:24pm
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.
Feb 24, 2022 at 1:30pm
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?
Feb 24, 2022 at 2:09pm
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.
Feb 24, 2022 at 3:57pm
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
Feb 24, 2022 at 4:10pm
What's with the x-or's ?? :) :) :)
Feb 24, 2022 at 7:39pm
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.