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