I am trying to convert previous code to VS 2010. The code I am trying to convert is mentioned below. The function addCommand is defined like
addCommand(const ACHAR * cmdGroupName, const ACHAR * cmdGlobalName, const ACHAR * cmdLocalName, Adesk::Int32 commandFlags, AcRxFunctionPtr FunctionAddr,AcEdUIContext *UIContext=NULL, int fcode=-1, HINSTANCE hResourceHandle=NULL, AcEdCommand** cmdPtrRet=NULL)
The third required argument is of type ACHAR. The function is called in the following way.
char cmdLocRes[65];
// If idLocal is not -1, it's treated as an ID for
// a string stored in the resources.
if (idLocal != -1) {
// Load strings from the string table and register the command.
::LoadString(_hdllInstance, idLocal, cmdLocRes, 64);
acedRegCmds->addCommand(cmdGroup, cmdInt, cmdLocRes, cmdFlags, cmdProc);
My problem is that the variable cmdLocRes is of type char but the argument needs to be of type ACHAR.
How can I convert the same ?
ACHAR is a typedef (made by Autodesk in file AdAChar.h) of wchar_t. So the question is how to convert a char to wchar_t.
In a wider context this problem is because of the existence of unicode. Linux and Windows programmers normally discuss it without understanding each other. As I do not understand it, too, I cannot explain it. There are threads for the eager beaver: What's "wrong" with C++ wchar_t and wstrings? What are some alternatives to wide characters?
The folling might give you an idea how to convert it.
// Convert char to wchar_t
char cmdLocRes[65];
// Remark: Make sure cmdLocRes contains elements!
cmdLocRes[0] = 'A';
cmdLocRes[1] = '\0';
// Get a wstringstream
std::wstringstream str;
// Write the char array to the wstringstream
str << cmdLocRes;
// Get a wstring from the wstringstream
std::wstring wstr = str.str();
// Get a wchar_t from the wstring
const wchar_t *chr1 = wstr.c_str();
const ACHAR *chr2 = wstr.c_str(); // We see that wchar_t == ACHAR!
Better think of using wchar_t cmdLocRes[65] instead of char cmdLocRes[65]!
Sorry for the code style, but this text field is another great example for how not to do it. It took me longer to try to format the code block (and please look at it!!!) than to write the answer. Jesus!!!
Related
As the title states I have a simple char that retrieves a full path name of a file I am looking for and I need to convert it to const wchar_t. How can I achieve this? Here is an example of the code:
int main()
{
char filename[] = "poc.png";
char fullFilename[MAX_PATH];
GetFullPathName(filename, MAX_PATH, fullFilename, nullptr);
const wchar_t *path = fullFilename;
}
As you can see I am trying to get the filename to convert but I couldn't find a way to do so. What would be the most simple solution to this?
Your code doesn't show any need to convert between char and wchar_t. Most likely you don't actually need to convert the character types. If you want to use the wchar_t-friendly GetFullPathNameW, then just use wchar_t instead of char.
int main()
{
wchar_t fullFilename[MAX_PATH];
GetFullPathNameW(L"poc.png", MAX_PATH, fullFilename, nullptr);
const wchar_t *path = fullFilename;
return 0;
}
If you really do need to convert between wchar_t-based C-style strings and char-based C-style strings, then you can use the APIs MultiByteToWideChar and WideCharToMultiByte.
I am trying to compare the file name against a list of strings to see if they match up and if they do then return accordingly
I am using the following condition:
if (strstr(file, str) != NULL) {
return 1;
}
Though MSVC++2012 prompts me with the following error on strstr:
Error: no instance of overloaded function "strstr" matches the argument list
argument types are: (WCHAR [260], char *)
The question is: what is the meaning of the error above and how could it be fixed?
The problem you have got comes out from the fact that the strstr function expects to see two char pointers (char *) as its arguments, but it receives the WCHAR array instead as the first argument.
Unlike the usual 8-bit char, WCHAR represents a 16-bit Unicode character.
The one way to fix your error is to convert your Unicode file name to the char array as following:
char cfile[260];
char DefChar = ' ';
WideCharToMultiByte(CP_ACP, 0, file, -1, cfile, 260, &DefChar, NULL);
And then use cfile instead of file.
But this approach will only work with ASCII characters.
For that reason, you could consider using another string comparison method, suitable for the WCHAR strings (wstring).
The following code might help you with that second approach:
// Initialize the wstring for file
std::wstring wsfile (file);
// Initialize the string for str
std::string sstr(str);
// Initialize the wstring for str
std::wstring wstr(sstr.begin(), sstr.end());
// Try to find the wstr in the wsfile
int index = wsfile.find(wstr);
// Check if something was found
if(index != wstring::npos) {
return 1;
}
The good SO answer about usage of the find method in std::wsting: Find method in std::wstring.
More on converting string to wstring: Mijalko: Convert std::string to std::wstring.
Please leave some feedback in comments if it does not help.
Is there any method?
My computer is AMD64.
::std::string str;
BOOL loadU(const wchar_t* lpszPathName, int flag = 0);
When I used:
loadU(&str);
the VS2005 compiler says:
Error 7 error C2664:: cannot convert parameter 1 from 'std::string *__w64 ' to 'const wchar_t *'
How can I do it?
First convert it to std::wstring:
std::wstring widestr = std::wstring(str.begin(), str.end());
Then get the C string:
const wchar_t* widecstr = widestr.c_str();
This only works for ASCII strings, but it will not work if the underlying string is UTF-8 encoded. Using a conversion routine like MultiByteToWideChar() ensures that this scenario is handled properly.
If you have a std::wstring object, you can call c_str() on it to get a wchar_t*:
std::wstring name( L"Steve Nash" );
const wchar_t* szName = name.c_str();
Since you are operating on a narrow string, however, you would first need to widen it. There are various options here; one is to use Windows' built-in MultiByteToWideChar routine. That will give you an LPWSTR, which is equivalent to wchar_t*.
You can use the ATL text conversion macros to convert a narrow (char) string to a wide (wchar_t) one. For example, to convert a std::string:
#include <atlconv.h>
...
std::string str = "Hello, world!";
CA2W pszWide(str.c_str());
loadU(pszWide);
You can also specify a code page, so if your std::string contains UTF-8 chars you can use:
CA2W pszWide(str.c_str(), CP_UTF8);
Very useful but Windows only.
If you are on Linux/Unix have a look at mbstowcs() and wcstombs() defined in GNU C (from ISO C 90).
mbs stand for "Multi Bytes String" and is basically the usual zero terminated C string.
wcs stand for Wide Char String and is an array of wchar_t.
For more background details on wide chars have a look at glibc documentation here.
Need to pass a wchar_t string to a function and first be able to create the string from a literal string concantenated with an integer variable.
The original string looks like this, where 4 is the physical drive number, but I want that to be changeable to match whatever drive number I want to pass to the function
auto TargetDrive = L"\\\\.\\PhysicalDrive4";
The following works
int a = 4;
std::string stddrivestring = "\\\\.\\PhysicalDrive" + to_string(a);
std::wstring widedrivestring = std::wstring(stddrivestring.begin(), stddrivestring.end());
const wchar_t* TargetDrive = widedrivestring.c_str();
I am using Visual Studio c++ and want to convert the Cstring to Byte. I have written this code but it gave me error in the second line that "data" is undefined.
CString data = _T( "OK");
LPBYTE pByte = new BYTE[data.GetLength() + 1];
memcpy(pByte, (VOID*)LPCTSTR(data), data.GetLength());
Further more I need to convert LPBYTE to const char for strcmp function. I have written the code but I can't find the issue with it.
const LPBYTE lpBuffer;
LPBYTE lpData = lpBuffer;
CString rcvValue(LPCSTR(lpBuffer));
const CHAR* cstr = (LPCSTR)rcvValue;
if (strcmp (cstr,("ABC")) == 0)
{
////
}
The CString type is a template specialization of CStringT, depending on the character set it uses (CStringA for ANSI, CStringW for Unicode). While you ensure to use a matching encoding when constructing from a string literal by using the _T macro, you fail to account for the different size requirements when copying the controlled sequence to the buffer.
The following code fixes the first part:
CString data = _T("OK");
size_t size_in_bytes = (data.GetLength() + 1) * sizeof(data::XCHAR);
std::vector<BYTE> buffer(size_in_bytes);
unsigned char const* first = static_cast<unsigned char*>(data.GetString());
unsigned char const* last = first + size_in_bytes;
std::copy(first, last, buffer.begin());
The second question is really asking to solve a solved problem. The CStringT type already provides a CStringT::Compare member, that can be used:
const LPBYTE lpBuffer;
CString rcvValue(static_cast<char const*>(lpBuffer));
if (rcvValue.Compare(_T("ABC")) == 0)
{
////
}
General advice: Always prefer using the concrete CStringT specialization matching your character encoding, i.e. CStringA or CStringW. The code will be much easier to read and reason about, and when you run into problems you need help with, you can post a question at Stack Overflow, without having to explain, what compiler settings you are using.
Make sure you include atlstr.h to provide the definition of CString, as below:
#include "stdafx.h"
#include <Windows.h>
#include <atlstr.h>
int _tmain(int argc, _TCHAR* argv[])
{
CString data = _T( "OK");
LPBYTE pByte = new BYTE[data.GetLength() + 1];
memcpy(pByte, (VOID*)LPCTSTR(data), data.GetLength());
return 0;
}
I'm fairly certain Jay is correct for your first question. You need to include the right header.
For your second question, why would you expect that code to work? Let's walk through what the code you've written actually does.
Create a char pointer (char *) without initializing it. This leaves lpData/lpBuffer pointing to a random location in memory.
Create a CString and initialize it with this random pointer.
Extract the buffer from the CString and compare it to a string literal.
Keeping in mind that the CString contains random garbage, what exactly do you expect this code to do? (Other than crash horribly? =) )
I also want to point out that you need to be more consistent in your approach to strings. Do you plan to support both char and wchar_t based strings as your use of TCHAR in the first sections suggests? Do you want to work with C-Style strings or do you want to use objects like CString? If you want to work with CString's, just use the Compare function that CString provides. Don't bother with strcmp.
Probably you didn't include the cruicial header
#include <afx.h>
int main()
{
CString data = _T( "OK");
LPBYTE pByte = new BYTE[data.GetLength() + 1];
memcpy(pByte, (VOID*)LPCTSTR(data), data.GetLength());
return 0;
}
This code works fine.
You should rather use
CString ss = "123ABC";
BYTE* bp = (BYTE*)ss.GetBuffer(ss.GetLength());
BYTE expected[16] ;
CopyMemory(expected,bp,sizeof(expected));
Just using '=' won't work.
Is there any method?
My computer is AMD64.
::std::string str;
BOOL loadU(const wchar_t* lpszPathName, int flag = 0);
When I used:
loadU(&str);
the VS2005 compiler says:
Error 7 error C2664:: cannot convert parameter 1 from 'std::string *__w64 ' to 'const wchar_t *'
How can I do it?
First convert it to std::wstring:
std::wstring widestr = std::wstring(str.begin(), str.end());
Then get the C string:
const wchar_t* widecstr = widestr.c_str();
This only works for ASCII strings, but it will not work if the underlying string is UTF-8 encoded. Using a conversion routine like MultiByteToWideChar() ensures that this scenario is handled properly.
If you have a std::wstring object, you can call c_str() on it to get a wchar_t*:
std::wstring name( L"Steve Nash" );
const wchar_t* szName = name.c_str();
Since you are operating on a narrow string, however, you would first need to widen it. There are various options here; one is to use Windows' built-in MultiByteToWideChar routine. That will give you an LPWSTR, which is equivalent to wchar_t*.
You can use the ATL text conversion macros to convert a narrow (char) string to a wide (wchar_t) one. For example, to convert a std::string:
#include <atlconv.h>
...
std::string str = "Hello, world!";
CA2W pszWide(str.c_str());
loadU(pszWide);
You can also specify a code page, so if your std::string contains UTF-8 chars you can use:
CA2W pszWide(str.c_str(), CP_UTF8);
Very useful but Windows only.
If you are on Linux/Unix have a look at mbstowcs() and wcstombs() defined in GNU C (from ISO C 90).
mbs stand for "Multi Bytes String" and is basically the usual zero terminated C string.
wcs stand for Wide Char String and is an array of wchar_t.
For more background details on wide chars have a look at glibc documentation here.
Need to pass a wchar_t string to a function and first be able to create the string from a literal string concantenated with an integer variable.
The original string looks like this, where 4 is the physical drive number, but I want that to be changeable to match whatever drive number I want to pass to the function
auto TargetDrive = L"\\\\.\\PhysicalDrive4";
The following works
int a = 4;
std::string stddrivestring = "\\\\.\\PhysicalDrive" + to_string(a);
std::wstring widedrivestring = std::wstring(stddrivestring.begin(), stddrivestring.end());
const wchar_t* TargetDrive = widedrivestring.c_str();