Разные окончания строк в MSVC и g

#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 не

  1. Это ядро Linux изменяет окончания строк или компилятор?
  2. Как правильно всегда определять окончания строк и пустую строку в каждой системе?

Комментарии:

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 являются невидимыми символами.