Код «возврат каретки»
Код «возврат каретки» \r выполняет «возврат каретки», перемещая курсор к началу той же строки без перехода на следующую. Если вы вывели на экран какую-то информацию, перевели курсор назад к началу этой строки и затем вывели на экран другую информацию, то старое сообщение стирается, а на его месте появляется новое. Рис. 4.2 иллюстрирует различия между escape-последовательностями «возврат каретки» и «новая строка». Когда вы работаете с клавиатурой, нажатие клавиши Enter производит действие, аналогичное тому, что в языке Си называется новой строкой. Некоторые программисты называют это комбинацией возврата каретки и перевода строки, сокращенно CR/LF (от английского carriage return/line feed). Использование кода «возврат каретки» в языке Си не приводит к переходу на новую строку. Рис. 4.2. Различия между кодами «возврат каретки» и «новая строка» Действие кода \r можно видеть на примере следующей инструкции: puts(«Левый\rПравый»); В результате ее выполнения на экране появится только слово «Правый». И вот почему: после отображения на экране слова «Левый», код \r переводит курсор в начало этой строки, и при отображении слова «Правый» составляющие его символы замещают собой символы слова «Левый». Код \r сам по себе не уничтожает выведенные на экран символы, когда возвращает курсор, и только вывод новых символов после возврата курсора стирает уже существующий текст.
Код «возврат на шаг»
В отличие от кода \r, который возвращает курсор в начало строки, код «возврат на шаг» \b передвигает курсор только на одну позицию влево. При перемещении курсора существующие символы не уничтожаются, как и при возврате каретки. Если вы используете коды «возврат каретки» или «возврат на шаг», а затем вводите код «новая строка», курсор переходит к следующей строке, не уничтожая существующий текст.
Код «перевод страницы»
Когда вы посылаете информацию на печатающее устройство (как именно это делается, вы узнаете позже), код «перевод страницы» \f вытягивает из него текущую страницу. Этот код распознается большинством принтеров. После вывода сообщения на печать, большинство программистов использует код «перевод страницы», чтобы быть уверенными в том, что страница с последним сообщением готова и на нее не будет печататься другая информация. Если вывести изображение этого кода на экран при помощи функции puts() или putchar(), он появится в виде маленького графического символа, который никак не влияет на остальную информацию, отображаемую на дисплее.
Отображение специальных символов на экране монитора
Вы можете использовать escape-последовательности для вывода на дисплей специальных символов. Программисты часто используют их для вывода символов, изображение которых невозможно получить иным способом:
Escape-последо-вательность | Функция |
\’ | отображает одинарную кавычку |
\» | отображает двойную кавычку |
\\ | отображает обратную косую черту |
Например, вы желаете вывести на экран текст: Мы зовем ее «Наташа» который содержит кавычки с именем «Наташа». Если вы попробуете отобразить эту строку с помощью инструкции puts(«Мы зовем ее «Наташа»»); то получите от компилятора сообщение об ошибке. Вспомните, параметр, передаваемый функции puts(), должен начинаться и заканчиваться кавычками, чтобы компилятор Си знал, где начинается и где заканчивается строка. В приведенном выше ошибочном примере, компилятор будет интерпретировать параметр как «Мы зовем ее» с дополнительными символами «Наташа»»», которые расположены снаружи по отношению к паре двойных кавычек, но внутри пары скобок, содержащих параметр для вызова функции puts(). Для компилятора в такой строке оказывается слишком много информации. Приведем теперь правильную запись этой инструкции: puts(«Мы зовем ее \»Наташа\»»); Рис. 4.3. Отображение символов «кавычки» На рис. 4.3 показано, каким образом компилятор интерпретирует эту строку. Кроме кавычек и обратной косой черты, вы можете использовать управляющие коды для отображения различных графических символов. IBM PC и совместимые компьютеры могут отображать набор символов, известных как расширенный набор ASCII-символов. Он включает в себя все буквы, цифры и знаки препинания, которые можно ввести с клавиатуры, а также некоторые графические символы и греческие буквы*. Каждый символ в наборе имеет собственный номер, например, номер 3 соответствует символу «сердечко» (по карточной терминологии — «черви»). Чтобы отобразить символ на экране, надо поместить соответствующий ему номер (в виде трех цифр) после знака обратной косой черты: putchar(‘\003’); В результате выполнения этой инструкции на дисплей выводится символ «сердечко». Для того чтобы отобразить символы всех карточных мастей, используйте следующую программу: ______________________________ * В русифицированных наборах — буквы русского алфавита. (Прим.перев.) main() < puts("Черви \003\n"); puts("Бубны \004\n"); puts("Трефы \005\n"); puts("Пики \006\n"); >Функция puts() выведет на экран названия всех карточных мастей и соответствующие им графические символы (рис.4.4). В табл.4.1 приведены некоторые символы, которые могут быть изображены только путем использования их кодов. Рис. 4.4. Отображение графических символов по их кодам Для отображения графических символов можно использовать и функцию putchar() за счет двойственности символьных переменных. Если вы определили переменную типа int, ей, понятное дело, можно присвоить числовое значение: int count; count=5; Если затем вы используете эту переменную как параметр, передаваемый функции putchar() putchar(count); символ, ассоциированный со значением переменной, будет отображен на экране. Таблица 4.1. Некоторые используемые коды символов. Один из символов в наборе ASCII не появляется на экране, зато при попытке вывести его раздается звонок! Использование escape-последовательности \007 приводит к подаче звукового сигнала встроенным динамиком вашего компьютера. Приведенная ниже программа дважды подает звуковой сигнал, привлекая внимание к сообщению на экране: #define BELL ‘\007’ /* BELL легче запомнить, чем \007 */ main() < putchar(BELL); /*Подача звукового сигнала*/ putchar(BELL); /*Подача звукового сигнала*/ puts("Вниманию покупателей!\n"); puts("В отделе спортивных товаров \ проводится сезонная распродажа\n"); >Директива #define определяет константу BELL со значением \007. И хотя для определения константы вам пришлось ввести с клавиатуры четыре символа, компилятор воспримет ее как обычную символьную константу. Сигнал динамика слышится тогда, когда вы пытаетесь вывести константу BELL на дисплей с помощью функции putchar().
Замечания по Си++ | |
Если вы чувствуете в себе силы, то можете познакомиться с некоторой дополнительной информацией о специальных символах. Вы можете найти описание набора ASCII-символов во многих руководствах по компьютерам и печатающим устройствам. Обычно номера кодов приведены в десятичной и шестнадцатеричной системах счисления. Некоторые компиляторы Си воспринимают запись в этих форматах, но стандарты Си K&R и ANSI подразумевают использование восьмеричных кодов. Применяйте восьмеричные коды (приведенные в табл.4.1) для совместимости с любыми компиляторами Си. Расширенный набор ASCII-символов содержит все буквы и символы, которые можно отобразить на экране монитора, а не только те, которые вводятся непосредственно с клавиатуры. В некоторых источниках вы можете найти его подмножество, набор ASCII-символов, который включает только коды от 0 до 127 в десятичной системе счисления. Сюда входят только символы, которые можно ввести с клавиатуры. |
Последовательность символов которая оканчивается символом возврат каретки
Алфавит языка — это тот набор знаков (символов), который допустим в данном языке. Такое определение справедливо и для языка человека, и для языков программирования.
В языке С++ алфавит можно подразделить на следующие группы знаков:
прописные и строчные латинские буквы ( A, B, . Z, a, b, . z );
арабские цифры ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 );
специальные знаки: » , < >| [ ] ( ) + — / % \ ; ‘ . : ? < = >_ ! & * # ~ ^
пробельные символы — это символы пробела, табуляции, перехода на новую строку.
Идентификаторы
Идентификатор — это имя какого-либо объекта программы. Например, имена дают переменным, функциям, классам и т.д. Имя может состоять из латинских букв, цифр и символа _ (символ подчеркивания). Начинаться имя может с буквы или символа подчеркивания, но не с цифры. Важно учитывать, что прописные и строчные латинские буквы, используемые в идентификаторах, считаются различными (это требование является общим для всех С-подобных языков: С, С++, С#, Java, Perl и многих других. В таких же языках, как Fortran, Pascal, Basic не делается различия в именах между прописными и строчными латинскими буквами).
Пример допустимых идентификаторов:
alfa Alfa ALFA x _x a25 i_tek
Обратите внимание: здесь alfa , Alfa и ALFA — разные имена.
Имена, подобные приведённым ниже, ни в коем случае нельзя использовать в качестве идентификаторов:
25a (начинается с цифры);
Альфа (кириллица не допустима).
Общепринятые рекомендации по использованию имён :
желательно, чтобы имя объекта было осмысленным;
в качестве имён констант используйте имена, состоящие из прописных латинских букв, например: PI , GAMMA ;
не используйте имена, начинающиеся с символа подчеркивания, так как такие имена часто используют разработчики компиляторов для своих целей;
чем больше область видимости имени, тем более выразительным и длинным должно быть имя. Короткие однобуквенные или двухбуквенные имена допустимы только внутри небольших блоков программы, внутри коротких функций пользователя.
Длина имени в большинстве случаев не ограничена, но на длину внешних имён (имён библиотек, функций) может накладывать ограничение операционная система.
Ключевые слова
Ключевые (зарезервированные) слова — это слова, которые можно использовать в программе только по их прямому назначению, т.е. эти имена нельзя использовать для обозначения, например, своих переменных.
В языке С++ имеется 63 ключевых слова. Все они приведены в таблице:
Нет смысла заучивать сразу все ключевые слова языка С++. Лучше по мере изучения языка запоминать и ключевые слова. А пока достаточно знать несколько наиболее употребительных ключевых слов, которые начнем использовать в ближайшее время, например:
for, do, if, else, return, int, double .
Константы
Константы — это неизменяемые величины. В языке C++ имеется пять типов констант: целые, вещественные, символьные, строковые и булевые.
1. Целые константы. Правила языка допускают использование трёх видов целых констант: десятичных, шестнадцатеричных и восьмеричных. Основание определяется префиксом в записи константы. Для десятичных констант префикс не нужен.
Десятичное целое — это последовательность десятичных цифр, начинающаяся не с нуля (если это не число нуль), например:
Восьмеричное целое — это последовательность цифр, начинающаяся с 0 и не содержащая десятичных цифр старше 7 , например:
016 — восьмеричное представление десятичного целого 14 ;
025 — восьмеричное представление десятичного целого 21 .
Шестнадцатеричное целое — это последовательность шестнадцатеричных цифр ( 0, 1,…, 9, А, B, С, D, Е, F ), перед которой записаны символы 0х или 0Х , например:
0х25 — шестнадцатеричное представление десятичного целого 37 ;
0ХFF — шестнадцатеричное представление десятичного целого 255 .
2.Вещественные константы . Для представления вещественных (нецелых) чисел используются константы, представляемые в памяти компьютера в форме с плавающей точкой. Каждая вещественная константа состоит из следующих частей: целая часть (десятичная целая константа); десятичная точка; дробная часть (десятичная целая константа); признак показателя » е » или » Е «; показатель десятичной степени (десятичная целая константа, возможно, со знаком). При записи констант с плавающей точкой могут опускаться целая или дробная часть (но не одновременно); десятичная точка или символ экспоненты с показателем степени (но не одновременно). Примеры констант с плавающей точкой:
125. 3.14159265 1.0е-5 .314159Е25 0.0
3.Символы, или символьные константы . Для изображения отдельных знаков, имеющих индивидуальные внутренние коды, используются символьные константы. Каждая символьная константа — это лексема, которая состоит из изображения символа и ограничивающих апострофов. Например: ‘A’ , ‘a’ , ‘5’ , ‘?’ , и т.д.
Внутри апострофов можно записать любой символ, изображаемый на дисплее или принтере в текстовом режиме. Однако в компьютере используются и коды, не имеющие графического представления на экране дисплея, клавиатуре или принтере. Примерами таких кодов служит код перехода курсора дисплея на новую строку или код возврата каретки (возврат курсора к началу текущей строки). Для изображения в программе соответствующих символьных констант используются комбинации из нескольких символов, имеющих графическое представление. Каждая такая комбинация начинается с символа ‘\’ (обратная косая черта — back slash ). Такие наборы литер, начинающиеся с символа ‘\’ , в литературе по языкам C и С++ называют управляющими последовательностями. Ниже приводится их список:
‘\n’ — перевод строки;
‘\t’ — горизонтальная табуляция;
‘\r’ — возврат каретки (курсора) к началу строки;
‘\\’ — обратная косая черта \ ;
‘\» — апостроф (одиночная кавычка);
‘\»‘ — кавычка (символ двойной кавычки);
‘\0’ — нулевой символ;
‘\b’ — возврат на одну позицию (на один символ);
‘\f’ — перевод (прогон) страницы;
‘\v’ — вертикальная табуляция;
Обратите внимание на то, что перечисленные константы изображаются двумя или более литерами, а обозначают они одну символьную константу, имеющую индивидуальный двоичный код. Управляющие последовательности являются частным случаем эскейп-последовательностей ( ESCAPE-sequence ), к которым также относятся лексемы вида ‘\ddd’ либо ‘\xhh’ или ‘\Xhh’ , где
‘\ddd’ — восьмеричное представление любой символьной константы. Здесь d — восьмеричная цифра (от 0 до 7 ). Например, ‘\017’ или ‘\233’ .
‘\xhh’ или ‘\Xhh’ — шестнадцатеричное представление любой символьной константы. Здесь h — шестнадцатеричная цифра (от 0 до F ). Например, ‘\x0b’ , ‘\x1A’ , и т.д.
Символьная константа (символ) имеет целый тип, т.е. символы можно использовать в качестве целочисленных операндов в выражениях.
4.Строки, или строковые константы . Строки вообще-то не относятся к константам языка С++, а представляют собой отдельный тип его лексем. Для них в литературе используется еще одно название: «строковые литералы». Строковая константа определяется как последовательность символов (см. выше символьные константы), заключенная в двойные кавычки (не в апострофы!):
Среди символов строки могут быть эскейп-последовательности, т.е. сочетания знаков, соответствующие неизображаемым символам, или символам, задаваемым их внутренними кодами. В этом случае, как и в представлениях отдельных символьных констант, их изображения начинаются с обратной косой черты ‘\’ :
«\n Текст \n разместится \n на 3-х строках»
Представления строковых констант в памяти компьютера подчиняются следующим правилам. Все символы строки размещаются подряд, и каждый символ (в том числе представленный эскейп-последовательностью) занимает ровно 1 байт. В конце записи строковой константы компилятор помещает символ ‘\0’ .
Таким образом, количество байтов, выделяемое в памяти компьютера для представления значения строки, на единицу больше, чем число символов в записи этой строковой константы:
«Строка в 18 байт.»
Внимание . При работе с символьной информацией важно помнить, что длина символьной константы, например, ‘A’ равна 1 байту, а длина строки «A» равна 2 байтам, т.к. строка заканчивается нуль-символом ( ‘\0’ ).
5.Булевые константы . Имеется всего два значения: true — истина и false — ложь.
Комментарии
Комментарий — это последовательность любых знаков (символов), которая используется в тексте программы для её пояснения. Обычно в тексте программы делают вводный комментарий к программе в целом (её назначение, автор, дата создание и т.д.), а далее дают комментарии к отдельным фрагментам текста программы, смысл которых не является очевидным. Важно объяснить не только то, что делается, а для чего это делается. Комментарии важны в любом случае: делается ли программа для себя, или с ней будут работать другие люди.
Комментарии игнорируются компилятором языка программирования, они нужны только для человека. В языке С++ имеется два вида комментариев: однострочные и многострочные.
Однострочный комментарий начинается с символов // (две косые черты). Всё, что записано после этих символов и до конца строки, считается комментарием. Например:
// Это текст комментария
Многострочный комментарий начинается парой символов /* (косая черта и звёздочка) и заканчивается символами */ (звёздочка и косая черта). Текст такого комментария может занимать одну или несколько строк. Всё, что находится между знаками /* и */ , считается комментарием. Например:
Строки в C# и .NET
От переводчика: Джон Скит написал несколько статей о строках, и данная статья является первой, которую я решил перевести. Дальше планирую перевести статью о конкатенации строк, а потом — о Юникоде в .NET.
Тип System.String (в C# имеющий алиас string) является одним из наиболее часто используемых и важных типов в .NET, и вместе с тем одним из самых недопонимаемых. Эта статья описывает основы данного типа и развенчивает сложившиеся вокруг него мифы и непонимания.
Так что же такое string
Строка в .NET (далее — string, я не буду использовать полное имя System.String каждый раз) является последовательностью символов. Каждый символ является символом Юникода в диапазоне от U+0000 до U+FFFF (будет рассмотрено далее). Строковый тип имеет следующие характеристики:
Строка является ссылочным типом
Существует распространённое заблуждение о том, что строка является значимым типом. Это заблуждение истекает из свойства неизменяемости строки (см. следующий пункт), так как для неискушенного программиста неизменяемость часто по поведению кажется схожей со значимыми типами. Тем не менее, string — ссылочный тип, со всеми присущими ссылочным типам характеристиками. Я более детально расписал о различиях между ссылочными и значимыми типами в своих статьях «Parameter passing in C#» и «Memory in .NET — what goes where».
Строка является неизменяемой
Никак невозможно изменить содержимое созданной строки, по крайней мере в безопасном (safe) коде и без рефлексии. Поэтому вы при изменении строк изменяете не сами строки, а значения переменных, указывающих на строки. Например, код s = s.Replace («foo», «bar»); не изменяет содержимое строки s, которое было до вызова метода Replace — он просто переназначает переменную s на новообразованную строку, которая является копией старой за исключением всех подстрок «foo», заменённых на «bar».
Строка может содержать значение null
В языке C строки являются последовательностями символов, оканчивающимися символом ‘\0‘, также называемым «nul» или «null». Я называю его «null», так как именно такое название имеет символ ‘\0’ в таблице символов Юникода. Не путайте символ «null» с ключевым словом null в C# — тип System.Char является значимым, а потому не может принимать значение null . В .NET строки могут содержать символ «null» в любом месте и работать с ним без каких-либо проблем. Тем не менее, некоторые классы (к примеру, в Windows Forms) могут расценивать «null»-символ в строке как признак конца строки и не учитывать всё содержимое строки после этого символа, поэтому использование «null»-символов таки может стать проблемой.
Строка переопределяет оператор равенства ==
При вызове оператора == для определения равенства двух строк происходит вызов метода Equals , который сравнивает именно содержимое строк, а не равенство ссылок. К примеру, выражение «hello».Substring(0, 4)==»hell» возвратит true , хотя ссылки на строки по обеих сторонах оператора равенства разные (две ссылки ссылаются на два разных строковых экземпляра, которые, при этом, содержат одинаковые значения). Вместе с тем необходимо помнить, что равенство значений, а не ссылок происходит только тогда, когда оба операнда на момент компиляции являются строго строковым типом — оператор равенства не поддерживает полиморфизм. Поэтому если хотя бы один из сравниваемых операндов будет иметь тип object , к примеру (хотя внутренне и будет оставаться строкой), то будет выполнено сравнение ссылок, а не содержимого строк.
Интернирование
В .NET существует понятие «пула интернирования» (intern pool). По своей сути это всего лишь набор строк, но он обеспечивает то, что когда вы в разных местах программы используете разные строки с одним и тем же содержимым, то это содержимое будет храниться лишь один раз, а не создаваться каждый раз по-новому. Вероятно, пул интернирования зависит от конкретного языка, однако он определённо существует в C# и VB.NET, и я бы был очень удивлён, увидев язык на платформе .NET, не использующий пул интернирования; в MSIL пул интернирования очень просто использовать, гораздо проще, нежели не использовать. Наряду с автоматическим интернированием строковых литералов, строки можно интернировать вручную при помощи метода Intern , а также проверять, является ли та или иная строка уже интернированной при помощи метода IsInterned . Метод IsInterned не интуитивен, так как вы ожидаете, что он возвратит Boolean , а вот и нет — если текущая строка уже существует в пуле интернирования, то метод возвратит ссылку на неё, а если не существует, то null . Подобно ему, метод Intern возвращает ссылку на интернированную строку, причём вне зависимости от того, была ли текущая строка в пуле интернирования до вызова метода, или же она была туда занесена вместе с вызовом метода, или же пул интернирования содержит копию текущей строки.
Литералы
Литерал — это, грубо говоря, «захардкодженное» в коде значение строки. Есть два типа строковых литералов в C# — стандартные (regular) и дословные (verbatim). Стандартные литералы в C# схожи с таковыми в большинстве языков программирования — они обрамляются в двойные кавычки («), а также могут содержать специальные символы (собственно двойные кавычки («), обратный слеш (\), перенос строки (carriage return — CR), подача строки (line feed — LF) и некоторые другие), требующие экранирования. Дословные литералы позволяют почти то же самое, что и стандартные, однако дословный литерал оканчивается на первых не продублированных двойных кавычках. Чтобы собственно вставить в дословный литерал двойные кавычки, вам нужно их продублировать («»). Также, в отличие от стандартного литерала, в дословном могут присутствовать символы возврата каретки и переноса строки без экранирования. Для использования дословного литерала необходимо указать @ перед открывающей кавычкой. Ниже в таблице собраны примеры, демонстрирующие различия между описанными типами литералов.
Стандартный литерал | Дословный литерал | Результирующая строка |
---|---|---|
«Hello» | @»Hello» | Hello |
«Обратный слеш: \\» | @»Обратный слеш: \» | Обратный слеш: \ |
«Двойная кавычка: \»» | @»Двойная кавычка: «»» | Двойная кавычка: « |
«CRLF:\r\nПосле CRLF» | @»CRLF: После CRLF» | CRLF: После CRLF |
- \’ — одинарная кавычка, используется для объявления литералов типа System.Char
- \» — двойная кавычка, используется для объявления строковых литералов
- \\ — обратный слеш
- \0 — null-символ в Юникоде
- \a — символ Alert (№7)
- \b — символ Backspace (№8)
- \f —смена страницы FORM FEED (№12)
- \n — перевод строки (№10)
- \r — возврат каретки (№13)
- \t — горизонтальная табуляция (№9)
- \v — вертикальная табуляция (№11)
- Uxxxx — символ Юникода с шестнадцатеричным кодом xxxx
- \xn[n][n][n] — символ Юникода с шестнадцатеричным кодом nnnn, версия предыдущего пункта с переменной длиной цифр кода
- \Uxxxxxxxx — символ Юникода с шестнадцатеричным кодом xxxxxxxx, используется для вызова суррогатных пар.
Строки и отладчик
Довольно часто при просмотре строк в отладчике (используя VS.NET 2002 и VS.NET 2003) люди сталкиваются с проблемами. Ирония в том, что эти проблемы чаще всего создаёт отладчик, пытаясь быть полезным. Иногда он отображает строку в виде стандартного литерала, экранируя обратными слешами все спецсимволы, а иногда он отображает строку в виде дословного литерала, оглавляя её @. Поэтому многие спрашивают, как удалить из строки @, хотя его там фактически нет. Кроме этого, отладчики в некоторых версиях VS.NET не отображают строки с момента первого вхождения null-символа \0, и что ещё хуже, неправильно вычисляют их длины, так как подсчитывают их самостоятельно вместо запроса к управляемому коду. Естественно, всё это из-за того, что отладчики рассматривают \0 как признак окончания строки.
Учитывая такую путаницу, я пришел к выводу, что при отладке подозрительных строк их следует рассматривать множеством способов, дабы исключить все недоразумения. Я предлагаю использовать приведённый ниже метод, который будет печатать содержимое строки в консоль «правильным» способом. В зависимости от того, какое приложение вы разрабатываете, вы можете вместо вывода в консоль записывать строки в лог-файл, отправлять в трассировщики, выводит в модальном Windows-окне и т.д.
static readonly string[] LowNames = < "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US" >; public static void DisplayString (string text) < Console.WriteLine ("String length: ", text.Length); foreach (char c in text) < if (c < 32) < Console.WriteLine ("<> U+", LowNames[c], (int)c); > else if (c > 127) < Console.WriteLine ("(Possibly non-printable) U+", (int)c); > else < Console.WriteLine ("U+", c, (int)c); > > >
Использование памяти и внутренняя структура
В текущей реализации .NET Framework каждая строка занимает 20+(n/2)×4 байт, где n — количество символов в строке или, что одно и то же, её длина. Строковый тип необычен тем, что его фактический размер в байтах изменяется им самим. Насколько я знаю, так могут делать только массивы. По факту, строка — это и есть массив символов, расположенный в памяти, а также число, обозначающее фактический размер массива в памяти, а также число, обозначающее фактическое количество символов в массиве. Как вы уже поняли, длина массива не обязательно равна длине строки, так как строки могут перераспределяться со стороны mscorlib.dll для облегчения их обработки. Так само делает, к примеру, StringBuilder . И хотя для внешнего мира строки неизменяемые, внутри mscorlib они ещё как изменяемые. Таким образом, StringBuilder при создании строки выделяет несколько больший символьный массив, нежели того требует текущий литерал, а потом прибавляет новые символы в созданный массив до тех пор, пока они «влезают». Как только массив заполняется, создаётся новый, ещё больший массив, и в него копируется содержимое из старого. Кроме этого, в числе, обозначающем длину строки, первый бит отведён под специальный флаг, определяющий, содержит ли строка не-ASCII символы или нет. Благодаря этому флагу исполняющая среда в некоторых случаях может проводить дополнительные оптимизации.
Хотя со стороны API строки не являются null-терминированными, внутренне символьные массивы, представляющие строки, являются. А это значит, что строки из .NET могут напрямую передаваться в неуправляемый код безо всякого копирования, предполагая, что при таком взаимодействии строки будут маршаллированы как Юникод.
Кодировки строк
Если вы не знакомы с кодировками символов и Юникодом, пожалуйста, прочтите сначала мою статью о Юникоде (или её перевод на Хабре).
Как я уже сказал вначале статьи, строки всегда хранятся в Юникод-кодировке. Всякие домыслы о Big-5-кодировках или UTF-8-кодировках являются ошибкой (по крайней мере, по отношению к .NET) и являются следствием незнания самих кодировок или того, как .NET обрабатывает строки. Очень важно понять этот момент — рассматривание строки как такой, которая содержит некий валидный текст в кодировке, отличной от Юникода, почти всегда является ошибкой.
Далее, набор символов, поддерживаемых Юникодом (одним из недостатков Юникода является то, что один термин используется для разных вещей, включая кодировки и схемы кодировок символов), превышает 65536 символов. А это значит, что один char (System.Char) не может содержать любой символ Юникода. А это приводит к понятию суррогатных пар, где символы с кодом выше U+FFFF представляются в виде двух символов. По сути, строки в .NET используют кодировку UTF-16. Возможно, большинству разработчиков и не нужно углубляться касательно этого в детали, но по крайней мере это стоит знать.
Региональные и интернациональные странности
Некоторые странности в Юникоде ведут к странностям при работе со строками и символами. Большинство строковых методов зависимы от региональных настроек (являются culture-sensitive — регионально-чувствительными), — другими словами, работа методов зависит от региональных настроек потока, в котором эти методы выполняются. Например, как вы думаете, что возвратит этот метод «i».toUpper() ? Большинство скажут: «I», а вот и нет! Для турецких региональных настроек метод вернёт «İ» (код U+0130, описание символа: «Latin capital I with dot above»). Для выполнения регионально-независимой смены регистра вы можете использовать свойство CultureInfo.InvariantCulture и передать его как параметр в перегруженную версию метода String.ToUpper , которая принимает CultureInfo .
Есть и другие странности, связанные со сравнением и сортировкой строк, а также с нахождением индекса подстроки в строке. Некоторые из этих операций регионально-зависимы, а некоторые — нет. Например, для всех регионов (насколько я могу видеть) литералы «lassen» и «la\u00dfen» (во втором литерале шестнадцатеричным кодом указан символ «S острое» или «эсце́т») определяются как равные при передачи их в методы CompareTo или Compare , но вот если передать их в Equals , то будет определено неравенство. Метод IndexOf будет учитывать эсцет как «ss» (двойное «s»), но вот если вы используете одну из перегрузок CompareInfo.IndexOf , где укажете CompareOptions.Ordinal , то эсцет будет обработан правильно.
Некоторые символы Юникода вообще абсолютно невидимы для стандартного метода IndexOf . Однажды кто-то спросил в группе новостей C#, почему метод поиска и замены уходит в бесконечный цикл. Этот человек использовал метод Replace для замены всех сдвоенных пробелов одним, а потом проверял, окончилась ли замена и нет ли больше сдвоенных пробелов в строке, используя IndexOf . Если IndexOf показывал, что сдвоенные пробелы есть, строка снова отправлялась на обработку к Replace . К сожалению, всё это «ломалось», так как в строке присутствовал некий «неправильный» символ, расположенный точно между двумя пробелами. IndexOf сообщал о присутствии сдвоенного пробела, игнорируя этот символ, а Replace не выполнял замену, так как «видел» символ. Я так и не узнал, что это был за символ, но подобная ситуация легко воспроизводится при помощи символа U+200C, который является «не-связующим символом нулевой ширины» (англ. zero-width non-joiner character), что бы это не значило, чёрт возьми! Поместите такой или ему подобный в вашу строку, и IndexOf будет его игнорировать, а Replace — нет. Снова-таки, чтобы заставить оба метода работать одинаково, вы можете использовать CompareInfo.IndexOf и указать ему CompareOptions.Ordinal . Мне кажется, что уже написано достаточно много кода, который будет «валиться» на таких «неудобных» данных. И я даже не намекаю, что мой собственный код застрахован от подобного.
Microsoft опубликовала некоторые рекомендации касательно обработки строк, и хотя они датируются 2005-м годом, их всё ещё сто́ит прочесть.
Выводы
Для такого базового типа, как строка (да и вообще для текста в общем), строка в .NET является намного сложней, нежели вам может показаться. Очень важно понять основы, описанные в этой статье, даже если некоторые нюансы сравнения и регистра строк в мульти-региональных контекстах будут от вас ускользать. В частности, жизненно важной является способность диагностировать ошибки кодировок строк, правильно логируя эти самые строки.
От переводчика: Так как статья относительно не новая, я решил проверить описанные Джоном Скитом «странности» и проблемы в строках. В результате, мне удалось воспроизвести всё то, что описано в разделе «Региональные и интернациональные странности», используя версии .NET Framework 3.5, 4.0 и 4.5 включительно. Вместе с тем странности касательно отображения литералов в отладчике, описанные в разделе «Строки и отладчик», я не встречал ни разу, по крайней мере в MS Visual Studio 2008, 2010 и 2012 включительно.
Новая строка — Newline
Новая строка вставлена между словами «Hello» и «world»
Новая строка (часто называется конец строки, конец строки (EOL ), перевод строки или разрыв строки ) — это управляющий символ или последовательность управляющих символов в спецификации кодировки символов (например, ASCII или EBCDIC ) который используется для обозначения конца строки текста и начала новой строки. Некоторые текстовые редакторы устанавливают этот специальный символ при нажатии клавиши ↵ Enter .
При отображении (или печати) текстового файла этот управляющий символ заставляет текстовый редактор отображать следующие символы в новой строке.
- 1 История
- 2 Представление
- 2.1 Unicode
- 2.2 Escape-последовательности
- 2.3 В языках программирования
- 2.4 Проблемы с различными форматами новой строки
- 2.5 Преобразование между форматами новой строки
История
В середине 1800-х годов, задолго до появления из телетайпов и телетайпов, операторов азбуки Морзе или телеграфистов изобрели и использовали просигналы азбуки Морзе для кодирования форматирования текста с пробелами в формальном письменном текстовые сообщения. В частности, азбука Морзе, представленная конкатенацией двух буквальных текстовых символов азбуки Морзе «A», отправленных без обычного межсимвольного интервала, используется в коде Морзе для кодирования и обозначения новой строки в формальном текстовом сообщении.
Позже, в эпоху современных телетайпов, были разработаны стандартизированные коды управления набором символов для помощи в форматировании текста с пробелами. ASCII был разработан одновременно Международной организацией по стандартизации (ISO) и Американской ассоциацией стандартов (ASA), последняя является организацией-предшественником Американского национального института стандартов (ANSI). В период с 1963 по 1968 год проекты стандартов ISO поддерживали использование только CR + LF или LF в качестве новой строки, в то время как проекты ASA поддерживали только CR + LF.
Последовательность CR + LF обычно использовалась во многих ранних компьютерных системах, которые использовали машины Teletype — как правило, Teletype Model 33 ASR — как консольное устройство, потому что эта последовательность требовалась для размещения этих принтеров в начале новой строки. Разделение новой строки на две функции скрывало тот факт, что печатающая головка не могла вовремя вернуться из крайнего правого угла в начало следующей строки, чтобы напечатать следующий символ. Любой символ, напечатанный после CR, часто печатался как пятно в середине страницы, пока печатающая головка все еще возвращала каретку в первое положение. «Решением было сделать новую строку двумя символами: CR, чтобы переместить каретку в первый столбец, и LF, чтобы переместить бумагу вверх». Фактически, часто приходилось отправлять дополнительные символы — посторонние CR или NUL — которые игнорируются, но дают печатающей головке время переместиться к левому полю. Многие ранние видеодисплеи также требовали нескольких символов для прокрутки экрана.
В таких системах приложения должны были напрямую взаимодействовать с машиной Teletype и следовать ее соглашениям, поскольку концепция драйверов устройств, скрывающих такие детали оборудования от приложения, еще не была хорошо разработана. Поэтому текст обычно составлялся для удовлетворения потребностей телетайпов. Большинство миникомпьютерных систем из DEC использовали это соглашение. CP / M также использовал его для печати на тех же терминалах, что и миникомпьютеры. Оттуда MS-DOS (1981) приняла CP / M’s CR + LF для обеспечения совместимости, и это соглашение было унаследовано более поздней операционной системой Microsoft Windows.
Операционная система Multics начала разработку в 1964 году и использовала только LF в качестве новой строки. Multics использовала драйвер устройства для преобразования этого символа в любую последовательность, необходимую для принтера (включая дополнительные символы-заполнители), и однобайтный байт был более удобен для программирования. То, что кажется более очевидным выбором — CR — не использовалось, поскольку CR обеспечивал полезную функцию наложения одной строки на другую для создания эффектов жирным шрифтом и зачеркиванием. Возможно, что более важно, использование только LF в качестве ограничителя линии уже было включено в проекты возможного стандарта ISO / IEC 646. Unix следовала практике Multics, а более поздние Unix-подобные системы следовали за Unix. Это создавало конфликты между Windows и Unix-подобными ОС, в результате чего файлы, созданные в одной ОС, не могли быть правильно отформатированы или интерпретированы другой ОС (например, сценарий оболочки UNIX, написанный в текстовом редакторе Windows, например Блокнот ).
Представление
Понятия перевода строки (LF) и возврата каретки (CR) тесно связаны и могут рассматриваться как по отдельности, так и вместе. На физическом носителе пишущих машинок и принтеров две оси движения, «вниз» и «поперек», необходимы для создания новой строки на стр.. Хотя конструкция машины (пишущая машинка или принтер) должна рассматривать их по отдельности, абстрактная логика программного обеспечения может объединить их вместе как одно событие. Вот почему новую строку в кодировке символов можно определить как LF и CR , объединенные в один (обычно называемый CR + LF или CRLF ).
Некоторые наборы символов предоставляют отдельный код символа новой строки. EBCDIC, например, предоставляет код символа NL в дополнение к кодам CR и LF. Unicode, помимо предоставления управляющих кодов ASCII CR и LF , также предоставляет «следующую строку» (NEL) контрольный код, а также контрольные коды для маркеров «разделитель строк» и «разделитель абзацев».
Unicode
Стандарт Unicode определяет количество символов, которые соответствующие приложения должны распознавать как терминаторы строки:
LF :Перевод строки, U + 000A VT :Вертикальная табуляция, U + 000B FF :Подача страницы, U + 000C CR :Возврат каретки, U + 000D CR + LF: CR (U + 000D), за которым следует LF (U + 000A) NEL : Следующая строка, U + 0085 LS :Разделитель строк, U + 2028 PS :Разделитель абзацев, U + 2029
Это может показаться слишком сложным по сравнению с таким подходом, как преобразование всех разделители строк до одного символа, например LF. Однако Unicode был разработан для сохранения всей информации при преобразовании текстового файла из любой существующей кодировки в Unicode и обратно. Следовательно, Unicode должен содержать символы, включенные в существующие кодировки. NL включен в EBCDIC с кодом 0x15 и часто отображается в NEL, который является управляющим символом в наборе управления C1. Как таковой, он определен ECMA 48 и распознается кодировками, соответствующими ISO / IEC 2022 (что эквивалентно ECMA 35). Комплект управления C1 также совместим с ISO-8859-1. Подход, принятый в стандарте Unicode, позволяет выполнять двустороннее преобразование с сохранением информации, в то же время позволяя приложениям распознавать все возможные типы терминаторов линии.
Распознавание и использование кодов новой строки больше 0x7F (NEL, LS и PS) выполняется нечасто. Это несколько байтов в UTF-8, а код для NEL использовался как символ многоточие ( … ) в Windows-1252. Например:
- ECMAScript принимает LS и PS как разрывы строк, но рассматривает U + 0085 (NEL) пробел вместо строки -break.
- Windows 10 не обрабатывает любые из NEL, LS или PS как разрывы строк в текстовом редакторе по умолчанию, Блокнот.
- , по умолчанию для GNOMEсреды рабочего стола, LS и PS рассматриваются как символы новой строки, но не для NEL.
- JSON допускает LS и PS в строках, тогда как ECMAScript до ES2019 рассматривал их как символы новой строки и, следовательно, недопустимый синтаксис.
- YAML больше не распознает их как особые, начиная с версии 1.2, для совместимости с JSON.
символы Unicode U + 2424 (SYMBOL FOR NEWLINE,  ), U + 23CE (RETURN SYMBOL, ⏎ ), U + 240D (СИМВОЛ ВОЗВРАТА ПЕРЕВОЗКИ, ␍ ) и U + 240A (СИМВОЛ ДЛЯ ЛИНИЙ ПОДАЧИ, ␊ ) предназначены для представления читателю документа видимого пользователем символа, d, таким образом, не распознаются как перевод строки.
escape-последовательности
escape-последовательность — это комбинация символов, которая не представляет собой текста; вместо отображения (в виде текста) предполагается, что он будет перехвачен программой и должна выполняться специальная функция. Escape-последовательности также используются для обработки (установка, поиск, замена и т. Д.) Специальных символов.
Escape-последовательности
Специальный символ Escape-последовательность Используется. Примеры перевод строки \ n Perl, Vim. Vim: :% s /> /> \ r \ t / g = заменить каждый символ ‘>’ на ‘> табулятор новой строки’ в весь файл возврат каретки \ r табулятор \ t В языках программирования
Для облегчения создания переносимых программ, языков программирования предоставить некоторые абстракции для работы с различными типами последовательностей новой строки, используемыми в разных средах.
Язык программирования C предоставляет управляющие последовательности ‘\ n’ (новая строка) и ‘\ r’ (возврат каретки). Однако они не обязательно должны быть эквивалентами управляющих символов ASCII LF и CR. Стандарт C гарантирует только две вещи:
- Каждая из этих управляющих последовательностей отображается на уникальный номер, определенный реализацией, который может быть сохранен в единственном значении char.
- При записи в файл устройство node или socket / fifo в текстовом режиме, ‘\ n’ прозрачно транслируется в исходную последовательность новой строки, используемую системой, которая может быть длиннее одного символа. При чтении в текстовом режиме собственная последовательность новой строки переводится обратно в ‘\ n’. В двоичном режиме преобразование не выполняется, и внутреннее представление, созданное с помощью ‘\ n’, выводится напрямую.
На платформах Unix, где возник C, собственная последовательность новой строки — ASCII LF (0x0A), поэтому ‘\ n’ просто определено как это значение. Поскольку внутреннее и внешнее представление идентичны, перевод, выполняемый в текстовом режиме, представляет собой no-op, а в Unix нет понятия текстового режима или двоичного режима. Это привело к тому, что многие программисты, которые разработали свое программное обеспечение в системах Unix, просто полностью игнорировали это различие, в результате чего код не переносился на другие платформы.
Библиотечную функцию C fgets () лучше избегать в двоичном режиме, потому что любой файл, записанный не в соответствии с соглашением о новой строке Unix, будет неправильно прочитан. Кроме того, в текстовом режиме любой файл, записанный без собственной системной последовательности новой строки (например, файл, созданный в системе Unix, а затем скопированный в систему Windows), также будет неправильно прочитан.
Другой распространенной проблемой является использование ‘\ n’ при обмене данными с использованием Интернет-протокола, который требует использования ASCII CR + LF для конечных строк. Запись ‘\ n’ в поток текстового режима корректно работает в системах Windows, но производит только LF в Unix и что-то совершенно другое в более экзотических системах. Немного лучше использовать «\ r \ n» в двоичном режиме.
Многие языки, такие как C ++, Perl и Haskell, предоставляют ту же интерпретацию ‘\ n’, что и C. В C ++ есть альтернативная модель ввода-вывода, в которой манипулятор std :: endl может использоваться для вывода новой строки (и очищает буфер потока).
Java, PHP и Python предоставляют последовательность ‘\ r \ n’ (для ASCII CR + LF). В отличие от C, они гарантированно представляют значения U + 000D и U + 000A соответственно.
Библиотеки ввода-вывода Java не переводят их прозрачно в зависящие от платформы последовательности новой строки при вводе или выводе. Вместо этого они предоставляют функции для записи полной строки, которая автоматически добавляет собственную последовательность новой строки, и функции для чтения строк, которые принимают любой из CR, LF или CR + LF в качестве признака конца строки. (см. BufferedReader.readLine () ). Метод System.lineSeparator () можно использовать для получения нижележащего разделителя строк.
Строка eol = System.lineSeparator (); Строка lineColor = "Цвет: Красный" + eol;
Python разрешает «универсальную поддержку новой строки» при открытии файла для чтения, при импорте модулей и при выполнении файла.
В некоторых языках созданы специальные переменные, константы и подпрограммы для облегчения перевода строки во время выполнения программы. В некоторых языках, таких как PHP и Perl, двойные кавычки требуются для выполнения escape-замены для всех escape-последовательностей, включая ‘\ n’ и ‘\ r’. В PHP, чтобы избежать проблем с переносимостью, последовательности новой строки должны выдаваться с использованием константы PHP_EOL.
string eol = Environment.NewLine; строка lineColor = "Цвет: Красный" + eol; строка eol2 = "\ n"; строка lineColor2 = "Цвет: синий" + eol2;
Проблемы с разными форматами новой строки
A текстовый файл, созданный и просматриваемый с расширением. Помимо текстовых объектов, есть только маркеры EOL с шестнадцатеричным значением 0A.
Несмотря на то, что управляющие символы однозначно определены в соответствующей таблице кодировки символов, используемой текстовым файлом, проблема все еще существует : существуют разные соглашения для установки и отображения разрыва строки.
Для обозначения одинарного разрыва строки программы Unix используют перевод строки , шестнадцатеричное значение которого в ASCII равно 0a , в то время как большинство программ являются общими для MS-DOS и Microsoft Windows используют возврат каретки + перевод строки , шестнадцатеричное значение которого в ASCII равно 0d 0a . В ASCII возврат каретки — это отдельный управляющий символ.
Различные соглашения о переводе строки приводят к тому, что текстовые файлы, которые были переданы между системами разных типов, отображаются неправильно.
Текст в файлах, созданных с помощью программ, которые являются общими для Unix-подобных или классической Mac OS, отображается как одна длинная строка в большинстве программ, общих для MS-DOS и Microsoft Windows, потому что они не отображают ни один перевод строки , ни один возврат каретки в качестве разрыва строки.
И наоборот, при просмотре файла, созданного с компьютера Windows в Unix-подобной системе, дополнительный CR может отображаться как второй разрыв строки, как ^ M или как в конце каждой строки.
Кроме того, программы, отличные от текстовых редакторов, могут не принимать файл, например некоторый файл конфигурации, закодированный с использованием иностранного соглашения о новой строке, в качестве допустимого файла.
Проблему трудно обнаружить, потому что некоторые программы правильно обрабатывают внешние символы новой строки, а другие — нет. Например, компилятор может дать сбой из-за неясных синтаксических ошибок, даже если исходный файл выглядит правильно при отображении на консоли или в файле. В Unix-подобной системе команда cat -v myfile.txt отправит файл на стандартный вывод (обычно в терминал) и сделает видимым ^ M, что может быть полезно для отладки. Современные текстовые редакторы обычно распознают все разновидности символов новой строки CR + LF и позволяют пользователям переходить между разными стандартами. Веб-браузеры обычно также могут отображать текстовые файлы и веб-сайты, которые используют разные типы символов новой строки.
Даже если программа поддерживает различные соглашения о новой строке, эти функции часто недостаточно помечены, описаны или задокументированы. Обычно меню или поле со списком, в котором перечислены различные соглашения о новой строке, будут отображаться для пользователей без указания, будет ли выбор повторно интерпретирован, временно преобразован или окончательно преобразован. Некоторые программы неявно конвертируют при открытии, копировании, вставке или сохранении — часто непоследовательно.
Большинство текстовых Интернет протоколов (включая HTTP, SMTP, FTP, IRC и многие другие) требуют использования ASCII CR + LF (‘\ r \ n’, 0x0D 0x0A) на уровне протокола, но рекомендуют терпимые приложения также распознает одиночный LF (‘\ n’, 0x0A). Несмотря на продиктованный стандарт, многие приложения ошибочно используют escape-последовательность C новой строки ‘\ n’ (LF) вместо правильной комбинации escape-последовательностей возврата каретки и escape-последовательностей новой строки ‘ \ r \ n ‘(CR + LF) (см. раздел Новая строка в языках программирования выше). Это случайное использование неправильных управляющих последовательностей приводит к проблемам при попытке связи с системами, придерживающимися более строгой интерпретации стандартов вместо предлагаемой толерантной интерпретации. Одной из таких нетерпимых систем является qmail агент пересылки почты, который активно отказывается принимать сообщения от систем, которые отправляют чистый LF вместо требуемого CR + LF.
Стандартный формат Интернет-сообщения для состояний электронной почты: CR и LF ДОЛЖНЫ встречаться вместе только как CRLF; они НЕ ДОЛЖНЫ появляться в теле независимо друг от друга.
Протокол передачи файлов может автоматически преобразовывать символы новой строки в файлах, передаваемых между системами , с разными представлениями новой строки, когда передача выполняется в «режиме ASCII». Однако передача двоичных файлов в этом режиме обычно приводит к катастрофическим результатам: любое появление байтовой последовательности новой строки — которая не имеет семантики терминатора строки в этом контексте, но является лишь частью нормальной последовательности байтов — будет преобразовано в любое представление новой строки другая система использует, эффективно разрушая файл. FTP-клиенты часто используют некоторую эвристику (например, проверка расширений файлов ) для автоматического выбора двоичного или ASCII-режима, но в конечном итоге пользователи должны сами убедиться, что их файлы переведены в правильный режим. Если есть какие-либо сомнения относительно правильного режима, следует использовать двоичный режим, так как в этом случае файлы не будут изменены FTP, хотя они могут отображаться некорректно.
Преобразование между форматами новой строки
часто используется для преобразования текстового файла между различными форматами новой строки; большинство современных редакторов могут читать и записывать файлы, используя как минимум различные соглашения ASCII CR / LF. Например, редактор может сделать файл совместимым с текстовым редактором Windows Notepad. Внутри vim
: set fileformat = dos: wq
Редакторы могут не подходить для преобразования больших файлов или массового преобразования большого количества файлов. Для больших файлов (в Windows NT / 2000 / XP) часто используется следующая команда:
D: \>TYPE unix_file | FIND / V "">dos_file
Программы специального назначения для преобразования файлов между различными соглашениями о новой строке включают unix2dos и dos2unix, mac2unix и unix2mac, mac2dos и dos2mac и перевернуть. Команда tr доступна практически в каждой Unix-подобной системе и может использоваться для выполнения произвольных операций замены над отдельными символами. Текстовый файл DOS / Windows можно преобразовать в формат Unix, просто удалив все символы ASCII CR с помощью
$ tr -d '\ r' < inputfile>outputfile
или, если в тексте есть только CR новые строки, путем преобразования всех CR новые строки в LF с
$ tr '\ r' '\ n' < inputfile>outputfile
Те же задачи иногда выполняются с awk, sed или в Perl, если на платформе есть интерпретатор Perl:
$ awk ' 'inputfile>outputfile # UNIX в DOS (добавление CR в ОС Linux и BSD, не имеющих расширений GNU) $ awk' 'inputfile>outputfile # DOS в UNIX (удаление CR в ОС Linux и BSD, не имеющих расширений GNU) $ sed -e' s / $ / \ r / 'inputfile>outputfile # UNIX в DOS (добавление CR в ОС на базе Linux, использующей расширения GNU) $ sed -e 's / \ r $ //' inputfile>outputfile # DOS в UNIX (удаление CR в ОС на базе Linux, использующих расширения GNU) $ perl -pe 's / \ r ? \ n | \ r / \ r \ n / g 'inputfile>outputfile # Конвертировать в DOS $ perl -pe' s / \ r? \ n | \ r / \ n / g 'inputfile>outputfile # Конвертировать в UNIX $ perl -pe 's / \ r? \ n | \ r / \ r / g' inputfile>outputfile # Преобразовать в старый Mac
Команда file может определить тип окончания строки :
$ file myfile.txt myfile.txt: Текст ASCII на английском языке с терминаторами строки CRLF
Команда Unix egrep (расширенный grep) может использоваться для печати имен файлов файлов Unix или DOS ( при условии только файлов в стиле Unix и DOS, без Mac OS):
$ egrep -L '\ r \ n' myfile.txt # показать файл стиля UNIX (завершение LF) $ egrep -l '\ r \ n' myfile.txt # показать файл стиля DOS (CRLF завершается)
Другие инструменты позволяют пользователю визуализировать символы EOL:
$ od -a myfile.txt $ cat -e myfile.txt $ hexdump -c myfile.txt
Интерпретация
Два Способы просмотра новых строк, оба из которых являются самосогласованными, заключаются в том, что новые строки либо разделяют строки, либо завершают строки. Если символ новой строки считается разделителем, после последней строки файла не будет новой строки. У некоторых программ возникают проблемы с обработкой последней строки файла, если она не заканчивается символом новой строки. С другой стороны, программы, которые ожидают использования новой строки в качестве разделителя, будут интерпретировать последнюю новую строку как начало новой (пустой) строки. И наоборот, если символ новой строки считается терминатором, ожидается, что все текстовые строки, включая последнюю, будут завершены новой строкой. Если последняя последовательность символов в текстовом файле не является новой строкой, последняя строка файла может считаться неправильной или неполной текстовой строкой, или файл может считаться неправильно обрезанным.
В тексте, предназначенном в первую очередь для чтения людьми, использующими программное обеспечение, которое реализует функцию переноса слов, символ новой строки обычно необходимо сохранять только в том случае, если требуется разрыв строки, независимо от того, будет ли следующий слово поместится в одной строке, например, между абзацами и в вертикальных списках. Следовательно, в логике текстового редактора и многих других, новая строка используется как разрыв абзаца и известна как «жесткий возврат», в отличие от «мягкого возврата», который выполняется динамически созданы для реализации переноса слов и могут изменяться с каждым экземпляром отображения. Во многих приложениях существует отдельный управляющий символ , называемый «разрыв строки вручную», для принудительного разрыва строки внутри одного абзаца. Глиф для управляющего символа для жесткого возврата обычно представляет собой pilcrow (¶), а для ручного переноса строки — обычно стрелка возврата каретки (↵).
Обратный и частичный перевод строки
RI, (U + 008D REVERSE LINE FEED, ISO / IEC 6429 8D, десятичный 141) используется для перемещения положение печати назад на одну строку (путем обратной подачи бумаги или путем перемещения курсора дисплея на одну строку вверх), чтобы другие символы могли быть напечатаны поверх существующего текста. Это можно сделать, чтобы сделать их более жирными или добавить подчеркивание, зачеркивание или другие символы, такие как диакритические знаки.
. Аналогично, PLD (U + 008B ЧАСТИЧНАЯ СТРОКА ВПЕРЕД, десятичная 139) и PLU (U + 008C PARTIAL LINE BACKWARD, десятичное 140) можно использовать для перемещения вперед или назад позиции печати текста на некоторую долю вертикального межстрочного интервала (обычно половину). Их можно использовать в комбинации для нижних индексов (путем перехода вперед, а затем в обратном направлении) и верхних индексов (путем поворота и последующего продвижения), а также может быть полезно для печати диакритических знаков.
См. Также
- Управляющие символы каретки ASA
- Управляющие коды C0 и C1
- Конец файла
- Отсутствие строки
- Разрыв страницы
- Возврат каретки
- Enter key
Ссылки
Внешние ссылки
- Ссылка на Unicode, см. параграф 5.8 в Глава 5 стандарта Unicode 4.0 (PDF)
- Символ новой строки [NEL]
- Загадка конца строки
- Понимание новых строк в Wayback Machine (архивировано 20 августа 2006 г.) в O’Reilly-Net — статья Ксавьера Нориа.
- «Конец -of-Line Story «