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

How do I use subscript digits in my C++ program?

本文关键字:下标 数字 C++ 程序      更新时间:2023-10-16

我目前正在编写一个C++程序,该程序涉及数学。因此,我试图将某些对象表示为在其类的 wstring 成员变量中具有下标数字。但是,尝试以任何身份存储这些字符会强制将它们转换为非下标对应字符。相比之下,粘贴在代码中的字符的直接使用将根据需要进行维护。以下是我尝试的几个案例:

setlocale(LC_ALL, "");
wchar_t txt = L'u2080';
wcout << txt << endl;
myfile << txt << endl;

这会将"0"输出到文件和控制台。

setlocale(LC_ALL, "");
wcout << L"x₀₁" << endl;
myfile << L"x₀₁" << endl;

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

setlocale(LC_ALL, "");
wcout << "x₀₁" << endl;
myfile << "x₀₁" << endl;

这会将"xâ'?"输出到控制台,如果可能的话,我想避免这样做,并将"x₀₁"输出到我想要的文件。理想的程序状态是属性同时输出到文件和控制台的状态,但如果这是不可能的,则最好将非下标字符打印到控制台。

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

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

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

输出:

X₀ X₁ X₂ X₃ X₄ X₅ X₆ X₇ X₈ X₉
X⁰ X¹ X² X³ X⁴ X⁵ X⁶ X⁷ X⁸ X⁹

更方便的方法可能是直接创建wstring。在这里wsupwsub采用wstring并返回转换后的wstring。他们无法处理的角色保持不变。

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

输出:

superscript:   ⁰¹²³⁴⁵⁶⁷⁸⁹ ⁺⁻⁼⁽⁾ ⁿⁱ
subscript:     ₀₁₂₃₄₅₆₇₈₉ ₊₋₌₍₎ ₐₑₒₓₔ ₕₖₗₘₙₚₛₜ
an expression: x⁽ⁿ⁻¹⁾

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

您应该配置控制台和您打开文件的程序,它应该将您的字符串解释为其编码(例如 utf32(。

例如,在Windows中,您可以使用SetConsoleOutputCP函数设置控制台代码页。 若要查看文件不同的编码,可以将文件添加到 VS 解决方案,右键单击/打开方式/源代码(文本(与编码,然后选择编码。