如何读取 C++ 中的重音字符并将它们与 isalnum 一起使用?
How can I read accented characters in C++ and use them with isalnum?
我正在用法语编程,因此,我需要使用重音字符。我可以使用输出它们
#include <locale>
和 setlocale(LC_ALL, "")
,但我读重音字符时似乎有问题。这是我用来说明问题的简单示例:
#include <locale>
#include <iostream>
using namespace std;
const string SymbolsAllowed = "+-*/%";
int main()
{
setlocale(LC_ALL, ""); // makes accents printable
// Traduction : Please write a string with accented characters
// 'é' is shown correctly :
cout << "Veuillez écrire du texte accentué : ";
string accentedString;
getline(cin, accentedString);
// Accented char are not shown correctly :
cout << "Accented string written : " << accentedString << endl;
for (unsigned int i = 0; i < accentedString.length(); ++i)
{
char currentChar = accentedString.at(i);
// The program crashes while testing if currentChar is alphanumeric.
// (error image below) :
if (!isalnum(currentChar) && !strchr(SymbolsAllowed.c_str(), currentChar))
{
cout << endl << "Character not allowed : " << currentChar << endl;
system("pause");
return 1;
}
}
cout << endl << "No unauthorized characters were written." << endl;
system("pause");
return 0;
}
这是程序崩溃前的输出示例:
Veuillez écrire du texte accentué : éèàìù
Accented string written : ʾS.?—
我注意到 Visual Studio 的调试器显示我编写的内容与它输出的内容不同:
[0] -126 '‚' char
[1] -118 'Š' char
[2] -123 '…' char
[3] -115 '' char
[4] -105 '—' char
显示的错误似乎表明 只能使用 -1 到 255 之间的字符 但是,根据 ASCII table 我使用的重音字符的值在上面的例子中不要超过这个限制。
这是弹出的错误对话框图片:Error message: Expression: c >= -1 && c <= 255
有人可以告诉我我做错了什么或者给我一个解决方案吗?先感谢您。 :)
char
在您的系统上(实际上,在许多系统上)是有符号类型,因此它的值范围是 -128 到 127。代码在 128 到 255 之间的字符看起来像如果它们存储在 char
中,则为负数,这实际上是您的调试器告诉您的内容:
[0] -126 '‚' char
那是-126,不是126。换句话说,130或0x8C。
isalnum
和朋友们将 int
作为参数,它(如错误消息所示)被限制为值 EOF
(-1您的系统)和范围 0-255。 -126 不在此范围内。因此错误。您可以转换为 unsigned char
,或者(可能更好,如果它适用于 Windows),使用两个参数 std::isalnum
in <locale>
出于我完全无法理解的原因,Windows 似乎在 CP-437 but processing output in CP-1252 中提供控制台输入。这两个代码页的高半部分完全不同。因此,当您键入 é
时,它会作为 130 (0xC2) 从 CP-437 发送到您的程序,但是当您将相同的字符发送回控制台时,它会根据 CP-1252 作为(低) 打开单引号 ‚
(看起来很像逗号,但实际上不是)。所以那是行不通的。您需要让输入和输出位于同一代码页上。
我对Windows的了解不多,不过你可以在MS docs中找到一些有用的信息。该页面包含指向设置输入和输出代码页的 Windows 特定函数的链接。
有趣的是,您程序源代码中的重音字符似乎是 CP-1252,因为它们打印正确。如果您决定放弃代码页 1252——例如,通过采用 Unicode——您也必须修复您的源代码。
使用 is*
和 to*
函数,您确实需要在将输入传递给函数之前将其转换为 unsigned char
:
if (!isalnum((unsigned char)currentChar) && !strchr(SymbolsAllowed.c_str(), currentChar)) {
当您使用它时,我建议您也不要使用 strchr
,而改用这样的方式:
std::string SymbolsAllowed = "+-*/%";
if (... && SymbolsAllowed.find(currentChar) == std::string::npos)
当您使用它时,您可能应该忘记您甚至 听说过 exit
函数。你不应该在 C++ 中使用它。在这种情况下(从 main
退出)你应该 return
。否则,抛出一个异常(如果你想退出程序,从那里捕获 main
和 return 中的异常)。
如果我写这篇文章,我的工作总体上会有所不同。 std::string
已经有一个函数可以完成你的循环试图完成的大部分工作,所以我会设置 symbolsAllowed
来包含 all 你想要的符号允许,然后搜索它不包含的任何内容:
// Add all the authorized characters to the string:
for (unsigned char a = 0; a < std::numeric_limits<unsigned char>::max(); a++)
if (isalnum(a) || isspace(a)) // you probably want to allow spaces?
symbolsAllowed += a;
// ...
auto pos = accentedString.find_first_not_of(symbolsAllowed);
if (pos != std::string::npos) {
std::cout << "Character not allowed: " << accentedString[pos];
return 1;
}
我正在用法语编程,因此,我需要使用重音字符。我可以使用输出它们
#include <locale>
和 setlocale(LC_ALL, "")
,但我读重音字符时似乎有问题。这是我用来说明问题的简单示例:
#include <locale>
#include <iostream>
using namespace std;
const string SymbolsAllowed = "+-*/%";
int main()
{
setlocale(LC_ALL, ""); // makes accents printable
// Traduction : Please write a string with accented characters
// 'é' is shown correctly :
cout << "Veuillez écrire du texte accentué : ";
string accentedString;
getline(cin, accentedString);
// Accented char are not shown correctly :
cout << "Accented string written : " << accentedString << endl;
for (unsigned int i = 0; i < accentedString.length(); ++i)
{
char currentChar = accentedString.at(i);
// The program crashes while testing if currentChar is alphanumeric.
// (error image below) :
if (!isalnum(currentChar) && !strchr(SymbolsAllowed.c_str(), currentChar))
{
cout << endl << "Character not allowed : " << currentChar << endl;
system("pause");
return 1;
}
}
cout << endl << "No unauthorized characters were written." << endl;
system("pause");
return 0;
}
这是程序崩溃前的输出示例:
Veuillez écrire du texte accentué : éèàìù
Accented string written : ʾS.?—
我注意到 Visual Studio 的调试器显示我编写的内容与它输出的内容不同:
[0] -126 '‚' char
[1] -118 'Š' char
[2] -123 '…' char
[3] -115 '' char
[4] -105 '—' char
显示的错误似乎表明 只能使用 -1 到 255 之间的字符 但是,根据 ASCII table 我使用的重音字符的值在上面的例子中不要超过这个限制。
这是弹出的错误对话框图片:Error message: Expression: c >= -1 && c <= 255
有人可以告诉我我做错了什么或者给我一个解决方案吗?先感谢您。 :)
char
在您的系统上(实际上,在许多系统上)是有符号类型,因此它的值范围是 -128 到 127。代码在 128 到 255 之间的字符看起来像如果它们存储在char
中,则为负数,这实际上是您的调试器告诉您的内容:[0] -126 '‚' char
那是-126,不是126。换句话说,130或0x8C。
isalnum
和朋友们将int
作为参数,它(如错误消息所示)被限制为值EOF
(-1您的系统)和范围 0-255。 -126 不在此范围内。因此错误。您可以转换为unsigned char
,或者(可能更好,如果它适用于 Windows),使用两个参数std::isalnum
in<locale>
出于我完全无法理解的原因,Windows 似乎在 CP-437 but processing output in CP-1252 中提供控制台输入。这两个代码页的高半部分完全不同。因此,当您键入
é
时,它会作为 130 (0xC2) 从 CP-437 发送到您的程序,但是当您将相同的字符发送回控制台时,它会根据 CP-1252 作为(低) 打开单引号‚
(看起来很像逗号,但实际上不是)。所以那是行不通的。您需要让输入和输出位于同一代码页上。我对Windows的了解不多,不过你可以在MS docs中找到一些有用的信息。该页面包含指向设置输入和输出代码页的 Windows 特定函数的链接。
有趣的是,您程序源代码中的重音字符似乎是 CP-1252,因为它们打印正确。如果您决定放弃代码页 1252——例如,通过采用 Unicode——您也必须修复您的源代码。
使用 is*
和 to*
函数,您确实需要在将输入传递给函数之前将其转换为 unsigned char
:
if (!isalnum((unsigned char)currentChar) && !strchr(SymbolsAllowed.c_str(), currentChar)) {
当您使用它时,我建议您也不要使用 strchr
,而改用这样的方式:
std::string SymbolsAllowed = "+-*/%";
if (... && SymbolsAllowed.find(currentChar) == std::string::npos)
当您使用它时,您可能应该忘记您甚至 听说过 exit
函数。你不应该在 C++ 中使用它。在这种情况下(从 main
退出)你应该 return
。否则,抛出一个异常(如果你想退出程序,从那里捕获 main
和 return 中的异常)。
如果我写这篇文章,我的工作总体上会有所不同。 std::string
已经有一个函数可以完成你的循环试图完成的大部分工作,所以我会设置 symbolsAllowed
来包含 all 你想要的符号允许,然后搜索它不包含的任何内容:
// Add all the authorized characters to the string:
for (unsigned char a = 0; a < std::numeric_limits<unsigned char>::max(); a++)
if (isalnum(a) || isspace(a)) // you probably want to allow spaces?
symbolsAllowed += a;
// ...
auto pos = accentedString.find_first_not_of(symbolsAllowed);
if (pos != std::string::npos) {
std::cout << "Character not allowed: " << accentedString[pos];
return 1;
}