简体   繁体   English

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

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

I'm currently writing a C++ program that's rather math-involved.我目前正在编写一个涉及数学的 C++ 程序。 As such, I'm trying to denote some objects as having subscript numbers in a wstring member variable of their class.因此,我试图将某些对象表示为在其类的 wstring 成员变量中具有下标数字。 However, attempts at storing these characters in any capacity forces them into their non-subscript counterparts.然而,以任何容量存储这些字符的尝试都会迫使它们成为非下标对应物。 By contrast, direct uses of the characters that are pasted in the code are maintained as desired.相比之下,粘贴在代码中的字符的直接使用可以根据需要保留。 Here are several cases I experimented with:以下是我试验过的几种情况:

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

This outputs "0" to both the file and console.这将向文件和控制台输出“0”。

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

This outputs "x01" to both the file and console.这会将“x01”输出到文件和控制台。

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

This outputs "xâ'?â'?"这输出“xâ'?â'?” to the console, which I'd like to avoid if possible, and "x₀₁" to the file which is what I want.到控制台,如果可能的话,我想避免这种情况,并且“x₀₁”到我想要的文件。 An ideal program state would be one that property outputs to both the file and to console, but if that's not possible, then printing non-subscript characters to the console is preferable.理想的程序状态是将属性输出到文件和控制台的状态,但如果不可能,那么最好将非下标字符打印到控制台。

My code intends to convert ints into their corresponding subscripts.我的代码打算将整数转换为其相应的下标。 How do I manipulate these characters as smoothly as possible without them getting converted back?我如何尽可能顺利地操纵这些字符而不将它们转换回来? I suspect that character encoding plays a part, but I do not know how to incorporate Unicode encoding into my program.我怀疑字符编码起了一定作用,但我不知道如何将 Unicode 编码合并到我的程序中。

I find these things tricky and I'm never sure if it works for everyone on every Windows version and locale, but this does the trick for me:我发现这些事情很棘手,我不确定它是否适用于每个 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';    
}

Output:输出:

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

A more convenient way may be to create wstring s directly.更方便的方法可能是直接创建wstring Here wsup and wsub takes a wstring and returns a converted wstring .这里wsupwsub接受一个wstring并返回一个转换后的wstring Characters they can't handle are left unchanged.他们无法处理的角色保持不变。

#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';
}

Output:输出:

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

My console didn't manage to display the subscript versions of hklmnpst - but apparently the transformation was correct because it shows up here ok after copy/pasting.我的控制台无法显示hklmnpst的下标版本 - 但显然转换是正确的,因为它在复制/粘贴后可以正常显示。

You should configure console and the program you open the file that it should interpret your string as its encoding (eg. utf32).您应该配置控制台和打开文件的程序,它应该将您的字符串解释为它的编码(例如 utf32)。

for example in windows you can set your console code page with SetConsoleOutputCP function.例如在 Windows 中,您可以使用 SetConsoleOutputCP 函数设置控制台代码页。 to view file different encoding you can add your file to vs solution, right click/open with / source code (text) with encoding than select your encoding.要查看文件不同的编码,您可以将文件添加到 vs 解决方案,右键单击/打开带有编码的 / 源代码(文本)而不是选择您的编码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM