My problem is that I have a string which is colored gray, the string is almost 1000 characters long. 2 of them must be in another color (red), but I don’t know how to change the color in the string.
Here is the code:
FILE *f = fopen("map.txt", "rb");
if (!f) {
perror("fopen");
exit(EXIT_FAILURE);
}
int c;
int j = 0;
MOVE(1, 1);
while ((c = fgetc(f)) != EOF && j < (REIHE * ZEILE) + REIHE) {
content[j] = (char)c;
j++;
}
content[j] = '\0';
if (laengekontrast10 != 0) {
printf("\033[38;2;%d;%d;%dm", laengekontrast10, laengekontrast10, laengekontrast10);
fwrite(content, 1, (REIHE * ZEILE) + 30, stdout);
printf(ANSIC_RESET);
for (int k = 0; k < (REIHE * ZEILE) + REIHE; k++) {
if (content[k] == '[' || content[k] == ']') {
printf(ANSIC_FG_RED"%c"ANSIC_RESET, content[k]);
}
}
}
I have tried to put the for
loop with the if
statement between the 2 printf
(the ones for the colors) but it didn't work, I expect to change the color of whole string to gray, except the 2 chars '['
and ']'
they should be red.
The problem with your code is you do not print the whole string and you reset the color after the brackets.
Here is a different approach where for each character in the string, you determine the color, change it if necessary and print the character:
#include <stdio.h>
#define ANSIC_RESET "\033[0m"
#define ANSIC_FG_RED "\033[31m"
#define RED_RGB 0x800000
void show_string(const char *content, int laengekontrast10) {
int cur_color = -1;
int def_color = laengekontrast10 * 0x010101;
for (size_t k = 0; content[k] != '\0'; k++) {
char c = content[k];
int color = def_color;
if (c == '[' || c == ']')
color = RED_RGB;
// you can easily add more colors for other characters here
if (color != cur_color) {
if (color == RED_RGB) {
fputs(ANSIC_FG_RED, stdout);
} else {
printf("\033[38;2;%d;%d;%dm",
(color >> 16) & 255,
(color >> 8) & 255,
color & 255);
}
cur_color = color;
}
putchar(c);
}
fputs(ANSIC_RESET, stdout);
}
Here is a less generic alternative that prints the string blocks using fwrite
:
#include <stdio.h>
#define ANSIC_RESET "\033[0m"
#define ANSIC_FG_RED "\033[31m"
void show_string(const char *content, int laengekontrast10) {
size_t pos = 0, chunk;
while (content[pos]) {
if ((chunk = strcspn(contents + pos, "[]")) != 0) {
printf("\033[38;2;%d;%d;%dm", laengekontrast10, laengekontrast10, laengekontrast10);
fwrite(content + pos, 1, chunk, stdout);
pos += chunk;
}
if ((chunk = strspn(contents + pos, "[]")) != 0) {
fputs(ANSIC_FG_RED, stdout);
fwrite(content + pos, 1, chunk, stdout);
pos += chunk;
}
}
if (pos) {
fputs(ANSIC_RESET, stdout);
}
}
There is an approach where you have to change the colors and must apply ANSI escape codes during the initial printing process rather than attempting to modify colors after the text is already printed.This is because your attempt to print the entire string in gray first (fwrite
), then tries to print [
and ]
in red afterward. This results in red characters appearing after the gray string, not embedded within it. So I would suggest you print each character individually, and applying the colors code before printing the characters. So you can try this code:
Also here's some documentation that really helps : https://blog.mbedded.ninja/programming/ansi-escape-sequences/
#include <stdio.h>
#include <stdlib.h>
#define ANSIC_RESET "\033[0m"
#define ANSIC_FG_RED "\033[31m"
#define ANSIC_FG_GRAY "\033[38;2;128;128;128m" // RGB gray
int main() {
FILE *f = fopen("map.txt", "rb");
if (!f) { perror("fopen"); exit(EXIT_FAILURE); }
char content[2000];
int c, j = 0;
while ((c = fgetc(f)) != EOF && j < sizeof(content) - 1) {
content[j++] = (char)c;
}
content[j] = '\0';
fclose(f);
for (int k = 0; k < j; k++) {
if (content[k] == '[' || content[k] == ']') {
printf(ANSIC_FG_RED "%c" ANSIC_RESET, content[k]);
} else {
printf(ANSIC_FG_GRAY "%c" ANSIC_RESET, content[k]);
}
}
printf("\n");
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With