C++ 重载操作符<<实现cout定位输出以及设置颜色:cout<<Goto(x,y)<<setC(color)<<123<<cr;

简介: C++ 重载操作符<<实现cout定位输出以及设置颜色:cout<<Goto(x,y)<<setC(color)<<123<<cr;

调用<windows.h>库中几个最常用的WINAPI函数,重载了操作符<<,使得cout可以定位输出以及设置颜色。


用法: cout<<Goto(x,y)<<setC(foreColor,bgColor)<<“输出内容”<<cr;


Goto(x,y) 定位到坐标(x,y) ,控制台窗口的左上角第一格坐标为(0,0);

Goto(x)    定位坐标到本行的 x ,即默认y为当前行;

Goto()      回到本行行首,即回车不换行。

cr()           回车且换行,与std::endl等效。

setC(foreColor,bgColor) 设置前景色和背景色;

setC(foreColor) 只设置前景色,背景色不变;

setC() 前景色和背景色恢复到控制台默认值。

foreColor,bgColor 取值范围 0 ~ 15,对应颜色值如下:

   /* setC()设置的颜色值与 DOS内部命令COLOR的相类似


   如下列表中,只要把其中的A~F换成10~15即可:  


   D:\CPP>color /?

   设置默认的控制台前景和背景颜色。


       0 = 黑色       8 = 灰色

       1 = 蓝色       9 = 淡蓝色

       2 = 绿色       A = 淡绿色

       3 = 浅绿色   B = 淡浅绿色

       4 = 红色       C = 淡红色

       5 = 紫色       D = 淡紫色

       6 = 黄色       E = 淡黄色

       7 = 白色       F = 亮白色

   */


源代码:


#include <iostream>
#include <windows.h>
#define Stream std::basic_ostream<T1, T2>&
using namespace std;
struct HannsC { DWORD fc; DWORD bg; };
struct HannXy { SHORT pX; SHORT pY; };
HannsC setC(DWORD fc = 7, DWORD bg = 0)
{
  return {fc % 16, bg % 16 *16};
}
HannXy Goto(SHORT x = 0, SHORT y = -1)
{
  return {x, y};
}
template<typename T1, typename T2>
Stream operator<<(Stream _os, HannsC _mc)
{
  HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
  SetConsoleTextAttribute(hConsole,_mc.fc|_mc.bg);
  return _os;
}
template<typename T1, typename T2>
Stream operator<<(Stream _os, HannXy _xy)
{
    CONSOLE_SCREEN_BUFFER_INFO pBuffer;
  COORD position = {_xy.pX, _xy.pY};
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 
  if (position.Y==-1){
    GetConsoleScreenBufferInfo(hConsole, &pBuffer); 
    position.Y = pBuffer.dwCursorPosition.Y;
  }    
    SetConsoleCursorPosition(hConsole, position);
  return _os;
}
template<typename T1, typename T2>
Stream cr(Stream _out)
{
  _out.put('\n');
  _out.flush();
  return _out;
}
int main(void)
{
  cout << setC(23,3) << "abcdefghijklmnopqrstuvwxyz" << cr;
  cout << Goto(16,3) << setC(14,9) << "abcdefghijkl" 
     << setC(9,14) << Goto(30) << 123 << cr << cr;
  cout << setC(13,6) << 12312303236131230 << cr;
  cout << setC(3,15) << Goto(18,10) << "3.14159265358979323";
  cout << Goto(30) << setC(12) << "END!" << Goto() << "cr && !lf";
  cout << setC() << cr;
  return 0;
}



输出效果:

20210303105608300.png

DOS颜色命令COLOR的色号着实有点难记,顺便吐槽一下微软翻译的颜色中文名;还是自己动手宏定义这些颜色名称吧:



20210303205905337.png


源代码稍微作改进,既方便颜色的记忆也增加了代码的可阅读性:

