clone a wchar_t* in c++ - c++

I want to clone a path that is held in a var named szPath to a new wchar_t.
szPath is of the type wchar_t *. so i tried doing something like:
szPathNew = *szPath;
but this is referring to the same place in memory.
what should i do? i want to deep clone it.

Do this,
wchar_t clone[260];
wcscpy(clone,szPath);
Or, if you want to allocate memory yourself,
wchar_t *clone = new wchar_t[wcslen(szPath)+1];
wcscpy(clone,szPath);
//use it
delete []clone;
Check out : strcpy, wcscpy, _mbscpy at MSDN
However, if your implementation doesn't necessarily require raw pointers/array, then you should prefer this,
#include<string>
//MOST SAFE!
std:wstring clone(szPath);

Do not use raw C strings in C++. If you want wide character strings, you can use std::wstring:
#include <string>
...
std::wstring szPathClone1 = szPath; // Works as expected
If you insist on using wchar_t buffers directly, you can use the wcscpy function.
PS: You also seem to be confused by pointer usage, you should first learn more about pointers.

The _wcsdup function duplicates (clones) a string. Note that this allocates new memory, so you will need to free it later:
wchar_t * szPathClone = _wcsdup(szPath);
// ...
free(szPathClone);

Related

Convert std::wstring to WCHAR array

I have been searching the internet for days about this question. I have made a win32 project in which I want to convert a wstring to a WCHAR array
Please give an example
If you find out any mistakes please give an example
wstring timeNow = L"Hello";
WCHAR timeWchar[6] = {(WCHAR)timeNow.c_str()}; // Not Working
Instead of the text I see only a square when I run my program
I assume that by WCHAR, you mean wchar_t.
You can loop over the array and assign the elements.
Or if you don't feel like writing the loop yourself, you can use an algorithm from the standard library. Example:
assert(timeNow.size() < 6);
wchar_t timeWchar[6] {};
std::ranges::copy(timeNow, timeWchar);
You can't really initialize an array with a pointer.
This is closer to what you want without making a copy of the string into an array. just use a pointer to reference the chars.
wstring timeNow = L"Hello";
const WCHAR* timeWchar = timeNow.c_str();
99% of the time, the above works for whatever you need to do assuming you don't need to modify the chars.
If really need to make a make a copy of the characters into a different array, such as when you need to manipulate the string, this will do in Windows just fine - assuming you have a fixed size array that is big enough to receive the copy.
wstring timeNow = L"Hello";
WCHAR timeWchar[6];
StringCchCopyW(timeWchar, ARRAYSIZE(timeWchar), timeNow.c_str());
If you don't know the length ahead of time, then you'll need to allocate it before making the copy:
size_t allocSize = timeNow.size() + 1;
WCHAR timeWchar = new WCHAR[allocSize];
StringCchCopyW(timeWchar, allocSize, timeNow.c_str());
/* don't forget to `delete [] timeWchar` when you are done */
But then again why mess with new and delete when you can just let C++ do the work for you. Make a copy of the string and then use a pointer to reference the characters in the copy.
wstring timeNowCopy = timeNow;
const WCHAR* timeWchar = timeNowCopy.c_str(); // timeWchar points to the array copied into timeNowCopy.
If you can maintain the lifetime of timeNowCopy and timeWchar on the stack together, then you don't need to explicitly new or delete anything.
just do its .data() .
WCHAR timeWchar[6] = ...
wont work anyway
in which I want to convert a wstring to a WCHAR array
if you mean wchar_t [6] type - you just do not need this.
you don't have a situation where you can go with wchar_t [6] but can't with wstr.data() .

what are alternatives for CString methods of GetBuffer and ReleaseBuffer in MinGW?

I found a nice example how to play with folder selecting dialog: http://bobmoore.mvps.org/Win32/w32tip70.htm - and all this is working except of this example using CString which I can't have on MinGW because it doesn't have stdafx.h. So I must use either string or char*.
But here the problem is that this example uses CString methods: GetBuffer and ReleaseBuffer which I don't have in string object. Is there any other method of passing folder name to folder selection window ?
When dealing with the Windows API and buffers, you can use std::vector<BYTE> for bytes and std::vector<TCHAR> for strings. (TCHAR is defined as wchar_t if UNICODE is defined and char otherwise. This way the code works for both UNICODE and ANSI). When instantiating the vector, give it a size to allocate memory:
// can hold MAX_PATH TCHARs, including terminating '\0'
std::vector<TCHAR> buffer(MAX_PATH);
Now you can treat is almost exactly like a buffer of TCHARs allocated with new or created on the stack.
BROWSEINFO bi = {0};
bi.pszDisplayName = &buffer[0];
However, buffer.size() will always return the full vector length. If you need to know the length of the string stored within the vector, or want to use string related methods,
you can copy it to a std::string:
if( LPITEMIDLIST pidl = SHBrowseForFolder(&bi) ) {
// this way it works for both UNICODE and ANSI:
std::basic_string<TCHAR> folderName(&buffer[0]);
if( SHGetPathFromIDList(pidl,&buffer[0]) ) {
MessageBox(0, &buffer[0], folderName.c_str(), MB_OK);
}
// TODO: free pidl with IMalloc* obtained through SHGetMalloc()
}
Since std::string is just another contiguous container, you could (ab)use that instead of the vector. However, size() will return the number of elements stored in the string, even if they are \0. You would have to resize() the string to the first occurrence of \0 (that is what CString::ReleaseBuffer() does) which is done automatically when you assign the buffer to the string in the above example. Because a string is not meant to be used as a buffer (even if it is technically possible) i strongly recommend using the vector approach.
With std::string you have a read-only access to the underlying representation by using c_str(), but nothing else.
In your case, I think the only option is to use some old-fashioned memory management, and then copy the result in a std::string.

