printf cstring only first character (c++)

Visual Studio 2012 C++


CString cscommand;
            printf("cscommand:[%s]", cscommand);



Where is the rest of my "test"?  

Who is Participating?
mccarlConnect With a Mentor IT Business Systems Analyst / Software DeveloperCommented:
Try using the %ls format specifier, as in...
printf("cscommand:[%ls]", cscommand);

Open in new window

HooKooDooKuConnect With a Mentor Commented:
%s is for a null terminated string, not a CString object.
But you can get the null terminated string associated with a CString with the GetBuffer() member function.

Try something like this:
printf("cscommand:[%s]", cscommand.GetBuffer());

Many times, you don't have to explicitly call the GetBuffer() function because CString has a built-in conversion function that converts a CString object to a null-terminated string.  But that works when calling a function with a signature calling for a null-terminated string.  But printf can be supplied ANY type of variable.  So the compiler doesn't understand that the format string you supplied to printf needs a null-terminated string.

In other words, here's a way that should make your function work:

void printfstr(char* pFormat, char* pString)

void myFunc()
  CString cscommand;
  printfstr("cscommand:[%s]", cscommand);

With this code, the compiler knows that printfstr needs a char*, and since CString has a conversion function for that, your entire string should print.
frankhelkConnect With a Mentor Commented:
First @HooKooDooKu: The affected standard lib functions are usually overloaded to allow either "classic" null terminated strings or CString objects. No need for such encapsulation. If uncertain, one of these would surely do:
printf("cscommand:[%ls]", cscommand.ToString());
printf("cscommand:[%ls]", LPTSTR cscommand); // VC++
printf("cscommand:[%c]", cscommand.GetAt(0));
printf("cscommand:[%c]", cscommand[]);

Open in new window

There are more variants to accomplish that ....

BTW, from some help about CString:
You can access individual characters within a CString object with the GetAt and SetAt member functions. You can also use the array element, or subscript, operator ( [ ] ) instead of GetAt to get individual characters (this is similar to accessing array elements by index, as in standard C-style strings). Index values for CString characters are zero based.

Second, @mccarl: Close, but no hit. This would work as long as the string contains only 1 character. The s format code makes the field 1 characters long, but extends it ot the length of the string if the string is longer. The format string should read "cscommand: %1.1s", where %x.ys means "string (s), x charcters long, not to be exteded to more than y characters".

Summarized, you could usually replace any "classic" C string with CString objects in standard lib functions - the compiler will handle that thru type conversions.
The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

gateguardAuthor Commented:
Try using the %ls format specifier, as in...

a TCHAR is mapped to char in case of MBCS (multibyte-character set) but mapped to wchar_t (2-bytes) in case of UNICODE. the second is default for new mfc applications. if you look at the bytes for L"test" you have 't' '\0' 'e' '\0' 's' '\0' 't' '\0' '\0 '\0'.  so each ansi char is followed by a binary zero char for your sample string. if you printf a wchar_t buffer instead of char buffer with %s format specifier, the printf expects a const char * and would stop printing at the first binary zero character. that seems to happen in your case. to help from that, either turn your project from UNICODE to MBCS, or use the %ls as mccarl and frankhelf have shown, or use CString::Format function, or simply concatenate the strings by operator +=

CString csprintout = _T("cscommand:[");
csprintout += cscommand + _T("]");
std::cout << (LPCTSTR)csprintout << std::endl;

Open in new window

note, the above would work for both TCHAR mappings and therefore would allow to change between MBCS and UNICODE.

But you can get the null terminated string associated with a CString with the GetBuffer()
that is not quite  correct. the GetBuffer would return a writeable TCHAR pointer to the CString. the TCHAR array the pointer is pointing to is null-terminated. but, as the printf also would accept a const TCHAR* (LPCTSTR), the GetBuffer is not needed but a simple cast to const TCHAR* would do. to invoke the cast operator in the printf, it is better coding to do the cast explicitly, cause printf is a c function with variable argument list (...) and the printf would not be able to make the cast implicitly. the reason why it nevertheless works without explicit cast is because the CString reference address contains the same address as the pointer to the internal TCHAR buffer. but actually that is a trick that only works with CString but not with other string classes. so, you better don't use printf at all but c++ operator<<, or at least, make an explicite cast whenever you need a TCHAR buffer from a CString.

mccarlIT Business Systems Analyst / Software DeveloperCommented:
Second, @mccarl: Close, but no hit
Sorry Frank, but NOT close and no where near a hit for you.

Firstly, if you read my post again *carefully* you will see that I placed an "l" (lowercase L) in front of the "s" format specifier, not a 1 (number one). The lowercase L changes the interpretation of the pattern from single byte null-terminated string to a multi-byte double-null terminated string.

Secondly, if you read the original poster question again, I think you have the idea all wrong. They had the output of just the first character but they wanted the full string to be printed. You are stating the opposite, ie. how to print the first character of a string of many characters.
you could usually replace any "classic" C string with CString objects in standard lib functions - the compiler will handle that thru type conversions
the statement is not true in general. a "classic" C string is a zero-terminated char array and it usually is not required to be const. if a C function requires a writeable char buffer, the CString cannot be passed as argument without casting off constness or calling GetBuffer function. moreover, in the above case it obviously is a wide character string which rarely can be named a 'classic' C string. finally, it is not the compiler which makes the "type" conversion but the CString class actively provides a cast operator and manages to have the address of the CString also is a valid address to the internal - already zero-terminated - buffer. for a variable argument list as taken by printf, the compiler principally does neither type check nor conversion. that is one of the reasons why printf is a dangerous and not recommendable function.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.