C ++西班牙语问号

时间:2013-07-23 11:17:38

标签: c++ windows character-encoding

我开始用C ++开发,我正在开发一个简单的计算器,当我的程序向用户询问是否要退出时,字符'¿'不会出现(西班牙语中的问题介于'¿'之间)和'?')

有人可以帮助我吗?

PD:问题只发生在Windows中,而不是Linux中

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

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

6 个答案:

答案 0 :(得分:3)

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

根本问题不在于控制台中不存在¿,而是控制台和C ++文本编辑器对该字符的含义存在分歧。对于除英语所需的字符之外的许多字符,两者使用不同的字符代码。字符代码32-126(字母,数字,标点符号和括号)通用相同。但是,字符代码128到255,从西班牙语的角度来看,包括所有重音字符,“u with diaeresis”(例如“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 char可以提供帮助,但不多。

第二种方法是使用诸如CharToOemA之类的Windows功能。例如 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 我必须警告说,这个片段包含许多可以轻易绊倒初学者的细微之处。你必须确保文本的来源是一个char数组;如果您使用字符指针,sizeof将无法正常工作,您必须使用strlen(source)+1。对于源代码,我使用了初始化为文字的char数组的自然选项,但是你不能为目标执行此操作,因为这样的数组的内容是只读的。如果您使用的是新的char数组或未初始化为文字的数组,则可以对源和目标使用相同的char数组。这个例子感觉非常像C。

答案 1 :(得分:1)

您可以使用_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回答。

答案 2 :(得分:1)

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

<强> 1。将代码页更改为UTF-8

只需在cmd中调用以下命令即可完成此操作:

chcp 65001

<强> 2。确保使用的字体包含要显示的字符

Lucidia控制台应该这样做,因为它支持¿(以及WGL4中包含的其他字符)。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

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