尽管我的C ++经验大大减少,但我正在尝试帮助C ++程序员使他的库在Mac上运行。目前,问题似乎仅与语言环境/编码有关。
为了创建一个最小的工作示例,我测试了以下代码,该代码将一行UTF-8字符读取为一个宽字符串(wstring),然后遍历该字符串并打印每个字符。
虽然它在Linux盒子上可以正常工作,所有字符都打印在不同的行中,但是使用Mac盒子时,我得到的是每行打印每个字节(而不是每个字符)。
代码是:
#include <sstream>
#include <iostream>
#include <string>
#include <boost/locale.hpp>
using namespace std;
int main() {
std::ios_base::sync_with_stdio(false);
boost::locale::generator gen;
locale mylocale = gen("pt_PT.UTF-8");
locale::global(mylocale);
wstring userInput;
getline(wcin, userInput);
wcerr << "Size of string is " << userInput.length() << endl;
for (int i = 0; i < userInput.length(); ++i) {
wcerr << userInput.at(i) << endl;
}
return 0;
}
我的测试字符串是一个愚蠢的葡萄牙语句子:
O coração é um órgão frágil.
我正在尝试使用Boost_locale,因为有人告诉我这是他使unicode在Mac上正常工作的方法,但是我很乐于仅使用C ++标准库的解决方案。
编辑:
以下代码在Mac上有效。由于包含codecvt,因此无法在我的Linux机器上进行编译,但是我可以使用一些CPP指令来对其进行管理。
#include <sstream>
#include <iostream>
#include <fstream>
#include <codecvt>
#include <locale>
#include <string>
using namespace std;
int main() {
// setting std::local::global seems not to work (??)
wcin.imbue(std::locale(locale(""), new std::codecvt_utf8<wchar_t>));
wcerr.imbue(std::locale(locale(""), new std::codecvt_utf8<wchar_t>));
wstring userInput;
getline(wcin, userInput);
wcerr << "Size of string is " << userInput.length() << endl;
for (int i = 0; i < userInput.length(); ++i) {
wcerr << userInput.at(i) << endl;
}
return 0;
}
此行为是由以下事实引起的:在UTF-8编码中,一个字符(也称为代码点)由一个或多个代码单元表示。
本质上是:
for (int i = 0; i < userInput.length(); ++i)
遍历代码单元。您可以通过userInput.length()
数字大于字符串中的字符数来验证该行为。
通过做:
wcerr << userInput.at(i) << endl;
您将endl
在每个代码单元之后附加一个,从而分隔属于同一代码点的代码单元,这些代码单元会生成无效字符。
如果您只输出:
wcerr << userInput << endl;
您将完整保留您的字符串。
如果要分别输出每个字符,则必须考虑属于同一代码点的多个代码单元,并分别输出它们。
更新:
wcin
默认情况下不执行到代码点的转换。您需要明确声明输入的编码并进行转换。本质上,这是以下代码的作用。您的示例的唯一主要区别是,我使用了C ++ 11标准库而不是Boost。
#include <codecvt>
#include <iostream>
int main() {
std::locale::global( std::locale( std::locale(""), new std::codecvt_utf8<wchar_t> ) );
std::wcin.imbue( std::locale() );
std::wcout.imbue( std::locale() );
std::wcerr.imbue( std::locale() );
std::wstring user_input;
std::wcin >> user_input;
for( int i = 0; i < user_input.length(); ++i ) {
std::wcout << user_input[i] << std::endl;
}
// Converting characters to uppercase
const std::ctype<wchar_t>& f = std::use_facet<std::ctype<wchar_t>>( std::locale() );
for( int i = 0; i < user_input.length(); ++i ) {
std::wcout << f.toupper(user_input[i]) << std::endl; // f.tolower() for lowercase
}
return 0;
}
PS要进行编译,您将需要传递C ++ 11标准标志。
g++ -std=c++11 main.cpp
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句