Рядок (програмування): відмінності між версіями

[перевірена версія][перевірена версія]
Вилучено вміст Додано вміст
Dr.Phil~ukwiki (обговорення | внесок)
Немає опису редагування
стиль, оформлення
Рядок 1:
{{Otheruses|Рядок (значення)}}
 
'''Рядок''' ({{lang-en|String}} - — «[[нитка]], низка») або '''рядковий тип даних'''  — це [[тип даних]], значеннями якого є довільна послідовність (рядок) символів [[Абетка|алфавіту]]. Кожна змінна такого типу (рядкова змінна) може бути представлена фіксованою кількістю [[байт]]ів або мати довільну довжину.
 
== Внутрішнє представлення рядка в пам'яті ==
Рядок 8:
Основні проблеми в машинному поданні строкового типу:
* рядки можуть мати досить істотний розмір (до декількох десятків мегабайтів);
* змінюється з часом розмір - — виникають труднощі з додаванням і видаленням символів.
У поданні рядків в пам'яті комп'ютера існує два принципово різних підходи.
 
Рядок 20:
* рядок може містити будь-які дані;
* можливо на програмному рівні стежити за виходом за межі рядка при її обробці;
* можливо швидке виконання операції виду «взяття N-огого символу з кінця рядка».
 
==== Недоліки ====
* проблеми зі зберіганням і обробкою символів довільної довжини;
* збільшення витрат на зберігання рядків - — значення «довжина рядка» також займає місце і в разі великої кількості рядків маленького розміру може істотно збільшити вимоги алгоритму до [[Оперативна пам'ять|оперативної пам'яті]];
* обмеження максимального розміру рядка. У сучасних мовах програмування це обмеження скоріше теоретичне, так як зазвичай розмір рядка зберігається в 32-бітовому полі, що дає максимальний розмір рядка в 4 294 967 295 байт (4 [[Гігабайт|гігабайти]]);
 
Рядок 32:
Другий метод полягає у використанні «завершального байту»<ref>http://queue.acm.org/detail.cfm?id=2010365</ref><ref>http://russian.joelonsoftware.com/Articles/BacktoBasics.html</ref>. Одне з можливих значень символів алфавіту (як правило, це символ з кодом 0) вибирається як ознака кінця рядка, і рядок зберігається як послідовність байтів від початку до кінця. Є системи, в яких роль ознаки кінця рядка виконує не символ 0, а байт 0xFF (255) або код символу «$».
 
Метод має три назви -&nbsp;— ASCIIZ (або asciiz, символи в кодуванні [[ASCII]] з нульовим завершальним байтом), C-strings (найбільшого поширення метод отримав саме в мові [[C (мова програмування)|Сі]]), [[Нуль-термінований рядок|нуль-термінований рядок]] ({{lang-en|null-terminated string}}).
 
==== Переваги ====
Рядок 44:
==== Недоліки ====
* значний час виконання операцій отримання довжини і конкатенації рядків;
* відсутність засобів контролю за виходом за межі рядка, в разі пошкодження завершального байта можливість пошкодження великих областей пам'яті, що може привести до непередбачуваних наслідків -&nbsp;— втрати даних, краху програми і навіть всієї системи;
* неможливість використовувати символ завершального байту в якостіяк елемента рядка.
* неможливість використовувати деякі кодування з розміром символу в кілька байт (наприклад, [[UTF-16]]), тому що у багатьох таких символах, наприклад Ā (0x0100), один з байтів дорівнює нулю (в той же час, кодування [[UTF-8]] вільне від цього недоліку).
 
Рядок 52:
 
=== Подання у вигляді списку ===
Мови [[Erlang]]<ref>Simon St. Laurent. Introducing Erlang. &nbsp;O’ReillyO'Reilly Media, Inc., 2013. &nbsp;— P. 62. &nbsp;— 185 p. &nbsp;— ISBN 978-1-449-33176-4.</ref>, [[Haskell]]<ref>http://book.realworldhaskell.org/read/characters-strings-and-escaping-rules.html</ref>, [[Пролог (мова програмування)|Пролог]]<ref>http://www.swi-prolog.org/pldoc/man?section=text-representation</ref> використовують для строкового типу список символів. Цей метод робить мову більш «теоретично елегантним» за рахунок дотримання ортогональностиортогональності в системі типів, але приносить суттєві втрати швидкодії.
 
