今天整理自己以前代码的时候突然想向终端中央输出某些字段,在html等前端无疑很容易实现,那像这种终端输出怎么实现呢?于是开始了一系列的查找,先上结论代码:
#include <stdio.h>
#include <windows.h>
int lenth, lenth2;
int hight, hight2;
void myprintf(boolean b, char *str) {
COORD coord;
if(!b) { //几句纯粹是调一下左右,更好看
lenth =lenth2- strlen(str);
}
coord.X = lenth;
coord.Y = hight = (b ? hight+2 : hight2);
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
printf(str) //这个函数没办法把可变参数传进来,个中曲折,后面再说
}
int main() {
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO scr;
GetConsoleScreenBufferInfo(out, &scr);
lenth2 = lenth = scr.srWindow.Right / 2; //初始化横向位置
hight2 = hight = scr.srWindow.Bottom / 3; //初始化纵向位置
myprintf(FALSE,"!!!!!!");
myprintf(TRUE,"1234567");
myprintf(TRUE,"7654321");
return 0;
}
效果如图:纵向处于界面的1/3处,横向处于1/2处
定位代码的实现
指定位置的写入由 COORD 和SetConsoleCursorPosition,GetStdHandle实现的,上述代码有具体用法。
GetStdHandle(STD_OUTPUT_HANDLE) 获得标准输出句柄
COORD coord 表示位置的结构体,内有两个参数,相当于x轴,y轴
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord) 将光标定位到指定位置上,接下来的printf就会从该位置书写
获取终端的长宽,或者说缓冲区
使用三步获取缓冲区的数据,结构体CONSOLE_SCREEN_BUFFER_INFO,分别是:
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE)
CONSOLE_SCREEN_BUFFER_INFO scr
GetConsoleScreenBufferInfo(out, &scr)scr的成员srWindow就是可以看见的窗口大小数据,我在代码里用的也是这个部分。
可变长参数函数书写的妥协
肉眼可见,我这个自定义的printf函数没办法传递参数,只能传递字符串完整打印,但其实我也是有挣扎过了,最后实在解决不了,如果有人能解决感激不尽。
接下来讲一下我挣扎的过程,最开始我直接找到了printf的源代码,打算模仿写一下,结果如下:
#include <stdarg.h> //这个是可变入参头文件
void myprintf(boolean b, char *str, ...) {
va_list ap;//可变入参
va_start(ap,str);
COORD coord;
if(!b) {
lenth =lenth2- strlen(str);
}
coord.X = lenth;
coord.Y = hight = (b ? hight+2 : hight2);
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
printf(str,ap);//这个地方只有printf("%s",'数据')才不会出错,因为此处的ap是指针
va_end(ap);
}
使用va_list,va_start,va_arg,va_end等一系列宏把可变长参数取出来。但问题在于,取出来的是指针,而不是数据,它决定了只有char型才能正常显示(我的电脑指针是4字节,只能正常显示4个字符,而且还是倒叙的,估计是因为指针存在栈里,倒叙出来的)。限制非常大,想要正常的把我自己定义的myprintf使用,就需要自己把输入的可变参数进行解析,就像自己写个printf函数一样,网上有很多,这里就不赘述了。
然后我试图使用宏来解决#define MY_PRINTF(...) printf(__VA_ARGS__),很显然宏的入参没办法像函数那样多变,没办法满足我的需求,兜兜转转还是放弃了宏,维持现在的样子了。