Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to change color in a string in c?

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.

like image 319
Simon Rogl Avatar asked Sep 14 '25 12:09

Simon Rogl


2 Answers

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);
    }
}
like image 139
chqrlie Avatar answered Sep 17 '25 02:09

chqrlie


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;
}
like image 21
Jose Luis Dionicio Avatar answered Sep 17 '25 03:09

Jose Luis Dionicio