C++, WCHAR[] to std::cout and comparision - c++

I need to put WCHAR[] to std::cout ... It is a part of PWLAN_CONNECTION_NOTIFICATION_DATA passed from Native Wifi API callback.
I tried simply std::cout << var; but it prints out the numeric address of first char. the comparision (var == L"some text") doesn't work either. The debugger returns the expected value, however the comparision returns 0. How can I convert this array to a standard string(std::string)?
Thanks in advance

Some solutions:
Write to std::wcout instead
Convert:
The standard way, using std::codecvt
The Win32 way, using WideCharToMultibyte

For printing to cout, you should use std::wcout instead.
As for the comparison, I'm not really sure what you mean.
if var is a wchar_t[], then you are comparing two pointers. And the result will most likely be false, because while the string contents may be the same, they are physically allocated in different memory locations. The answer is to either use a function like strcmp which compares C-style strings (char pointers), or to use the C++ string class.
and the operator== usually returns a bool, not an integer. So it can return false, but it can't return 0... Unless you've created some weird overload yourself. (and that is only possible if var is a user-defined type.

Assuming var is a wchar_t *, var == L"some text" does a pointer comparison. In order to compare the string pointed to by var, use a function such as wcscmp.

use the following
#ifdef UNICODE
#define tcout wcout
#else
#define tcout cout
#endif

Related

std::string without null-character

Is a std::string without a null-character in the end valid and can it be acquired like this?:
std::string str = "Hello World";
str.resize(str.size() - 1);
For those who are curious:
I have a 3rd party function taking a string and iterating over the chars (using iterators). Unfortunately the function is buggy (as its a dev-version) and cannot deal with null-characters. I dont have another signature to chose from, I cant modify the function (as I said, 3rd party and we dont want to fork) and at the same time I dont want to reinvent the wheel. As far as I can tell, the function should work as desired without the null-character so I want atleast to give it a try.
The iteration takes place like this:
bool nextChar(CharIntType& c)
{
if (_it == _end) return false;
c = *_it;
++_it;
return true;
}
where _it is initialized to std::string::begin() and _end to std::string::end()
Until C++11, std::string was not required to include a trailing nul until you called c_str().
http://en.cppreference.com/w/cpp/string/basic_string/data
std::string::data()
Returns pointer to the underlying array serving as character storage. The pointer is such that the range [data(); data() + size()) is valid and the values in it correspond to the values stored in the string.
The returned array is not required to be null-terminated.
If empty() returns true, the pointer is a non-null pointer that should not be dereferenced. (until c++11)
The returned array is null-terminated, that is, data() and c_str() perform the same function.
If empty() returns true, the pointer points to a single null character. (since c++11)
From this we can confirm that std::string::size does not include any nul terminator, and that std::string::begin() and std::string::end() describe the ranges you are actually looking for.
We can also determine this by the simple fact that std::string::back() doesn't return a nul character.
#include <iostream>
#include <string>
int main() {
std::string s("hello, world");
std::cout << "s.front = " << s.front() << " s.back = " << s.back() << '\n';
return 0;
}
http://ideone.com/nUX0AB
While it is possible to have non null terminated strings I would not recommend it, strings are null terminated for a good reason, i would actually recommend in this instance that you either go ahead and write the function properly or get in touch with the third party and have them fix it.
To answer your questions yes a std::string is valid if it is not null terminated, to achieve this you can use the overload of string copy with a maximum length loaded, once again i do not recommend this.
See this page for more information:
http://c2.com/cgi/wiki?NonNullTerminatedString
This is a very late answer but I just post it so that anyone who comes later can use it for their reference. If you write a null terminated string into the string.data() array, it will terminate the string and would not let you to continue concatenate the string if you need to. The way to solve it is already answer in the question.
str.resize(str.size() - 1);
This would solve the problem, I have tested out in my code.

What is a #define string's type?

I think I am going about this wrong. I'm working on making a SO for a MSR type object. And by default (if I read it correctly) OPOS uses unicode. So I made my C++ automated class use unicode as well and from what I understand there is no way around it. In the OPOS head class there are 2 string definitions, the third one is one my creation:
#define OPOS_ROOTKEY "SOFTWARE\\OLEforRetail\\ServiceOPOS"
#define OPOS_CLASSKEY_MSR "MSR"
#define OPOSMSR OPOS_ROOTKEY "\\" OPOS_CLASSKEY_MSR "\\"
This is so that a person can access the registry. So I decided to make myself a registry helper class instead of having it all in my SO. Looks like I'm having a hard time trying to figure out how I should do this in the end. I copied working code from another SO I had, but I feel that that code was not made correctly, and I want my code made right the first time.
So I came up with this, but I can not figure out how to combine my string with the class name. I made the class name as a parameter in my constructor.
RegistryHelper::RegistryHelper(LPCTSTR deviceName) {
cout << "RegistryHelper::RegistryHelper()+" << endl;
baseOpen = true;
CString test;
test.Format("%s%s",OPOSMSR, theClass); //fail
REGSAM access = KEY_READ | KEY_WOW64_64KEY;
LONG nError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, theClass ,0, access,&hBaseKey); //not what I want, but would compile, I want test here instead of theClass
if (nError != ERROR_SUCCESS) {
cerr << "(E)RegistryHelper::RegistryHelper(): Failed to load base key. [" <<(int)nError << "]" << endl;
RegCloseKey(hBaseKey);
baseOpen = false;
}
cout << "RegistryHelper::RegistryHelper()-" << endl;
}
Any tips on what I am doing wrong? since I'm on the subject: I'm going to post all my code for this. How bad is it?
What I'm after is something like this
unsigned int baud;
char* parity;
bool MSRSO::LoadRegistryValuesIntoMemory(LPCSTR deviceName) {
RegistryHelper reg(deviceName);
bool required = reg.LoadDWORD("BaudRate", 19200, baud);
required = required && reg.LoadREGSZ("Parity", "NONE", parity);
//other values
reg.Close();
return required;
}
Keep in mind I'm a C# and java guy so I may have my data types wrong. I only wrote simple hello world programs and temp conversion programs for myself in C++ on a SUPER old linux box back in the day. Although I am getting better at C++ I'm still not comfortable with it. So to sum up what is the data type of the #define type? How do I combine it with LPCTSTR? Should I have done that so that I can access registry values ONLY?
Thank you.
Your code has inconsistencies between narrow and wide strings. A literal 'a' has the type char, and is a narrow character. A literal L'a' has the type wchar_t, and is a wide character.
Next, we can apply these to strings:
"abc" is a narrow string of type const char (&)[4].
L"abc" is a wide string of type const wchar_t (&)[4].
To reduce the hassle of supporting both, there is what is known as the TCHAR. Defined in a Windows header, this type is char or wchar_t, depending on whether UNICODE is defined. If it is defined, TCHAR will be wchar_t. If it is not defined, TCHAR will be char.
This also came with a TEXT macro that converts a string literal into characters of type TCHAR. That is, if UNICODE is defined, TEXT("abc") will be equivalent to L"abc", and if it is not defined, TEXT("abc") will be equivalent to "abc".
Strings were also given some typedefs as well:
LP[C][W|T]STR
The LP indicates a pointer, and the STR indicates "to a string". If C is included, the string will be a constant one. If W or T is included, the string will be made of characters of type wchar_t or TCHAR respectively.
For example:
LPSTR: char *
LPCSTR: const char *
LPWSTR: wchar_t *
LPCTSTR: const TCHAR *
Using this information, you can correctly understand why using TCHAR and TEXT will cause your code to become compatible with something else, whether it uses narrow or wide characters.
Here's a simple example, keeping in mind that std::string is, for our purposes, std::basic_string<char>:
std::basic_string<TCHAR> s(TEXT("abcd"));
s += TEXT("ZYXW"); //s is now `TEXT("abcdZXW")
Change
#define OPOS_ROOTKEY "SOFTWARE\\OLEforRetail\\ServiceOPOS"
#define OPOS_CLASSKEY_MSR "MSR"
#define OPOSMSR OPOS_ROOTKEY "\\" OPOS_CLASSKEY_MSR "\\"
to
#define OPOS_ROOTKEY L"SOFTWARE\\OLEforRetail\\ServiceOPOS"
#define OPOS_CLASSKEY_MSR L"MSR"
#define OPOSMSR OPOS_ROOTKEY L"\\" OPOS_CLASSKEY_MSR "\\"

