Click here to Skip to main content
15,886,873 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
There is a function called FormatMessageV which is part of the CString class that is supposed to 'Format a message string using a variable argument list' according to MSDN. But other than the said operation, unfortunately it also replaces \n in the message with \r\n which I don't want.

What I have tried:

I tried to pass the ASCII value of LF instead of \n in the message but not surprisingly that didn't alter the routine's behavior. I couldn't come across anything online that mentions why this happens and how to prevent it.
Following is a sample code that demonstrates the issue.
C++
#include <atlstr.h>
#include <iostream>
 
CString FormatV(LPCTSTR first, ...)
{ 
    va_list vaList = nullptr;
    CString buffer;
    va_start(vaList, first);
    buffer.FormatMessageV(first, &vaList); //this adds \r before \n
    va_end(vaList);
 
    return buffer;
}
 
int main() 
{
    CString text = L"\nint Fun(LPCTSTR commandLine, 
    UINT number)\n{ Perform(commandLine,% 1); \n }"; // Notice that 
                                                     // it has only \n s
    CString formattedText = FormatV(text, 1); //formattedText has \r\n s
    if (formattedText.Find(L'\r', 0) != -1)
        std::cout << "Has CR in it!";
}
Posted
Updated 30-Oct-23 11:48am
v2
Comments
Richard MacCutchan 30-Oct-23 5:02am    
That is standard in Windows, as a newline on its own is not considered sufficient. This is a throwback to the early days when everything used the terminal. What exact problem are you trying to solve?
WilEpic 30-Oct-23 5:51am    
Ah, interesting. The problem I am trying to solve involves creating source files and part of that is creating these chunks of code using the CStrings (as shown in the sample code) to be consistent with the existing codebase. But since I want the line ending to be consistent between Windows and Linux I am trying to 'format' the text like the above with only \n. But FormatMessageV just replaces the LF with CRLF. Since this seems to be the standard behavior of this routine, I will have to find alternative functions then!

As Richard said, this is normal Windows behaviour. If you want to remove the \r, then use the Replace command to convert the Windows line endings to Unix line endings:
C++
formattedText.Replace(_T("\r\n"), _T("\n"));
 
Share this answer
 
Comments
CPallini 30-Oct-23 15:44pm    
5.
The FormatMessageV used for the formatting error messages from the system or specified module. It is wrap around the FormatMessageW function (winbase.h) - Win32 apps | Microsoft Learn[^]. Adding CRLF standard behavior in that case. Maybe you just need to format the string? Then you can use CString.FormatV. It is similar to sprintf and does not change the \n into \n\r. But then you need to change "%" into "%%", see for the details: sprintf, _sprintf_l, swprintf, _swprintf_l, __swprintf_l | Microsoft Learn[^].
If you formatting the error messages then just replace CRLF in the resulted string as were suggested already.
 
Share this answer
 
Comments
CPallini 30-Oct-23 15:43pm    
5.
Maxim Kartavenkov 30-Oct-23 15:52pm    
Thanks
WilEpic 31-Oct-23 4:53am    
Is there a flag that can be used to turn off this default behaviour for FormatMessageV? I also tried FormatV by changing % into %% and it didn't actually transform the string, instead just added %1 instead of the actual var arg.
If none of these functions work, I will just replace the CRLF in the resulting string as the last resort.
Maxim Kartavenkov 31-Oct-23 5:03am    
in your code you also do not transform the string because '%' character in FormatMessage API have different meaning. Use printf function format specification depending on what's your input arguments format: Format specification syntax: printf and wprintf functions
For example if you want to set integer value at the place you have "%" then use "%d".
WilEpic 31-Oct-23 5:42am    
You are right, but this happens in so many places, not just one so it would be nightmarish to change the format specification at each instance instead of passing %1 %2, etc for each arg.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900