(А)
string str = "Hello\nWorld";
Когда я печатаю str
, вывод:
Hello
World
(Б)
string str;
cin >> str; //given input as Hello\nWorld
Когда я печатаю str
, вывод:
Hello\nWorld
В чем разница между (а) и (б)?
(А)
string str = "Hello\nWorld";
Когда я печатаю str
, вывод:
Hello
World
(Б)
string str;
cin >> str; //given input as Hello\nWorld
Когда я печатаю str
, вывод:
Hello\nWorld
В чем разница между (а) и (б)?
Компилятор C++ имеет определенные правила, когда предоставляются управляющие символы - документация. Как вы можете видеть, когда вы указываете \n
в строковом литерале, он заменяется компилятором с помощью строки (значение 0xa для ASCII). Таким образом, вместо 2 символов, \
и n
, вы получаете один символ с двоичным кодом 0xa (я предполагаю, что вы используете кодировку ASCII), что заставляет консоль выводить на новую строку при печати. Когда вы читаете строку, компилятор не участвует, и ваша строка содержит фактические символы \
и n
в ней.
Если указано в строковом литерале, "\n" будет переведено в соответствующий код ascii (0x0a
на linux) и сохранен как есть. Он не будет храниться как обратная косая черта, за которым следует буква n
. Последовательности Escape предназначены только для вас, чтобы позволить строковые литералы со встроенными символами новой строки.
С другой стороны, ваша оболочка, работающая в терминале, не выполняет такую подстановку: она отправляет буквальную обратную косую черту и n
, которая будет напечатана как таковая.
Чтобы напечатать новую строку, введите новую строку:
$ echo "Hello
World" | ./your-program
Строка в cout << "Hello\nworld" преобразуется компилятором в скомпилированную строку, где escape-коды преобразуются в символы, поэтому функция cout при выполнении не видит строку с двумя символами "\n", но эквивалентный код для следующий линия знак.
Но cin получает строку каждого типизированного символа во время выполнения и не конвертирует escape-коды. Поэтому, если вы хотите конвертировать эти коды эвакуации, вам нужно выполнить функцию замены.
cin
не включает компилятор C++. Эквивалентные последовательности в строковых литералах являются особенностью C++ lexer, которая является частью компилятора C++. Потоки более или менее дают вам то, что пришло из ОС (они могут делать некоторые переводы CRLF → CR или аналогичные на основе ОС, но это они).
Почему escape-символы не работают, когда я читаю cin?
Поскольку потоковые считыватели определены таким образом. В основе каждого символа читается отдельно. Только функции более высокого уровня придавали персонажу дополнительное значение.
Когда компилятор обрабатывает строковый литерал "Hello\nWorld"
, его файловый читатель передает ему два символа. Только компилятор/парсер C++ переводит их в один символ на основе правил языка.
Символы Escape в строке интерпретируются компилятором. Последовательность \n
состоит из двух действительных символов, которые компилятор преобразует в один символ новой строки во время компиляции. Одна и та же последовательность не интерпретируется каким-либо образом, когда вы вводите ее в командной строке, поэтому вы получаете точные два введенных символа.
Если вы хотите обработать строку, чтобы интерпретировать escape-последовательности, вам придется сделать это самостоятельно (или использовать соответствующую библиотеку).
В скомпилированном коде символьный литерал \n
заменяется значением, специфичным для реализации, которое система выполнения рассматривает как символ новой строки. Определение языка не требует какого-либо конкретного значения.
При чтении ввода с консоли или файла входящий текст не компилируется, а последовательность символов "\n" не имеет особого значения. Это всего лишь два символа.