== Реалізація в мовах програмування ==
* У перших мовах програмування взагалі не було строкового типу; програміст повинен був сам будувати функції для роботи з рядками того чи іншого типу.
 
* У Сі використовуються нуль-терминироватьтерміновані рядки з повним ручним контролем з боку програміста.
 
* У стандартному Паскалі рядок виглядає як масив з 256 байтів; перший байт зберігав довжину рядка, в інших зберігається її тіло. Таким чином, довжина рядка не може перевищувати 255 символів. У Borland Pascal 7.0 також з'явилися рядки «по типу [[C++|Сі]]<nowiki/>» -&nbsp;— очевидно, через те, що в число підтримуваних платформ увійшла [[Microsoft Windows|Windows]].
 
* У [[Object Pascal]] та [[C++]] STL рядок є «чорним ящиком», в якому виділення / вивільнення пам'яті відбувається автоматично -&nbsp;— без участі програміста. При створенні рядка пам'ять виділяється автоматично; як тільки на рядок не залишиться жодного посилання, пам'ять повертається системі. Перевага цього методу в тому, що програміст не замислюється над роботою рядків. З іншого боку, програміст має недостатній контроль над роботою програми в критичних до швидкості ділянках; також важко реалізується передача таких рядків як параметр в DLL. Також [[Object Pascal]] автоматично стежить, щоб в кінці рядка був символ з кодом 0. Тому якщо функція вимагає на вході нуль-терминироватьтермінований рядок, для конвертації треба просто написати <code>PAnsiChar(рядкова_змінна)</code> або <code>PWideChar (рядкова_змінна) (для Pascal)</code>, <code>змінна c_str() (для Builder / STL)</code>.
 
* У C # та іншими мовами із збіркою сміття рядок є незмінним об'єктом; якщо рядок потрібно модифікувати, створюється інший об'єкт. Цей метод повільний і витрачає чимало тимчасової пам'яті, але добре поєднується з концепцією збірки сміття. Перевага цього методу в тому, що присвоювання відбувається швидко і без дублювання рядків. Також є деякий ручний контроль над конструюванням рядків (в [[Java]], наприклад, через класи StringBuffer і StringBuilder) -&nbsp;— це дозволяє зменшити кількість виділень і вивільнень пам'яті і, відповідно, збільшити швидкість.
 
* У деяких мовах (наприклад, Standard ML) крім цього, є додатковий модуль для забезпечення ще більшої ефективності -&nbsp;— «підрядок» (SubString). Його використання дозволяє виконувати операції над рядками без копіювання їхніх тіл за допомогою маніпулювання індексами початку і кінця підстрокамипідрядка; фізичне копіювання відбувається лише при необхідності перетворення подстрокпідрядків ву рядки.
 
== Операції ==
 
=== Найпростіші операції з рядками ===
* Отримання символу за номером позиції ([[Індекс|індексу]]) -&nbsp;— в більшості мов це тривіальна операція;
* Конкатенація (з'єднання) рядків.
 
Рядок 87:
 
=== Більш складні операції ===
* Знаходження мінімального надрядкунадрядка, що містить всі зазначені рядки;
* Пошук в двох масивах рядків збігаються послідовностей (завдання про [[плагіат]]).
 
Рядок 96:
 
== Подання символів рядка ==
До останнього часу один символ завжди кодувався одним байтом (8 двійкових бітів; застосовувалися також кодування з 7 бітами на символ), що дозволяло представляти 256 (128 при семібітномусемибітному кодуванні) можливих значень. Однак для повноцінного представлення символів алфавітів кількох мов (багатомовних документів, друкарських символів -&nbsp;— кілька видів лапок, тире, кількох видів прогалин і для написання текстів на ієрогліфічних мовах -&nbsp;— китайською, японською та корейською) 256 символів недостатньо. Для вирішення цієї проблеми існує кілька методів:
* Перемикання мови керуючими кодами. Метод не стандартизований і позбавляє текст самостійності (тобто послідовність символів без керуючого коду на початку втрачає сенс); використовувався в деяких ранніх русифікації [[ZX Spectrum|ZX-Spectrum]] і БК.
 
Рядок 109:
* [[Частота кадрів]]
* [[Чорний список]]
 
== Примітки ==
{{reflist}}
 
{{Compu-stub}}
{{Без джерел|дата=червень 2010}}