Introduction
This article is for programmers who port C/C++ code to C#. Porting code from C/C++ to C# can result in much effort when printf is involved, as printf has some functionality, which C# does not provide the same way. This is why I wrote the attached DLL, which allows to use printf within the .NET framework.
For a brief overview about printf, you may want to visit these pages:
Using the Code - Standard Methods
For most cases, using the static methods of the PrintFCompatibility
class will do fine. It provides these static methods/properties:
FPrintF
(for printing into a file stream) PrintF
(for printing into a the standard output; see also PrintfPrint property) SnPrintF
(for printing into a string with maximum number of characters defined) SPrintF
(for printing into a string) PrintfPrint
(for assigning the output for the PrintF function. The default is Console output, but you can change it to any other supported output, e.g. any kind of stream or into a variable).
The following code is taken from the Test program which shows the basic functionality.
int length;
length = CppCompatibility.PrintFormatted.PrintFCompatibility.PrintF("%f\n", 3.14159265d);
System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
CppCompatibility.PrintFormatted.PrintFCompatibility.PrintfPrint =
new CppCompatibility.PrintFormatted.PrintFStream(memoryStream,
System.Text.Encoding.Unicode);
length = CppCompatibility.PrintFormatted.PrintFCompatibility.PrintF("%f", 3.14159265d);
memoryStream.Close();
memoryStream.Dispose();
string formatted;
length = CppCompatibility.PrintFormatted.PrintFCompatibility.SPrintF(out formatted, "%f", 3.14159265d);
Using the Code - Streams
If you want to print into several streams, this could be cumbersome with the PrintFCompatibility
class. Instead, you may like to use the following classes:
PrintFFileStream
PrintFStream
Each instance of the above classes can handle its own stream, which simplifies your code.
The following code is taken from the Test and shows use of the IPrintf interface and the the PrintFStream and PrintFFileStream classes:
CppCompatibility.PrintFormatted.IPrintF printfConsole =
new CppCompatibility.PrintFormatted.PrintFConsole(true);
length = printfConsole.PrintF("Error Console: %20.15f\n", 3.14159265d);
string tempFilePath = System.IO.Path.GetTempFileName();
System.IO.FileStream fileStream = new System.IO.FileStream(tempFilePath, System.IO.FileMode.OpenOrCreate);
CppCompatibility.PrintFormatted.IPrintF printfFile =
new CppCompatibility.PrintFormatted.PrintFFileStream(fileStream,
System.Text.Encoding.UTF8);
length = printfFile.PrintF("File Stream: %20.15f\n", 3.14159265d);
fileStream.Close();
fileStream.Dispose();
After creating your PrintFFileStream
or PrintFStream
object, just use the PrintF
function on that object.
If you don't want to use the above approach, you can use the following approaches with the PrintFCompatibility
class:
- Specify the PrintfPrint object and use PrintF as shown in section "Using the Code - Standard Methods"
- For file streams, always specify the
FileStream
object with the FPrintF method of the PrintFCompatibility
class.
Using the Code - Console
If you want to use Console output, you can use the PrintFConsole
class. It's constructor allows to specify if you want to use the error console (specify useErrorConsole
parameter to be true), or if you use the standard console (don't specify the useErrorConsole
parameter or set it to false).
bool useErrorConsole = true;
CppCompatibility.PrintFormatted.IPrintF printfFile =
new CppCompatibility.PrintFormatted.PrintFConsole(useErrorConsole);
printfFile.PrintF("%20.15f\n", 3.14159265d);
useErrorConsole = false;
CppCompatibility.PrintFormatted.IPrintF printfFile =
new CppCompatibility.PrintFormatted.PrintFConsole(useErrorConsole);
printfFile.PrintF("%20.15f\n", 3.14159265d);
CppCompatibility.PrintFormatted.IPrintF printfFile =
new CppCompatibility.PrintFormatted.PrintFConsole();
printfFile.PrintF("%20.15f\n", 3.14159265d);
The "n" Format
C/C++ defines the "n" format, which prints the numbers of characters that have been output to the point where the "n" format is specified. It expects output into an address of a signed integer variable. This results in the following dilemma:
- Updating an int variable in a function with C# requires to specify that variable with the ref keyword.
- For compatibility with C/C++ the interface specifies the params keyword for all function calls. This however makes it impossible to specify a variable with the ref keyword.
The resolution is to use the FormatInfoN
class:
FormatInfoN fin = new FormatInfoN();
string result;
int length = PrintFCompatibility.SPrintF(out result, "%15d%n", 13, fin);
int characterCount = fin.PrintedCharacterCount;
History
Version Number | Description |
0.1 | Initial release |
0.2 | Fixed handling of plain text in format specifier. |