我有以下字符串:
index 0 1 2 3 4 5 6 7
std::string myString with the content of "\xff\xff\xff\x00\xff\x0d\x0a\xf5"
Run Code Online (Sandbox Code Playgroud)
当我引用myString [3]时,我得到了预期的'\ x00'值.
但是当我指的是myString [5]时,我得到两个值"\ x0d\x0a"而不仅仅是'\ x0d'.
更有趣的是myString [6]值,即'\ xf5'.这次它就像\ x0d不存在而且引用了正确的位置.
我的问题是:std:string对象中的\ x0d字符有什么特别之处?为什么索引时会跳过它?就像这样计算:
index 0 1 2 3 4 5 5 6
std::string myString = "\xff\xff\xff\x00\xff\x0d\x0a\xf5"
Run Code Online (Sandbox Code Playgroud)
作为注释,'\ x0d'字符是第13个ASCII字符"回车",'\ x0a'是换行符.
更新:可以是std :: string将"\ x0d\x0a"视为单个字符,因此只占用字符串中的一个位置吗?这个'\ x0d'是关于std :: string的"神秘"字符吗?
你确定发生了这种情况std::string吗?std::string::operator[]返回a const char &,那怎么能返回两个字符('\x0d' 和 '\x0a')?
也就是说,"\x0d\x0a"通常用于Windows下的行结尾,而只'\x0a'在Linux下使用,因此在Windows 下将前者转换为后者是相对常见的 - 例如,我正在考虑fopen调用时的行为"wt".我猜想会发生类似的事情.
编辑:根据您对原始问题的评论,我想我可以猜到发生了什么.
我相信你的字符串并不真正包含你认为它包含的内容.您被误导是因为您用于将字符串输出到文件(可能是ofstream?)的机制正在执行行尾转换.这意味着将'\n'(Unix行尾代码)转换为'\r\n'(Windows行尾代码).行尾转换的目的是使代码在操作系统之间更加可移植.您可以通过以二进制模式打开文件来禁止它; for ofstream,这是通过ios_base::binary在打开文件时指定标志来完成的,但默认情况下不设置此标志.
(有关不同操作系统上的行尾标记的更多信息,请参阅此Wikipedia文章.)
这就是我认为正在发生的事情.你的字符串实际包含
index 0 1 2 3 4 5 6
myString contents "\xff\xff\xff\x00\xff\x0a\xf5"
Run Code Online (Sandbox Code Playgroud)
你正在输出这样的东西:
ofstream file("myfile.txt");
for(size_t i=0; i<myString.size(); i++)
ofstream << myString[i];
Run Code Online (Sandbox Code Playgroud)
因为最终的行的翻译上面expalined中,'\x0a'在myString[5]正在作为输出'\x0d\x0a',这就是是混淆你.
这里出现问题的一件事是以下行不符合您的预期:
std::string myString = "\xff\xff\xff\x00\xff\x0d\x0a\xf5";
Run Code Online (Sandbox Code Playgroud)
这将调用std::string(const char *)构造函数,该构造函数旨在将C样式的以null结尾的字符串转换为C++ std::string.此构造函数从给定指针开始读取字节并将它们复制到new,std::string直到它到达空字节(\ x00).这与C函数的行为一致,例如strlen().
所以,当你myString构造它时,它由一个长度为3的字符串组成,带有bytes\xff,\ xff,\ xff.对大于2的索引的访问是访问数组末尾的字节(最多会产生运行时错误,或者最坏的情况下会产生未定义的行为).
请注意,a std::string可以保存中间空字节,但是您不能使用上面的构造函数来初始化这样的字符串,因为空字节被解释为终止传递给构造函数的C样式字符串.
将\ x00字节更改为其他内容再次尝试您的代码是值得的,只是为了看看它与您已经描述的不同:
std::string myString = "\xff\xff\xff\x01\xff\x0d\x0a\xf5"
Run Code Online (Sandbox Code Playgroud)
另外,检查myString.length()上面的构造函数,看看你得到了什么.