#c #parsing #visual-c #g
#c #синтаксический анализ #visual-c #g
Вопрос:
Я пытаюсь разобрать текст из файла, в котором я должен обнаружить пустые строки. Я запускаю код в 2 местах:
- win 10, visual studio 2019 (MSVC)
- под WSL, ubuntu 20.04, g
Тот же компьютер, тот же файл, тот же код.
while (getline(inputFile, line))
{
if (line.length() == 1)
{
std::cout << "Empty line" << std::endl;
}
/*blabla*/
С помощью этого кода MSVC не печатает пустые строки, это делает g .
if (line.empty())
{
std::cout << "Empty line" << std::endl;
}
С помощью этого кода MSVC находит пустые строки, а g — нет.
if (int(line[0]) == 10 || int(line[0]) == 13)
{
std::cout << "Empty line" << std::endl;
}
С помощью этого кода g находит пустые строки, MSVC не
- Это ядро Linux изменяет окончания строк или компилятор?
- Как правильно всегда определять окончания строк и пустую строку в каждой системе?
Комментарии:
1.
r
,n
может заменить магические числа 10,13.2. Соглашение об окончаниях строк зависит от операционной системы. Существует соглашение Windows (
rn
) и соглашение Unix (n
), а старожилы помнят классическое (до OS X) соглашение Mac (r
). Если вы переносите текстовые файлы между разными операционными системами, вам необходимо либо перекодировать их с помощью какого-либо инструмента, либо быть готовым к разбору разных окончаний строк в вашей программе. Естественно, программа Unix будет восприниматьсяr
как обычный символ, а не как часть последовательности в конце строки. Вы несете ответственность за то, чтобы отказаться от него.3. Примечание: Выполнение
line[0]
над пустой строкой приводит к неопределенному поведению программы.4. Возможно, вы захотите проверить общие
unix2dos
иdos2unix
инструменты, которые добавляют или удаляютr
предыдущееn
.
Ответ №1:
Ваши трудности связаны с тем фактом, что вы смешиваете окончания строк Windows и Linux на одном компьютере. WSL — это Linux-подобная среда, и обработка файлов Windows в WSL ничем не отличается от их обработки на реальной машине Linux, то есть проблематична.
std::getline
удаляет окончания n
строк (0x0A), и, кроме того, в MSVC чтение файла в текстовом режиме автоматически удаляет символы r
(0x0D). Последнее не происходит в Linux.
Таким образом, чтение текстового файла Windows (с rn
окончаниями строк) на платформе, отличной от Windows, приведет к удалению n
, но останется r
в конце строки.
Если вы хотите справиться с этой ситуацией, вы можете удалить конечную r
строку вручную. Например
while (std::getline(inputFile, line))
{
if (!line.empty() amp;amp; line.back() == 'r')
{
line.pop_back();
}
if (line.empty())
{
std::cout << "Empty line" << std::endl;
}
Обычно полезно распечатать line
в двоичном режиме при отладке, потому r
что и n
являются невидимыми символами.