wostringstream, Ascii, Unicode, Win32 and integer concatenation to string

I am writing a library that uses Win32 APIs, and I would like to be able to compile it for both ASCII and Unicode (wide character is the type), and I am generating an internal class name (read: WinAPI "class") that I am appending an integer to a string to to create unique class names for various windows functions.
The definitions of the variables used:
LPCTSTR lpszClassName; // This is char* if ASCII, wchar_t* if Unicode.
#ifdef UNICODE
std::wostringstream Convert;
#else
std::ostringstream Convert;
#endif
The function in question:
void Base::MakeClassName () {
#ifdef _DEBUG_
cerr << "Base::MakeClassName() called\n";
#endif
static int name_mod = 0;
name_mod++;
lpszClassName = TEXT("Win32WinNo");
Convert << lpszClassName << name_mod;
lpszClassName = Convert.str().c_str();
#ifdef _DEBUG_
cerr << "Generated class name = " << lpszClassName << "\n";
#endif
}
In ASCII, I get Generated class name = Win32WinNo1
In Unicode, I get a hex value. Which suggests to me the wide character wostringstream is not doing what I want. Either way, CreateWindow doesn't seem to like it (program hangs, if I debug it, it crashes.)
I am not 100% familiar with stringstream, and going by the limited documentation, it returns a 'string' object, but I need a pointer to a C style string for LPCTSTR, so thus, the Convert.str().c_str(). What I am getting is not working right, and If I try TEXT("Win32WinNo1") in my RegisterClass and CreateWindow calls, it works, but this returned string from above is junk.
What am I doing wrong? I am also concerned if it is not appending the integer to the string. does wostringstream covert the integer to wchar_t?
ostringstream::str returns a copy of the string object currently associated with the string stream buffer. c_str points to a buffer internal to that temporary string. lpszClassName is a dangling pointer as soon as this temporary string goes out of scope.
This is probably the reason why your program crashes/hangs.
You output to cerr, which is still a narrow stream. It will likely display the pointer value of lpszClassName and not the wide string it points to.
I think you need to surround your string-literals with _T() so they will be chars or wchar_ts depending on your UNICODE settings.
For example _T("Hello World").

