Возврат каретки + перевод строки в необработанных строковых литералах?
Рассмотрим файл C++ с окончаниями строк UNIX (т.е. '\x0a'
вместо "\x0d\x0a"
) и включает следующий необработанный строковый литерал:
const char foo[] = R"(hello^M
)";
(где ^M
фактический байт 0x0d (т.е. возврат каретки)).
Каким должен быть результат последующего сравнения строк (с учетом стандартного определения необработанных строковых литералов)?
strcmp("hello\r\n", foo);
Должны ли строки сравниваться с равными или нет? (т.е. 0
или же !=0
?)
С GCC 4.8 (на Fedora 19) они сравниваются неравно.
Это ошибка или функция в GCC?
1 ответ
Что касается стандарта, вы можете использовать только члены базового исходного набора символов в строковых литералах (и в других местах программы). То, как физическое представление программы отображается на базовый исходный набор символов, определяется реализацией.
g ++, очевидно, считает, что ASCII \x0a, ASCII \x0d и ASCII \x0d\x0a - все допустимые представления члена базового исходного набора символов, называемого "новой строкой". Что вполне разумно, учитывая, что желательно, чтобы исходный код, передаваемый между компьютерами Windows, Unix и Mac OS X Classic, сохранял свое значение.
Необработанные строковые литералы не являются полностью необработанными, поскольку они поступают в вашу программу через компилятор, который считывает и интерпретирует входные файлы C++. Перед strcmp'ing 2 строки вы можете проверить размер вашей необработанной строки - он будет отличаться от ожидаемого на количество символов ^M (\x0d).
Вы можете прибегнуть к чтению данных как двоичному, например (пример двоичного чтения / w):
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;
}