C语言中的printf
、fprintf
、sprintf
、snprintf
、vprintf
、vfprintf
、vsprintf
和vsnprintf
都是用于格式化输出的函数。它们主要的区别在于输出的目的地以及是否支持可变参数列表。
1. printf
printf
用于将格式化的输出发送到标准输出(通常是控制台)。
用法:
#include <stdio.h>
int main() {
int num = 10;
printf("The number is %d\n", num);
return 0;
}
2. fprintf
fprintf
用于将格式化的输出发送到指定的文件流。
用法:
#include <stdio.h>
int main() {
int num = 10;
FILE *fp = fopen("output.txt", "w");
if (fp != NULL) {
fprintf(fp, "The number is %d\n", num);
fclose(fp);
}
return 0;
}
3. sprintf
sprintf
用于将格式化的输出存储在一个字符串中。
用法:
#include <stdio.h>
int main() {
int num = 10;
char buffer[50];
sprintf(buffer, "The number is %d", num);
printf("%s\n", buffer);
return 0;
}
4. snprintf
snprintf
类似于 sprintf
,但它会避免缓冲区溢出。snprintf
限制了写入字符的最大数量。
用法:
#include <stdio.h>
int main() {
int num = 10;
char buffer[50];
snprintf(buffer, sizeof(buffer), "The number is %d", num);
printf("%s\n", buffer);
return 0;
}
5. vprintf
vprintf
用于将格式化的输出发送到标准输出,使用 va_list
类型的参数列表。
用法:
#include <stdio.h>
#include <stdarg.h>
void my_vprintf(const char *format, ...) {
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
int main() {
my_vprintf("The number is %d\n", 10);
return 0;
}
6. vfprintf
vfprintf
用于将格式化的输出发送到指定的文件流,使用 va_list
类型的参数列表。
用法:
#include <stdio.h>
#include <stdarg.h>
void my_vfprintf(FILE *file, const char *format, ...) {
va_list args;
va_start(args, format);
vfprintf(file, format, args);
va_end(args);
}
int main() {
FILE *fp = fopen("output.txt", "w");
if (fp != NULL) {
my_vfprintf(fp, "The number is %d\n", 10);
fclose(fp);
}
return 0;
}
7. vsprintf
vsprintf
用于将格式化的输出存储在一个字符串中,使用 va_list
类型的参数列表。
用法:
#include <stdio.h>
#include <stdarg.h>
void my_vsprintf(char *buffer, const char *format, ...) {
va_list args;
va_start(args, format);
vsprintf(buffer, format, args);
va_end(args);
}
int main() {
char buffer[50];
my_vsprintf(buffer, "The number is %d", 10);
printf("%s\n", buffer);
return 0;
}
8. vsnprintf
vsnprintf
类似于 vsprintf
,但它会避免缓冲区溢出。vsnprintf
限制了写入字符的最大数量。
用法:
#include <stdio.h>
#include <stdarg.h>
void my_vsnprintf(char *buffer, size_t size, const char *format, ...) {
va_list args;
va_start(args, format);
vsnprintf(buffer, size, format, args);
va_end(args);
}
int main() {
char buffer[50];
my_vsnprintf(buffer, sizeof(buffer), "The number is %d", 10);
printf("%s\n", buffer);
return 0;
}
总结
-
printf
: 将格式化输出发送到标准输出(控制台)。 -
fprintf
: 将格式化输出发送到指定的文件流。 -
sprintf
: 将格式化输出存储在一个字符串中,不检查缓冲区溢出。 -
snprintf
: 将格式化输出存储在一个字符串中,并指定最大写入字符数,以避免缓冲区溢出。 -
vprintf
: 与printf
类似,但使用va_list
类型的参数列表。 -
vfprintf
: 与fprintf
类似,但使用va_list
类型的参数列表。 -
vsprintf
: 与sprintf
类似,但使用va_list
类型的参数列表。 -
vsnprintf
: 与snprintf
类似,但使用va_list
类型的参数列表。综合使用sprintf、fprintf和vfprintf,创建log_printf函数,该函数实现日志打印,生成日志头部信息,包含系统时间、文件名和行号
void log_printf(const char *c_file_name, unsigned int line, const char *fmt, ...)
{
// 定义一个字符数组用于存储打印的字符串
char printfstr[128];
// 清空字符数组,将所有元素置为0
memset(printfstr, 0, sizeof(printfstr));
// 格式化并生成日志头部信息,包含系统时间、文件名和行号
sprintf(printfstr, "[Time:%d File:%s Line:%d]", SystemTick, filename(c_file_name), line);
// 将日志头部信息写入指定的流(串口USART1_STREAM)
fprintf(USART1_STREAM, "%s", printfstr);
// 定义一个 va_list 变量,用于处理可变参数列表
va_list arg;
// 初始化 va_list 变量,指向可变参数列表的第一个参数
va_start(arg, fmt);
// 使用 vfprintf 将格式化的日志信息写入指定的流
vfprintf(USART1_STREAM, fmt, arg);
// 结束可变参数列表的处理
va_end(arg);
// 将换行符写入指定的流
fprintf(USART1_STREAM, "%s", "\\r\\n");
}
int main() {
log_printf(__FILE__,__LINE__,"==================APP DATE:%s \n",__DATE__); //输出编译日期
log_printf(__FILE__,__LINE__,"==================APP TIME:%s \n",__TIME__); //输出编译时间
}