By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,018 Members | 884 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,018 IT Pros & Developers. It's quick & easy.

Implementing CString with std::string and std::wstring

bajajv
100+
P: 152
Hi, I was trying to implement CString with std::string and std::wstring.
class CString
{
public:
std::string str;
CString() {str = "ABCD";} //this works
}:

class CString
{
public:
std::wstring wstr;
CString() {wstr = "ABCD";} //this doesn't works
}:
The wstring is giving error for =operator. What do I need to add here for wstring?
I am using MS visual studio 2005, but I want to make it compiler independent.
Dec 8 '09 #1
Share this Question
Share on Google+
10 Replies


Banfa
Expert Mod 5K+
P: 8,916
What error is it giving?

Have you tried L"ABCD"?
Dec 8 '09 #2

weaknessforcats
Expert Mod 5K+
P: 9,197
Your Visual Studio project has a charactert set property. This is where you specify char or Unicode. In your code there should never be explicit char or wide char syntax.

You write your code to use the Microsoft-specific amppings between char and Unicode. Do reasearch on the TCHAR mappings.

Note that Windoes does all processing using Unicode. Unless your program specifically needs the char character set, there should be no use of char in your program.
Dec 8 '09 #3

bajajv
100+
P: 152
I want to write a CString which can be OS independent. Is this possible with wide char? I am trying for UNICODE only.
Dec 10 '09 #4

bajajv
100+
P: 152
Thanks Banfa. I missed that.
Dec 10 '09 #5

Banfa
Expert Mod 5K+
P: 8,916
I think you may have a little trouble creating an OS independent multi-byte/wide character string because I believe Windows uses wide characters, that is characters with 16 or more bits per character like UNICODE where as Linux uses multi-byte characters that is the bytes are all 8 bits but sometimes a characters uses more than 1 of them like UTF8.

With wide characters all the characters are the same width (16 bits I think for UNICODE), with multi-byte characters not all characters are the same width, in UTF8 characters can be 1,2,3 or 4 bytes. The first few bits of the byte tell you whether there are more bytes to follow. Additionally in UTF8 there is a 1 - 1 mapping of the first 127 ASCII codes and the first 127 UTF8 codes.

Anyway in Linux a std::string can be used to hold either an ASCII string or a UTF8 string since the basic data unit of both is 8 bit octets. This is not true for Windows if the program is compiled to use UNICODE then it needs to use wide characters wchar_t (although as weaknessforcats says you shouldn't use them directly but through the TCHAR type) which actually have more bits per character (like I siad I think 16).

Because of this difference I think you would find it hard to make a OS independent wide/multi-byte character type.
Dec 10 '09 #6

bajajv
100+
P: 152
Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. #include <string>
  3. #include <stdarg.h>
  4.  
  5. using namespace std;
  6.  
  7. class MyString
  8. {
  9. public:
  10.    wstring wStr;
  11.    MyString ()  {wStr = L"";}
  12.    MyString (wstring str)  {wStr = str;}
  13.    void Format(const wchar_t*lpszFormat, ...);   
  14. };
  15.  
  16. void MyString::Format(const wchar_t* lpszFormat, ...)
  17. {
  18.     wchar_t szBuffer[256];
  19.     va_list args;
  20.     va_start(args, lpszFormat);
  21.     vswprintf(szBuffer, 256, lpszFormat, args);
  22.     va_end (args);
  23.     // Got the string in szBuffer, Now convert to a wchar_t*
  24.     wcscpy(const_cast<wchar_t*>(this->wStr.c_str()), szBuffer);
  25. }
  26.  
  27. int main()
  28. {
  29.     wstring firstName = L"Vipul";
  30.     wstring lastName = L"Bajaj";
  31.     MyString myStr (firstName); 
  32.     wprintf(L"%s\n", myStr.wStr.c_str());
  33.     cout<<myStr.wStr.c_str()<<endl;
  34.     myStr.Format(L"%s%s", firstName.c_str(), lastName.c_str());
  35.     wprintf(L"%s\n", myStr.wStr.c_str());
  36.  
  37. return 0;
  38. }
The above code works fine, but doesnt works when I change the format control string.

e.g. if I change the format string to "%s %s", the code below will not work -
wcscpy(const_cast<wchar_t*>(this->wStr.c_str()), szBuffer);
How can I improve this?
is there any way to accomodate that space, or a slash '\' or anything in between those two '%s'?
Dec 12 '09 #7

bajajv
100+
P: 152
One reason could be that the space between - "%s %s" - is in ASCII... but it should also be wide character, as I am providing it using an L - L"%s %s"... Please clear this doubt.. Is this L converting the space also to wide character?
Dec 12 '09 #8

weaknessforcats
Expert Mod 5K+
P: 9,197
Why aren't you using:

Expand|Select|Wrap|Line Numbers
  1. wcout << myStr << endl;
?

Avoid the printf family of functions. They are from C and they do not allow print of user defined types so there's no way to print a Date or a Person object.

A wcscpy does not convert a char string to a wchar_t string. You need to call MultiByteToWideString.

Again, all of this is done for you already if you use TCHAR.
Dec 12 '09 #9

bajajv
100+
P: 152
But I cant use windows specific things. I need to make it work on both windows and unix.
Dec 14 '09 #10

Banfa
Expert Mod 5K+
P: 8,916
Since Windows and UNIX handle multi-byte, wide characters rather differently you are unlikely to be able to to create a class that will do both.

As weaknessforcats says you should be using TCHAR for Windows which wont work for *nix, as I have said you need to be use std:string for *nix which wont work for Windows. Windows and *nix have very different approaches to implementing wide/multi-byte characters.

The only way to implement your class as a normal class would be to make it very complex internally effectively implement 2 different methods to choose between depending on the operating system detected.

An easier method might be to use the adaptor or façade design patterns. These patterns effectively allow you to wrap one class in another or to wrap some API in a class. You would create a standard declaration of a string class that your code can call but you would provide different implementations depending on the target OS during compile time.

That way you could provide one implementation that worked on Windows and another that worked on *nix.
Dec 14 '09 #11

Post your reply

Sign in to post your reply or Sign up for a free account.