0

There are lots of times this question has been asked and as many answers - none of which work for me and, it seems, many others. The question is about wide CStrings and 8bit chars under MFC. We all want an answer that will work in ALL cases, not a specific instance.

void Dosomething(CString csFileName)
{
    char cLocFileNamestr[1024];
    char cIntFileNamestr[1024];
    // Convert from whatever version of CString is supplied
    // to an 8 bit char string
    cIntFileNamestr = ConvertCStochar(csFileName);

    sprintf_s(cLocFileNamestr, "%s_%s", cIntFileNamestr, "pling.txt" );
    m_KFile = fopen(LocFileNamestr, "wt");
}

This is an addition to existing code (by somebody else) for debugging. I don't want to change the function signature, it is used in many places. I cannot change the signature of sprintf_s, it is a library function.

Peemer
  • 49
  • 1
  • 6
  • 2
    In what encoding would you like your C-style string, and what do you want to do with characters that aren't representable in it? – Wintermute May 26 '15 at 09:26
  • There are no 8-bit characters in MFC, or Windows for that matter. Those are [MBCS](https://msdn.microsoft.com/en-us/library/cwe8bzh0.aspx) characters, that are interpreted based on a particular [Code page](http://en.wikipedia.org/wiki/Code_page). Characters - in general - cannot be properly interpreted, unless you specify its encoding. Which encoding should your target string be in? What about non-representable characters? And why aren't you simply calling [swprintf_s](https://msdn.microsoft.com/en-us/library/ce3zzk1k.aspx) instead? – IInspectable May 26 '15 at 10:01
  • possible duplicate of [Convert CString to const char\*](http://stackoverflow.com/questions/859304/convert-cstring-to-const-char) – IInspectable May 26 '15 at 10:05
  • Over complication is a major problem here. This is for debugging for me ( not in Russian). Characters will be as typed on an English keyboard using English letters to make sense in English. Sorry for the duplication but I have been at it for ages. – Peemer May 27 '15 at 09:31

2 Answers2

1

You are leaving out a lot of details, or ignoring them. If you are building with UNICODE defined (which it seems you are), then the easiest way to convert to MBCS is like this:

CStringA strAIntFileNameStr = csFileName.GetString(); // uses default code page

CStringA is the 8-bit/MBCS version of CString.

However, it will fill with some garbage characters if the unicode string you are translating from contains characters that are not in the default code page.

Instead of using fopen(), you could use _wfopen() which will open a file with a unicode filename. To create your file name, you would use swprintf_s().

Joseph Willcoxson
  • 5,853
  • 1
  • 15
  • 29
  • So, one of the things said about CStrings is that it is easy to convert to traditional char* strings. What if the function we are trying to poke these characters into is a legacy function that only accepts char* strings in ascii? – Peemer May 27 '15 at 09:34
0

an answer that will work in ALL cases, not a specific instance...

There is no such thing.

It's easy to convert "ABCD..." from wchar_t* to char*, but it doesn't work that way with non-Latin languages.

Stick to CString and wchar_t when your project is unicode.

If you need to upload data to webpage or something, then use CW2A and CA2W for utf-8 and utf-16 conversion.

CStringW unicode = L"Россия";
MessageBoxW(0,unicode,L"Russian",0);//should be okay

CStringA utf8 = CW2A(unicode, CP_UTF8);
::MessageBoxA(0,utf8,"format error",0);//WinApi doesn't get UTF-8

char buf[1024];
strcpy(buf, utf8);
::MessageBoxA(0,buf,"format error",0);//same problem

//send this buf to webpage or other utf-8 systems
//this should be compatible with notepad etc. 
//text will appear correctly
ofstream f(L"c:\\stuff\\okay.txt");
f.write(buf, strlen(buf));

//convert utf8 back to utf16
unicode = CA2W(buf, CP_UTF8);
::MessageBoxW(0,unicode,L"okay",0);
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • Once again, change the function rather than convert the characters. – Peemer May 27 '15 at 09:37
  • If it's guaranteed to be in English, then simply use `CStringA` and `CStringW` to convert back and forth between ANSI and Unicode. See Joe Willcoxson's answer. `CString` is defined as `CStringW` or `CStringA` depending on `#ifdef _UNICODE` – Barmak Shemirani May 27 '15 at 17:09