Using C++Builder 10.4 (latest updates as of 5-Dec-2020) and attempting to use some sample code from RAD Studio Docwiki (specifically the C++ Version & not Delphi) [Environment & target: Windows 10, 32 bit target] I've run into a couple issues. The example code simply breaks.
Issue 1: wcstombs, which is documented to convert wchar_t string to char string: Apparently this converts only the very first item in the string. the result shows only the first character, and looking @ a watch on the wchar_t and the char variables, it shows a full string in wchar_t, just a single character in the char string.
Issue2: attempting to use this code (directly from the example, with the headers as noted in the example)
wchar_t *pwcsEOL = L'\0';
char *pwchi= L"Hi there!";
results in error messages saying that cannot initialize wchar_t to an rvalue of wchar_t; the char is the same. Since these are the explicit examples as posted int eh code in the Docwiki, I'm not sure what to do.
Any help, especially with converting w wchar_t (character in an array, or as an entire string) would be appreciated.
Below is the code, directly from Docwiki. I'm only trying to use the single line: x = wcstombs( pbuf, pwchi,MB_CUR_MAX);, but have attempted to set it up with the entire 4 variable definition & initialization lines. The last 2 give errors. Using a previously generated
wchar_t TestVar *; line & filling it from System Time is accepted by wcstombs, but yields only 1 character converted.
Example
#include <stdio.h>
#include <stdlib.h>
void main(void)
{
int x;
char *pbuf = (char*)malloc( MB_CUR_MAX);
wchar_t *pwcsEOL = L'\0';
char *pwchi= L"Hi there!";
printf (" Convert entire wchar string into a multibyte string:\n");
x = wcstombs( pbuf, pwchi,MB_CUR_MAX);
printf ("Character converted: %u\n", x);
printf ("Multibyte string character: %1s\n\n",pbuf);
printf (" Convert when target is NULL\n");
x = wcstombs( pbuf, pwcsEOL, MB_CUR_MAX);
printf ("Character converted: %u\n",x);
printf ("Multibyte string: %1s\n\n",pbuf);
}
wcstombs & wchar_t issues
Moderator: 2ffat
Re: wcstombs & wchar_t issues
The DocWiki example you are looking at has many mistakes in it, so it is no wonder why you are having trouble with it.LexRutter wrote: ↑Sat Dec 05, 2020 10:24 am Using C++Builder 10.4 (latest updates as of 5-Dec-2020) and attempting to use some sample code from RAD Studio Docwiki (specifically the C++ Version & not Delphi) [Environment & target: Windows 10, 32 bit target] I've run into a couple issues. The example code simply breaks.
That is because MB_CUR_MAX "defines an integer expression giving the maximum number of bytes needed to represent a single wide character in the current locale", which in your case is likely 1 byte. So the pbuf buffer is not large enough to hold more than 1 char on output. You can verify that by looking at the return value of wcstombs(), which returns the number of chars output, not counting a null terminator.LexRutter wrote: ↑Sat Dec 05, 2020 10:24 am Issue 1: wcstombs, which is documented to convert wchar_t string to char string: Apparently this converts only the very first item in the string. the result shows only the first character, and looking @ a watch on the wchar_t and the char variables, it shows a full string in wchar_t, just a single character in the char string.
That code is completely wrong. It is trying to assign a single wchar_t to a wchar_t* pointer, and it is trying to assign a const wchar_t[] string literal to a char* pointer. Both of which are wrong and will not compile.LexRutter wrote: ↑Sat Dec 05, 2020 10:24 am Issue2: attempting to use this code (directly from the example, with the headers as noted in the example)
wchar_t *pwcsEOL = L'\0';
char *pwchi= L"Hi there!";
results in error messages saying that cannot initialize wchar_t to an rvalue of wchar_t; the char is the same.
The pwcsEOL mistake can be fixed by doing either this:
Code: Select all
wchar_t wcsEOL = L'\0';
...
x = wcstombs( pbuf, &wcsEOL, MB_CUR_MAX);
Code: Select all
const wchar_t *wcsEOL = L"\0";
...
x = wcstombs( pbuf, pwcsEOL, MB_CUR_MAX);
Code: Select all
const wchar_t *pwchi = L"Hi there!";
Try this instead:
Code: Select all
#include <stdio.h> // better: <cstdio>
#include <stdlib.h> // better: <cstdlib>
/* uncomment this if using the <c...> C++ headers above...
using std::printf;
using std::wcstombs;
*/
int main()
{
size_t x;
char buf[20];
const wchar_t *pwcsEOL = L"\0";
const char *pwchi = L"Hi there!";
printf ("Convert entire wchar string into a multibyte string:\n");
x = wcstombs( buf, pwchi, 20 );
printf ("Character converted: %zu\n", x);
if (x != (size_t)-1) {
printf ("Multibyte string character: %.*s\n\n", (int)x, buf);
}
printf ("Convert when target is NULL\n");
x = wcstombs( buf, pwcsEOL, 20 );
printf ("Character converted: %zu\n", x);
if (x != (size_t)-1) {
printf ("Multibyte string: %.*s\n\n", (int)x, buf);
}
return 0;
}
Code: Select all
#include <vcl.h>
#pragma hdrstop
#include <iostream>
using std::cout;
int main()
{
AnsiString str;
UnicodeString pwcsEOL = L"\0";
UnicodeString pwchi = L"Hi there!";
cout << "Convert entire wchar string into a multibyte string:\n";
str = pwchi;
cout << "Character converted: " << str.Length() << "\n";
cout << "Multibyte string character: " << str.c_str() << "\n\n";
cout << "Convert when target is NULL\n";
str = pwcsEOL;
cout << "Character converted: " << str.Length() << "\n";
cout << "Multibyte string: " << str.c_str() << "\n\n";
return 0;
}
Remy Lebeau (TeamB)
Lebeau Software
Lebeau Software
Re: wcstombs & wchar_t issues
Thanks very much, I do appreciate the detailed response, it's quite helpful.
Some additional comments, the code with the note "it's wrong" happens to come directly from the Embarcadero Help page examples. I really appreciated the note about it - gets a bit frustrating when the Examples and samples don't work.
I did eventually find some other, more elegant solutions to the problem. Along the way I also discovered that the example routine for converting a single character actually give a large destination and a single-character source. It would appear that the functions are actually written with some issues. (Even with a large-bite target, the way it's written you can only use a single-character source, where the function I tried to use lets you use any length source, but only allows a single character in the destination. I did notice that while working with it originally.)
Finally, I've been trying to work mostly with C++ and Builder VCL calls. Without any written libraries (i.e. Books), and what I'd term an awkward help & search function, it's been a struggle to find the best, most logical routines. This forum looks like it's a wealth of information. I'll close by repeating: Thanks for all the comments and pointers. Really a big help.
Some additional comments, the code with the note "it's wrong" happens to come directly from the Embarcadero Help page examples. I really appreciated the note about it - gets a bit frustrating when the Examples and samples don't work.
I did eventually find some other, more elegant solutions to the problem. Along the way I also discovered that the example routine for converting a single character actually give a large destination and a single-character source. It would appear that the functions are actually written with some issues. (Even with a large-bite target, the way it's written you can only use a single-character source, where the function I tried to use lets you use any length source, but only allows a single character in the destination. I did notice that while working with it originally.)
Finally, I've been trying to work mostly with C++ and Builder VCL calls. Without any written libraries (i.e. Books), and what I'd term an awkward help & search function, it's been a struggle to find the best, most logical routines. This forum looks like it's a wealth of information. I'll close by repeating: Thanks for all the comments and pointers. Really a big help.