C++: Format String Containing Hex Value

1

Working with C++ on Visual Studio 2010.

Trying to come up with a robust function that will take a hex value as string and size as integer and then output the formatted hex value.

For e.g.,

If the input string is "A2" and size is 1, then the output is "0xA2"

If the input string is "800" and size is 2, then the output is "0x0800"

If the input string is "DEF" and size is 4, then the output is "0x00000DEF"

If the input string is "00775" and size is 4, then the output is "0x00000775"

If the input string is "FB600" and size is 3, then the output is "0x0FB600"

The basic idea is, multiply size by 2 and then if the string length is less than that, then add leading zeros to the hex value and then append it with "0x".

"0x" is appended irrespective of whether leading zeros are added.

As you see in 1st example, there's no zeros to add as the string already contains 2 characters.

I came up with below function, but it's having memory corruption. Also when i try to process large amount of data by calling this function few hundrend times, it crashes. Seems my logic has memory holes in it.

So am hoping that someone can come up with a robust intelligent code for this function.

What i tried:

void formatHexString(char* inputHex, int size, char* outputFormattedHex)
{
    int len = size * 2;
    int diff = len - strlen(inputHex);
    char * tempHex = new char [diff + 2]; //"2" is for holding "0x"
    tempHex[0] = '0';
    tempHex[1] = 'x';

    if (len > strlen(inputHex))
    {

        for (int i = 2; i < ((len - strlen(inputHex)) + 2); i++)
        {
            tempHex[i] = '0';

        }

    }

    strcat(tempHex, inputHex);
    sprintf(outputFormattedHex, "%s", tempHex);

    delete [] tempHex;

    cout <<outputFormattedHex <<endl;
}


int main 
{
    char bbb1[24];
    formatHexString("23", 1, bbb1);
    char bbb2[24];
    formatHexString("A3", 2, bbb2);
    char bbb3[24];
    formatHexString("0AA23", 4, bbb3);
    char bbb4[24];
    formatHexString("7723", 4, bbb4);
    char bbb5[24];
    formatHexString("AA023", 4, bbb5);
    return 0;
}

UPDATED:

I cannot modify the arguments to original function as this function is called from a different application. So i modified my original function with your code, but this is not working. Any ideas?

void formatHexString(char* inputHex, int size, char* outputFormattedHex)
{
    string input(inputHex);
    std::size_t const input_len(input.length());

    if (!size || (size * 2 < input_len))
        size = input_len / 2 + input_len % 2;

    std::stringstream ss;
    ss << "0x" << std::setw(2 * size) << std::setfill('0') << input;
    sprintf(outputFormattedHex, "%s", ss.str());
}
c++
asked on Stack Overflow Jul 25, 2018 by (unknown user) • edited Jul 26, 2018 by (unknown user)

2 Answers

3
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <cstddef>

std::string formatHexString(std::string const & input, std::size_t size = 0)
{
    std::size_t const input_len(input.length());

    // always round up to an even count of digits if no size is specified
    // or size would cause the output to be truncated
    if (!size || (size * 2 < input_len))
        size = input_len / 2 + input_len % 2;

    std::stringstream ss;
    ss << "0x" << std::setw(2 * size) << std::setfill('0') << input;
    return ss.str();
}

int main()
{
    std::cout << formatHexString(   "23") << '\n'
              << formatHexString(   "A3", 2) << '\n'
              << formatHexString( "AA23", 4) << '\n'
              << formatHexString( "7723", 4) << '\n'
              << formatHexString("AA023", 4) << '\n';
}

Solution without std::stringstream:

#include <string>
#include <cstddef>

std::string formatHexString(std::string const & input, std::size_t size = 0)
{
    std::size_t const input_len(input.length());

    // always round up to an even count of digits if no size is specified
    // or size would cause the output to be truncated
    if (!size || (size * 2 < input_len))
        size = input_len / 2 + input_len % 2;

    std::string result("0x");

    for (std::size_t i = 0, leading_zeros = size * 2 - input_len; i < leading_zeros; ++i)
        result += '0';

    result += input;
    return result;
}

Updated:

#define  _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
#include <cstddef>
#include <cstdio>

void formatHexString(char const * inputHex, int size, char * outputFormattedHex)
{
    int const input_len(std::strlen(inputHex));

    if (!size || (size * 2 < input_len))
        size = input_len / 2 + input_len % 2;

    std::stringstream ss;
    ss << "0x" << std::setw(2 * size) << std::setfill('0') << inputHex;
    std::strcpy(outputFormattedHex, ss.str().c_str());
}

int main()
{
    char output[24];
    formatHexString("23", 1, output);
    std::cout << output << '\n';

    formatHexString("A3", 2, output);
    std::cout << output << '\n';

    formatHexString("0AA23", 4, output);
    std::cout << output << '\n';

    formatHexString("7723", 4, output);
    std::cout << output << '\n';

    formatHexString("AA023", 4, output);
    std::cout << output << '\n';
}
answered on Stack Overflow Jul 25, 2018 by Swordfish • edited Jul 26, 2018 by Swordfish
0

It is unclear from your question, what you expect to happen with leading zeros on the input: I.e. either input "00000000EA" Size 2 turns to "00EA", or it keeps all its leading zeros.

This simple solution is for both cases (bTrim = true, for the 1st case):

#include <string>

void formatHexString(std::string & strHex, unsigned int nSize, bool bTrim = true) 
{
    if (bTrim) // Trim leading-zeros:
        strHex = strHex.substr(strHex.find_first_not_of('0'));

    if (nSize > strHex.length()) // Pad with leading-zeros to fit nSize:
        strHex.insert(0, std::string(nSize - strHex.length(), '0').c_str());

    strHex.insert(0, "0x"); // Insert prefix
}

-

If it's important to keep the original signature, wrap the above formatHexString with:

void formatHexString(char* inputHex, int size, char* outputFormattedHex)
{
    std::string strHex(inputHex);
    formatHexString(strHex, size * 2);
    strcpy_s(outputFormattedHex, strHex.length()+1, strHex.c_str()); // Visual Studio
}
answered on Stack Overflow Jul 26, 2018 by Amit G. • edited Jul 26, 2018 by Amit G.

User contributions licensed under CC BY-SA 3.0