-1

I have below function that supports for conversion of LPCTSTR to BYTE , but the input str only support digits as of now.

void StrToByte2(LPCTSTR str, BYTE *dest)
{
    UINT count = _ttoi(str);
    BYTE buf[4] = { 0 };
    char string[10] = { 0 };
    sprintf_s(string, 10, "%04d", count);
    for (int i = 0; i < 4; ++i)
    {
        if ((string[i] >= '0') && (string[i] <= '9'))
            buf[i] = string[i] - '0';
    }
    dest[0] = (BYTE)(buf[0] << 4) | buf[1];
    dest[1] = (BYTE)(buf[2] << 4) | buf[3];
}

If i call this function on "1234" ( any digits) , dest output some 12814,

struct st               
{
    byte    btID[2];
    int     nID;
};

PTR ptr(new st);
StrToByte2(strCode, ptr->btID);

but when i call this function on any hexadecimal ex A123 , it outputs 0000 always.

Below function is used to convert back the dest code to str

CString Byte2ToStr(const byte* pbuf)
{
    CString str;
    str.Format(_T("%02X%02X"), pbuf[0], pbuf[1]);
    return str;
}

How can i get A123 to converted to bytes and than back to str to display A123?? Please help!!

pushE
  • 394
  • 3
  • 16
  • 1
    So you want the function to be able to handle *hexa-decimal* numbers? – Some programmer dude Oct 31 '18 at 15:23
  • 1
    By the way, a good start might be to learn about [the standard character classification functions](https://en.cppreference.com/w/cpp/string/byte#Character_classification). More specifically `isxdigit` and `isdigit` (as well as e.g. `toupper`). – Some programmer dude Oct 31 '18 at 15:26
  • For me the question is unclear. Please [edit] your question and show us some examples of calls to `StrToByte2` with the expected result in the `dest` buffer. – Jabberwocky Oct 31 '18 at 15:29
  • Till now lets handle hexa decimal only , A111,B222,C333,D444,E555,F666 – pushE Oct 31 '18 at 15:30
  • Oh and if you handle the difference between narrow and wide characters properly, there's no need for the temporary `count` and `string` variables. – Some programmer dude Oct 31 '18 at 15:31
  • @Jabberwocky tried to add how i am using this function. – pushE Oct 31 '18 at 15:44
  • @Someprogrammerdude actually above code is already running on client side, now the entry done is hexadecimal and software is giving issues at client side,if you can help me with exact function that can work . Bcox current situation is no time to study :( – pushE Oct 31 '18 at 15:45
  • Please show some examples of input and expected output for the `StrToByte2` function. – Jabberwocky Oct 31 '18 at 15:54
  • 1
    *"If i call this function on "1234" ( any digits) , dest output shows 1234"* That's not true, your function doesn't do that. First of all, tell us if you are using Unicode or not (check project settings -> character set). Describe the problem and the solution you are thinking of. Put a `printf` function to display the output. My guess is that you are trying to [convert hexadecimal string to bytes](https://stackoverflow.com/q/46870603/4603670) – Barmak Shemirani Oct 31 '18 at 16:04
  • 2
    Whatever you do, that `union` is the precursor to undefined behavior. Have a look at [this Q&A](https://stackoverflow.com/q/11373203/1889329). – IInspectable Oct 31 '18 at 16:20
  • @BarmakShemirani project us UNICODE character set – pushE Oct 31 '18 at 16:25
  • Guys this function is not wrriten by me , but i just want this to support for hexadecimal as well – pushE Oct 31 '18 at 16:28
  • 2
    There's a big red flag with the union you use: It seems to attempt [*type punning*](https://en.wikipedia.org/wiki/Type_punning) between the array and the `WORD` variable. In C++ that's not allowed and leads to [*undefined behavior*](https://en.wikipedia.org/wiki/Undefined_behavior). In C++ you *must* read the union member that was last written to. – Some programmer dude Oct 31 '18 at 16:32
  • @Someprogrammerdude that we can look into later also, but how can i get this function support for what we want to achieve ?? – pushE Oct 31 '18 at 16:34
  • @BarmakShemirani yes out put for 1234 was 12814 , i mention 1234 bcox in UI i could actually see 1234 , but when enter A123 , always 0000 – pushE Oct 31 '18 at 16:48
  • We don't know, *what* you are trying to achieve. Your problem statement is dubious at best. Be a developer and produce a succinct problem statement. You'll find that the solution is beyond trivial once you have done that. – IInspectable Oct 31 '18 at 18:45

1 Answers1

1
PTR ptr(new st);

This is a memory leak in C++, because new st allocates memory and there is no way to release it.

UINT count = _ttoi(str);
...
sprintf_s(string, 10, "%04d", count);

This is converting string to integer, then converts integer back to string. It doesn't seem to have a real purpose.

For example, "1234" is converted to 1234, and back to "1234". But "A123" is not a valid number so it is converted to 0, then converted to "0000". So this method fails. You can just work with the original string.

It seems this function tries to fit 2 integers in to 1 byte. This can be done as long as each value is less than 16 or 0xF (I don't know what purpose this might have) It can be fixed as follows:

void StrToByte2(const wchar_t* str, BYTE *dest)
{
    int len = wcslen(str);
    if(len != 4)
        return; //handle error
    char buf[4] = { 0 };
    for(int i = 0; i < 4; ++i)
        if(str[i] >= L'0' && str[i] <= L'9')
            buf[i] = (BYTE)(str[i] - L'0');
    dest[0] = (buf[0] << 4) + buf[1];
    dest[1] = (buf[2] << 4) + buf[3];
}

CStringW Byte2_To_Str(BYTE *dest)
{
    CStringW str;
    str.AppendFormat(L"%X", 0xF & (dest[0] >> 4));
    str.AppendFormat(L"%X", 0xF & (dest[0]));
    str.AppendFormat(L"%X", 0xF & (dest[1] >> 4));
    str.AppendFormat(L"%X", 0xF & (dest[1]));
    return str;
}

int main()
{
    BYTE dest[2] = { 0 };
    StrToByte2(L"1234", dest);
    OutputDebugStringW(Byte2_To_Str(dest));
    OutputDebugStringW(L"\n");
    return 0;
}

If the string is hexadecimal, you can use sscanf to convert each pair of character to bytes.

Basically, "1234" changes to 12 34
"A123" changes to A1 23

bool hexstring_to_bytes(const wchar_t* str, BYTE *dest, int dest_size = 2)
{
    int len = wcslen(str);

    if((len / 2) > dest_size)
    {
        //error
        return false;
    }

    for(int i = 0; i < len / 2; i++)
    {
        int v;
        if(swscanf_s(str + i * 2, L"%2x", &v) != 1) 
            break;
        dest[i] = (unsigned char)v;
    }

    return true;
}

CStringW bytes_to_hexstring(const BYTE* bytes, int byte_size = 2)
{
    CString str;
    for(int i = 0; i < byte_size; i++)
        str.AppendFormat(L"%02X ", bytes[i] & 0xFF);
    return str;
}

int main()
{
    CStringW str;
    CStringW new_string;

    BYTE dest[2] = { 0 };

    str = L"1234";
    hexstring_to_bytes(str, dest);
    new_string = bytes_to_hexstring(dest);
    OutputDebugString(new_string);
    OutputDebugString(L"\n");

    str = L"A123";
    hexstring_to_bytes(str, dest);
    new_string = bytes_to_hexstring(dest);
    OutputDebugStringW(new_string);
    OutputDebugStringW(L"\n");

    return 0;
}
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77