wostringstream, Ascii, Unicode, Win32 and integer concatenation to string - c++

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").

Related

C++ File Write includes the memory address of the string instead of the contents

All,
I'm still learning C++ but I have an issue in a project I'm tinkering with that I'm curious about. I've noticed that when I try to print the contents of a string that is a member of a class, I get the memory address instead of the contents. I understand that this is because the item is a pointer, but what I"m confused about is that I am using the -> operator to deference it.
Why can I evaluate the class member in an if statement using the -> operator to dereference it but when printing to a file string in the same manner I get the memory address instead?
An example is below:
Lets say I have a class called pClass with a member called m_strEmployeeName. As a side note (I don't know if it matters), the m_strEmployeeName value is CString rather than std::string, so there could be some unknown conversion issue possibly as well.
If I used the following simple code, I get a memory address.
std::ofstream file("testfile.text");
file << pClass->m_strEmployeeName;
file.close();
I get the same behavior with the following dereferencing method (which I would expect since -> is the same thing).
std::ofstream file("testfile.text");
file << (*pClass).m_strEmployeeName;
file.close();
Any idea on what I'm doing wrong?
It is because your CString class is actualy CStringW class wich contain wchar_t strings so std::ofstream not contain operator >> overload that support wchar_t* strings. To print CStringW class objects you may use this type of stream std::wofstream it recognize wchar_t* strings properly and output will be right.
std::wofstream file("testfile.text");
file << pClass->m_strEmployeeName;
file.close();
You may also create your program in multibyte character support. It can be specified in your project settings. But I suggest you to stay with UNICODE.
Try casting CString to a char pointer:
file << (LPCTSTR)pClass->m_strEmployeeName;
see: How to convert CString and ::std::string ::std::wstring to each other?
Note: This will only work if you have TCHAR defined as 8 bits. If you're using 16-bit UNICODE TCHAR, you'd have one more conversion.
Here is one way of doing the TCHAR conversion:
char c_str[1000];
size_t ret;
wcstombs_s(
&ret,
c_str,
sizeof(c_str),
(LPCTSTR)pClass->m_strEmployeeName,
pClass->m_strEmployeeName.GetLength()
);
std::ofstream file("testfile.text");
file << c_str;
file.close();
Useful if you need 8-bit ASCII file but have a UNICODE CString to work with.

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 "\\"

C++: LPWSTR prints as an address in cout

I have a variable of type LPTSTR, which I print to std::cout with <<. In an ANSI system (don't know exactly where it is determined) it worked fine, it printed the string. Now in a Unicode system I get a hex address instead of the string. So, why does LPSTR (to which LPTSTR is resolved if UNICODE is not defined) act differently from LPWSTR (... if UNICODE is defined) and how do I print the string pointed by the latter one?
For Unicode strings you want wcout.
You may be seeing hex because the ANSI/ASCII output stream doesn't know how to handle Unicode characters.
LPTSTR and LPWSTR are actually C-isms inherited from the C Windows API days. For C++ I would strongly encourage you to use std::string and/or std::wstring instead.
If you need to roll your own macro, you'll want something like:
#ifdef _UNICODE
std::wostream& COUT = std::wcout;
#else
std::ostream& COUT = std::cout;
#endif

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.

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

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