Romz
Romz

Reputation: 1457

How to convert from int to wchar_t*?

I did it like this:

static wchar_t* Convert1(tDWORD data) 
{
  wchar_t result[10];
  swprintf(result, sizeof(result) / sizeof(*result), L"%d", data);
  wprintf(L"[%ls]\n", result);
  return result;
}

And it didn't work, I guess because of stack memory has been cleared after return (Could someone explain to me why?). Then I tried like this:

static wchar_t* Convert2(tDWORD data) 
{
  wchar_t* result = (wchar_t*)malloc(sizeof(wchar_t) * 10);
  swprintf(result, sizeof(result) / sizeof(*result), L"%d", data);
  wprintf(L"[%ls]\n", result);
  return result;
}

And it works, but I get only first digit of any number, and not the whole number. How to do this the right way ?

Upvotes: 1

Views: 6963

Answers (4)

Sean
Sean

Reputation: 62492

In the first case you're returning a pointer to a buffer on the stack, which will be destroyed when your function returns. In the second case you're allocating memory which the caller will have to be responsible for.

Try this:

static std::wstring Convert1(DWORD data) 
{
  const size_t bufferSize = 10;
  wchar_t result[bufferSize];
  swprintf(result, bufferSize, L"%d", data);
  return result;
}

or for a more C++ aproach...:

static std::wstring Convert1(DWORD data) 
{
  std::wostringstream stream;
  stream << data;
  return stream.c_str();
}

Upvotes: 2

thb
thb

Reputation: 14454

You are thinking of result as a string of characters, which is a natural enough to think. However, severely speaking, result is not a string of characters but rather the address of the initial character only. Therefore, sizeof(result) does not do what you think. Try wcslen() or wcsnlen()—though, really, what you might prefer to do is to learn C++-style strings.

Regarding Convert1(), you are right: result is a local array, allocated on the stack, deallocated when its function returns.

By the way, your Convert2() may leak memory, depending on how its caller handles it. You might prefer to have it return a std::shared_ptr or, better, std::unique_ptr, instead of a plain pointer for this reason.

Upvotes: 1

WhozCraig
WhozCraig

Reputation: 66234

Consider using a string stream and a by-val wstring, such as:

#include <iostream>
#include <sstream>
#include <string>
#include <cstdint>
using namespace std;

typedef uint32_t tDWORD;

static std::wstring Convert1(tDWORD data)
{
    std::wostringstream os;
    os << data;
    return os.str();
}

int main(int argc, char *argv[])
{
    tDWORD dwTest = 1024;
    std::wstring res = Convert1(dwTest);
    std::wcout << res << std::endl;
    return EXIT_SUCCESS;
}

Output

1024

Sorry I had to fake the typedef. Hope it is close to what you were using. The major benefit of doing this is all the memory management, conversion, etc, is handled for you by the library, having to hand-roll near-nothing on your side.

Upvotes: 3

m4tx
m4tx

Reputation: 4511

Try this:

static wchar_t* Convert1(tDWORD data) 
{
  wchar_t *result = new wchar_t[10];
  swprintf(result, 10, L"%d", data);
  wprintf(L"[%ls]\n", result);
  return result;
}

You tried to return the adress of the local variable (array) - local variables are cleared after returning of their scope. That's why you say that the memory was cleared. Also, allocating memory like this: wchar_t result[10] is allocating memory on stack. Allocating like this: new wchar_t[10] is allocating memory on heap.

Also, I replaced sizeof(result) / sizeof(*result) with just 10. You cannot measure array capacity in C++, unfortunately :)

You can also use your wchar_t* result = (wchar_t*)malloc(sizeof(wchar_t) * 10); instead of my wchar_t *result = new wchar_t[10]; - my solution is only a bit clear, but it does the same.

Upvotes: 4

Related Questions