#include <iostream>
#include <windows.h>
using namespace std;
#define cBlack   0
#define cNavy  1
#define cGreen   2
#define cTeal  3
#define cMaroon  4
#define cPurple  5
#define cOlive   6
#define cSliver  7
#define cGray  8
#define cBlue  9
#define cLime  10
#define cCyan  11
#define cRed   12
#define cMagenta 13
#define cYellow  14
#define cWhite   15
struct HannsC { DWORD fc; DWORD bg; };
struct HannXy { SHORT pX; SHORT pY; };
HannsC setC(DWORD fc = cSliver, DWORD bg = cBlack)
{
  return {fc % 16, bg % 16 *16};
}
HannXy Goto(SHORT x = 0, SHORT y = -1)
{
  return {x, y};
}
ostream& operator<<(ostream& _os, HannsC _mc)
{
  HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
  SetConsoleTextAttribute(hConsole,_mc.fc|_mc.bg);
  return _os;
}
ostream& operator<<(ostream& _os, HannXy _xy)
{
    CONSOLE_SCREEN_BUFFER_INFO pBuffer;
  COORD position = {_xy.pX, _xy.pY};
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 
  if (position.Y==-1){
    GetConsoleScreenBufferInfo(hConsole, &pBuffer); 
    position.Y = pBuffer.dwCursorPosition.Y;
  }    
    SetConsoleCursorPosition(hConsole, position);
  return _os;
}
ostream& cr(ostream& _out)
{
  _out.put('\n');
  _out.flush();
  return _out;
}
int main(void)
{
  cout << setC(cNavy,cLime) << "abcdefghijklmnopqrstuvwxyz" << cr;
  cout << Goto(16,3) << setC(cYellow,cBlue) << "abcdefghijkl" 
     << setC(cBlue,cYellow) << Goto(30) << 123 << cr << cr;
  cout << setC(cMagenta,cOlive) << 12312303236131230 << cr;
  cout << setC(cGreen,cWhite) << Goto(18,9) << "3.1415926535897932384626";
  cout << Goto(30) << setC(cRed) << "END!" << Goto() << "cr && !lf";
  cout << setC(cCyan) << cr << cr << "my C++ version: " << __cplusplus ;
  cout << setC() << cr;
  return 0;
}


20210303210346115.png



附录:SetConsoleTextAttribute:


   函数原型:

 

WINBASEAPI WINBOOL WINAPI SetConsoleTextAttribute(HANDLE hConsoleOutput,WORD wAttributes);


   函数用法:

 

HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
      SetConsoleTextAttribute(hConsole,foregroundColor|backgroundColor);

只有三原色用以下宏常量设置:


FOREGROUND_RED        表示设置前景色为红色。

FOREGROUND_GREEN      表示设置前景色为绿色。

FOREGROUND_BLUE       表示设置前景色为蓝色。

BACKGROUND_RED        表示设置背景色为红色。

BACKGROUND_GREEN      表示设置背景色为绿色。

BACKGROUND_BLUE       表示设置背景色为蓝色。

其他颜色就用此6个宏及以下两个宏,做或运算得到。

FOREGROUND_INTENSITY  表示设置前景色为高亮显示。

BACKGROUND_INTENSITY  表示设置背景色为高亮显示。


例如设置高亮白色字体,用以下代码:

FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE

不知道写库函数的人是怎么想的,只给定三原色......^_^



目录
相关文章
|
2月前
|
C++
C++(十九)new/delete 重载
本文介绍了C++中`operator new/delete`重载的使用方法,并通过示例代码展示了如何自定义内存分配与释放的行为。重载`new`和`delete`可以实现内存的精细控制,而`new[]`和`delete[]`则用于处理数组的内存管理。不当使用可能导致内存泄漏或错误释放。
|
3月前
|
存储 人工智能 C++
【C++】有N种颜色的小球,开始同一种颜色小球装在同一个筐里面,颜色从1到N标号。有下面两个操作(Cab),把颜色是b的 (源码)【独一无二】
【C++】有N种颜色的小球,开始同一种颜色小球装在同一个筐里面,颜色从1到N标号。有下面两个操作(Cab),把颜色是b的 (源码)【独一无二】
|
3月前
|
传感器 算法 C++
C++ PCL 设置法向量的方向
C++ PCL 设置法向量的方向
78 0
|
3月前
|
编译器 C++
VS Code设置C++编译器路径
VS Code设置C++编译器路径
46 0
|
3月前
|
存储 C++
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
42 0
|
4月前
|
NoSQL 编译器 Redis
c++开发redis module问题之如果Redis加载了多个C++编写的模块,并且它们都重载了operator new,会有什么影响
c++开发redis module问题之如果Redis加载了多个C++编写的模块,并且它们都重载了operator new,会有什么影响
|
4月前
|
存储 C++
【C++】string类的使用③(非成员函数重载Non-member function overloads)
这篇文章探讨了C++中`std::string`的`replace`和`swap`函数以及非成员函数重载。`replace`提供了多种方式替换字符串中的部分内容,包括使用字符串、子串、字符、字符数组和填充字符。`swap`函数用于交换两个`string`对象的内容,成员函数版本效率更高。非成员函数重载包括`operator+`实现字符串连接,关系运算符(如`==`, `&lt;`等)用于比较字符串,以及`swap`非成员函数。此外,还介绍了`getline`函数,用于按指定分隔符从输入流中读取字符串。文章强调了非成员函数在特定情况下的作用,并给出了多个示例代码。
|
4月前
|
NoSQL Redis C++
c++开发redis module问题之避免多个C++模块之间因重载operator new而产生的冲突,如何解决
c++开发redis module问题之避免多个C++模块之间因重载operator new而产生的冲突,如何解决
|
5月前
|
C++
C++函数的默认参数、占位符、重载
C++函数的默认参数、占位符、重载
|
8天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
34 4