Есть ли способ изменить цвет определенного текста в программе на C в DevC ?

#c #winapi #colors #console

#c #winapi #Цвет #консоль

Вопрос:

По сути, я работаю над этой программой текстового редактора для школьного проекта, которая использует простые функции подачи и строки для создания, добавления, удаления, отображения, дублирования или поиска в текстовых файлах. Мне удалось объединить все функции, и мой вопрос относится к моей Search() функции, которую я прикреплю в конце этого для справки. Если ключевое слово поиска найдено, функция печатает, в какой строке оно было найдено, и печатает саму строку. Что я хотел бы сделать, это, если возможно, изменить цвет ключевого слова поиска при печати строки, чтобы оно выделялось, и пользователь мог сразу определить, где находится его ключевое слово в строке. Я не спрашиваю об этом, не проводя НИКАКИХ исследований по этому вопросу; Я немного покопался, и, похоже, я могу использовать escape-последовательности ANSI или последовательности виртуальных терминалов консоли Windows для достижения того, что я пытаюсь сделать, и я просмотрел документацию на веб-сайте Microsoft, но, к сожалению, япока мне не нравится вызывать API-интерфейсы Windows, и мне действительно не помешала бы помощь, чтобы выяснить, как именно это сделать. Кроме того, заранее приношу извинения, если код, который я прикрепляю, иногда кажется неэффективным или ненужным, только начал изучать C пару месяцев назад. Я использую компилятор gcc с DevC в Windows 10. TIA.

 void Search(void) {
    FILE *fptr;
    char name[20], key[30], line[100];
    int linenum=1, found=0;
    printf("Enter name of text file to search from, or enter 'exit' to cancel and return to menu: ");
    gets(name);
    if(strcmp(name,"exit") == 0)
        return;
    strcat(name,".txt");
    fptr = fopen(name,"r");
    while(!fptr) {                                  // just some input validation
        printf("Error. Text file not found. Make sure it exists and is placed in the same folder as the .exe file for this program.");
        fclose(fptr);
        printf("nnEnter name of text file to search from, or enter 'exit' to cancel and return to menu: ");
        gets(name);
        if(strcmp(name,"exit") == 0)
            return;
        strcat(name,".txt");
        fptr = fopen(name,"r"); 
    }
    printf("Enter your search keyword (remember, it is case sensitive): "); //searching staarts here
    gets(key);
    while(!feof(fptr)) {
        fgets(line,100,fptr);
        if(strstr(line,key)) {
            printf("Keyword found in line %d:n", linenum);
            printf("----------------------------------------------------------------------------------------------n");
            printf("%s",line);
            printf("----------------------------------------------------------------------------------------------nn");
            found=1;
        }
        linenum  ;
    }
    if(!found) 
        printf("Keyword not found in file.");
    printf("nPress any key to return to main menu: ");
    getch();
}
 

Причина, по которой я использовал длинный ———— разделители — это то, что я хочу отличать содержимое текстового файла от содержимого того, что написано в окне консоли.

Комментарии:

1. В зависимости от вашей консоли вы можете использовать экранирующие коды ANSI

2. Также называемые виртуальными последовательностями терминалов .

3. Да, я столкнулся с этим, исследуя, как это сделать, просто я не мог найти достаточно простого ответа относительно того, как на самом деле реализовать их в моем коде. Действительно ценю толчок в правильном направлении.

Ответ №1:

В принципе, вы можете полагаться на string class для выполнения этой задачи, использовать string :: find для извлечения местоположения ключа, а затем использовать string:: substr для печати значения ключа.

Обратитесь к приведенному ниже коду:

 void Search(void) {
    ...
    printf("Enter your search keyword (remember, it is case sensitive): "); //searching staarts here
    gets_s(key);
    while (!feof(fptr)) {
        fgets(line, 100, fptr);
        if (strstr(line, key)) {
            std::string str(line);
            printf("Keyword found in line %d:n", linenum);
            printf("----------------------------------------------------------------------------------------------n");
            int pos = str.find(key);
            int len = strlen(key);
            int len_t = strlen(line);
            if (pos != 0)
            {
                printf("%s", str.substr(0, pos).c_str());
                printf("x1b[31m%s", str.substr(pos, len).c_str());
                printf("x1b[0m%srn", str.substr(len pos, len_t).c_str());
            } 
            else
            {
                 printf("x1b[31m%s", str.substr(pos, len).c_str());
                 printf("x1b[0m%srn", str.substr(pos len, len_t).c_str());
            }           
            printf("x1b[0m----------------------------------------------------------------------------------------------nn");
            found = 1;
        }
        linenum  ;
    }
    if (!found)
        printf("Keyword not found in file.");
    printf("nPress any key to return to main menu: ");
    getch();
}
 

Отладка:
введите описание изображения здесь

Комментарии:

1. Вау, это потрясающе. Это именно то, на что я надеялся. Большое вам спасибо!

Ответ №2:

В качестве альтернативы вы могли бы просто использовать функции консоли Windows API:

 #include <stdio.h>
#include <windows.h>

int main()
{
  HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
  SetConsoleTextAttribute(hstdout, FOREGROUND_RED|FOREGROUND_INTENSITY);
  printf("hello ");
  SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN|FOREGROUND_INTENSITY);
  printf("world");
  return 0;
}