Why std::string object could not output correctly when calling CString::Format - string-formatting

I have written the following statements:
CString strResult;
std::string errorReason("no this item");
strResult.Format("the error reason is: %s", errorReason);
It seems that it could not format the std::string object correctly; However, if I just replace std::string as CStirng, then strResult could format correctly.
Why va_arg could support CStirng, instead of std::string?
Thanks

Unlike CString, std::string doesn't provide an implicit conversion to const char* (for good reasons) and, what is more important in this case, the binary layout of std::string may not be compatible with const char*. You should use errorReason.c_str() instead.

Related

Does sprintf() require format specifiers to work properly?

I have read the post sprintf format specifier replace by nothing, and others related, but have not seen this addressed specifically.
Until today, I have never seen sprintf used with only 2 arguments.
The prototype my system uses for sprintf() is:
int sprintf (char Target_String[], const char Format_String[], ...);
While working with some legacy code I ran across this: (simplified for illustration)
char toStr[30];
char fromStr[]={"this is the in string"};
sprintf(toStr, fromStr);
My interpretation of the prototype is that the second argument should be comprised of a const char[], and accepting standard ansi C format specifiers such as these.
But the above example seems to work just fine with the string fromStr as the 2nd argument.
Is it purely by undefined behavior that this works?, or is this usage perfectly legal?
I a working on Windows 7, using a C99 compiler.
Perfectly legal. The variadic arguments are optional.
In this case the printf serves as strcpy but parses the fmt string for % specifiers.
I'd write sprintf(toStr,"%s",fromStr); so it doesn't have to parse that long string.
The behavior you are observing is correct, a format string is not required to have any conversion specifiers. In this case the variable-length argument list, represented by ..., has length of zero. This is perfectly legal, although it's definitely less efficient than its equivalent
strcpy(toStr, fromStr);
It's perfectly legal code, but
If you just want to copy a string, use strcpy() instead.
If you are working with user input, you could be making yourself vulnerable to a format string attack.
Synopsis for sprintf is:
int sprintf(char *str, const char *format, ...);
That means 2 arguments are legal option.
It works because you have no further parameter (ie no control format %) to print.
It's no difference than printf without second parameter:
int printf ( const char * format, ... );
It also works if you don't have any second parameter:
printf(fromStr);
the second argument should be comprised of a const char[]
A const specifier of a function argument guarantees that the function does not change the value of that argument (given it can change it which is the case on arrays because they are passed by address to the function). It does not require that a const value to be used on the actual call.
The code you posted do not use a const string as the second argument to sprintf() but the conversion from non-const to const is implicit; there is no need to worry there.
accepting standard ansi C format specifiers
"accepting" does not mean "requiring". The format string you specified does not contain any format specifier. Accordingly, the function is called with only 2 arguments (no values to format). A third argument would be ignored by sprinf() anyway and many modern compilers would issue an warning about it.
Update: I don't want to start a debate about which compilers are modern and which are not.
It happens that I'm using the default compiler on OSX 10.11 and this what it outputs:
axiac: ~/test$ cc -v
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.3.0
Thread model: posix
axiac: ~/test$ cc -o 1 1.c
1.c:8:25: warning: data argument not used by format string [-Wformat-extra-args]
sprintf(x, "abc\n", n);
~~~~~~~ ^

Passing a pointer (string) to a C function

