我无法理解之间的差异std::string和std::wstring.我知道wstring支持Unicode字符等宽字符.我有以下问题:
std::wstring用完std::string?std::string保存整个ASCII字符集,包括特殊字符吗?std::wstring由所有流行的C++编译器的支持?string s = "????";
wstring ws = FUNCTION(s, ws);
Run Code Online (Sandbox Code Playgroud)
我如何将s的内容分配给ws?
搜索谷歌并使用了一些技术,但他们无法分配确切的内容.内容失真.
我一直在读一些关于Unicode的主题 - 特别是UTF-8 - (非)支持C++ 11,我希望Stack Overflow上的大师可以向我保证我的理解是正确的,或指出我在哪里误解或错过了某些情况.
首先,好的:您可以在源代码中定义UTF-8,UTF-16和UCS-4文字.此外,<locale>标头包含几个std::codecvt可以在UTF-8,UTF-16,UCS-4和平台多字节编码之间进行转换的实现(虽然API看起来很温和,但不是直截了当).这些codecvt实现可以imbue()在流上进行,以允许您在读取或写入文件(或其他流)时进行转换.
[ 编辑: Cubbi在评论中指出我忽略了提到<codecvt>标题,它提供了std::codecvt不依赖于语言环境的实现.此外,std::wstring_convert和wbuffer_convert函数可以使用这些codecvt来直接转换字符串和缓冲区,而不是依赖于流.
C++ 11还包括C99/C11 <uchar.h>标头,其中包含将来自平台多字节编码(可能是或不是UTF-8)的单个字符转换为UCS-2和UCS-4的功能.
但是,这是关于它的程度.虽然你当然可以将UTF-8文本存储在a中std::string,但我无法看到任何对它有用的东西.例如,除了在代码中定义文字之外,您不能将字节数组验证为包含有效的UTF-8,您无法找到长度(即Unicode字符的数量,对于某些"字符"的定义)包含UTF-8 std::string,并且不能std::string以字节为单位以任何方式迭代a .
同样,即使添加C++ 11 std::u16string也不支持UTF-16,但只支持较旧的UCS-2 - 它不支持代理对,只留下BMP.
鉴于UTF-8是在几乎所有Unix派生系统(包括Mac OS X和*Linux)上处理Unicode的标准方式,并且已经在很大程度上成为Web上事实上的标准,现代C++中缺乏支持似乎像一个相当严重的遗漏.即使在Windows上,新std::u16string功能并不真正支持UTF-16 这一事实似乎有些令人遗憾.
*由于在评论中指出,并明确提出在这里的Mac OS使用UTF-8的BSD衍生的部分,而可可使用UTF-16.
如果你设法阅读了所有这些,谢谢!只是几个简单的问题,因为这毕竟是Stack Overflow ...
以上分析是否正确,或者我是否缺少任何其他支持Unicode的设施?
在过去几年中,标准委员会在快速推进C++方面做得非常出色.他们都很聪明,我认为他们很清楚上述缺点.是否有一个众所周知的原因,即Unicode支持在C++中仍然很差?
展望未来,是否有人知道有任何纠正这种情况的建议?快速搜索isocpp.org似乎没有透露任何信息.
编辑:感谢大家的回复.我不得不承认,我发现它们有点令人沮丧 - 看起来现状在不久的将来不太可能改变.如果在认知方面存在共识,似乎完全的Unicode支持太难了,并且任何解决方案必须重新实现大多数ICU才被认为是有用的.
我个人不同意这一点; 我认为可以找到有价值的中间立场.例如,对于UTF-8和UTF-16的验证和归一化算法是由Unicode财团以及指定的,并且可以通过标准库中,比方说自由函数,一个被提供std::unicode的命名空间.仅这些对于需要与期望Unicode输入的库接口的C++程序来说是一个很大的帮助.但基于下面的答案(微笑,必须说,带着一丝苦涩),似乎Puppy关于这种有限功能的提议并不受欢迎.
我有一个程序声明一个像这样的字符串数组:
char *colors[4] = {"red", "orange", "yellow", "blue"};
Run Code Online (Sandbox Code Playgroud)
但是我得到了上面的编译器警告.它编译但我宁愿使用非弃用的方式(如果有的话).我试图找出它意味着什么,但我似乎无法弄明白.我听说'char'工作之前使用'const',但如果有人能解释错误的含义,那将会有所帮助.谢谢.
这个问题是Do C++ 11正则表达式与UTF-8字符串一起使用的扩展吗?
#include <regex>
if (std::regex_match ("?", std::regex("?") )) // "\u4e2d" also works
std::cout << "matched\n";
Run Code Online (Sandbox Code Playgroud)
该程序在Mac Mountain Lion上编译,clang++具有以下选项:
clang++ -std=c++0x -stdlib=libc++
Run Code Online (Sandbox Code Playgroud)
上面的代码有效.这是一个标准范围正则表达式,"[?-?????]"用于匹配任何日语汉字或汉字.它适用于Javascript和Ruby,但即使使用类似的版本,我似乎也无法使用C++ 11工作[\u4E00-\u9fa0].下面的代码与字符串不匹配.
if (std::regex_match ("?", std::regex("[?-?????]")))
std::cout << "range matched\n";
Run Code Online (Sandbox Code Playgroud)
改变语言环境也没有帮助.有任何想法吗?
所以我发现如果你添加+到最后,所有范围都有效.在这种情况下[?-?????]+,但如果你添加{1} [?-?????]{1}它不起作用.而且,它似乎超越了它的界限.它不会匹配拉丁字符,但它会匹配?这是\u306f和?它\u3041.他们都躺在下面\u4E00
nhahtdh还提出了regex_search,它也可以在不增加的情况下工作,+但它仍然会遇到与上面相同的问题,因为它会超出其范围.同时也使用了语言环境.Mark Ransom建议它将UTF-8字符串视为一组愚蠢的字节,我认为这可能就是它所做的.
进一步推动UTF-8变得混乱的理论[a-z]{1}和[a-z]+匹配a,但只[?-?????]+匹配任何角色,而不是[?-?????]{1}.
我一直在阅读一些关于Unicode的文章,并意识到我仍然对这件事做些什么感到困惑.
作为Windows平台上的c ++程序员,给予我的学科与任何教师大致相同:始终使用Unicode字符集; 如果可能的话,将其模板化或使用TCHAR; 喜欢wchar_t,std :: wstring over char,std :: string.
#include <tchar.h>
#include <string>
typedef std::basic_string<TCHAR> tstring;
// ...
static const char* const s_hello = "??"; // bad
static const wchar_t* const s_wchar_hello = L"??" // better
static LPCTSTR s_tchar_hello = TEXT("??") // even better
static const tstring s_tstring_hello( TEXT("??") ); // best
Run Code Online (Sandbox Code Playgroud)
不知怎的,我搞砸了,我引导自己相信如果我说"某事",那就意味着它是ASCII格式的,如果我说L"某事"就是Unicode.然后我读到了这个:
类型wchar_t是一种不同的类型,其值可以表示支持的语言环境(22.3.1)中指定的最大扩展字符集的所有成员的不同代码.类型wchar_t应具有与其他整数类型之一相同的大小,符号和对齐要求(3.11),称为其基础类型.类型char16_t和char32_t分别表示与uint_least16_t和uint_least32_t相同的大小,符号和对齐的不同类型,称为基础类型.
所以呢?如果我的语言环境从代码页949开始,那么wchar_t的扩展是从949 + 2 ^(sizeof(wchar_t)*8)?它说话的方式听起来像'我不在乎你的c ++实现是使用UTF编码还是什么'.
至少,我可以理解一切都取决于应用程序所在的语言环境.因此我测试了:
#define TEST_OSTREAM_PRINT(x) \
std::cout << "----" << std::endl; \
std::cout << "cout : " << x << std::endl; …Run Code Online (Sandbox Code Playgroud) 我需要获取std :: string中前N个字符的子字符串,假定为utf8.我学到了.substr不起作用的艰难方式......正如......期待的那样.
参考:我的字符串可能如下所示:任务:\n \n1亿2千万匹
好吧,在代码中使用Visual Studio Ultimate 2012(可能与ANSI,unicode等问题)构建时出现了奇怪的错误...
switch (input[index])
{
case '?': // Alef Hebrew character
if (/*conditional*/)
{
// Do stuff.
}
break;
case '?': // Beth Hebrew character
if (/*conditional*/)
{
//Do stuff
}
break;
default:
{
//Do some other stuff.
}
break;
}
Run Code Online (Sandbox Code Playgroud)
第二个案例参数生成......
Error C2196: case value '?' already used
Run Code Online (Sandbox Code Playgroud)
如果可能,简单修复.
以下代码在VS 2015(更新3)和gcc 6.3(C++ 14)上编译正常,没有任何问题.
#include <string>
#include <locale>
int main()
{
std::u16string ustr = u"Android";
bool var = std::isspace(ustr[0],std::locale());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,在clang/Xcode上它失败并出现以下错误
Error(s):
source_file.cpp:8:10: warning: unused variable 'var' [-Wunused-variable]
bool var = std::isspace(ustr[0],std::locale());
^
In file included from source_file.cpp:2:
In file included from /usr/include/c++/v1/locale:182:
/usr/include/c++/v1/__locale:705:44: error: implicit instantiation of undefined template 'std::__1::ctype<char16_t>'
return use_facet<ctype<_CharT> >(__loc).is(ctype_base::space, __c);
^
source_file.cpp:8:21: note: in instantiation of function template specialization 'std::__1::isspace<char16_t>' requested here
bool var = std::isspace(ustr[0],std::locale());
^
/usr/include/c++/v1/__locale:427:53: note: template is …Run Code Online (Sandbox Code Playgroud) 了解 unicode、语言环境、宽字符和转换对我来说是一次可怕的经历。
我需要读取包含俄语和英语,中国和乌克兰字符的文本文件一次全部
我的方法是以字节块读取文件,然后对块进行操作,在单独的线程上进行快速读取。(关联)
这是使用 std::ifstream.read(myChunkBuffer, chunk_byteSize)
但是,我知道如果我坚持使用char.
就此而言,我将一切都转化wchar_t为最佳状态并希望得到最好的结果。
我也知道Sys.setlocale(locale = "Russian") (链接),但它不是将每个字符解释为俄语吗?当我解析字节时,我不知道何时在我的 4 种语言之间切换。
在 Windows 操作系统上,我可以创建一个 .txt 文件并写上“??????!你好!” 在程序 Notepad++ 中,它将保存文件并以相同的字母重新打开。它是否以某种方式在每个字符后秘密添加隐形标记,以了解何时解释为俄语,何时解释为英语?
我目前的理解是:将所有内容都作为wchar_t(双字节),将任何文件解释为 UTF-16(双字节) - 是否正确?
另外,我希望保持代码跨平台。
对不起菜鸟
这里的东西(https://docs.microsoft.com/en-us/cpp/build/reference/source-charset-set-source-character-set),我知道所有关于VC ++/source-charset和/execution-charset。
所以有 3 件事我需要保持不变(如果有任何错误,请纠正我):
所以,如果有我保存源文件encodingA,设置/source-charset和/execution-charset作为encodingA,并有代码wchar_t c = L'é';或char16_t c = u'é'; 或者char32_t c = U'é',
程序会é根据encodingA我在“解释”期间选择的代码单元来更改代码单元吗?
或者é无论我选择什么编码,代码单元都不会改变?
(不要关心控制台输出)
如果编写可能使用不同字符类型编译的代码,TCHAR仍然是正确使用的类型,例如std::basic_stringstream<TCHAR>
或者现在有一些官方的C++/STL类型是首选,在wchar_t替换WCHAR,true替换TRUE和nullptr替换的方式NULL?
我在谈论我正在使用类,如basic_string使用TCHAR显式模板化的情况.
我想了解常规std::string和std::map操作如何处理字符串中的Unicode代码单元.
示例代码:
include <iostream>
#include "sys/types.h"
using namespace std;
int main()
{
std::basic_string<u_int16_t> ustr1(std::basic_string<u_int16_t>((u_int16_t*)"????", 4));
std::basic_string<u_int16_t> ustr2(std::basic_string<u_int16_t>((u_int16_t*)"abcd", 4));
for (int i = 0; i < ustr1.length(); i++)
cout << "Char: " << ustr1[i] << endl;
for (int i = 0; i < ustr2.length(); i++)
cout << "Char: " << ustr2[i] << endl;
if (ustr1 == ustr2)
cout << "Strings are equal" << endl;
cout << "string length: " << ustr1.length() << "\t" << ustr2.length() << endl; …Run Code Online (Sandbox Code Playgroud)