Conversion problem from char * to wchar_t*

The below line works. It prints Success.
wchar_t * s1 = (wchar_t *) L"INSERT INTO OE(sqltext) VALUES('this text')";
if(WriteToSQL(s1) == 0)
printf( "Success"); //Success
else
printf( "Failed");
I need to take user input to create dynamic sql. I need to do what
L prefix is doing.
When i take input and do the required conversion, it does not work.
char input[100];
char sql[500];
printf("Enter input string :: ");
fgets(input,100,stdin);
for(int i=0;i<100;i++)
if(input[i]==10)
input[i]=0;
strcpy(sql,"INSERT INTO OE(sqltext) VALUES('");
strcat(sql,input);
strcat(sql,"')");
wchar_t wsql[500];
MultiByteToWideChar( CP_UTF8, 0, sql, strlen(sql),
wsql, strlen(sql) + 1 );
if(WriteToSQL(wsql) == 0)
printf( "Success");
else
printf( "Failed"); // It failed
Long conversassion but finally it did work. Hex memory dump and input from usta was most helpful. Thanks everybody for their time.
You can't just cast a char * to wchar_t * and expect it to work. You must do proper conversion, for example using MultiByteToWideChar function.
And in general, be very careful with type casts, and in particular avoid using C-style casts in C++ programs. This very case is a good example of why: you told the compiler to shut up ((SQLWCHAR *) sql), and in return got a problem at runtime. Use casts only when you are absolutely sure you are doing the right thing, and know better than the compiler. Not surprisingly, such cases are relatively rare...
Why not using wide chars the whole way?
Like this:
wchar_t input[100];
wchar_t sql[500];
wprintf(L"Enter input string :: ");
fgetws(input,100,stdin);
for(int i=0;i<100;i++)
if(input[i]==10)
input[i]=0;
wcscpy(sql,L"INSERT INTO OE(sqltext) VALUES('");
wcscat(sql,input);
wcscat(sql,L"')");
if(WriteToSQL(sql) == 0)
printf( "Success");
else
printf( "Failed"); // It failed
Warning:I did not test it, but it should work.
Manjoor, by using _tmain you opted using generic text so be consistent and try to stick to generic-text types throughout your program. That way your code will be cleaner and you won't need to use nasty string conversions like MultiByteToWideChar. If you are in position to change WriteToSQL function signature, pass argument 's' as SQLTCHAR* type. Declare sql and input variables as TCHAR arrays, use string routines from TCHAR.H (e.g. _tprintf instead printf, _T() macro for hardcoded strings...). For each routine you are using, go to its MSDN page and check Generic-text routine mappings to see which one you should use.
Google for Microsoft's support for UNICODE in order to better understand issue you had in the example you provided.

