直接启动应用程序时,控制台中的 C++ 彩色文本不显示

如何解决直接启动应用程序时,控制台中的 C++ 彩色文本不显示

enter image description here

我已经为我用 C++ 编写的应用程序实现了我自己的 Logging 类。我使用这种为文本着色的方式 (https://stackoverflow.com/a/54062826/12873837) 实现了 Logging 类。如果我使用调试器在 Visual Studio 中启动我的程序,它确实工作得很好,但如果我直接启动我的应用程序就不行。 ANSI 转义颜色代码不是彩色文本,而是在我的实际控制台输出之前直接打印出来。任何想法为什么会发生这种情况?

这个截图是输出,如果我直接启动应用程序。

解决方法

感谢@1201ProgramAlarm,我终于在这里找到了解决方案:https://stackoverflow.com/a/63426872/12873837

这对我来说非常好:)

,

也许这段代码很有用

Printing Unicode


#include <iostream>
#include <set>
#include <string>
#include <locale>

// WINDOWS
#if (_WIN32)
#include <Windows.h>
#include <conio.h>
#define WINDOWS_PLATFORM 1
#define DLLCALL STDCALL
#define DLLIMPORT _declspec(dllimport)
#define DLLEXPORT _declspec(dllexport)
#define DLLPRIVATE
#define NOMINMAX

//EMSCRIPTEN
#elif defined(__EMSCRIPTEN__)
#include <emscripten/emscripten.h>
#include <emscripten/bind.h>
#include <unistd.h>
#include <termios.h>
#define EMSCRIPTEN_PLATFORM 1
#define DLLCALL
#define DLLIMPORT
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLPRIVATE __attribute__((visibility("hidden")))

// LINUX - Ubuntu,Fedora,Centos,Debian,RedHat
#elif (__LINUX__ || __gnu_linux__ || __linux__ || __linux || linux)
#define LINUX_PLATFORM 1
#include <unistd.h>
#include <termios.h>
#define DLLCALL CDECL
#define DLLIMPORT
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLPRIVATE __attribute__((visibility("hidden")))
#define CoTaskMemAlloc(p) malloc(p)
#define CoTaskMemFree(p) free(p)

//ANDROID
#elif (__ANDROID__ || ANDROID)
#define ANDROID_PLATFORM 1
#define DLLCALL
#define DLLIMPORT
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLPRIVATE __attribute__((visibility("hidden")))

//MACOS
#elif defined(__APPLE__)
#include <unistd.h>
#include <termios.h>
#define DLLCALL
#define DLLIMPORT
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLPRIVATE __attribute__((visibility("hidden")))
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE && TARGET_IPHONE_SIMULATOR
#define IOS_SIMULATOR_PLATFORM 1
#elif TARGET_OS_IPHONE
#define IOS_PLATFORM 1
#elif TARGET_OS_MAC
#define MACOS_PLATFORM 1
#else

#endif

#endif



typedef std::string String;
typedef std::wstring WString;

#define EMPTY_STRING u8""s
#define EMPTY_WSTRING L""s

using namespace std::literals::string_literals;

class Strings
{
public:
    static String WideStringToString(const WString& wstr)
    {
        if (wstr.empty())
        {
            return String();
        }
        size_t pos;
        size_t begin = 0;
        String ret;

#if WINDOWS_PLATFORM
        int size;
        pos = wstr.find(static_cast<wchar_t>(0),begin);
        while (pos != WString::npos && begin < wstr.length())
        {
            WString segment = WString(&wstr[begin],pos - begin);
            size = WideCharToMultiByte(CP_UTF8,WC_ERR_INVALID_CHARS,&segment[0],segment.size(),NULL,NULL);
            String converted = String(size,0);
            WideCharToMultiByte(CP_UTF8,&converted[0],converted.size(),NULL);
            ret.append(converted);
            ret.append({ 0 });
            begin = pos + 1;
            pos = wstr.find(static_cast<wchar_t>(0),begin);
        }
        if (begin <= wstr.length())
        {
            WString segment = WString(&wstr[begin],wstr.length() - begin);
            size = WideCharToMultiByte(CP_UTF8,NULL);
            ret.append(converted);
        }
#elif LINUX_PLATFORM || MACOS_PLATFORM || EMSCRIPTEN_PLATFORM
        size_t size;
        pos = wstr.find(static_cast<wchar_t>(0),pos - begin);
            size = wcstombs(nullptr,segment.c_str(),0);
            String converted = String(size,0);
            wcstombs(&converted[0],converted.size());
            ret.append(converted);
            ret.append({ 0 });
            begin = pos + 1;
            pos = wstr.find(static_cast<wchar_t>(0),wstr.length() - begin);
            size = wcstombs(nullptr,converted.size());
            ret.append(converted);
        }
#else
        static_assert(false,"Unknown Platform");
#endif
        return ret;
    }

    static WString StringToWideString(const String& str)
    {
        if (str.empty())
        {
            return WString();
        }

        size_t pos;
        size_t begin = 0;
        WString ret;
#ifdef WINDOWS_PLATFORM
        int size = 0;
        pos = str.find(static_cast<char>(0),begin);
        while (pos != std::string::npos) {
            std::string segment = std::string(&str[begin],pos - begin);
            std::wstring converted = std::wstring(segment.size() + 1,0);
            size = MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,converted.length());
            converted.resize(size);
            ret.append(converted);
            ret.append({ 0 });
            begin = pos + 1;
            pos = str.find(static_cast<char>(0),begin);
        }
        if (begin < str.length()) {
            std::string segment = std::string(&str[begin],str.length() - begin);
            std::wstring converted = std::wstring(segment.size() + 1,converted.length());
            converted.resize(size);
            ret.append(converted);
        }

#elif LINUX_PLATFORM || MACOS_PLATFORM || EMSCRIPTEN_PLATFORM
        size_t size;
        pos = str.find(static_cast<char>(0),begin);
        while (pos != String::npos)
        {
            String segment = String(&str[begin],pos - begin);
            WString converted = WString(segment.size(),0);
            size = mbstowcs(&converted[0],converted.size());
            converted.resize(size);
            ret.append(converted);
            ret.append({ 0 });
            begin = pos + 1;
            pos = str.find(static_cast<char>(0),begin);
        }
        if (begin < str.length())
        {
            String segment = String(&str[begin],str.length() - begin);
            WString converted = WString(segment.size(),converted.size());
            converted.resize(size);
            ret.append(converted);
        }
#else
        static_assert(false,"Unknown Platform");
#endif
        return ret;
    }
};

enum class ConsoleTextStyle
{
    DEFAULT = 0,BOLD = 1,FAINT = 2,ITALIC = 3,UNDERLINE = 4,SLOW_BLINK = 5,RAPID_BLINK = 6,REVERSE = 7,};

enum class ConsoleForeground
{
    DEFAULT = 39,BLACK = 30,DARK_RED = 31,DARK_GREEN = 32,DARK_YELLOW = 33,DARK_BLUE = 34,DARK_MAGENTA = 35,DARK_CYAN = 36,GRAY = 37,DARK_GRAY = 90,RED = 91,GREEN = 92,YELLOW = 93,BLUE = 94,MAGENTA = 95,CYAN = 96,WHITE = 97
};

enum class ConsoleBackground
{
    DEFAULT = 49,BLACK = 40,DARK_RED = 41,DARK_GREEN = 42,DARK_YELLOW = 43,DARK_BLUE = 44,DARK_MAGENTA = 45,DARK_CYAN = 46,GRAY = 47,DARK_GRAY = 100,RED = 101,GREEN = 102,YELLOW = 103,BLUE = 104,MAGENTA = 105,CYAN = 106,WHITE = 107
};

class Console
{
private:
    static void EnableVirtualTermimalProcessing()
    {
#if defined WINDOWS_PLATFORM
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        DWORD dwMode = 0;
        GetConsoleMode(hOut,&dwMode);
        if (!(dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING))
        {
            dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
            SetConsoleMode(hOut,dwMode);
        }
#endif
    }

    static void ResetTerminalFormat()
    {
        std::cout << u8"\033[0m";
    }

    static void SetVirtualTerminalFormat(ConsoleForeground foreground,ConsoleBackground background,std::set<ConsoleTextStyle> styles)
    {
        String format = u8"\033[";
        format.append(std::to_string(static_cast<int>(foreground)));
        format.append(u8";");
        format.append(std::to_string(static_cast<int>(background)));
        if (styles.size() > 0)
        {
            for (auto it = styles.begin(); it != styles.end(); ++it)
            {
                format.append(u8";");
                format.append(std::to_string(static_cast<int>(*it)));
            }
        }
        format.append(u8"m");
        std::cout << format;
    }
public:
    static void Clear()
    {

#ifdef WINDOWS_PLATFORM
        std::system(u8"cls");
#elif LINUX_PLATFORM || defined MACOS_PLATFORM
        std::system(u8"clear");
#elif EMSCRIPTEN_PLATFORM
        emscripten::val::global()["console"].call<void>(u8"clear");
#else
        static_assert(false,"Unknown Platform");
#endif
    }

