Is there any way to change the colour of a string within a string in c++

This is the code, I have a string called Battlelogs which stores the result of all the battles that take place in a turn, FactionFighter is the name of the attacker and FactionDefender is the name of the defending faction, there are 14 total factions and it is set to one of those prior to the fight, all of this works but the problem is each faction has their own colour, and I want to have the text show the colour of the faction on their name.

So if the rebels are grey and the bandit horde are green, it would display the word rebels in grey and bandit horde in green, I know how to change the colour of text that is put out with cout, but as this is strings within strings I don't know how to do it.

Battlelogs += FactionFighter + " attempted to raid the lands of the " + FactionDefender + " but were unsuccessful\n";

Any help will be greatly appreciated
I wanted to do the same thing but wanted to make it easier than some solutions I found.
The code in the function is not mine, I Just put it in a function so I could call it easier.
Valid colors are 0-15, 0 is black (which you can't see on a black screen).
You can run it to see the other colors.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>
using namespace std;

void SetColor(int ColorPicker)
{
WORD consoleColor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
	{
	consoleColor = (csbi.wAttributes & 0xF0) + (ColorPicker & 0x0F);
	SetConsoleTextAttribute(hStdOut, consoleColor);
	}
}

int main(int argc, char** argv) 
{
// Sample colors
SetColor(12); // Red
std::cout  << " This is Red " ;
SetColor(15); // White
std::cout  << " This is White ";
SetColor(9); // Red
std::cout  << " This is Blue" << endl;
SetColor(7); // Reset to Default

for (int i =1; i <= 15; i++)
{SetColor(i);cout << i << " ";}

SetColor(7); // Default
return 0;
}


Last edited on
@Attempted

Here's a small program I wrote to show how to use up to 240 different color combinations in a program. There's actually 255, but, I'm not counting where the background color matches the text color.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Colored Text on Paper.cpp : main project file.

#include <iostream>
#include <string>
#include <windows.h>

enum Colors{
	black,          //  0 text color - multiply by 16, for background colors
	dark_blue,      //  1
	dark_green,     //  2
	dark_cyan,      //  3
	dark_red,       //  4
	dark_magenta,   //  5
	dark_yellow,    //  6
	light_gray,     //  7
	dark_gray,      //  8
	light_blue,     //  9
	light_green,    // 10
	light_cyan,     // 11
	light_red,      // 12
	light_magenta,  // 13
	light_yellow,   // 14
	white           // 15
};

using std::cout;
using std::endl;
using std::cin;
using std::string;

void ClearScreen();

#define on , // So I can use the function - void text(text_color on background_color)
// To more easily remember which is text color vs background color

// My text color function. Use it if you wish.
void text(int text_color = 7 on int paper_color = 0)
{
	// defaults to light_gray on black
	int color_total = (text_color + (paper_color * 16));
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_total);
}

int main()
{
	string Color[16] = { "Black", "Dark Blue", "Dark Green", "Dark Cyan", "Dark Red", "Dark Magenta", "Dark Yellow", "Light Gray",
		"Dark Gray", "Light Blue", "Light Green", "Light Cyan", "Light Red", "Light Magenta", "Light Yellow", "White" };
	int i, j;

	for (j = 0; j<16; j++)
	{
		for (i = 0; i<16; i++)
		{
			if (j == i) // If text color is same as paper color
			{
				text();
				cout << "---> *** Place-holder --- Text same color as background *** <---" << endl;
				i++; // Skip to next color
			}
			if (i<16) // If not white on white, then continue
			{
				text(i on j);
				cout << Color[i] << " on " << Color[j] << " (Text color=" << i << "+Background color=" << j * 16 << " (" << j << "*16)=" << i + (j * 16) << ")" << endl;
			}
		}
	}
	text(); // Able to use names here, because of enum Colors{};

	cout << endl << endl << "Where a number is skipped, the text would be same color as the backgound.." << endl;
	cout << "To use color, add to your list of ";
	text(light_red on black);
	cout << "#include";
	text();
	cout << "'s, if not already used.." << endl;
	text(light_red on black);
	cout << "#include <windows.h>";
	text();
	cout << "." << endl << "Declare the following, afterwards.." << endl;
	text(light_red on black);
	cout << "HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);" << endl;
	text();
	cout << "and use the folowing, whenever you wish to change colors.." << endl;
	text(light_red on black);
	cout << "SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color_total );" << endl;
	text();
	cout << "Or examine the '";
	text(light_red on black);
	cout << "void text(int text_color on int paper_color);";
	text();
	cout << "' function," << endl << "at the top of this program. Works great, doesn't it ??" << endl;
	cout << "Just make sure to add '";
	text(light_red on black);
	cout << "#define on ,";
	text();
	cout << "', if you want to use the '";
	text(light_red on black);
	cout << "on";
	text();
	cout << "' word," << endl;
	cout << "instead of a comma, to separate the two color choices." << endl << endl;
	cout << "Press enter to exit.." << endl;
	cin.clear();
	cin.sync();
	cin.get();
	ClearScreen();
	return 0;
}

