std :: string的字符引用

cit*_*itn -1 c++ stdstring

我有以下字符串:

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的"神秘"字符吗?

其他信息:http://en.wikipedia.org/wiki/Newline

Mar*_*n B 9

你确定发生了这种情况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',这就是是混淆你.


Gre*_*ill 9

这里出现问题的一件事是以下行不符合您的预期:

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()上面的构造函数,看看你得到了什么.

  • @cmdev:不要添加备注.粘贴一个小的,可编译的程序,显示您描述的行为,以便我们可以将其粘贴到我们的编辑器中并使用它.现在,大多数答案都提到了你所说的一点是没有实际意义的.如果我们必须猜出问题是什么,您如何期望得到适合您问题的答案? (4认同)