C++一周总结(一)
本周C++学习情况总结
作为新手,写了一周的C++代码遇到了各种各样的问题,幸运的是由超能的度娘以及一帮技术博主们的分享,还有身边的C++先行者们的指导,整体体验虽不能说是顺利,也不会是痛苦的独自战斗。我们不是一个人在战斗。
本周所做工作及亮点
首先介绍一下这一周在C++这一门编程语言上我都干了些什么。
- 看完了C++ Primer Plus这本书
- 用C++写了一个网上银行的程序(当然是部分,登录注册以及所有的界面设计)
总的来说本周的工作亮点有三个
- 网上银行界面设计方面的方式:所有界面设计都在*.txt文本文件设计,并在需要时调用这些特定的部分
- 网上银行底层函数封装完成
- 对C++语言的使用熟悉
遇到的困难
但是不管怎么说,应为刚大致学完一本C++入门书籍,所以,即使有较为深厚的C语言编程功底,我在写这部分网上银行代码时,也遇到了不小的阻力:
- 对C++标准库函数不熟悉
- 对C++区别于C语言的新特性的不熟悉
- 编程思想相对来说还是C语言那一套
- 对C++面向对象的特性使用的不好
一周C++知识点总结
本周我第一次使用C++写一个类似于课程大设计的项目:网上银行。在最后的两天内,我完成了网上银行登录、注册以及界面设计方面的代码编写、底层函数封装的工作,可以说基本是完成了网上银行最繁琐、最困难的一部分工作,至于后期的取款、还款、消费只要逻辑清晰便可借助于已有的底层函数较为简单的实现。在本周的编程学习过程中,我遇到了大量的问题,但在网络与同学的帮助下,基本解决了我目前遇到的所有问题,下面,将针对每一个问题,给出我的解决方法、编程技巧。
下图是我保存网上银行界面设计的文本文件。程序通过特定的字符串识别各界面对应的位置,并将其输出到控制台。图中的’*'对应的位置即为用户信息打印的位置,程序通过识别这些特殊字符,达到格式化输出用户信息的目的。
下图是我存放网上银行客户信息的文本文件,它使用’|‘来区别用户的各项信息,程序通过识别特定字符串"$account$"来识别用户信息记录的起始位置,并依赖’|'来识别用户各项信息。
下面是程序具体运行情况,从运行情况看,程序已经可以完美运行注册、登录、数据加载、界面显示的功能。
string字符串的查找、替换
这次程序设计,因为我是用的是将所有界面、客户数据存入文本文件的思路,所以在实现过程中会设计到大量的字符串操作。这对我的字符串使用提出了很多难题,其中最为突出的便是字符串的查找、替换。查找和替换操作在网上银行界面显示的底层函数中处于重要地位,主要用来从文件中提取需要的字符串,并将用户信息格式化打印到控制台。
熟悉C语言char类型字符串的人都知道,C语言为字符串操作提供了很多方便的标准库,但是在使用中会有不方便之处,比如繁琐的调用。本次为了简化操作,我选用C++中的string类来完成大部分的字符串操作。
-
string字符串的查找
在本次程序设计分过程中遇到的最重要的字符串操作需求便是string字符串的查找,为此,我重新翻看C++ Primer Plus的string类讲解部分,并且在网上查找到了一些有用的资料。下面对这阶段学到的技巧来对大家进行分享。
因为目前我的需求仅仅是在从文件中读取的字符串中查找到特殊字符串,所以我只使用了两种string类字符串查找方法,大致分为两类:特殊字符串独占一行、特殊字符串在行内。
-
特殊字符串独占一行
在网上银行是界面设计文件中,我使用独占一行的特殊字符串来识别每个功能对应的界面存储位置。
总的来说这种情况比较简单,尤其是在使用string类的情况下。正因为有这种需求,我在一开始尝试char类型字符串之后果断放弃,转用string类字符串。
这种情况下,只需在程序开头创建一个string类字符串,用于存放特殊字符,并在程序每读取一行文件之后将此行文件与其相比较,相同即为需要的特殊行。其具体程序如下:
string filename;
string start = "1.menu_start";
string end = "1.menu_end";
filename = online_bank_gui_file;
gui_show(filename, start, end);
以下是gui_show()函数:
//打印文本文件filename位于start和end字符串之间的所有字符
void gui_show(string filename, string start, string end)
{
bool start_flag = false;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED |FOREGROUND_GREEN);//设置红色和绿色相加==>黄色
ifstream fin(filename.c_str());
string ch;
string ch1;
while (!fin.eof())
{
ch1 = ch;
getline(fin, ch);
if (start_flag)
{
if (ch == end)
{
cout << ch1 << '\b';
break;
}
cout << ch1 << endl;
}
else
if (ch == start)
{
start_flag = true;
ch = "";
}
}
fin.close();
}
经实际测试,程序运行良好,具体效果参考文章开头部分,但是后期依旧会对此函数的安全性进行加强,对其增加返回值等。
-
特殊字符串在行内
针对这种情况,第一种方法不适用,需要寻求更高级的解决方式。经查找,我选用find()函数来实现此功能。
- find()函数:
- 原型:
//string (1) size_type find (const basic_string& str, size_type pos = 0) const noexcept; //c-string (2) size_type find (const charT* s, size_type pos = 0) const; //buffer (3) size_type find (const charT* s, size_type pos, size_type n) const; //character (4) size_type find (charT c, size_type pos = 0) const noexcept;
- 使用示例:
cout << st1.find('a', 2) << endl;//4 在st1中,从位置2(包括位置2)开始,查找字符a,返回首次匹配的位置,若匹配失败,返回npos cout << st2.find(str1, 2) << endl;//6 从st2的位置2开始匹配,返回第一次成功匹配时匹配的串(str1)的首字符在st2中的位置,失败返回npos
在程序中,我通过调用find()函数来确定特殊字符串在一行数据中的起始位置,并根据特殊字符串的长度来确定其范围。示例如下:
- find()函数:
string find_str = "******************************";
string find_num = "*********"; //程序中使用的两个特殊字符串
replace_start = ch1.find(find_str); //找到特殊字符串find_str的起始位置
if (replace_start != -1) //如果找到
replace_end = replace_start + 30; //根据find_str的长度为30来确定其范围
else
cout << "未找到相应字符串" << endl;
-
string字符串的替换
本次编程string字符串替换工作被我安排在获取正确查找到特殊字符之后,通过一个for循环,将输入流中的字符全部提取出来,并且当替换字符串太短,用不光特殊字符串所在空间的话,多余空间使用字符’ '(space键)来填充。这一功能已被我封装成函数,如下:
string string_relpace(string raw, string rep, int start, int end) //用rep替换raw位于start和end之间的所有字符,不够的用空格填充
{
string fill = " ";
string raw_c;
raw_c = raw;
for (int i = start; i <= end; i++)
{
if (i - start <= rep.size())
raw_c[i] = rep[i - start];
else
raw_c[i] = fill[0];
}
return raw_c;
}
经实测,函数运行效果令人满意,具体执行情况参照本文开头网络银行界面打印的截图。
C++中数值类型与string类的相互转化
为实现客户信息提取、存储、运算工作,我需要将客户信息中的数字信息转化为字符串,并在其他操作中将字符串再转化成数字。
- 数值类型转换为string
- 使用函数模板 + ostringstream
//ostringstream对象用来进行格式化的输出,常用于将各种类型转换为string类型
//ostringstream只支持<<操作符
template<typename T> string numtoString(const T& t)
{
ostringstream oss; //创建一个格式化输出流
oss << t; //把值传递如流中
return oss.str();
}
-
使用标准函数库函数std::to_string()
std命令空间下有一个C++标准库函数std::to_string(),可用于将数值类型转换为string。使用时需要include头文件 string
函数原型声明如下:
string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);
- string转化为数值类型
- 使用函数模板 + istringstream
//模板函数:将string类型变量转换为常用的数值类型(此方法具有普遍适用性)
template <class Type>
Type stringToNum(const string& str)
{
istringstream iss(str);
Type num;
iss >> num;
return num;
}
-
使用C++标准库函数
使用C++11引入的C++库函数将string转换为数值类型,相应的库函数申明于头文件<string>中。
-
使用C语言标准库函数
使用此方法需要先将string字符串转化成char类型字符串,之后使用相应的类型转化函数转化成想要的数值类型。需要包含标准库函数<stdlib.h>
cin.clear()的使用
在编写网上银行程序时,我遇到了一个较为奇怪的问题,就是当我需要的输入为int变量,如数字2时,输入一个字符,如字符’w’时,会导致程序死掉,示例代码如下:
int input;
cout << "input:";
cin >> input;
while (input != 10) //判断条件换成!cin结果一样
{
cout << "The input is inappropriate!" << endl;
cout << "input:";
cin >> input; //will not work
}
此时运行,得到执行结果显示,程序死在了while循环里,并且在输入错误时,input获取错误值,如下:
问题分析:程序中输入字符’w’之后,cin一直无法从数据块填充缓冲区中读取正确的int型整数。输入与预期格式不匹配反过来将导致 cin >> input 的结果为false。输入出错,导致输入流状态位被设置。然而设置流状态位有一个非常重要的后果:流将对后面的输入或输出关闭,直到位被清除 。所以,while循环里的 cin >> input 将不会工作。此时,可以使用 rdstate() 函数来查看流状态,它将返回流状态。
解决方案:
-
使用 cin.clear() 清除cin内部标志符
首先第一种方案仅执行 cin.clear() 。为保证以后的输入正常进行,我们使用 cin.clear() 清除cin的错误标志。但是由于这种方法并不会清除输入。但这种方法获得的执行结果与源程序一样。
- 错误分析:程序使用 cin.clear() 清除cin的错误标志,使while循环内的输入得以工作。但是由于数据块填充缓冲区中的数据一直是错误的,所以程序中输入字符’w’之后,cin一直无法从缓冲区中读取正确的int型整数。输入与预期格式不匹配反过来将导致 cin >> input 的结果为false。由于缓冲区内的字符’w’一直未被读出,导致即使重新从缓冲区内取值,cin也不会成功取得正确的值。这造成input的值一直是false,程序死在while循环。本程序将while循环判断条件换成 !cin 也是会得到相同的执行结果。
由于导致程序进入死循环的不匹配输入仍留在输入队列中,程序必须跳过它。下面是几种可以实现这一需求的解决方案
-
使用 cin.sync() 清除输入缓冲区中的数据。
遇到上述问题之后,我去论坛上寻找解决方案时,遇到了一种解决方法,便是使用sync函数清除数据块填充缓冲区内的数据。但是遗憾的是,将while循环修改为如下形式后,在我的VS2017上运行的结果依然是错误的,程序依旧死在了while循环中。
while (input != 10) { cout << "The input is inappropriate!" << endl; cout << "input:"; cin.clear(); //清除cin错误标志 cin.sync(); //清除数据块填充缓冲区内的数据 cin >> input; }
再次查阅论坛之后得到如下解释:由于VS自身问题,sync函数无法得到预期目标。但是,这个方法在linux系统上使用是可以的。
-
使用ignore函数清空缓冲区数据
ignore()函数接受两个参数,一个数字,指定要读取的最大字符数;另一个是字符,用作输入分界符。例如函数调用:cin.ignore(1024,’\n’); 表示读取并丢弃接下来1024个字符或直到到达第一个换行符。具体示例代码如下:
while (!cin) { cout << "The input is inappropriate!" << endl; cout << "input:"; cin.clear(); //一定配合cin.clear()使用,否则失败 cin.ignore(1024,'\n'); cin >> input; }
VS中sync函数使用不方便,可以使用ignore函数替代。并且,这也是一个很好的解决方案,效果类似于第五个方案中的第二个方法。
-
将输入缓冲区中的错误数据读出,扔掉,重新输入。
这里将提供两种此类解决方法,均可正常使用。
-
第一种方法就是一直读取字符,直到达到空白为止。这里使用issapce()函数,这是一个cctype函数,它在参数是空白字符时返回true。
-
第二种方法是,丢弃行中的剩余部分,而不仅仅是下一个单词。
-
第三种方法是,将行中的剩余部分读取到一个string类字符串中,以此来清空输入缓存。
下面是上述三种方法的示例代码:
while (input != 10) //第一种方法 { cout << "The input is inappropriate!" << endl; cout << "input:"; cin.clear(); while (!isspace(cin.get())) continue; //去除不匹配的输入 cin >> input; } while (!cin) //第二种方法 { cout << "The input is inappropriate!" << endl; cout << "input:"; cin.clear(); while (cin.get() != '\n') continue; //去除行中剩余部分 cin >> input; } string ch; while (!cin) //第三种方法 { cout << "The input is inappropriate!" << endl; cout << "input:"; cin.clear(); cin >> ch; cin >> input; }
下面是三种方法分别执行的结果:
从运行结果可以看出,第一、第三种解决方法运行效果基本相同,一次仅能消除行中的一个单词,遇到多个单词的话,便需要多次循环才可消除行中所有剩余部分;第二种方法最好,一次便可消除行中所有剩余部分,不管其为什么格式。
关于clear
、sync
、ignore
三个函数的区别可以参考这两篇博文。
http://blog.csdn.net/playboy_lei/article/details/50549838
https://stackoverflow.com/questions/5131647/why-would-we-call-cin-clear-and-cin-ignore-after-reading-input
C++文件操作
在这一步分开始前,我们先来看一下标准C语言下的文件操作,示例程序如下:
/* FEOF example */
#include <stdio.h>
int main()
{
FILE * pFile; //声明一个文件指针
char buffer [100];
pFile = fopen ("myfile.txt" , "r"); //以读的方式打开文件
if (pFile == NULL) perror ("Error opening file"); //打开失败就输出error
else
{
while ( ! feof (pFile) ) //未读到文件尾就继续读文件
{
if ( fgets (buffer , 100 , pFile) == NULL ) break; //读完了,就跳出循环
fputs (buffer , stdout); //输出到程序默认终端(控制台...)
}
fclose (pFile); //关闭文件
}
return 0;
}
C++操作文件的方法相较于C语言有较大的不同,下面仅就文件的基础读取、写入方式进行探讨,更加完整的文件操作方法可以参见这一网站:http://www.cplusplus.com/doc/tutorial/files/ 。
打开文件
C++提供了如下三个类,来进行文件的输入输出。
类 | 含义 |
---|---|
ofstream | Stream class to write on files |
ifstream | Stream class to read from files |
fstream | Stream class to both read and write from/to files |
因为这些类都是从头文件iostream中的类派生出来的,所以这些新类的对象可以使用cin、cout的使用方法。
要让程序写入文件,必须这样做:
- 创建一个ofstream对象来管理输出流;
- 将该对象与特定的文件关联起来;
- 以使用cout的方式使用该对象,唯一的区别就是输出将进入文件,不是屏幕。
读取文件的要求与写入文件相似:
- 创建一个ifstream对象来管理输入流;
- 将该对象与特定的文件相关联起来;
- 以使用cin的方式使用该对象,唯一的区别在于程序的输入方式为文件,而不是键盘等设备。
示例代码:
ofstream fout;
fout.open("test.txt"); //可以简写成:ofstream fout("test.txt")
fout << "Test Data";
fout.close();
ifstream fin("test.txt"); //也可以拆开写
string ch;
fin >> ch;
fin.close();
-
文件的输入和输出都被缓冲的。比如创建ifstream对象与fin一样,将创建一个由fin对象管理的输入缓冲区。通过缓冲,传输数据的速度比逐字节传输要快的多。
-
警告:以默认方式打开文件进行输出将自动把文件的长度截短为零,这相当于删除已有的内容。
-
文件模式:描述文件将被如何使用(读、写、追加等)
下表列出了文件模式常量
常量 含义 ios_base::in 打开文件,以便读取 ios_base::out 打开文件,以便输出 ios_base::binary 二进制文件 ios_base::ate 打开文件,并将文件指针移到文件尾 ios_base::app 将输出内容追加到文件尾 ios_base::trunc 文件如果作为输出被打开并且已经存在,就将此文件以前内容删除(截短文件) 将流与文件关联时(使用文件名初始化文件流对象、使用open()方法),都可以提供指定文件模式的第二个参数,示例如下:
ofstream fout;
fout.open("test.txt",ios_base::app | ios_base::out);
ifstream fin("test.txt",ios_base::in);
fstream file("test.txt", ios_base::in | ios_base::out | ios_base::app);
C++三个文件操作新类均有其默认的文件模式:
类 | 默认文件模式 |
---|---|
ofstream | ios_base::out |
ifstream | ios_base::in |
fstream | ios_base::out |ios_base::in |
关闭文件
当输入输出流对象过期(如程序终止)时,到文件的连接将自动关闭。此外,我们可以使用 close() 方法来显示地关闭文件的连接。这样之后,当前操作的文件才可以被其他文件对象连接。
fout.close();
fin.close();
值得注意的是,关闭这样的连接并不会删除流,这只是断开流到文件的连接。比如fin对象与其管理的输入缓冲区仍然存在,可以将流重新连接到同一个文件或另一个文件。
Text files
对于文本文件流,ios_base::binary不会被包含在其文件模式中。其操作方式同cin、cout相同。具体参见上述示例代码。
流状态检查和is_open()
C++文件流类从ios_base类那里继承了一个流状态成员,该成员存储了指出流状态的信息:一切顺利、已达文件尾、I/O操作失败…如果一切顺利,流状态为0,其他一切问题提都是通过将相应位置1来记录的。
标志位 | 返回值 |
---|---|
bad() | 如果写或读操作出错,返回true |
fail() | 当bad()返回true以及出现格式错误(需要int结果输入为char)时均会返回true |
eof() | 进行读操作的文件已经读到文件尾 |
good() | bad、fail、eof返回true时均将返回false |
- 较新的C++实现提供一种更好的检查文件是否被打开的方法——is_open()方法,文件成功打开时返回true。
- is_open()较上述老式检测方法的好处在于:可以检测出其他方式不能检测出的微妙问题,如:
- 试图以不合适的文件模式打开文件是失败。方法is_open()可以检测到这种错误。
- is_open()方法可以检测到good()能够检测到的错误。
一种将文件全部逐行读出的方式
文件操作时,经常会逐行操作文件,这里给出一种将文件全部逐行读出并做处理的程序设计方式。
//程序用来查找文件中使用'|'分割开来的字符串,通过'|'在每一行出现的次数确定特定项目存储位置
string get_a_item(string filename, string item, string value) //获取账号的一个项目
{
ifstream fin(filename.c_str());
string ch; //用来获取文件的一整行,最终返回文件的一张行
string ch1; //用来获取每一个被'|'分割开的字符串
string account_start = "$account$";
bool start_flag = false;
bool get_item = false;
int get_info = 0;
int item_loc;
if (item == "name")
item_loc = 2;
else if(item == "password")
item_loc = 3;
else if (item == "phone")
item_loc = 4;
while (!fin.eof())
{
getline(fin, ch); //获取文件的一行
ch1 = ""; //清空ch1字符串
if (start_flag) //如果检测到数据开始的特殊字符串
{
for (int i = 0; i < ch.size(); i++) //在获得的行内逐字符寻找,找到就跳出循环
{
if (ch[i] == '|')
get_info++;
else
if (get_info == item_loc - 1)
ch1 = ch1 + ch[i];
if (get_info == item_loc)
{
get_info = 0;
break;
}
}
if (ch1 == value) //判断该值是否为寻找的值
{
get_item = true;
break;
}
}
else
if (ch == account_start) //判断当前行是否为起始行
start_flag = true;
}
fin.close();
fin.clear();
if (get_item) //找到便返回所在行
return ch;
else //未找到便返回特殊字符串"$none$"
return "$none$";
}
C++中函数strcpy和strcpy_s
在VS2017中,很多标准字符串操作函数因为安全性问题(主要为:函数传入参数未加const,导致输入字符串可能被修改),在调用时会产生警告,并导致编译不通过。比如:
char ch[] = "nihao a";
char ch1[10];
strcpy(ch1, ch);
编译后出错:
错误 C4996 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
可以看出,编译器提示strcpy这个函数不安全,建议使用strcpy_s函数,或者使用_CRT_SECURE_NO_WARNINGS。按照提示,我们用系统给的两种方法来优化程序。
-
第一种,在程序开头加上 #define _CRT_SECURE_NO_WARNINGS,结果尴尬的是程序依旧报错,且错误信息相同。现在只能尝试使用函数strcpy_s。
-
第二种,使用函数strcpy_s。
- 定义:
_ACRTIMP errno_t __cdecl strcpy_s(
_Out_writes_z_(_SizeInBytes) char* _Destination,
_In_ rsize_t _SizeInBytes,
_In_z_ char const* _Source
);
- 参数说明:
参数 | 说明 |
---|---|
_Destination | 目标字符串 |
_SizeInBytes | 复制的长度 |
_Source | 源字符串 |
- 使用示例
char ch[] = "nihao a";
char ch1[10];
int len = strlen(ch); //计算字符串长度
strcpy_s(ch1, len + 1, ch);
C++改变控制台输出字符的颜色
C++控制台程序运行时输出框默认的文字颜色是白色。在控制台应用程序中,为了强调效果、增强输出的艺术感,我们需要改变控制台输出的字符颜色。改变控制台输出字符颜色的方法有两种:
- 在控制台输出框中修改其属性
具体方法如下图所示:
-
在代码中通过SetConsoleTextAttribute()函数进行修改
SetConsoleTextAttribute是一个可以在API(应用程序编程接口)中设置控制台窗口字体颜色和背景色的计算机函数,该函数被广泛应用于电脑编程与软件开发中。
函数原型为:BOOL SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes)
consolehwnd = GetStdHandle(STD_OUTPUT_HANDLE);
GetStdHandle(nStdHandle)是返回标准的输入、输出或错误的设备的句柄,也就是获得输入、输出/错误的屏幕缓冲区的句柄。
其参数nStdHandle的值为下面几种类型的一种:
值 含义 STD_INPUT_HANDLE 标准输入的句柄 STD_OUTPUT_HANDLE 标准输出的句柄 STD_ERROR_HANDLE 标准错误的句柄 wAttributes是用来设置颜色的参数:
wAttributes 颜色 对应的值 FOREGROUND_BLUE 字体颜色:蓝 1 FOREGROUND_GREEN 字体颜色:绿 2 FOREGROUND_RED 字体颜色:红 4 FOREGROUND_INTENSITY 前景色高亮显示 8 BACKGROUND_BLUE 背景颜色:蓝 16 BACKGROUND_GREEN 背景颜色:绿 32 BACKGROUND_RED 背景颜色:红 64 BACKGROUND_INTENSITY 背景色高亮显示 128 程序中wAttributes存储为8位字节,每一位分别控制上表对应的控制项。
使用示例:
cout << "原色testCOLOR(没有设置字体颜色)" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); //设置三色相加
cout << "白色testCOLOR(红色绿色蓝色相加)" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED); //设置红色
cout << "红色testCOLOR(设置的颜色为红色)" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN); //设置绿色
cout << "绿色testCOLOR(设置的颜色为绿色)" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE); //设置蓝色
cout << "蓝色testCOLOR(设置的颜色为蓝色)" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN); //设置红色和绿色相加
cout << "黄色testCOLOR(红色和绿色相加色)" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE); //设置红色和蓝色相加
cout << "粉色testCOLOR(红色和蓝色相加色)" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE); //设置绿色和蓝色相加
cout << "青色testCOLOR(绿色和蓝色相加色)" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY); //设置颜色,没有添加颜色,故为原色
cout << "原色testCOLOR(没有设置字体颜色)" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); //设置三色相加
cout << "白色testCOLOR(红色绿色蓝色相加)" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | BACKGROUND_INTENSITY | BACKGROUND_GREEN); //设置红色,背景色绿色
cout << "红色testCOLOR(设置的颜色为红色)" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN | BACKGROUND_INTENSITY | BACKGROUND_BLUE); //设置绿色,背景色蓝色
cout << "绿色testCOLOR(设置的颜色为绿色)" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0XFC); //设置为白底红字:11111100
cout << "红色testCOLOR(设置的颜色为红色)" << endl;
程序输出为: