如何在 C++ 程序中使用下标数字?

Mic*_*ger 6 c++ unicode

我目前正在编写一个涉及数学的 C++ 程序。因此,我试图将某些对象表示为在其类的 wstring 成员变量中具有下标数字。然而,以任何容量存储这些字符的尝试都会迫使它们成为非下标对应物。相比之下,粘贴在代码中的字符的直接使用可以根据需要保留。以下是我试验过的几种情况:

setlocale(LC_ALL, "");
wchar_t txt = L'\u2080';
wcout << txt << endl;
myfile << txt << endl;
Run Code Online (Sandbox Code Playgroud)

这将向文件和控制台输出“0”。

setlocale(LC_ALL, "");
wcout << L"x??" << endl;
myfile << L"x??" << endl;
Run Code Online (Sandbox Code Playgroud)

这会将“x01”输出到文件和控制台。

setlocale(LC_ALL, "");
wcout << "x??" << endl;
myfile << "x??" << endl;
Run Code Online (Sandbox Code Playgroud)

这输出“xâ'?â'?” 到控制台,如果可能的话我想避免,还有“x??” 到我想要的文件。理想的程序状态是将属性输出到文件和控制台的状态,但如果不可能,那么最好将非下标字符打印到控制台。

我的代码打算将整数转换为其相应的下标。我如何尽可能顺利地操纵这些字符而不将它们转换回来?我怀疑字符编码起了一定作用,但我不知道如何将 Unicode 编码合并到我的程序中。

Ted*_*gmo 2

我发现这些事情很棘手,我不确定它是否适用于每个 Windows 版本和区域设置的每个人,但这对我来说很有效:

\n\n
#include <Windows.h>\n#include <io.h>     // _setmode\n#include <fcntl.h>  // _O_U16TEXT\n\n#include <clocale>  // std::setlocale \n#include <iostream>\n\n// Unicode UTF-16, little endian byte order (BMP of ISO 10646)\nconstexpr char CP_UTF_16LE[] = ".1200";\n\nconstexpr wchar_t superscript(int v) {\n    constexpr wchar_t offset = 0x2070;       // superscript zero as offset\n    if (v == 1) return 0x00B9;               // special case\n    if (v == 2 || v == 3) return 0x00B0 + v; // special case 2\n    return offset + v;\n}\n\nconstexpr wchar_t subscript(int v) {\n    constexpr wchar_t offset = 0x2080; // subscript zero as offset\n    return offset + v;\n}\n\nint main() {\n    // set these before doing any other output:\n    setlocale(LC_ALL, CP_UTF_16LE);\n    _setmode(_fileno(stdout), _O_U16TEXT);\n\n    // subscript\n    for (int i = 0; i < 10; ++i)\n        std::wcout << L\'X\' << subscript(i) << L\' \';\n    std::wcout << L\'\\n\';\n\n    // superscript\n    for (int i = 0; i < 10; ++i)\n        std::wcout << L\'X\' << superscript(i) << L\' \';\n    std::wcout << L\'\\n\';    \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n
X\xe2\x82\x80 X\xe2\x82\x81 X\xe2\x82\x82 X\xe2\x82\x83 X\xe2\x82\x84 X\xe2\x82\x85 X\xe2\x82\x86 X\xe2\x82\x87 X\xe2\x82\x88 X\xe2\x82\x89\nX\xe2\x81\xb0 X\xc2\xb9 X\xc2\xb2 X\xc2\xb3 X\xe2\x81\xb4 X\xe2\x81\xb5 X\xe2\x81\xb6 X\xe2\x81\xb7 X\xe2\x81\xb8 X\xe2\x81\xb9\n
Run Code Online (Sandbox Code Playgroud)\n\n

更方便的方法可能是wstring直接创建 s。这里wsupandwsub接受 awstring并返回转换后的wstring。他们无法处理的角色将保持不变。