Please read until the end before you say: "Oh no, this question again..."
I am right now seating in a C course and the following example has been provided in course book:
#include <stdio.h>
#include <stdint.h>
void Terminal_PrintData(uint16_t * const Data);
int main(void){
uint16_t StringData[] = "MyData";
Terminal_PrintData(StringData);
}
void Terminal_PrintData(uint16_t * const Data)
{
printf("Value: %s", *Data);
}
When I compile this masterpiece, this is what I get:
F:\AVR Microcontroller>gcc -o test test.c
test.c: In function 'main':
test.c:7:26: error: wide character array initialized from non-wide string
uint16_t StringData[] = "MyData";
My questions are:
Is it correct to declare a string with uint16_t?
What is recommended way to pass a string to a function?
Your immediate questions:
Is it correct to declare a string with uint16_t?
No.
All strings are always char[]. There ar also wide strings (strings of wide characters), which have the type wchar_t[], and are written with an L prefix (e.g. L"hello").
What is recommended way to pass a string to a function?
As a pointer to the first character in the string, so either char * or wchar_t *. The const qualifier makes no sense here; it would mean that the pointer (not the string itself) is constant (see here). I'd recommend writing wchar_t const * or const wchar_t * instead; it has a different meaning (i.e. the string can't be changed), but it's correct and meaningful.
You mention that this code is from a course book. I'm not sure whether you mean that these are lecture notes handed out by your professor, or whether you bought a published book. In either case, if this snippet is representative of the quality of the book/notes, get a refund.
For now, let's make this code work.
There's an error in this code that will cause the program to crash:
printf("... %s ...", ..., *string, ...) when string is a char* is always wrong. Don't dereference that pointer.
If you insist on using "wide" characters (which is questionable), you're going to have to change a few things:
Rather than using char, you need to include <wchar.h> and use wchar_t instead. As far as I know, uint16_t and uint8_t won't work unless you use explicit casting everywhere. That's because char doesn't have 8 bits, but CHAR_BIT bits.
Wide character literals must start with an L prefix.
Rather than using printf, you need to use wprintf.
In the format string, use %ls rather than %s. (Unless you use Microsoft's compiler.)
Finally, some less grave errors:
As noted, T * const arguments are useless. The author probably meant T const * (or equivalently const T *).
You can remove <stdint.h> and <stdio.h>. We're no longer using uint16_t, and <wchar.h> declares some wide character <stdio.h>-like functions.
I end up with the following code:
#include <wchar.h>
void Terminal_PrintData(wchar_t const * Data);
int main(void){
wchar_t StringData[] = L"MyData";
Terminal_PrintData(StringData);
}
void Terminal_PrintData(wchar_t const * Data)
{
wprintf(L"Value: %ls", Data);
}
This compiles and runs as expected with both GCC and Clang on Linux x86-64.
There are two kinds of strings: "non-wide" ones which consist of chars and "wide" ones which consist of wchar_ts and are written as L"" (single wchar_ts can be written as L''). There are functions to convert between them; apart from these, you cannot intermix them.
Depending on the system, a wchar_t can be 16 or 32 bits wide.
You should view your string as an array of characters (in this case, 8-bit characters) so a uint8_t would suffice. What you normally do is pass the beginning of the string (which is the pointer to the array) to your function. To make it safer, you could also pass the length of the string as an argument, but normally your string will end with a delimiter (\0).
when you pass stringData to your function, you're actually saying &stringData[0], literally "the address (&) of the first element ([0]) of the array".

Perform special kind of initialization of string in C

As you know in C, we can initialize string variables like this:
char text[1024] =
"Hello "
"World";
But what if I have a function that returns the word "World"?
char text[1024] =
"Hello "
World();
It seems to me that's not possible in C.
Please confirm.
What you want is not possible.
The L-value to the assigment operator needs to be modifyable, which an array isn't.
From the C11-Standard:
6.5.16/2
An assignment operator shall have a modifiable lvalue as its left operand.
The only exception to this is during initialisation when using literals as R-value:
char text[1024] = "Hello ""World";
From the C11-Standard:
6.7.9/14
An array of character type may be initialized by a character string literal or UTF−8 string
literal, optionally enclosed in braces. Successive bytes of the string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.
If World() is something that always returns "World", then define it as a macro:
#define World "World"
And then do:
char text[1024] =
"Hello "
World; //Without parentheses
EDIT
String concatenation in the way you expect to do is made by the C preprocessor.You are actually looking for a runtime concatenation of two strings, which can be performed in multiple ways. The simplest one is achieved by strcat function, but the initialization should be performed explicitly by a function:
char text[1024];
void init_text() {
strcpy(text, "Hello ");
strcat(text, World()); //World() defined somewhere else
}
Alternative using sprintf :
void init_text() {
sprintf(text, "Hello %s", World());
}
Then in the main function, call init_text() at the beginning:
int main() {
init_text();
...
}
It is not possible in standard C to initialize something with some runtime specific behavior. So the standard portable way is to initialize the data by calling a function at the beginning of main, as answered by Claudix.
However, if you are using some recent GCC compiler (or Clang/LLVM) you could otherwise, on some systems (including Linux and probably other POSIX systems), use some constructor attribute on function. So you would declare:
static void init_text(void) __attribute__((constructor));
and define init_text like in Claudix's answer without having to call it in your main : since it has the constructor attribute, it would be called magically before main, or during dlopen(3) if it appears inside a dynamically linked plugin or library.
A more portable trick might be to have a function returning that text which will initialize it during its first call. So instead of using text you would call get_my_text() everywhere (perhaps by putting #define text get_my_text() in a header, but I don't recommend doing so for readability reasons, so replace every occurrence of text by get_my_text() ...), and define it as:
const char*get_my_text() {
static char textbuf[1024];
if (textbuf[0]) {
// already initialized, so return it
return textbuf;
};
snprintf(textbuf, sizeof(textbuf), "Hello %s", World());
return textbuf;
}
Beware that such a trick is not reliable in multi-threaded programs: two threads might run get_my_text exactly at the same time, and you have a data race. In a multi-threaded app use e.g. pthread_once
You could even define get_my_text as a static inline function in your header file.
PS Always prefer snprintf(3) to sprintf to avoid buffer overflows. Also notice that in standard C++ any static or global data with some given constructor is initialized before main ... hence the name of GCC function attribute...

Pass a string containing a function name and its arguments to another function.

I would like to pass a string to a function in C in which the function will parse out a function name, the arguments for the function, and its datatypes, and then call the function for me. What is the best approach?
If you want to write a function with a format string and variable arguments like:
int function(const char* strFormat, ... )
{
//parse out the format using regex or something
//then store the data into the variable aruments
//or create a string concatenating everything
}
like, say printf, sprintf, or scanf does,
then the best thing for you to do is look at some good tutorials.
http://msdn.microsoft.com/en-us/library/fxhdxye9(v=vs.80).aspx
http://www.cprogramming.com/tutorial/c/lesson17.html
If you are wanting to actually pass a function name for the function to call, along with its arguments, you either need to implement some form of reflection or introspection in your c code, a really complex switch statement which calls the functions for you based upon the string value, or write some complex macros to act as a sort of a secondary
compiler.
glib's gobject is an excellent example of introspection in c.
http://developer.gnome.org/gobject/stable/
something simple without introspection may be:
void* function (const char* strFunctionName, ... )
{
if(!strcmp(strFunctionName, "functionA"))
{
//use va_list to parse out the arguments for the function.
functionA(//each of the arguments from va_list);
}
else if(!strcmp(strFunctionName, "functionB"))
{
//use va_list to parse out the arguments for the function.
functionB(//args from va_list);
}
...
}
If you have something more specific in mind, please specify in your question.
I'm not sure if this is standard, but you could use __PRETTY_FUNCTION__ in C++.
e.g:
void foo(int a, int b)
{
cout << __PRETTY_FUNCTION__ << endl;
}
outputs:
void foo(int, int)
If you want to make:
char *funct = "foo(bar)";
to actually call the function foo(), then its impossible, C just doesn't work that way. I would recommend that:
a) you sit down and rethink your application, because such behaviour shouldn't be needed for anything.
b) try a language with such capabilities, such as objective-c
c) if you really, really, really wanna do it... then make a string parser and lots of if's, or function pointers. Something in the lines of:
Get string in the form of "function(var1, var2, ..., varN)"
Get the name of the function (ie. everything before '(' )
Get all the parameters (strtok() for example)
Identify the function comparing constant names with your string ( strcmp() )
If the parameters are numeric ( isdigit() or sscanf( string, "%d", &parameter ) > 0 ) convert them to a usable primitive (atoi(), atof(), etc or sscanf())
Pass the params to your function.
If you want to execute a code from a string (I'm just guessing, your question is hard to understand), then there are many options available: from embedding the whole Clang and LLVM into your code (and making sure its JIT is aware of all your declarations you're going to export) to embedding a simple scripting language (like Lua or Guile) and providing wrappers for all the functions you want to call this way.

char array to LPCTSTR conversion in c

Does anyone know how to convert a char array to a LPCTSTR in c?
Edit:
For more reference, I need to add an integer to a string then convert that string to LPCTSTR for the first parameter of the windows function CreateFile().
This is the hardcoded example which I am currently using, but I need to be able to pass in any number to use as a port number.
CreateFile(_T("\\\\.\\COM11")... //hardcoded for com port 11
and here are several things I have tried, which I believe include the following suggestions for the next 2 answers of this post. They don't work unfortunately. If anyone could point out something I've done wrong and could possibly solve my problem, I'd appreciate it.
All of these examples assume that portNum is an int that is already assigned a valid value
1
char portName[12] = { 0 };
sprintf_s( portName, sizeof( portName ), "\\\\.\\COM%i", portNum );
CreateFile(portName...
I've also tried #1 with a LPCSTR case for what it's worth...
2
LPCSTR SomeFunction(LPCSTR aString) {
return aString;
}
main() {
char portName[12] = { 0 };
sprintf_s( portName, sizeof( portName ), "\\\\.\\COM%i", portNum );
LPCSTR lpPortName = SomeFunction(portName);
CreateFile(lpPortName...
3
const char * portName = "";
sprintf_s( portName, sizeof( portName ), "\\\\.\\COM%i", portNum );
LPCSTR lpPortName = portName;
CreateFile(lpPortName...
You can implicitly convert a char array to an LPCSTR without any casts:
void SomeFunction(LPCSTR aString);
...
char myArray[] = "hello, world!";
SomeFunction(myArray);
An LPCSTR is a Windows typedef for a long pointer to a constant string. Back in the dark days of Win16 programming, there were different types of pointers: near pointers and far pointers, sometimes also known as short and long pointers respectively. Near pointers could only point to a 64KB segment of memory determined by one of the x86 segment registers. Far pointers could point to anything. Nowadays in Win32 with virtual memory, there is no need for near pointers -- all pointers are long.
So, an LPSTR is a typedef for a char *, or pointer to a string. An LPCSTR is the const version, i.e. it is a typedef for a const char *. In C, arrays decay into pointers to their first elements, so a char[] decays into a char*. Finally, any type of "pointer to T" (for any type T) can be implicitly converted into a "pointer to const T". Thus, combining these three facts, we see that we can implicitly convert a char[] into an LPCSTR.
In response to your edit, I'm going to guess that you're compiling a Unicode application. If you look carefully at the documentation for CreateFile(), you'll notice that the filename parameter is actually an LPCTSTR, not an LPCSTR (note the T).
For pretty much every Win32 function that takes an argument of some string type (perhaps indirectly, i.e. as a member of a structure passed as a parameter), there are actually two versions of that function: one which takes 8-bit ANSI strings, and one which takes 16-bit wide-character strings. To get the actual function names, you append an A or a W to the function name. So, the ANSI version of CreateFile() is named CreateFileA(), and the wide-character version is named CreateFileW(). Depending on whether or not you're compiling with Unicode enabled (i.e. whether the preprocessor symbol _UNICODE is defined), the symbol CreateFile is #defined to either CreateFileA or CreateFileW as appropriate, and likewise for every other function that has an ANSI and a wide-character version.
Along the same lines, the type TCHAR is typedefed to either char or wchar_t, depending on whether Unicode is enabled, and LPCTSTR is typedefed to a pointer to a const TCHAR.
Thus, to make your code correct, you should replace the strings you're using with TCHAR strings, and use the type-generic version of sprintf_s, _stprintf_s:
TCHAR portName[32];
_stprintf_s(portName, sizeof(portName)/sizeof(TCHAR), _T("\\\\.\\COM%d"), portNum);
CreateFile(portName, ...);
Alternatively, you can explicitly use the ANSI or wide-character versions of everything:
// Use ANSI
char portName[32];
sprintf_s(portName, sizeof(portName), "\\\\.\\COM%d", portNum);
CreateFileA(portName, ...);
// Use wide-characters
wchar_t portName[32];
swprintf_s(portName, sizeof(portName)/sizeof(wchar_t), L"\\\\.\\COM%d", portNum);
CreateFileW(portName, ...);
In what format is your char array?
Is it a const char[] or a non-const?
LPCSTR is just the (somewhat) confusing Microsoft name for "Long Pointer to Constant String".
LPCSTR bar = "hello";
const char *foo = bar;
const char *evil = "hello";
LPCSTR sauron = evil;
If you need to get a non-const version, you either cast away the constness, or you copy to a new array. I would probably prefer the latter. Variables are often const for a reason, and changing them is almost always bad practice.
try like this.........
TCHAR *pcCommPort = TEXT("COM1");
HANDLE h = CreateFile(pcCommPort,other arguments);
char* filename;
LPCTSTR ime = CA2W(filename);
This is String Conversion Macro and works on my VS12
You have string functions for TCHAR. You can use, for example, stprintf_s accepting TCHAR. This way, you make the code "independent" of unicode or multi-byte character set.
Your code (variant 1) becomes:
TCHAR portName[12] = { 0 };
stprintf_s( portName, sizeof( portName ) / sizeof(TCHAR), _T("\\\\.\\COM%i"), portNum );
CreateFile(portName...
"Does anyone know how to convert a char array to a LPCSTR in c?"
You don't have to do anything at all. It automatically converts to that type (except in initializers and sizeof).
"CreateFile(portName..."
Perhaps you should tell us the error message that VC++ gives you at compile time?
Perhaps you should also tell us what error message VC++ gave you when Adam Rosenfield's whcar_t version didn't work for you?
I'm not sure if you figured something out in the end but I had the same problem and following worked well for me:
int comPortNum = 5;
char comPortName[32];
sprintf((LPTSTR)comPortName, TEXT("\\\\.\\COM%d"), comPortNum);
HANDLE h = CreateFile(comPortName,other arguments);
It is an old classical question. I use it in UNICODE.
char *pChar = "My Caption of My application";
WCHAR wsz[512];
swprintf(wsz, L"%S", pChar);
SetWindowText(hWnd, // ウィンドウまたはコントロールのハンドル
wsz // タイトルまたはテキスト
);

Resources