源码:
/*
*
* PrintfWithBuffer.h
*
* 带有缓冲的printf
* 可以避免大量printf带来的闪烁
*
* by huidong 2020.7.21 <mailkey@yeah.net>
*
*/
#pragma once
#include <stdio.h>
#include <Windows.h>
namespace cmd_buffer
{
// cmd 缓冲输出存储器
char* m_cmd_buffer = NULL;
// 缓冲器大小
UINT m_buffer_size = 0;
// 设置光标位置
void Gotoxy(int x, int y)
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); // 移动光标
}
// 初始化cmd缓冲器
//
// size 缓冲内容最大长度(字节)
void InitCMDBuffer(UINT size = 1024000)
{
m_buffer_size = size;
m_cmd_buffer = new char[size + 1];
sprintf_s(m_cmd_buffer, size, "");
}
// 关闭cmd缓冲器
void CloseCMDBuffer()
{
delete[] m_cmd_buffer;
m_cmd_buffer = NULL;
m_buffer_size = 0;
}
// 输出缓冲区内容
void FlushCMDBuffer()
{
Gotoxy(0, 0);
printf("%s", m_cmd_buffer);
}
// 将内容输出至缓冲区
void BufferPrint(const char* _Format, ...)
{
// 可变参列表
va_list list;
va_start(list, _Format);
// 存储可变参部分的值
char* str_temp_beffer = new char[m_buffer_size + 1];
// 将可变参的值写入临时变量
vsprintf_s(str_temp_beffer, m_buffer_size, _Format, list);
// 写入总缓冲区
sprintf_s(m_cmd_buffer, m_buffer_size, "%s%s", m_cmd_buffer, str_temp_beffer);
delete[] str_temp_beffer;
va_end(list);
}
// 清空缓冲区
void ClearBuffer()
{
if (m_cmd_buffer != NULL)
{
sprintf_s(m_cmd_buffer, m_buffer_size, "");
}
}
}
using cmd_buffer::InitCMDBuffer;
using cmd_buffer::CloseCMDBuffer;
using cmd_buffer::FlushCMDBuffer;
using cmd_buffer::BufferPrint;
using cmd_buffer::ClearBuffer;
使用示例:
#include "PrintfWithBuffer.h"
int main()
{
InitCMDBuffer();
int i = 20;
char str[] = "hello";
BufferPrint("%d is a num and \'%s\' isn\'t a num.", i, str);
FlushCMDBuffer();
CloseCMDBuffer();
while (true);
return 0;
}
输出:
BufferPrint是支持可变参的,所以printf函数可以直接换成BufferPrint函数。
你只需要在开启缓冲输出之前 InitCMDBuffer(); 进行初始化一下,就可以调用BufferPrint函数了。
调用完BufferPrint,你需要使用 FlushCMDBuffer 函数输出存储在缓冲区的内容。
最后,使用完时,记得 CloseCMDBuffer 结束缓冲输出。
另外,由于缓冲区大小有限,建议使用ClearBuffer函数清空缓冲区。