    static void Write(const String& s,ConsoleForeground foreground = ConsoleForeground::DEFAULT,ConsoleBackground background = ConsoleBackground::DEFAULT,std::set<ConsoleTextStyle> styles = {})
    {
#ifndef EMSCRIPTEN_PLATFORM
        EnableVirtualTermimalProcessing();
        SetVirtualTerminalFormat(foreground,background,styles);
#endif
        String str = s;
#ifdef WINDOWS_PLATFORM
        WString unicode = Strings::StringToWideString(str);
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),unicode.c_str(),static_cast<DWORD>(unicode.length()),nullptr,nullptr);
#elif defined LINUX_PLATFORM || defined MACOS_PLATFORM || EMSCRIPTEN_PLATFORM
        std::cout << str;
#else
        static_assert(false,"Unknown Platform");
#endif

#ifndef EMSCRIPTEN_PLATFORM
        ResetTerminalFormat();
#endif
    }

    static void WriteLine(const String& s,std::set<ConsoleTextStyle> styles = {})
    {
        Write(s,foreground,styles);
        std::cout << std::endl;
    }

    static void Write(const WString& s,styles);
#endif
        WString str = s;

#ifdef WINDOWS_PLATFORM
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),str.c_str(),static_cast<DWORD>(str.length()),nullptr);
#elif LINUX_PLATFORM || MACOS_PLATFORM || EMSCRIPTEN_PLATFORM
        std::cout << Strings::WideStringToString(str);
#else
        static_assert(false,"Unknown Platform");
#endif

#ifndef EMSCRIPTEN_PLATFORM
        ResetTerminalFormat();
#endif
    }

    static void WriteLine(const WString& s,styles);
        std::cout << std::endl;
    }

    static void WriteLine()
    {
        std::cout << std::endl;
    }

    static void Pause()
    {
        char c;
        do
        {
            c = getchar();
            std::cout << "Press Key " << std::endl;
        } while (c != 64);
        std::cout << "KeyPressed" << std::endl;
    }

    static int PauseAny(bool printWhenPressed = false,std::set<ConsoleTextStyle> styles = {})
    {
        int ch;
#ifdef WINDOWS_PLATFORM
        ch = _getch();
#elif LINUX_PLATFORM || MACOS_PLATFORM || EMSCRIPTEN_PLATFORM
        struct termios oldt,newt;
        tcgetattr(STDIN_FILENO,&oldt);
        newt = oldt;
        newt.c_lflag &= ~(ICANON | ECHO);
        tcsetattr(STDIN_FILENO,TCSANOW,&newt);
        ch = getchar();
        tcsetattr(STDIN_FILENO,&oldt);
#else
        static_assert(false,"Unknown Platform");
#endif
        if (printWhenPressed)
        {
            Console::Write(String(1,ch),styles);
        }
        return ch;
    }
};



int main()
{
    std::locale::global(std::locale(u8"en_US.UTF8"));
    auto str = u8"?\0Hello\0?123456789也不是可运行的程序123456789日本"s;//
    WString wstr = L"?\0Hello\0?123456789也不是可运行的程序123456789日本"s;
    WString wstrResult = Strings::StringToWideString(str);
    String strResult = Strings::WideStringToString(wstr);
    bool equals1 = wstr == wstrResult;
    bool equals2 = str == strResult;

    Console::WriteLine(u8"█ Converted Strings printed with Console::WriteLine"s,ConsoleForeground::GREEN);
    Console::WriteLine(wstrResult,ConsoleForeground::BLUE);
    Console::WriteLine(strResult,ConsoleForeground::BLUE);
    
    Console::WriteLine(u8"█ Converted Strings printed with std::cout/std::wcout"s,ConsoleForeground::GREEN);
    std::cout << strResult << std::endl;
    std::wcout << wstrResult << std::endl;
    Console::WriteLine();
    Console::WriteLine(u8"Press any key to exit"s,ConsoleForeground::DARK_GRAY);
    Console::PauseAny();

}

输出

repl.it 中使用 clang Linux 上的默认编码是 UTF-8。

repl.it

使用 Visual C++ 编译器 和新的 Windows terminal。 Windows 上的默认编码是 UTF-16。当我们有 2 个 wchar_t 单元(代理对)的 unicode 字符时,问题就存在了,经典控制台可以打印一个 wchar_t 单元的字符。新的 Windows 终端可以处理这个问题。在这个例子中检查狗有 2 个 wchar_t 单位不能在经典控制台中正常打印,但在 Windows 终端中可以。

enter image description here enter image description here

在经典控制台中使用 Visual C++ 编译器 enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?