Tip șir

În informatică , un tip de șir ( în engleză  șir „fir, șir”) este un tip de date ale cărui valori sunt o secvență arbitrară (șir) de caractere alfabetice . Fiecare variabilă de acest tip ( variabilă șir ) poate fi reprezentată printr-un număr fix de octeți sau poate avea o lungime arbitrară.

Reprezentarea memoriei

Unele limbaje de programare impun restricții cu privire la lungimea maximă a unui șir, dar majoritatea limbilor nu au astfel de restricții. Când utilizați Unicode, fiecare caracter de tip șir poate necesita doi sau chiar patru octeți pentru a-l reprezenta.

Principalele probleme în reprezentarea pe mașină a tipului șirului sunt:

Există două abordări fundamental diferite pentru reprezentarea șirurilor în memoria computerului.

Reprezentare matrice de caractere

În această abordare, șirurile sunt reprezentate printr -o matrice de caractere ; dimensiunea matricei este stocată într-o zonă separată (de servicii). De la numele limbajului Pascal , unde această metodă a fost implementată pentru prima dată, această metodă se numește șiruri Pascal .

O versiune ușor optimizată a acestei metode este așa-numita. Formatul c-addr u (din limba engleză  adresa aliniată la caractere + număr nesemnat ) utilizat în Forth . Spre deosebire de șirurile Pascal, aici dimensiunea matricei nu este stocată împreună cu datele șirului, ci face parte din pointerul către șir.

Beneficii
  • programul în fiecare moment conține informații despre dimensiunea șirului, astfel încât operațiunile de adăugare a caracterelor până la sfârșit, copiere a șirului și obținerea efectivă a mărimii șirului se realizează destul de rapid;
  • șirul poate conține orice date;
  • este posibilă la nivel de program să se monitorizeze ieșirea din limitele liniei în timpul procesării acestuia;
  • este posibilă efectuarea rapidă a unei operații de genul „luarea celui de-al N-lea caracter de la sfârșitul șirului”.
Dezavantaje
  • probleme cu stocarea și procesarea caracterelor de lungime arbitrară;
  • creșterea costului de stocare a șirurilor - valoarea „lungimei șirurilor” ocupă și ea spațiu și, în cazul unui număr mare de șiruri de dimensiuni mici, poate crește semnificativ cerințele algoritmului pentru RAM;
  • limita maximă a dimensiunii liniei. În limbajele de programare moderne, această limitare este mai mult una teoretică, deoarece de obicei dimensiunea unui șir este stocată într-un câmp de 32 de biți, ceea ce oferă o dimensiune maximă a șirului de 4.294.967.295 octeți (4 gigaocteți);
  • când se folosește un alfabet cu o dimensiune variabilă a caracterelor (de exemplu, UTF-8 ), dimensiunea nu stochează numărul de caractere, ci dimensiunea șirului în octeți, astfel încât numărul de caractere trebuie numărat separat.

Metoda de terminare a octetilor

A doua metodă este utilizarea „octetului de terminare” [1] [2] . Una dintre valorile posibile ale caracterelor alfabetului (de obicei un caracter cu codul 0) este aleasă ca terminator al șirului, iar șirul este stocat ca o secvență de octeți de la început până la sfârșit. Există sisteme în care octetul 0xFF (255) sau codul caracterului „$” este folosit ca semn al sfârșitului de linie, nu caracterul 0.

Metoda are trei nume - ASCIIZ (sau asciz, caractere ASCII cu un octet terminat nul), șiruri de caractere C (metoda este cea mai utilizată în limbajul C ) și metoda șirurilor terminate nul .

Beneficii
  • absența informațiilor suplimentare de serviciu despre linie (cu excepția octetului final);
  • capacitatea de a reprezenta un șir fără a crea un tip de date separat;
  • fără limită pentru dimensiunea maximă a liniei;
  • utilizarea economică a memoriei;
  • ușurința obținerii sufixului șirului;
  • ușurința de a trece șiruri de caractere către funcții (se trece un pointer către primul caracter);
