通过 C++ main char** args 处理不同字符串编码的正确方法是什么?
What is the correct way of processing different strings encodings via c++ main char** args?
我需要一些说明。
问题是我有一个用 C++ 编写的 windows 程序,它使用 'wmain' windows 特定函数,该函数接受 wchar_t** 作为其参数。所以,有机会把任何你喜欢的作为命令行参数传递给这样的程序:例如,中文符号,日文符号等等。
老实说,我没有关于此函数通常使用的编码的信息。可能是 utf-32,甚至是 utf-16。
所以,问题:
什么不是 windows 特定的,而是 unix/linux 的标准主函数实现方法?我的第一个想法是使用 utf-8 编码的输入字符串并指定某种语言环境?
有人可以举一个这样的主要功能的简单例子吗?一个std::string怎么能装下一个中文符号呢?
- 当我们像这样访问每个字符(字节)时,我们是否可以像往常一样使用以utf-8编码并包含在std::string中的中文符号进行操作:string_object[i] ?
简而言之:
int main(int argc, char **argv) {
setlocale(LC_CTYPE, "");
// ...
}
http://unixhelp.ed.ac.uk/CGI/man-cgi?setlocale+3
然后你使用mulitbyte string functions。您仍然可以使用普通 std::string
来存储多字节字符串,但要注意其中的字符可能跨越多个数组单元格。 locale设置成功后,也可以使用wide streams(wcin, wcout, wcerr)从标准流中读写wide strings
1) 对于 linux,您将获得标准 main()
和标准 char
。它将使用 UTF-8 编码。因此,中文特定字符将包含在具有多字节编码的字符串中。
***编辑:**抱歉,是的:您必须设置默认的“”语言环境like here as well as cout.imbue()
。*
2) 所有经典的main()
例子都是很好的例子。如前所述,中文特定字符将包含在具有多字节编码的字符串中。因此,如果您使用默认的 UTF-8 语言环境计算出这样一个字符串,则计算流将解释特殊的 UTF8 编码序列,知道它必须将每个序列中的 2 到 6 个进行聚合才能产生中文输出。
3) 你可以像往常一样对字符串进行操作。但是,如果您计算字符串长度,则会出现一些问题:内存(例如:3 个字节)和用户看到的字符(例如:只有 1 个)之间存在差异。如果您向前或向后移动指针,则相同。您必须确保正确解释多字节编码,以免输出无效编码。
您可能对 this other SO question 感兴趣。
Wikipedia解释了UTF-8多字节编码的逻辑。通过这篇文章,您将了解任何字符 u
都是多字节编码字符,如果:
( ((u & 0xE0) == 0xC0)
|| ((u & 0xF0) == 0xE0)
|| ((u & 0xF8) == 0xF0)
|| ((u & 0xFC) == 0xF8)
|| ((u & 0xFE) == 0xFC) )
后面跟着一个或几个字符,例如:
((u & 0xC0) == 0x80)
所有其他字符都是 ASCII 字符(即不是多字节)。
免责声明:所有中文单词由GOOGLE translate service提供。
1) 使用正常 std::string
照常进行。 std::string
可以容纳任何字符编码和参数处理是简单的模式匹配。所以在安装了中文版程序的中文电脑上,它需要做的就是将中文版的标志与用户输入的进行比较。
2) 例如:
#include <string>
#include <vector>
#include <iostream>
std::string arg_switch = "开关";
std::string arg_option = "选项";
std::string arg_option_error = "缺少参数选项";
int main(int argc, char* argv[])
{
const std::vector<std::string> args(argv + 1, argv + argc);
bool do_switch = false;
std::string option;
for(auto arg = args.begin(); arg != args.end(); ++arg)
{
if(*arg == "--" + arg_switch)
do_switch = true;
else if(*arg == "--" + arg_option)
{
if(++arg == args.end())
{
// option needs a value - not found
std::cout << arg_option_error << '\n';
return 1;
}
option = *arg;
}
}
std::cout << arg_switch << ": " << (do_switch ? "on":"off") << '\n';
std::cout << arg_option << ": " << option << '\n';
return 0;
}
用法:
./program --开关 --选项 wibble
输出:
开关: on
选项: wibble
3)号
对于 UTF-8/UTF-16 数据,我们需要使用像 ICU
这样的特殊库
对于逐字符处理,您需要使用或转换为 UTF-32。
我需要一些说明。
问题是我有一个用 C++ 编写的 windows 程序,它使用 'wmain' windows 特定函数,该函数接受 wchar_t** 作为其参数。所以,有机会把任何你喜欢的作为命令行参数传递给这样的程序:例如,中文符号,日文符号等等。
老实说,我没有关于此函数通常使用的编码的信息。可能是 utf-32,甚至是 utf-16。 所以,问题:
什么不是 windows 特定的,而是 unix/linux 的标准主函数实现方法?我的第一个想法是使用 utf-8 编码的输入字符串并指定某种语言环境?
有人可以举一个这样的主要功能的简单例子吗?一个std::string怎么能装下一个中文符号呢?
- 当我们像这样访问每个字符(字节)时,我们是否可以像往常一样使用以utf-8编码并包含在std::string中的中文符号进行操作:string_object[i] ?
简而言之:
int main(int argc, char **argv) {
setlocale(LC_CTYPE, "");
// ...
}
http://unixhelp.ed.ac.uk/CGI/man-cgi?setlocale+3
然后你使用mulitbyte string functions。您仍然可以使用普通 std::string
来存储多字节字符串,但要注意其中的字符可能跨越多个数组单元格。 locale设置成功后,也可以使用wide streams(wcin, wcout, wcerr)从标准流中读写wide strings
1) 对于 linux,您将获得标准 main()
和标准 char
。它将使用 UTF-8 编码。因此,中文特定字符将包含在具有多字节编码的字符串中。
***编辑:**抱歉,是的:您必须设置默认的“”语言环境like here as well as cout.imbue()
。*
2) 所有经典的main()
例子都是很好的例子。如前所述,中文特定字符将包含在具有多字节编码的字符串中。因此,如果您使用默认的 UTF-8 语言环境计算出这样一个字符串,则计算流将解释特殊的 UTF8 编码序列,知道它必须将每个序列中的 2 到 6 个进行聚合才能产生中文输出。
3) 你可以像往常一样对字符串进行操作。但是,如果您计算字符串长度,则会出现一些问题:内存(例如:3 个字节)和用户看到的字符(例如:只有 1 个)之间存在差异。如果您向前或向后移动指针,则相同。您必须确保正确解释多字节编码,以免输出无效编码。
您可能对 this other SO question 感兴趣。
Wikipedia解释了UTF-8多字节编码的逻辑。通过这篇文章,您将了解任何字符 u
都是多字节编码字符,如果:
( ((u & 0xE0) == 0xC0)
|| ((u & 0xF0) == 0xE0)
|| ((u & 0xF8) == 0xF0)
|| ((u & 0xFC) == 0xF8)
|| ((u & 0xFE) == 0xFC) )
后面跟着一个或几个字符,例如:
((u & 0xC0) == 0x80)
所有其他字符都是 ASCII 字符(即不是多字节)。
免责声明:所有中文单词由GOOGLE translate service提供。
1) 使用正常 std::string
照常进行。 std::string
可以容纳任何字符编码和参数处理是简单的模式匹配。所以在安装了中文版程序的中文电脑上,它需要做的就是将中文版的标志与用户输入的进行比较。
2) 例如:
#include <string>
#include <vector>
#include <iostream>
std::string arg_switch = "开关";
std::string arg_option = "选项";
std::string arg_option_error = "缺少参数选项";
int main(int argc, char* argv[])
{
const std::vector<std::string> args(argv + 1, argv + argc);
bool do_switch = false;
std::string option;
for(auto arg = args.begin(); arg != args.end(); ++arg)
{
if(*arg == "--" + arg_switch)
do_switch = true;
else if(*arg == "--" + arg_option)
{
if(++arg == args.end())
{
// option needs a value - not found
std::cout << arg_option_error << '\n';
return 1;
}
option = *arg;
}
}
std::cout << arg_switch << ": " << (do_switch ? "on":"off") << '\n';
std::cout << arg_option << ": " << option << '\n';
return 0;
}
用法:
./program --开关 --选项 wibble
输出:
开关: on
选项: wibble
3)号
对于 UTF-8/UTF-16 数据,我们需要使用像 ICU
这样的特殊库对于逐字符处理,您需要使用或转换为 UTF-32。