Hi i need in my project to concat the name of my dialogbox (type wchar_t) and the name of a configuration (type TCHAR).
How can i do this?
thanks.
This depends, a TCHAR is ether a char or wchar_t depending on whether you build your appication as Unicode or not. If you build your app as Unicode you can simply do:
wcscat_s(dest, extra);
If you do not build your app as Unicode, you need to either convert the string of TCHAR:s (which is then a string of char:s) into a string of wchar_t:s or your string of wchar_t:s into a string of char:s. To do that you should look into the MultiByteToWideChar or WideCharToMultiByte functions. Both of these can look a little bit scary taking a lot of parameters so I usually use some helpers (please note that proper error-handling has been removed for clarity, a proper solution would also call the functions mentioned above in a loop that resizes the buffer if the call fails with ERROR_INSUFFICIENT_BUFFER):
std::wstring multiByteToWideChar(const std::string &s)
{
std::vector<wchar_t> buf(s.length() * 2);
MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
s.c_str(),
s.length(),
&buf[0],
buf.size());
return std::wstring(&buf[0]);
}
std::string wideCharToMultiByte(const std::wstring &s)
{
std::vector<char> buf(s.length() * 2);
BOOL usedDefault = FALSE;
WideCharToMultiByte(CP_ACP,
WC_COMPOSITECHECK | WC_DEFAULTCHAR,
s.c_str(),
s.length(),
&buf[0],
buf.size(),
"?",
&usedDefault);
return std::string(&buf[0]);
}
In addition to those I set up a type-traits class so I can compile my projects as Unicode or not without caring:
template <class CharT>
struct string_converter_t;
template <>
struct string_converter_t<char>
{
static std::wstring toUnicode(const std::string &s)
{
return multiByteToWideChar(s);
}
static std::string toAscii(const std::string &s)
{
return s;
}
static std::string fromUnicode(const std::wstring &s)
{
return wideCharToMultiByte(s);
}
static std::string fromAscii(const std::string &s)
{
return s;
}
};
And an almost identical instance for the wchar_t (which I leave as an excerise). In your case you could then simply do:
std::wstring result = dialog_name + string_converter_t<TCHAR>::toUnicode(config_name);
You mean TCHAR*? Because it would be kinda weird to have a single character as a name. Anyways: Just cast the TCHAR's to wchar_t - TCHAR is either char or wchar_t, either way it's save to cast to wchar_t.
http://msdn.microsoft.com/en-us/library/cc842072.aspx
This question is similar to this: Cannot convert from 'const wchar_t *' to '_TCHAR *'
To manipulate different type of chars manually have a look at this: http://www.codeproject.com/KB/TipsnTricks/StringManipulations.aspx
Related
I currently have a function defined in a header that looks like this
void foo::GetValue(std::string& str);
This function basically assigns a value to str. I need to come up with an alternative to str (basically, nothing that employs the standard library).
The implementation of the above function is like this in the .cpp file:
void foo::GetValue(std::string& str)
{
std::string s = bar.someMethod();
str = s;
}
I want to know what is the best/easiest option for replacing the header?
One approach I had was to replace std::string in the header file with char* so I would have this in the header:
void foo::GetValue(char* str);
And in the implementation I would have this:
void foo::GetValue(char* str)
{
std::string resp = bar.someMethod();
char* c = new char[resp.size() + 1];
std::copy(resp.begin(), resp.end(), c);
c[resp.size()] = '\0';
}
The problem with the above approach is that a lot of files are calling this function and they will need to modify their code. Also, they will need to free the above memory. Two concerns I have with this is that other callers to this function will need to do the following two things
Replace std::string being passed to the function with char*.
Free the char* when done using it.
These two items seem very costly to me to trust other callers to do.
Any suggestions on what I can do to solve this problem? Perhaps change the signature to something else? I would prefer if the caller still passes a string, however string.c_str() is a constant char pointer.
For a given C++ function like this:
std::string foo::GetValue(std::string& str)
{
return bar.someMethod(str);
}
Then your equivalent C code looks like this:
void foo_GetValue(char* str, char* res, size_t size)
{
std::string str_arg = str;
std::string result = bar.someMethod(str_arg);
strncpy(res, result.c_str(), size - 1);
res[size-1] = 0; // Ensure is NUL terminated
}
When calling from C:
void example() {
const BUFFER_LEN = 1024;
char buffer[BUFFER_LEN];
foo_GetValue("example", buffer, BUFFER_LEN);
}
I have this WINAPI function:
HANDLE file{ CreateFileA((LPCSTR)"\\\\.\\" + (???) ", FILE_APPEND_DATA,FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) };
I have a global variable "Path" of type std::string & a username which is type TCHAR*, I assume I need to convert those two variables to LPCSTR, however, I have no idea how to do that even after some time of googling. I'd appreciate any help.
Simply concatenate the two std::strings into a new std::string, and then use its c_str() method, eg:
std::string Path = ...;
std::string username = ...;
std::string fullpath = Path + username;
HANDLE file{ CreateFileA(fullpath.c_str(), ...) };
Or simply:
std::string Path = ...;
std::string username = ...;
HANDLE file{ CreateFileA((Path + username).c_str(), ...) };
Here is the code as below that I used:
class A
{
public:
CString abc;
void fun1();
};
void A::fun1()
{
wchar_t *Str = L"Stack Overflow";
CString xyz = Str; // This works fine.
abc = Str; // Whether this assignment is correct?
}
int main()
{
A obj;
obj.fun1();
return 0;
}
While debugging I found that when breakpoint crosses the initialization code
abc = Str, I see in variable windows the string in abc is not updated with "Stack Overflow".
Here xyz string is updated with "Stack Overflow" when I looked it into the debugger window.
I'm not familiar with CString (mostly developing on unix / linux environment) but referring to this, I would use CStringW to store a wchar_t string.
But I thing your initialisation of your CString is wrong. According to the MSDN doc, I would rather do something like:
CStringW abc = _T(L"Stack Overflow");
Otherwise I would recommend to use wcstombs from the cstdlib to convert a wchar_t* to a char * and stick to the standard.
See wcstombs documentation.
Is there an direct way to manage C++/CLI Strings in a wrapper to char* parameter for native C++ method?!
example:
void Test::TestFunc(System::String ^%str)
{
// right conversion to char* and consider the reference
}
native C++ function:
void TestB::Func(char *str)
{
...
}
my tricky way:
void Test::TestFunc(System::String ^%szRecvBuffer)
{
pin_ptr<const wchar_t> szRecvBufferP = PtrToStringChars(szRecvBuffer);
// Convert to a char*
size_t origsize = wcslen(szRecvBufferP) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
char nstring[newsize];
wcstombs_s(&convertedChars, nstring, origsize, szRecvBufferP, _TRUNCATE);
strcat_s(nstring, " (char *)");
char *szRecvBufferCh = nstring;
m_object->TestCommand(szRecvBufferCh); // parameter char*
System::String ^tmp = gcnew System::String(szRecvBufferCh);
szRecvBuffer = tmp;
}
greets leon22
You're doing a lot manually that the runtime will take care of for you.
void Test::TestFunc(String^% szRecvBuffer)
{
using System::Runtime::InteropServices::Marshal;
IntPtr memHandle = Marshal::StringToHGlobalAnsi(szRecvBuffer);
try
{
char* const str = static_cast<char*>(memHandle.ToPointer());
m_object->TestCommand(str);
szRecvBuffer = gcnew String(str);
}
finally
{
Marshal::FreeHGlobal(memHandle);
}
}
If you're using VC++ 2010, you can use std::unique_ptr<> with a custom deleter to avoid using try..finally, ultimately cutting the number of lines of code in half.
If the char* is an output parameter, then in C++/CLI you must pass System::StringBuilder^
If you search for "System::String" with Google, the second link is How to convert from System::String* to Char* in Visual C++ . This is obviously a FAQ!
(There appear to be about 5 different ways depending on the specifics of the conversion required, so I won't summarise them here: go read the article.)
You can't avoid having conversions in both directions, because System::String uses wchar_t, and a Unicode->Multibyte conversion is necessary to get char from that.
But marshal_as should make the conversion much easier.
I have the following method :
VariantFromString(strXMLPath ,vXMLSource);
and the signature of the method is:
HRESULT VariantFromString(PCWSTR wszValue, VARIANT &Variant);
Now while I am passing a CString as below:
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
{
return errno;
}
CString strXMLPath = cCurrentPath;
strXMLPath += XMLFILE;
VariantFromString(strXMLPath ,vXMLSource);
I am getting the error: Can not Convert from CString to PCWSTR
You really should be using Unicode (wchar_t instead of char). That is how the OS operates internally, and would prevent having to constantly convert between char types like this.
But in this scenario, you could use CString::AllocSysString to convert it to a BSTR, which is compatible with PCWSTR. Just make sure it gets freed with SysFreeString.
[edit]
For example, you could change your function to:
VARIANT VariantFromString(const CString& str)
{
VARIANT ret;
ret.vt = VT_BSTR;
ret.bstrVal = str.AllocSysString();
return ret;
}