考虑具有UNIX行结尾的C ++文件(即'\x0a'
而不是"\x0d\x0a"
)并包含以下原始字符串文字:
const char foo[] = R"(hello^M
)";
(其中^M
是实际字节0x0d(即回车))。
跟随字符串比较的结果应该是什么(在考虑原始字符串文字的标准定义时)?
strcmp("hello\r\n", foo);
字符串是否应该相等? (即0
或!=0
?)
使用GCC 4.8(在Fedora 19上),他们比较不平等。
这是GCC中的错误或功能吗?
答案 0 :(得分:4)
就标准而言,您只能在字符串文字(以及程序中的其他位置)中使用基本源字符集的成员。如何将程序的物理表示映射到基本源字符集是实现定义的。
g ++显然认为ASCII \ x0a,ASCII \ x0d和ASCII \ x0d \ x0a都是名为“newline”的基本源字符集成员的有效表示。这是完全合理的,因为在Windows,Unix和Mac OS X Classic机器之间传输的源代码需要保持其含义。
答案 1 :(得分:0)
原始字符串文字不是完全原始的,因为它们是通过读取并解释输入C ++文件的编译器到达您的程序的。在填充2个字符串之前,您可以检查原始字符串的大小-它与预期的^ M(\ x0d)个字符的数量不同。
您可以求助于以二进制形式读取数据,例如(binary read/w example):
std::ifstream infile ("test.txt", std::ifstream::binary);
infile.seekg (0,infile.end);
long size = infile.tellg();
infile.seekg (0);
char* buffer = new char[size];
infile.read (buffer,size);
或者您可以坚持使用原始文字,但是要有一些技巧-用文字中的其他字符替换所有“坏”字符,然后在使用此文字时进行反向替换,例如:
... all includes ...
std::string str = R"(hello|
)";
int main()
{
std::replace(str.begin(), str.end(), '|', '\015');
std::cout << strcmp("hello\r\n", str.data()) << std::endl;
}