【问题标题】:C++ spanish question markC++ 西班牙语问号
【发布时间】:2013-07-22 10:24:00
【问题描述】:

我开始用 C++ 开发,我正在控制台中开发一个简单的计算器,当我的程序询问用户是否要退出时,字符“¿”没有出现(西班牙语中的问题在“¿”之间和'?')

有人可以帮我吗?

PD:该问题仅发生在 Windows 中,而不发生在 Linux 中

编辑:这是输出代码的代码:

cout << '¿' <<"Desea salir (S/N)? " ;

【问题讨论】:

  • 请贴出输出字符的代码。
  • 大胆猜测:无论您输出什么都与您使用的任何终端仿真器不兼容。
  • 同意,这可能来自终端模拟器的编码。如果要显示“¿”等 UTF8 字符,请考虑在 Windows 下使用 Cygwin。
  • 更重要的是,a) 您使用的是运行英文版还是西班牙文版 Windows 的计算机?两者都需要支持吗?

标签: c++ windows character-encoding


【解决方案1】:

此字符根本不包含在基本 ascii 中。尝试使用 wstring http://www.cplusplus.com/reference/string/wstring/

【讨论】:

  • hist 终端仿真器的编码可以是utf8,在这种情况下std::string 和std::cout 可能是正确的。但我们不知道他做什么以及他是如何做到的......
  • 完全正常的字符范围是 -128 到 127。
  • 更正:Windows-1252 中的 #191 和 OEM(437,又名 DOS/US)中的 #167。
  • @Dzia,这是 C 的 char 类型的工件,默认情况下是无符号的,除非你在做算术,否则无关紧要。当涉及到代码到字符的转换时,重要的是位模式以及主机将如何解释它。如果您更愿意说在 Windows 1252 中字符 '¿' 是 -65,那很好。仍然是 10111111。当然,该映射是实现定义的。
【解决方案2】:

正如您在Ascii table 中看到的,符号 ¿ 的代码为 168。您可以在输出流中使用 \ddd 来打印一些特殊字符。

【讨论】:

  • 美国信息交换标准代码 (ASCII) 的代码为 0 到 127。引用的 ¿ 列在 扩展 ASCII 代码中。 扩展 ASCII 码有很多变体。
  • 我试过了,但有些页面说我的代码是 168 和其他 191
  • @Cako, 191 是你的 c++ 编辑器使用的代码。 168 是控制台使用的代码。您必须使用 168 才能在控制台上显示它。
【解决方案3】:

您可以使用_setmode 函数来做到这一点:

#include <iostream>
#include <string>

#if defined(WIN32) && !defined(UNIX)
# include <io.h>    // for _setmode()
# include <fcntl.h> // for _O_U16TEXT
#endif // WIN32 && !UNIX

int main()
{
#if defined(WIN32) && !defined(UNIX)
    _setmode(_fileno(stdout), _O_U16TEXT);
  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#endif // WIN32 && !UNIX

    std::wstring wstr = L"'¿' and '?'";

    std::wcout << L"WString : " << wstr << std::endl;
    system("pause");
    return 0;
}

要使用 iostream 库写入 UNICODE 字符(假设 LE 是 UTF-16 的标准 Windows 变体...),请使用 _O_U16TEXT 调用 _setmode(),然后使用 wcout。

但你不能再使用cout。它抛出一个断言。

查看this的答案。

【讨论】:

  • @Cako 如果它已经在 linux 上运行,而您只需在 windows 上修复它,请检查我的编辑。
  • 编译器说有错误:C:\Users\Carlos\Documents\cpp\Calculadora\main.cpp||In function 'int main()':| C:\Users\Carlos\Documents\cpp\Calculadora\main.cpp|33|错误:'_O_U16TEXT' 未在此范围内声明| ||=== 构建完成:1 个错误,0 个警告(0 分钟,0 秒)===|
【解决方案4】:

这是因为命令控制台默认不支持非 ASCII 字符(ASCII 主要有英文字符和少数重音字符)。要获得对其他字符类中字符的支持,请使用chcp 命令。请参阅它的文档here

在您的情况下,我认为您需要在运行程序之前在控制台中运行chcp 850

