[英]Why is ANSI printing the code the first time the function is called and printing colours the second time around?
我正在嘗試在 connect 4 游戲中更改我的 printf 語句的顏色 output。 我做了一個 function 來設置打印顏色並重置它。 它適用於我的大部分代碼,但不適用於第一次調用它時調用的第一個 function,但從那里開始工作。 問題中的function是主程序中調用的第一個function。
我嘗試了 function 的不同定位,將它定位在調用 function 的位置的任一側,並將顏色代碼直接輸入到 printf function,但它總是第一次失敗(而且只有第一次)。
#include <stdio.h>
void sprint_green();
void sprint_red();
int main_menu ( void ){
int a = 0;
char opt [20];
sprint_red();
printf("============================\n");
printf(" Welcome to Connect4!\n");
printf("============================\n");
sprint_reset();
// Continue asking for an option until a valid option (n/l/q) is entered
while (a == 0)
{
sprint_green();
printf("(N)ew game\n(L)oad game\n(Q)uit");
sprint_reset();
fgets(opt, 20, stdin);
// if 'n', return 1
if(opt[0] == 'n' || opt[0] == 'N'){
a = 1;
}
// if 'l', return 2
else if(opt[0] == 'l' || opt[0] == 'L'){
a = 2;
}
// if 'q', return -1
else if(opt[0] == 'q' || opt[0] == 'Q'){
a = -1;
printf("\nGoodbye!\n");
}
// if anything else, give error message and ask again..
else
{
printf("Invalid option\n");
}
}
system("cls");
return(a);
}
int main (void)
{
int i;
for(i = 0; i < 5; i++)
{
main_menu();
}
}
void sprint_green()
{
printf("\033[1;32m");
}
void sprint_red()
{
printf("\033[1;31m");
}
void sprint_reset()
{
printf("\033[0m");
}
前三個 printf 語句預計將打印為紅色,下一個將打印為綠色。 然而,它第一次被稱為打印 ANSI 顏色代碼。
[1;31m============================
Welcome to Connect4!
============================
[0m[1;32m(N)ew game
(L)oad game
(Q)uit[0m
然而,在運行一次游戲並再次開始(沒有關閉終端)之后,這些功能會按預期工作。
windows命令shell默認不啟動vt100仿真。 正如@Bodo 在他的回答中指出的那樣,這可以通過運行 shell 命令cls
來觸發。 但是,從技術上講,shell 命令不需要是cls
,甚至根本不需要是有效命令。 您可以通過一個空的system(" ")
調用來觸發它。 這也是可移植的,因為它除了立即啟動 shell 實例並將其終止外什么都不做。 因此它在 Windows 或 Linux 環境中應該同樣可以正常工作。
修復代碼:
#include <stdio.h>
#include <stdlib.h> // for system()
void sprint_green();
void sprint_red();
int main_menu ( void ){
int a = 0;
char opt [20];
system(" "); // Trigger ANSI emulation
sprint_red();
printf("============================\n");
printf(" Welcome to Connect4!\n");
printf("============================\n");
sprint_reset();
// Continue asking for an option until a valid option (n/l/q) is entered
while (a == 0)
{
sprint_green();
printf("(N)ew game\n(L)oad game\n(Q)uit");
sprint_reset();
fgets(opt, 20, stdin);
// if 'n', return 1
if(opt[0] == 'n' || opt[0] == 'N'){
a = 1;
}
// if 'l', return 2
else if(opt[0] == 'l' || opt[0] == 'L'){
a = 2;
}
// if 'q', return -1
else if(opt[0] == 'q' || opt[0] == 'Q'){
a = -1;
printf("\nGoodbye!\n");
}
// if anything else, give error message and ask again..
else
{
printf("Invalid option\n");
}
}
system("cls");
return(a);
}
int main (void)
{
int i;
for(i = 0; i < 5; i++)
{
main_menu();
}
}
void sprint_green()
{
printf("\033[1;32m");
}
void sprint_red()
{
printf("\033[1;31m");
}
void sprint_reset()
{
printf("\033[0m");
}
system("cls");
有效,但它會清除屏幕。 但是如果你只在啟動時調用它一次,它似乎會為整個應用程序修復它
根據
https://solarianprogrammer.com/2019/04/08/c-programming-ansi-escape-codes-windows-macos-linux-terminals/
和
https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences?redirectedfrom=MSDN
必須將 Windows 控制台置於 ANSI 轉義模式才能處理轉義序列而不是打印它們。
顯然執行cls
命令似乎可以做到這一點。
您可以通過設置標志ENABLE_VIRTUAL_TERMINAL_PROCESSING
使用GetConsoleMode()
和SetConsoleMode()
以編程方式設置終端模式
從引用的 Microsoft 頁面復制的代碼示例:
#include <stdio.h>
#include <wchar.h>
#include <windows.h>
int main()
{
// Set output mode to handle virtual terminal sequences
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hOut == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
DWORD dwMode = 0;
if (!GetConsoleMode(hOut, &dwMode))
{
return GetLastError();
}
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (!SetConsoleMode(hOut, dwMode))
{
return GetLastError();
}
// Try some Set Graphics Rendition (SGR) terminal escape sequences
wprintf(L"\x1b[31mThis text has a red foreground using SGR.31.\r\n");
wprintf(L"\x1b[1mThis text has a bright (bold) red foreground using SGR.1 to affect the previous color setting.\r\n");
/* ... more examples removed */
return 0;
}
顯然此解決方案僅適用於 Windows,但運行system("cls")
也是不可移植的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.