TCHAR[], LPWSTR, LPTSTR and GetWindow Text function

So the GetWindowText is declared on MSDN as follows:
int GetWindowText(
HWND hWnd,
LPTSTR lpString,
int nMaxCount
);
However for the code to work we have to declare the second parameter as
TCHAR[255] WTitle;
and then call the function GetWindowText(hWnd,Wtitle,255);
The LPTSTR is a pointer to an array of tchar, so declaring LPTSTR is similar to declaring TCHAR[]? It doesn't work this way though.
When using TCHAR[] the program returns valid GetWindowText result (it is an integer equal to the number of symbols in the title). The question is : how can I get the exact title out of TCHAR[] ? Code like
TCHAR[255] WTitle;
cout<< WTitle;
or
cout<< *Wtitle;
returns numbers. How can I compare this with a given string?
TCHAR[4] Test= __T("TEST")
if (WTitle == Test) do smth
doesn't work also.
Wow, let's see where to start from.
First off, the declaration of WTitle needs to look like this:
TCHAR WTitle[255];
Next, if cout is not working write, it's because you are in Unicode mode so you need to do this:
wcout << WTitle;
Or to fit better with the whole tchar framework, you can add this (actually, I'm surprised that this is not already part of tchar.h):
#ifdef _UNICODE
#define tcout wcout
#else
#define tcout cout
#endif
and then use:
tcout << WTitle;
OK, a few definitions first.
The 'T' types are definitions that will evaluate to either CHAR (single byte) or WCHAR (double-byte), depending upon whether you've got the _UNICODE symbol defined in your build settings. The intent is to let you target both ANSI and UNICODE with a single set of source code.
The definitions:
TCHAR title[100];
TCHAR * pszTitle;
...are not equivalent. The first defines a buffer of 100 TCHARs. The second defines a pointer to one or more TCHARs, but doesn't point it at a buffer. Further,
sizeof(title) == 100 (or 200, if _UNICODE symbol is defined)
sizeof(pszTitle) == 4 (size of a pointer in Win32)
If you have a function like this:
void foo(LPCTSTR str);
...you can pass either of the above two variables in:
foo(title); // passes in the address of title[0]
foo(pszTitle); // passes in a copy of the pointer value
OK, so the reason you're getting numbers is probably because you do have UNICODE defined (so characters are wide), and you're using cout, which is specific to single-byte characters. Use wcout instead:
wcout << title;
Finally, these won't work:
TCHAR[4] Test == __T("TEST") ("==" is equality comparison, not assignment)
if (WTitle == Test) do smth (you're comparing pointers, use wcscmp or similar)
Short answer: Unless you're coding for Win98, use wchar_t instead of TCHAR and wcout instead of cout
Long version:
The TCHAR type exists to allow for code to be compiled in multiple string modes. For example supporting ASCII and Unicode. The TCHAR type will conditionally compile to the appropriate character type based no the setting.
All new Win systems are Unicode based. When ASCII strings are passed to OS functions, they are converted to unicode and the call the real function. So it's best to just use Unicode throughout your application.
Use _tcscmp or a variant (which takes in the number of characters to compare). http://msdn.microsoft.com/en-us/library/e0z9k731.aspx
Like:
if (_tcscmp(WTitle, Test) == 0) {
// They are equal! Do something.
}
In C, wchar_t is a typedef for some integer type (usually short int). In C++, it's required to be a separate type of its own -- but Microsoft's compilers default to using a typedef for it anyway. To make it a separate type of its own, you need to use the /Zc:wchar_t compiler switch. Offhand, I don't know if that will entirely fix the problem though -- I'm not sure if the library has real overloads for wchar_t as a native type to print those out as characters instead of short ints.
Generally speaking, however, I'd advise against messing with Microsoft's "T" variants anyway -- getting them right is a pain, and they were intended primarily to provide compatibility with 16-bit Windows anyway. Given that it's now been about 10 years since the last release in that line, it's probably safe to ignore it in new code unless you're really sure at least a few of your customers really use it.