gil_mo
asked on
Need a macro that converts into wide-char string...
In one of the include files of my program, I have the following:
#define Str4 "1234"
I'm now looking for a macro that would convert this into a wide-character string. The macro should look like this:
#define WIDE(S) <Macro implementation...>
and then, WIDE(Str4) would expand to L"1234".
How do I do it??
Special note: Please avoid posting comments or suggestions that you havn't tested, like most postings below (until Jan-24)
#define Str4 "1234"
I'm now looking for a macro that would convert this into a wide-character string. The macro should look like this:
#define WIDE(S) <Macro implementation...>
and then, WIDE(Str4) would expand to L"1234".
How do I do it??
Special note: Please avoid posting comments or suggestions that you havn't tested, like most postings below (until Jan-24)
ASKER
jkr, WIDE(Str4) simply pastes L to Str4 to yield LStr4 rather than L"1234".
ASKER
(see my comment)
Hi gil_mo,
couldn't you simply call something like:
'L Str4'
There is (AFAIK) no difference between
'L"1234"' and
'L "1234"'...
ZOPPO
couldn't you simply call something like:
'L Str4'
There is (AFAIK) no difference between
'L"1234"' and
'L "1234"'...
ZOPPO
#define Str4 WIDE("1234")
ASKER
Zoppo, there *is* a difference (wouldn't compile with an extra space. Besides, how would you insert the space using the macro?).
jkr, oooooh my, you are suggesting that I replace the definition of Str4 with another! There are many places in the code where I use Str4 as it is now - it would cease to work!
jkr, oooooh my, you are suggesting that I replace the definition of Str4 with another! There are many places in the code where I use Str4 as it is now - it would cease to work!
wow, jkr, how did you do that? You added one comment and I recieved 18 (!) notification eMails ;-\
ASKER
(me too! something was baaaaad with E-E for a while there)
well, gil_mo, you're right, there's a difference ... so, only solution I see now is something like:
#ifdef I_WANNA_USE_UNICODE
#define WIDE(s) L##s
#else
#define WIDE(s) s
#endif
#define Str4 WIDE("1234")
...
and define I_WANNA_USE_UNICODE wherever you want it...
ZOPPO
#ifdef I_WANNA_USE_UNICODE
#define WIDE(s) L##s
#else
#define WIDE(s) s
#endif
#define Str4 WIDE("1234")
...
and define I_WANNA_USE_UNICODE wherever you want it...
ZOPPO
ASKER
mmmm... no decent answer for a couple of days now, me wonder... Could it be I found a limitation in the C language?
C doesn't have many limitations, try this:
#define Str4 "1234"
#define WIDE(S) L#S // Single # char instead of double
main()
{
WIDE(Str4) // would expand to L"1234"
}
#define Str4 "1234"
#define WIDE(S) L#S // Single # char instead of double
main()
{
WIDE(Str4) // would expand to L"1234"
}
ASKER
No, zebada, it expands to L"Str4". Did you try it out before posting your comment?
I tested it but obviously I was suffering from "brain fade" - sorry about that :(
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I was also thinking about this way of doing it, but never having used wide strings I am not familiar with the syntax used to declare them so this suggestion may be completely wrong:
However I assume that (expr) is equivalent to expr as described by the C definition of an expression.
#define Str4 "1234"
#define WIDE(S) L(S)
main()
{
WIDE(Str4) // would expand to L("1234")
}
However I assume that (expr) is equivalent to expr as described by the C definition of an expression.
#define Str4 "1234"
#define WIDE(S) L(S)
main()
{
WIDE(Str4) // would expand to L("1234")
}
ASKER
zebada, I'll buy your compiler for a million if it is so magnificant as to compile any of your suggestions.
You can send the million to my swiss bank account
#include <stdio.h>
#define Str4 "1234"
#define x(dummy) L
#define WIDE(S) x(dummy)S
main()
{
int i;
wchar_t *s;
s = WIDE(Str4);
for ( i=0 ; i<4 ; i++,s++ )
printf("%d\n",*s);
}
Here's the *.i preprocessor output:
main()
{
int i;
wchar_t *s;
s = L"1234";
for ( i=0 ; i<4 ; i++,s++ )
printf("%d\n",*s);
}
#include <stdio.h>
#define Str4 "1234"
#define x(dummy) L
#define WIDE(S) x(dummy)S
main()
{
int i;
wchar_t *s;
s = WIDE(Str4);
for ( i=0 ; i<4 ; i++,s++ )
printf("%d\n",*s);
}
Here's the *.i preprocessor output:
main()
{
int i;
wchar_t *s;
s = L"1234";
for ( i=0 ; i<4 ; i++,s++ )
printf("%d\n",*s);
}
gil_mo: zebada's suggestion works great in VC++ 6, and should work fine in any compiler. x(dummy) isn't the greates name and parameter - something like WIDE2() might be better - but it works right.
ASKER
Zebada, my apologies and a million is on its way.
Your solution doesn't compile with my *real* case (here I gave only a simplified case):
#define P_VERSION "1.0"
#define P_CODE "D" P_VERSION // Haa! concatenated string...
wcscpy(wStr, WIDE(P_CODE));
Anyway, you deserve the points, if you have an additional insight regarding the real situation, please tell.
I've never heard of *.i files - how do I generate them?
Your solution doesn't compile with my *real* case (here I gave only a simplified case):
#define P_VERSION "1.0"
#define P_CODE "D" P_VERSION // Haa! concatenated string...
wcscpy(wStr, WIDE(P_CODE));
Anyway, you deserve the points, if you have an additional insight regarding the real situation, please tell.
I've never heard of *.i files - how do I generate them?
This won't work at all, because you're #define-ing P_CODE to be
"D" "1.0"
Notice that you cannot do
L"D" "1.0"
even directly, because the L applies only to the first string. You have to do
L"D" L"1.0"
"D" "1.0"
Notice that you cannot do
L"D" "1.0"
even directly, because the L applies only to the first string. You have to do
L"D" L"1.0"
So what to do depends on what you need to not change...
If it's going to be concatenated, you have to have the L modifier on each string, so you need to change the #define.
Maybe something like this:
#define P_VERSION "1.0"
#define P_CODE L"D" WIDE(P_VERSION)
wcscpy(wStr, P_CODE);
But it seems you probably want your code to be an'e to do something like this:
wcscpy(wStr, WIDE(P_CODE));
strcpy(str, P_CODE);
There is unfortunately no way to do this, because the L modifier works only on single strings as I mentioned. You can have two defines:
#define P_VERSION "1.0"
#define P_CODE "D" P_VERSION
#define P_WCODE L"D" WIDE(P_VERSION)
wcscpy(wStr, P_WCODE);
strcpy(str, P_CODE);
Or you can not use concatenation:
#define P_CODE "D1.0"
wcscpy(wStr, WIDE(P_CODE));
strcpy(str, P_CODE);
Or you can use actual conversion functions:
MultiByteToWideChar(CP_ACP , MB_ERR_INVALID_CHARS, P_CODE, strlen(P_CODE), wStr, 256);
(instead of wcscpy, this is a Win function, other platforms may be different or you may have to write your own)
If it's going to be concatenated, you have to have the L modifier on each string, so you need to change the #define.
Maybe something like this:
#define P_VERSION "1.0"
#define P_CODE L"D" WIDE(P_VERSION)
wcscpy(wStr, P_CODE);
But it seems you probably want your code to be an'e to do something like this:
wcscpy(wStr, WIDE(P_CODE));
strcpy(str, P_CODE);
There is unfortunately no way to do this, because the L modifier works only on single strings as I mentioned. You can have two defines:
#define P_VERSION "1.0"
#define P_CODE "D" P_VERSION
#define P_WCODE L"D" WIDE(P_VERSION)
wcscpy(wStr, P_WCODE);
strcpy(str, P_CODE);
Or you can not use concatenation:
#define P_CODE "D1.0"
wcscpy(wStr, WIDE(P_CODE));
strcpy(str, P_CODE);
Or you can use actual conversion functions:
MultiByteToWideChar(CP_ACP
(instead of wcscpy, this is a Win function, other platforms may be different or you may have to write your own)
ASKER
conchita, thanks for your insights.
#define WIDE(s) L##s
(see
#define __T(x) L ## x
in 'tchar.h' - BTW: '##' is called the 'merging operator')
Feel free to ask if you need more information!