void ClearScreen()
{
	DWORD n;
	DWORD size;
	COORD coord = { 0 };
	CONSOLE_SCREEN_BUFFER_INFO csbi;
	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
	GetConsoleScreenBufferInfo(h, &csbi);
	size = csbi.dwSize.X * csbi.dwSize.Y;
	FillConsoleOutputCharacter(h, TEXT(' '), size, coord, &n);
	GetConsoleScreenBufferInfo(h, &csbi);
	FillConsoleOutputAttribute(h, csbi.wAttributes, size, coord, &n);
	SetConsoleCursorPosition(h, coord);
}
> I know how to change the colour of text that is put out with cout, but as this is strings within strings

Perhaps embed mark ups in the string to indicate text colour, and then while printing out the string, give special treatment for sections of text that are marked up.

Something along these lines perhaps:
(In this snippet, console::set_colour() is a stub, the code to change the colour has to be written).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <string>
#include <regex>

namespace console
{
    enum colour { GREY, RED, GREN, BLUE, /* ... */ DEFAULT = 255 };

    void set_colour( colour clr ) { /* TODO: whatever is needed to set the colour */ }

    std::ostream& print( std::ostream& stm, std::string str )
    {
        // mark up pattern: <colour=nnn>text</colour> where nnn is the value for the colour
        // numbered capture 1: (\\d+) integer representing colour
        // numbered capture 2: (.+?) the text to be printed (match as few as possible)
        static const std::regex pattern( "<colour=(\\d+)>(.+?)</colour>" ) ;
        std::smatch match ;

        while( std::regex_search( str, match, pattern ) ) // search for a mark up for colour
        {
            stm << match.prefix() ; // print the prefix before the match

            set_colour( colour( std::stoi( match[1] ) ) ) ; // todo: check if colour is within range
            stm << match[2] ; // print text excluding the tags for colour
            set_colour(DEFAULT) ; // restore default colour

            str = match.suffix() ; // set the string to suffix after the match and repeat the search
        }

        return stm << str ; // print the residue after the last match
    }
}

struct faction
{
    faction( console::colour clr, std::string name )
        : mark_up( "<colour=" + std::to_string(clr) + '>' + name + "</colour>" ) {}

    std::string mark_up ; // format: <colour=nnn>name</colour>

    operator const std::string& () const { return mark_up ; }

    friend std::ostream& operator<< ( std::ostream& stm, const faction& f )
    { return console::print( stm, f.mark_up ) ; }

    friend std::string operator+ ( const std::string& str, const faction& f ) { return str + f.mark_up ; }
    friend std::string operator+ ( const faction& f, const std::string& str ) { return f.mark_up + str ; }
    friend std::string operator+ ( const char* cstr, const faction& f ) { return cstr + f.mark_up ; }
    friend std::string operator+ ( const faction& f, const char* cstr ) { return f.mark_up + cstr ; }

};

const faction FactionFighter { console::RED, "FactionFighter" } ;
const faction FactionDefender { console::BLUE, "FactionDefender" } ;

int main()
{
    std::string str = "hello " + FactionFighter + " and hello " + FactionDefender + '\n' ;
    console::print( std::cout, str ) ;
}
It's best not to use all caps for enums to avoid name clashes with macros.
Topic archived. No new replies allowed.