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

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • bajajv
    New Member
    • Jun 2007
    • 152

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

    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.
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    What error is it giving?

    Have you tried L"ABCD"?

    Comment

    • weaknessforcats
      Recognized Expert Expert
      • Mar 2007
      • 9214

      #3
      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.

      Comment

      • bajajv
        New Member
        • Jun 2007
        • 152

        #4
        I want to write a CString which can be OS independent. Is this possible with wide char? I am trying for UNICODE only.

        Comment

        • bajajv
          New Member
          • Jun 2007
          • 152

          #5
          Thanks Banfa. I missed that.

          Comment

          • Banfa
            Recognized Expert Expert
            • Feb 2006
            • 9067

            #6
            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.

            Comment

            • bajajv
              New Member
              • Jun 2007
              • 152

              #7
              Code:
              #include <iostream>
              #include <string>
              #include <stdarg.h>
              
              using namespace std;
              
              class MyString
              {
              public:
                 wstring wStr;
                 MyString ()  {wStr = L"";}
                 MyString (wstring str)  {wStr = str;}
                 void Format(const wchar_t*lpszFormat, ...);   
              };
              
              void MyString::Format(const wchar_t* lpszFormat, ...)
              {
              	wchar_t szBuffer[256];
              	va_list args;
              	va_start(args, lpszFormat);
              	vswprintf(szBuffer, 256, lpszFormat, args);
              	va_end (args);
              	// Got the string in szBuffer, Now convert to a wchar_t*
              	wcscpy(const_cast<wchar_t*>(this->wStr.c_str()), szBuffer);
              }
              
              int main()
              {
              	wstring firstName = L"Vipul";
              	wstring lastName = L"Bajaj";
              	MyString myStr (firstName); 
              	wprintf(L"%s\n", myStr.wStr.c_str());
              	cout<<myStr.wStr.c_str()<<endl;
              	myStr.Format(L"%s%s", firstName.c_str(), lastName.c_str());
              	wprintf(L"%s\n", myStr.wStr.c_str());
              
              return 0;
              }
              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_ca st<wchar_t*>(th is->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'?

              Comment

              • bajajv
                New Member
                • Jun 2007
                • 152

                #8
                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?

                Comment

                • weaknessforcats
                  Recognized Expert Expert
                  • Mar 2007
                  • 9214

                  #9
                  Why aren't you using:

                  Code:
                  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 MultiByteToWide String.

                  Again, all of this is done for you already if you use TCHAR.

                  Comment

                  • bajajv
                    New Member
                    • Jun 2007
                    • 152

                    #10
                    But I cant use windows specific things. I need to make it work on both windows and unix.

                    Comment

                    • Banfa
                      Recognized Expert Expert
                      • Feb 2006
                      • 9067

                      #11
                      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.

                      Comment

                      Working...