\n\n
#include <Windows.h>\n#include <io.h>      // _setmode\n#include <fcntl.h>   // _O_U16TEXT\n\n#include <algorithm> // std::transform\n#include <clocale>   // std::setlocale \n#include <iostream>\n\n// Unicode UTF-16, little endian byte order (BMP of ISO 10646)\nconstexpr char CP_UTF_16LE[] = ".1200";\n\nstd::wstring wsup(const std::wstring& in) {\n    std::wstring rv = in;\n\n    std::transform(rv.begin(), rv.end(), rv.begin(),\n        [](wchar_t ch) -> wchar_t {\n            // 1, 2 and 3 can be put in any order you like\n            // as long as you keep them in the top section\n            if (ch == L\'1\') return 0x00B9;\n            if (ch == L\'2\') return 0x00B2;\n            if (ch == L\'3\') return 0x00B3;\n\n            // ...but this must be here in the middle:\n            if (ch >= \'0\' && ch <= \'9\') return 0x2070 + (ch - L\'0\');\n\n            // put the below in any order you like,\n            // in the bottom section\n            if (ch == L\'i\') return 0x2071;\n            if (ch == L\'+\') return 0x207A;\n            if (ch == L\'-\') return 0x207B;\n            if (ch == L\'=\') return 0x207C;\n            if (ch == L\'(\') return 0x207D;\n            if (ch == L\')\') return 0x207E;\n            if (ch == L\'n\') return 0x207F;\n\n            return ch; // no change\n        });\n    return rv;\n}\n\nstd::wstring wsub(const std::wstring& in) {\n    std::wstring rv = in;\n\n    std::transform(rv.begin(), rv.end(), rv.begin(),\n        [](wchar_t ch) -> wchar_t {\n            if (ch >= \'0\' && ch <= \'9\') return 0x2080 + (ch - L\'0\');\n            if (ch == L\'+\') return 0x208A;\n            if (ch == L\'-\') return 0x208B;\n            if (ch == L\'=\') return 0x208C;\n            if (ch == L\'(\') return 0x208D;\n            if (ch == L\')\') return 0x208E;\n            if (ch == L\'a\') return 0x2090;\n            if (ch == L\'e\') return 0x2091;\n            if (ch == L\'o\') return 0x2092;\n            if (ch == L\'x\') return 0x2093;\n            if (ch == 0x0259) return 0x2094; // small letter schwa: \xc9\x99\n            if (ch == L\'h\') return 0x2095;\n            if (ch >= \'k\' && ch <= \'n\') return 0x2096 + (ch - \'k\');\n            if (ch == L\'p\') return 0x209A;\n            if (ch == L\'s\') return 0x209B;\n            if (ch == L\'t\') return 0x209C;\n\n            return ch; // no change\n        });\n    return rv;\n}\n\nint main() {\n    std::setlocale(LC_ALL, CP_UTF_16LE);\n    if (_setmode(_fileno(stdout), _O_U16TEXT) == -1) return 1;\n\n    auto pstr = wsup(L"0123456789 +-=() ni");\n    auto bstr = wsub(L"0123456789 +-=() aeox\xc9\x99 hklmnpst");\n\n    std::wcout << L"superscript:   " << pstr << L\'\\n\';\n    std::wcout << L"subscript:     " << bstr << L\'\\n\';\n\n    std::wcout << L"an expression: x" << wsup(L"(n-1)") << L\'\\n\';\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n
superscript:   \xe2\x81\xb0\xc2\xb9\xc2\xb2\xc2\xb3\xe2\x81\xb4\xe2\x81\xb5\xe2\x81\xb6\xe2\x81\xb7\xe2\x81\xb8\xe2\x81\xb9 \xe2\x81\xba\xe2\x81\xbb\xe2\x81\xbc\xe2\x81\xbd\xe2\x81\xbe \xe2\x81\xbf\xe2\x81\xb1\nsubscript:     \xe2\x82\x80\xe2\x82\x81\xe2\x82\x82\xe2\x82\x83\xe2\x82\x84\xe2\x82\x85\xe2\x82\x86\xe2\x82\x87\xe2\x82\x88\xe2\x82\x89 \xe2\x82\x8a\xe2\x82\x8b\xe2\x82\x8c\xe2\x82\x8d\xe2\x82\x8e \xe2\x82\x90\xe2\x82\x91\xe2\x82\x92\xe2\x82\x93\xe2\x82\x94 \xe2\x82\x95\xe2\x82\x96\xe2\x82\x97\xe2\x82\x98\xe2\x82\x99\xe2\x82\x9a\xe2\x82\x9b\xe2\x82\x9c\nan expression: x\xe2\x81\xbd\xe2\x81\xbf\xe2\x81\xbb\xc2\xb9\xe2\x81\xbe\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的控制台无法显示hklmnpst- 的下标版本,但显然转换是正确的,因为复制/粘贴后它可以正常显示在此处。

\n