Initialize wide char array

I have a wide char variable which I want to initialize with a size of string.
I tried following but didn't worked.
std::string s = "aaaaaaaaaaaaaaaaaaaaa"; //this could be any length
const int Strl = s.length();
wchar_t wStr[Strl ]; // This throws error message as constant expression expected.
what option do i have to achieve this? will malloc work in this case?
Since this is C++, use new instead of malloc.
It doesn't work because C++ doesn't support VLA's. (variable-length arrays)
The size of the array must be a compile-time constant.
wchar_t* wStr = new wchar_t[Strl];
//free the memory
delete[] wStr;
First of all, you can't just copy a string to a wide character array - everything is going to go berserk on you.
A std::string is built with char, a std::wstring is built with wchar_t. Copying a string to a wchar_t[] is not going to work - you'll get gibberish back. Read up on UTF8 and UTF16 for more info.
That said, as Luchian says, VLAs can't be done in C++ and his heap allocation will do the trick.
However, I must ask why are you doing this? If you're using std::string you shouldn't (almost) ever need to use a character array. I assume you're trying to pass the string to a function that takes a character array/pointer as a parameter - do you know about the .c_str() function of a string that will return a pointer to the contents?
std::wstring ws;
ws.resize(s.length());
this will give you a wchar_t container that will serve the purpose , and be conceptually a variable length container. And try to stay away from C style arrays in C++ as much as possible, the standard containers fit the bill in every circumstance, including interfacing with C api libraries. If you need to convert your string from char to wchar_t , c++11 introduced some string conversion functions to convert from wchar_t to char, but Im not sure if they work the other way around.

What's the proper way to cast wstring to wchar*? (or string to char*)

[I'm new to D (currently writing my first useful program) and I don't have much C background - just some C# and other mostly pointerless languages.]
Do I need to always append '\0' to the wstring before casting? Is that the only way to ensure that my wchar* will be null-terminated? When it is cast, is it a new copy of the wstring, or does it just get a pointer to the same wstring you're casting?
For calling Windows *W functions use http://www.digitalmars.com/d/2.0/phobos/std_utf.html#toUTF16z
Also note that string literals already are 0-terminated so you can pass them directly.
The toStringz functions convert D strings to C-style zero-terminated strings.
immutable(char)* toStringz(const(char)[] s);
immutable(char)* toStringz(string s);
e.g.
string s;
immutable(char)* cstr = s.toStringz();
//or: toStringz(s);
toStringz allocates a new string on the heap only if the string isn't already null terminated, otherwise it just returns s.ptr.
If you merely want a pointer, the correct way is to use the 'ptr' property (available for all dynamic arrays, not just strings)
str.ptr
However, if you are wanting something to use with C, to ensure it is nul-terminated, use toStringz
import std.string;
toStringz(str);
toStringz will not perform a copy if the string is already nul terminated.

CStringT to char[]

I'm trying to make changes to some legacy code. I need to fill a char[] ext with a file extension gotten using filename.Right(3). Problem is that I don't know how to convert from a CStringT to a char[].
There has to be a really easy solution that I'm just not realizing...
TIA.
If you have access to ATL, which I imagine you do if you're using CString, then you can look into the ATL conversion classes like CT2CA.
CString fileExt = _T ("txt");
CT2CA fileExtA (fileExt);
If a conversion needs to be performed (as when compiling for Unicode), then CT2CA allocates some internal memory and performs the conversion, destroying the memory in its destructor. If compiling for ANSI, no conversion needs to be performed, so it just hangs on to a pointer to the original string. It also provides an implicit conversion to const char * so you can use it like any C-style string.
This makes conversions really easy, with the caveat that if you need to hang on to the string after the CT2CA goes out of scope, then you need to copy the string into a buffer under your control (not just store a pointer to it). Otherwise, the CT2CA cleans up the converted buffer and you have a dangling reference.
Well you can always do this even in unicode
char str[4];
strcpy( str, CStringA( cString.Right( 3 ) ).GetString() );
If you know you AREN'T using unicode then you could just do
char str[4];
strcpy( str, cString.Right( 3 ).GetString() );
All the original code block does is transfer the last 3 characters into a non unicode string (CStringA, CStringW is definitely unicode and CStringT depends on whether the UNICODE define is set) and then gets the string as a simple char string.
First use CStringA to make sure you're getting char and not wchar_t. Then just cast it to (const char *) to get a pointer to the string, and use strcpy or something similar to copy to your destination.
If you're completely sure that you'll always be copying 3 characters, you could just do it the simple way.
ext[0] = filename[filename.Length()-3];
ext[1] = filename[filename.Length()-2];
ext[2] = filename[filename.Length()-1];
ext[3] = 0;
I believe this is what you are looking for:
CString theString( "This is a test" );
char* mychar = new char[theString.GetLength()+1];
_tcscpy(mychar, theString);
If I remember my old school MS C++.
You do not specify where is the CStringT type from. It could be anything, including your own implementation of string handling class. Assuming it is CStringT from MFC/ATL library available in Visual C++, you have a few options:
It's not been said if you compile with or without Unicode, so presenting using TCHAR not char:
CStringT
<
TCHAR,
StrTraitMFC
<
TCHAR,
ChTraitsCRT<TCHAR>
>
> file(TEXT("test.txt"));
TCHAR* file1 = new TCHAR[file.GetLength() + 1];
_tcscpy(file1, file);
If you use CStringT specialised for ANSI string, then
std::string file1(CStringA(file));
char const* pfile = file1.c_str(); // to copy to char[] buffer