Dezavantaje
  • executarea îndelungată a operațiunilor de obținere a lungimii și concatenării șirurilor;
  • lipsa mijloacelor de control al ieșirii liniei, în caz de deteriorare a octetului final, posibilitatea de a deteriora suprafețe mari de memorie, ceea ce poate duce la consecințe imprevizibile - pierderea datelor, blocarea programului și chiar a întregului sistem;
  • incapacitatea de a utiliza caracterul octet final ca element șir.
  • incapacitatea de a utiliza unele codificări cu o dimensiune a caracterelor de mai mulți octeți (de exemplu, UTF-16), deoarece în multe astfel de caractere, de exemplu  (0x0100), unul dintre octeți este zero (în același timp, UTF- codificarea 8 este lipsită de acest dezavantaj).

Folosind ambele metode

În limbi precum, de exemplu, Oberon , un șir este plasat într-o matrice de caractere de o anumită lungime, iar sfârșitul său este indicat printr-un caracter nul. În mod implicit, întreaga matrice este umplută cu caractere nule. Această metodă vă permite să combinați multe dintre avantajele ambelor abordări, precum și să evitați majoritatea dezavantajelor acestora.

Vizualizare listă

Limbile Erlang [3] , Haskell [4] , Prolog [5] folosesc o listă de caractere pentru tipul șirului . Această metodă face limbajul mai „teoretic elegant” prin respectarea ortogonalității în sistemul de tipări , dar aduce o penalizare semnificativă de performanță.

Implementare în limbaje de programare

  • Primele limbaje de programare nu aveau deloc un tip de șir; programatorul trebuia să construiască funcții pentru lucrul cu șiruri de un tip sau altul.
  • C folosește șiruri terminate nul cu control manual complet de către programator.
  • În Pascal standard , un șir arată ca o matrice de 256 de octeți; primul octet a stocat lungimea șirului, restul și-a stocat corpul. Astfel, lungimea șirului nu poate depăși 255 de caractere. Borland Pascal 7.0 a introdus și linii „a la C ”, aparent datorită faptului că Windows a fost inclus printre platformele suportate .
  • În Object Pascal și C++ STL , un șir este o „cutie neagră” în care alocarea/dealocarea memoriei are loc automat - fără participarea programatorului . Când este creat un șir, memoria este alocată automat; de îndată ce nu mai există nicio referință la șir, memoria este returnată sistemului. Avantajul acestei metode este că programatorul nu trebuie să se gândească la modul în care funcționează șirurile. Pe de altă parte, programatorul are un control insuficient asupra funcționării programului în zonele critice pentru viteză; de asemenea, este dificil să treci astfel de șiruri ca parametru unui DLL . De asemenea, Object Pascal se asigură automat că la sfârșitul șirului există un caracter cu codul 0. Prin urmare, dacă funcția necesită un șir terminat cu nul ca intrare , trebuie doar să scrieți sau (pentru Pascal), (pentru Builder /STL) pentru a converti.PAnsiChar(строковая_переменная)PWideChar(строковая_переменная)переменная.c_str()
  • În C# și în alte limbaje colectate de gunoi , un șir este un obiect imuabil; dacă șirul trebuie modificat, se creează un alt obiect. Această metodă este lentă și irosește multă memorie temporară, dar merge bine cu conceptul de colectare a gunoiului. Avantajul acestei metode este că atribuirea este rapidă și fără rânduri duplicat. Există, de asemenea, un anumit control manual asupra construcției șirurilor de caractere (în Java , de exemplu, prin clase StringBuffer и StringBuilder) - acest lucru vă permite să reduceți numărul de alocări și ediții de memorie și, în consecință, să creșteți viteza.
    • În unele limbi (de exemplu, Standard ML ), în plus, există un modul suplimentar pentru a oferi o eficiență și mai mare - „substring” (SubString). Utilizarea acestuia vă permite să efectuați operații pe șiruri fără a copia corpurile acestora prin manipularea indicilor începutului și sfârșitului subșirului; copierea fizică are loc numai atunci când este necesară convertirea subșirurilor în șiruri.

Operațiuni

Operații de bază cu șiruri
  • obținerea unui caracter după numărul de poziție (index) - în majoritatea limbilor, aceasta este o operațiune banală;
  • concatenare (conectare) de șiruri.
