
- •1 Масиви
- •2 Рядки і символи
- •Реализация в языках программирования
- •[Править] в языке Си
- •Урок 6. Класс string
- •Класс string
- •Упражнение 3.12
- •Упражнение 3.13
- •Упражнение 3.14
- •Упражнение 3.15
- •Клас string: конструктори і присвоєння рядків, операції, відкладене копіювання Клас string: конструктори і присвоєння рядків, операції, відкладене копіювання
- •2 Рядки і символи
Реализация в языках программирования
В первых языках программирования вообще не было строкового типа; программист должен был сам строить функции для работы со строками того или другого типа.
В Си используются нуль-терминированные строки с полным ручным контролем со стороны программиста.
В стандартном Паскале строка выглядит как массив из 256 байтов; первый байт хранил длину строки, в остальных хранится её тело. Таким образом, длина строки не может превышать 255 символов. В Borland Pascal 7.0 также появились строки «а-ля Си» — очевидно, из-за того, что в число поддерживаемых платформ вошла Windows.
В Object Pascal и STL строка является «чёрным ящиком», в котором выделение/высвобождение памяти происходит автоматически — без участия программиста. При создании строки память выделяется автоматически; как только на строку не останется ни одной ссылки, память возвращается системе. Преимущество этого метода в том, что программист не задумывается над работой строк. С другой стороны, программист имеет недостаточный контроль над работой программы в критичных к скорости участках; также трудно реализуется передача таких строк в качестве параметра в DLL. Также Object Pascal автоматически следит, чтобы в конце строки был символ с кодом 0. Поэтому если функция требует на входе нуль-терминированную строку, для конвертации надо просто написать PAnsiChar(строковая_переменная) или PWideChar(строковая_переменная) (для Pascal), переменная.c_str() (для Builder/STL).
В C# и других языках со сборкой мусора строка является неизменяемым объектом; если строку нужно модифицировать, создаётся другой объект. Этот метод медленный и расходует немало временной памяти, но хорошо сочетается с концепцией сборки мусора. Преимущество этого метода в том, что присваивание происходит быстро и без дублирования строк. Также имеется некоторый ручной контроль над конструированием строк (в Java, например, через класс StringBuffer) — это позволяет уменьшить количество выделений и высвобождений памяти и, соответственно, увеличить скорость.
Нуль-терминированная строка или C-строка (от названия языка Си) или ASCIZ-строка (от названия директивы ассемблера .asciz) — способ представления строк в языках программирования, при котором вместо введения специального строкового типа используется массив символов, а концом строки считается первый встретившийся специальный нуль-символ (код ASCII 0x00). Например, в строковом буфере (области памяти, выделенной для хранения строки) размером 11 байт нуль-терминированная строка «СТРОКА» в кодировке Windows-1251 может представляться следующим образом:
С |
Т |
Р |
О |
К |
А |
NULL |
F |
% |
NULL |
4 |
0xD1 |
0xD2 |
0xD0 |
0xCE |
0xCA |
0xC0 |
0x00 |
0x46 |
0x25 |
0x00 |
0x34 |
Символы после нуль-символа называются мусором — это данные, которые могли остаться в буфере от предыдущих строк или от других использований памяти. Среди них также могут находиться нулевые символы.
При использовании однобайтных кодировок (ASCII) объём памяти, требуемый для представления строки из N символов, равен N + 1 байт. В том случае, когда для кодирования символов применяется Юникод, длина строки зависит от используемого представления Юникода (например, 2N + 2 байта для UCS-2).
Такие строки являются стандартом в Си и некоторых других языках программирования. Поскольку они используются для передачи строковых аргументов в стандартные функции во многих операционных системах, операции для работы с нуль-терминированными строками появились в Паскале и других языках.
Для ссылки на нуль-терминированную строку применяется указатель на первый её символ. Это простой, быстрый и гибкий подход, но чреватый ошибками. Программист постоянно должен следить за своим кодом, а именно:
быть уверенным, что не случаются переполнения буфера;
если на одну строку есть несколько ссылок, убедиться, что изменение или уничтожение этой строки не приведёт к нарушению работы программы;
высвобождать память, занятую строкой, как только она больше не нужна, и наоборот, не высвобождать, если строка ещё требуется.
Кроме того, некоторые операции со строками, например, конкатенация, для нуль-терминированных строк выполняются медленнее, чем для других типов строк.
Альтернативой нуль-терминированным строкам является способ, принятый в Паскале: строка начинается с первого элемента массива, а в нулевом элементе хранится длина строки. В этом случае не требуется специального терминатора для обозначения конца строки. С другой стороны, здесь на длину строки накладывается ограничение, связанное с вместимостью нулевого элемента массива, то есть в случае с однобайтовыми элементами длина строки не может превышать 255 символов. Нуль-терминированные строки такому ограничению не подвержены и теоретически могут хранить строки любой длины.