参考
https://cplusplus.com/reference/cstdio/printf/
https://cplusplus.com/reference/cstdio/fprintf/
https://cplusplus.com/reference/cstdio/sprintf/
https://cplusplus.com/reference/cstdio/snprintf/
https://cplusplus.com/reference/cstdio/vprintf/
https://cplusplus.com/reference/cstdio/vfprintf/
https://cplusplus.com/reference/cstdio/vsprintf/
https://cplusplus.com/reference/cstdio/vsnprintf/
摘要
本文详细介绍了C++标准库中用于格式化输出的多个函数,包括fprintf到文件流、printf到标准输出、sprintf到字符串缓冲区以及它们的变参版本vfprintf、vprintf和vsprintf。特别提到了防止缓冲区溢出的snprintf和vsnprintf函数。
fprintf()
参数
int fprintf ( FILE * stream, const char * format, ... );
功能
格式化输出到指定的stream中,可以是文件流也可以是stdout。
例子
/* fprintf example */
#include <stdio.h>
int main ()
{
FILE * pFile;
int n;
char name [100];
pFile = fopen ("myfile.txt","w");
for (n=0 ; n<3 ; n++)
{
puts ("please, enter a name: ");
gets (name);
fprintf (pFile, "Name %d [%-10.10s]\n",n+1,name);
}
fclose (pFile);
return 0;
}
返回
如果写入成功,返回写入的字符数;失败返回一个负数。
printf()
参数
int printf ( const char * format, ... );
功能
格式化输出到指定的标准输出stdout中。
例子
/* printf example */
#include <stdio.h>
int main()
{
printf ("Characters: %c %c \n", 'a', 65);
printf ("Decimals: %d %ld\n", 1977, 650000L);
printf ("Preceding with blanks: %10d \n", 1977);
printf ("Preceding with zeros: %010d \n", 1977);
printf ("Some different radices: %d %x %o %#x %#o \n", 100, 100, 100, 100, 100);
printf ("floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416);
printf ("Width trick: %*d \n", 5, 10);
printf ("%s \n", "A string");
return 0;
}
返回
如果写入成功,返回写入的字符数;失败返回一个负数。
sprintf()
参数
int sprintf ( char * str, const char * format, ... );
功能
格式化输出到指定的字符串缓冲区,不直接写入到设备中。需要注意缓冲区的大小,防止溢出。
例子
/* sprintf example */
#include <stdio.h>
int main ()
{
char buffer [50];
int n, a=5, b=3;
n=sprintf (buffer, "%d plus %d is %d", a, b, a+b);
printf ("[%s] is a string %d chars long\n",buffer,n);
return 0;
}
返回
如果写入成功,返回写入的字符数,这个字符数不包含字符串后面自动添加的null字符;失败返回一个负数。
snprintf()
参数
int snprintf ( char * s, size_t n, const char * format, ... );
功能
前面提到sprintf(),有溢出的风险。为了解决这个问题,snprintf函数添加一个参数,设置缓冲区大小。防止溢出,溢出的自动截断。这里需要注意的是:如果缓冲区大小是50,而format生成的字符串大小也是50,实际缓冲区存储的要比生成的少一个字符,因为缓冲区最后一个字符是\0
格式化输出到指定的字符串缓冲区,不直接写入到设备中。
例子
/* snprintf example */
#include <stdio.h>
int main ()
{
char buffer[5];
snprintf(buffer,5,"%s345","12");
printf("%s",buffer);//实际打印出来的1234。字符5没有写进去。
return 0;
}
返回
如果写入成功,返回写入的字符数;失败返回一个负数。
vfprintf()
参数
int vfprintf ( FILE * stream, const char * format, va_list arg );
功能
把可变参数格式化输出到流中,类似fprintf()。
例子
/* vfprintf example */
#include <stdio.h>
#include <stdarg.h>
void WriteFormatted (FILE * stream, const char * format, ...)
{
va_list args;
va_start (args, format);
vfprintf (stream, format, args);
va_end (args);
}
int main ()
{
FILE * pFile;
pFile = fopen ("myfile.txt","w");
WriteFormatted (pFile,"Call with %d variable argument.\n",1);
WriteFormatted (pFile,"Call with %d variable %s.\n",2,"arguments");
fclose (pFile);
return 0;
}
返回
如果写入成功,返回写入的字符数;失败返回一个负数。
vprintf
参数
int vprintf ( const char * format, va_list arg );
功能
把可变参数格式化输出到格式化输出中stdout,类似printf()。
例子
/* vprintf example */
#include <stdio.h>
#include <stdarg.h>
void WriteFormatted ( const char * format, ... )
{
va_list args;
va_start (args, format);
vprintf (format, args);
va_end (args);
}
int main ()
{
WriteFormatted ("Call with %d variable argument.\n",1);
WriteFormatted ("Call with %d variable %s.\n",2,"arguments");
return 0;
}
返回
如果写入成功,返回写入的字符数;失败返回一个负数。
vsprintf
参数
int vsprintf (char * s, const char * format, va_list arg );
功能
格式化输出到指定的字符串缓冲区,不直接写入到设备中。需要注意缓冲区的大小,防止溢出。
例子
/* vsprintf example */
#include <stdio.h>
#include <stdarg.h>
void PrintFError ( const char * format, ... )
{
char buffer[256];
va_list args;
va_start (args, format);
vsprintf (buffer,format, args);
perror (buffer);
va_end (args);
}
int main ()
{
FILE * pFile;
char szFileName[]="myfile.txt";
pFile = fopen (szFileName,"r");
if (pFile == NULL)
PrintFError ("Error opening '%s'",szFileName);
else
{
// file successfully open
fclose (pFile);
}
return 0;
}
返回
如果写入成功,返回写入的字符数;失败返回一个负数。
vsnprintf
参数
int vsnprintf (char * s, size_t n, const char * format, va_list arg );
功能
前面提到vsprintf(),有溢出的风险。为了解决这个问题,vsnprintf函数添加一个参数,设置缓冲区大小。防止溢出,溢出的自动截断。这里需要注意的是:如果缓冲区大小是50,而format生成的字符串大小也是50,实际缓冲区存储的要比生成的少一个字符,因为缓冲区最后一个字符是\0
格式化输出到指定的字符串缓冲区,不直接写入到设备中。
例子
/* vsnprintf example */
#include <stdio.h>
#include <stdarg.h>
void PrintFError ( const char * format, ... )
{
char buffer[256];
va_list args;
va_start (args, format);
vsnprintf (buffer,256,format, args);
perror (buffer);
va_end (args);
}
int main ()
{
FILE * pFile;
char szFileName[]="myfile.txt";
pFile = fopen (szFileName,"r");
if (pFile == NULL)
PrintFError ("Error opening '%s'",szFileName);
else
{
// file successfully open
fclose (pFile);
}
return 0;
}
返回
如果写入成功,返回写入的字符数;失败返回一个负数。