Operații cu derivate
  • obținerea unui subșir de indici de început și de sfârșit;
  • verificarea apariției unui șir în altul ( căutarea unui subșir într-un șir);
  • verificați dacă există șiruri de caractere care se potrivesc (se face distincție între majuscule sau minuscule );
  • obținerea lungimii șirului;
  • înlocuirea unui subșir într-un șir.
Operații la tratarea șirurilor de caractere ca liste
  • convoluție ;
  • cartografierea de la o listă la alta;
  • filtrarea listei după criterii.
Operații mai complexe
  • găsirea superșirului minim care conține toate șirurile specificate;
  • caută în două matrice de șiruri de caractere pentru secvențe potrivite ( problema plagiatului ) .
Sarcini posibile pentru șirurile de limbaj natural
  • comparație pentru proximitatea șirurilor specificate după un criteriu dat;
  • determinarea limbajului şi codificarea textului pe baza probabilităţilor caracterelor şi silabelor.

Reprezentarea caracterelor unui șir

Până de curând, un caracter era întotdeauna codificat ca un octet (8 biți binari; se foloseau și codificări cu 7 biți pe caracter), ceea ce făcea posibilă reprezentarea a 256 (128 cu o codare pe șapte biți) de valori posibile. Cu toate acestea, pentru o reprezentare completă a caracterelor alfabetelor mai multor limbi​​(documente în mai multe limbi, caractere tipografice - mai multe tipuri de ghilimele , liniuțe , mai multe tipuri de spații și pentru scrierea textelor în limbi hieroglifice - chineză , japoneză și coreeană ) 256 de caractere nu sunt suficiente. Există mai multe metode pentru a rezolva această problemă:

  • Schimbarea limbii prin coduri de control. Metoda nu este standardizată și privează textul de independență (adică o succesiune de caractere fără cod de control la început își pierde sensul); folosit în unele rusificări timpurii ale ZX-Spectrum și BK .
  • Folosind doi sau mai mulți octeți pentru a reprezenta fiecare caracter ( UTF-16 , UTF-32 ). Principalul dezavantaj al acestei metode este pierderea compatibilității cu bibliotecile de text anterioare atunci când reprezintă un șir ca ASCIIZ. De exemplu, sfârșitul unui șir nu mai trebuie considerat un octet cu valoarea 0, ci doi sau patru zero octeți consecutivi, în timp ce un singur octet „0” poate apărea în mijlocul unui șir, ceea ce derutează biblioteca.
  • Folosind o codificare cu o dimensiune variabilă a caracterelor. De exemplu, în UTF-8, unele caractere sunt reprezentate de un octet, altele de doi, trei sau patru. Această metodă vă permite să păstrați compatibilitatea parțială cu bibliotecile vechi (nu există caractere 0 în interiorul șirului și, prin urmare, 0 poate fi folosit ca semn al sfârșitului șirului), dar duce la imposibilitatea de a adresa direct un caracter în memorie prin numărul său de poziție în șir.

Analiză lexicală

Pentru a verifica conformitatea tuturor formelor de cuvinte în timpul analizei lexicale (semantice), sunt utilizate măsuri de similaritate simbol:

Vezi și

Note

  1. Cea mai scumpă greșeală de un octet - Coada ACM . Consultat la 17 septembrie 2016. Arhivat din original pe 19 septembrie 2016.
  2. Joel despre software - Înapoi la elementele de bază . Consultat la 17 septembrie 2016. Arhivat din original la 16 septembrie 2016.
  3. Simon St. Laurent. Vă prezentăm Erlang . - O'Reilly Media, Inc., 2013. - P.  62 . — 185p. - ISBN 978-1-449-33176-4 .
  4. Bryan O'Sullivan, Don Stewart, John Goerzen, Lumea Reală Haskell. Anexa B. Caractere, șiruri și reguli de evadare Arhivat 26 ianuarie 2012 la Wayback Machine
  5. SWI-Prolog Manual: 5.2.2 Reprezentarea textului: șiruri de caractere, atomi și liste de coduri Arhivat 17 iulie 2014 la Wayback Machine