【讨论】:

    【解决方案5】:

    假设您正在使用对 std::cout 的简单调用,如果您将命令行设置为 Unicode 模式,您应该能够打印 Unicode 字符串:

    1.将代码页更改为 UTF-8

    您只需在 cmd 中调用以下命令即可:

    chcp 65001
    

    2。确保您使用的字体具有您要显示的字符

    Lucidia 控制台应该可以解决问题,因为它支持 ¿(以及 WGL4 中包含的其他字符)。

    【讨论】:

    • 是的,我的 Windows 7 是西班牙语
    • 请注意,将控制台代码页设置为 65001 (UTF-8) 会破坏许多控制台应用程序。您可以尝试使用chcp 1252。这只会破坏 一些 应用程序。
    【解决方案6】:

    有几种方法可以解决这个问题。

    根本问题不在于控制台中不存在¿,而是控制台和您的C++ 文本编辑器在该字符是什么上存在分歧。两者对许多字符使用不同的字符代码,超出了英语所需的字符代码。字符代码 32-126(字母、数字、标点和括号)普遍相同。但是,从西班牙语的角度来看,字符代码 128 到 255 包括所有重音字符,“带分音符号的 u”(例如“pingüino”)、Ñ 以及开头的 ¿ 和 ¡,取决于具体环境。

    为什么在字符代码上有如此不便的分歧是一个历史偶然,它本身很有趣,但超出了这个问题的范围。为简单起见:在 Windows 操作系统中,“控制台”(通常)使用 OEM Code Page 437 中描述的字符列表,而 C++ 编辑器等 Windows 应用程序(通常)使用 Windows-1252 Code Page

    对于这个问题没有可移植(通用)的解决方案,因为不同字符集的问题是特定于平台的问题。不幸的是,Windows 的独特之处在于编辑器和(控制台)输出使用不同的集合。

    第一个也是最简单的解决方案(适用于玩具程序)是从 OEM 437 代码页中查找您想要的字符代码,然后使用它。对于¿,这是#168(十六进制的0xa8,或八进制的\250)。您可以将字符代码嵌入到字符串中,以明确您要执行的操作,其中之一是:

    std::cout << ""\x0a8""Cu""\x0a0""l es el primer n""\x0a3""mero?\n"; // hex
    std::cout << "\250Cu\240l es el primer n\243mero?\n";  // octal
    

    输出:

    ¿Cuál es el primer número?
    

    请注意我是如何对 ú 和 á 做同样的事情的。不幸的是,像这样编写字符串很快就会变得笨拙。使用宏或const chars 会有所帮助,但作用不大。

    第二种选择是使用 Windows 函数,例如 CharToOemA。例如1

    #include <windows.h>
    ...
    ...
    char pregunta[] = "¿Cuál es el primer número\n";
    char *pregunta_oem  = new char[sizeof(pregunta)/sizeof(char)];
    CharToOemA(pregunta, pregunta_oem);
    std::cout << pregunta_oem;
    delete []pregunta_oem;
    

    对于更复杂的程序,我会将该模式包装到实用函数或类中。

    另一种方法是更改​​控制台的代码页,使其与您的 C++ 编辑器和 Windows 的其余部分一致。您可以通过 CHCP 控制台命令或通过 SetConsoleOutputCP() 函数执行此操作,但这不适用于控制台使用的默认“光栅字体”,因此您还必须更改字体。当字体设置为 Lucida Console 之类的 unicode 字体时,此方法有效:

    std::cout << "¿Cuál es el primer número?\n"; // ┐Cußl es el...
    UINT originalCP = GetConsoleOutputCP();
    SetConsoleOutputCP(1252);
    std::cout << "¿Cuál es el primer número?\n"; // ¿Cuál es el...
    SetConsoleOutputCP(originalCP);
    

    (我不知道您是否可以从程序本身更改字体;我必须查一下。从控制台执行此操作的标准方法是单击角落上的小图标,单击属性,字体选项卡,然后从列表中选择一种字体)。


    1 我必须警告说,这个 sn-p 包含许多可能很容易绊倒初学者的微妙之处。您必须确保文本的来源是 char 数组;如果您使用的是字符指针,sizeof 将无法正常工作,您必须使用strlen(source)+1。对于源,我使用了初始化为文字的 char 数组的自然选项,但您不能对目标执行此操作,因为此类数组的内容是只读的。如果您使用的是新的 char 数组或未初始化为文字的数组,则可以对源和目标使用相同的 char 数组。这个例子感觉很像 C。

    【讨论】:

      猜你喜欢
      • 2012-10-26
      • 2017-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多