Tipul șirului în C. Lucrul cu șiruri. Clasa de șiruri. Constructori de clasă. Funcțiile assign(), append(), insert(), replace(), erase(), find(), rfind(), compare(), c_str(). Exemple

Lucrul cu șiruri. Clasa de șiruri. Constructori de clasă. Funcțiile assign() , append() , insert() , replace() , erase() , find() , rfind() , compare() , c_str() . Exemple

1. Care este scopul clasei șir în programele C++?

Clasa string este proiectată să funcționeze cu șiruri char*, care sunt șiruri terminate cu nul. Clasa string a fost introdusă ca o alternativă la lucrul cu șiruri char*. Linii care se termină cu un caracter ‘\0’ numite și C-strings. Deoarece string este o clasă, puteți declara obiecte din această clasă.

2. Ce module (biblioteci) trebuie conectate pentru a utiliza capacitățile clasei șir din MS Visual Studio C++?

Pentru a utiliza capacitățile clasei șir în MS Visual Studio (C++), trebuie să includeți biblioteca și spațiul de nume std.

#include folosind namespace std;
3. Cum este declarată o variabilă de tip șir? Exemple

Declararea unei variabile de tip șir se face în același mod ca o variabilă obișnuită. Posibila varianta de declaratie cu initializare simultana.

// tastați șir șir de caractere s1; // variabilă numită s1 de tip șir string s2 = "Aceasta este o variabilă șir" ; // declarație cu inițializare // folosind o variabilă de tip șir cu un operator de atribuire s1 = s2; // s1 = "Aceasta este o variabilă șir" s2 = „Text nou” ;
4. Care sunt avantajele și dezavantajele utilizării clasei șir în comparație cu tipul char*?

Crearea noului tip de șir s-a datorat deficiențelor de lucru cu șirurile de caractere, pe care le-a prezentat tipul char*. În comparație cu tipul char*, tipul șir are următoarele avantaje principale:

  • capacitatea de a procesa șiruri folosind operatori standard C++ ( = , + , = = , <> și așa mai departe.). După cum știți, atunci când utilizați tipul char*, chiar și cele mai simple operații cu șiruri de caractere păreau complicate și necesitau scrierea excesivă a codului de program;
  • asigurând o mai bună fiabilitate (securitate) a codului programului. De exemplu, la copierea șirurilor, tipul șirului oferă acțiuni adecvate care pot apărea dacă șirul sursă este mai mare decât șirul destinație;
  • furnizarea unui șir ca tip de date independent. Declarația tipului șirului de caractere ca șir este aceeași pentru toate variabilele din program, ceea ce asigură consistența datelor.

Principalul dezavantaj al tipului șir în comparație cu tipul char* este viteza mai mică de procesare a datelor. Acest lucru se datorează faptului că tipul șirului este, de fapt, o clasă container. Și lucrul cu o clasă necesită implementare suplimentară a codului programului, care, la rândul său, necesită timp suplimentar.

5. Ce operatori pot fi folosiți cu obiecte din clasa șir de caractere?

Clasa de șiruri este convenabilă deoarece vă permite să manipulați în mod convenabil șirurile folosind operatori standard (supraîncărcați).

Următorii operatori pot fi utilizați cu obiecte din clasa șir

  • = - misiune
  • + – concatenare (unirea șirurilor de caractere)
  • += – atribuire cu concatenare
  • == – egalitate
  • != – inegalitatea
  • < - Mai puțin
  • <= - mai mic sau egal
  • > - Mai mult
  • >= - mai mult sau egal
  • – indexare

Exemplu, ceea ce demonstrează utilizarea afirmațiilor de mai sus

// tip șir, operații pe șirurișir s1 = "s-1" ; șir s2 = "s-2" ; șir s3; bool b; // operațiunea "=" (atribuire șir) s3 = s1; // s3 = "s-1" // operația „+” - concatenare șiruri s3 = s3 + s2; // s3 = "s-1s-2" // operațiunea "+=" - atribuire cu concatenare s3 = "s-3" ; s3 += "abc" ; // s3 = "s-3abc" // operațiunea "==" - comparație de șiruri b = s2==s1; // b = fals b = s2=="s-2" ; // b = adevărat // operațiunea "!=" - comparație de șiruri (nu este egală) s1 = "s1" ; s2 = "s2" ; b = s1 != s2; // b = adevărat // operațiuni "<" и ">" - comparație de șiruri s1 = "abcd" ; s2 = "de"; b = s1 > s2; // b = fals b = s1< s2; // b = true // operațiuni "<=" и ">=" - comparație de șiruri (mai mică sau egală, mai mare sau egală) s1 = "abcd" ; s2 = "ab" ; b = s1 >= s2; // b = adevărat b = s1<= s2; // b = false b = s2 >= "ab" ; // b = adevărat // operație - indexare char c; s1 = "abcd" ; c = s1; // c = "c" c = s1; // c = "a"
6. Clasa string conține constructori?

Ca orice clasă, clasa șir are un număr de constructori. Principalele sunt următoarele:

Şir(); string(const char * str); string(const string & str);

7. Exemple de inițializare folosind constructori

Mai jos sunt exemple de inițializare a variabilelor de tip șir

String s1 ("Bună ziua!"); string s2 = "Bună ziua!" ; // inițializare - șir constructor (const char * str) char * ps = "Bună ziua" ; șir s3(ps); // șir de inițializare s4(s3); // inițializare - șir constructor (șir constant și șir)șir s5; // inițializare - constructor string().

8. Atribuirea șirurilor. funcția assign(). Exemple

Pentru a atribui un șir altuia, puteți utiliza una dintre cele două metode:

  • utilizați operatorul de atribuire ‘=’ ;
  • utilizați funcția assign() din clasa șir.

Funcția assign() are mai multe implementări supraîncărcate.

Prima opțiune este să apelați o funcție fără parametri

String &assign(void);

În acest caz, există o simplă atribuire a unui șir la altul.

A doua opțiune vă permite să copiați un număr specificat de caractere dintr-un șir:

String &assign(const string & s, size_type st, size_type num);

  • s – obiectul de la care este luat șirul sursă;
  • st – index (poziție) în linia de la care începe copierea a num caractere;
  • num – numărul de caractere de copiat din poziţia st;
  • size_type – tipul de date ordinal.

A treia variantă a funcției assign() copiează primul număr de caractere ale șirului s către apelant:

String & assign(const char * s, size_type num);

  • s – un șir care se termină cu caracterul ‘\0’ ;
  • num este numărul de caractere care sunt copiate în obiectul apelant. Primele num de caractere din șirul s sunt copiate.

Mai jos este un exemplu cu diferite implementări ale funcției assign().

Exemplu.

// atribuirea șirurilor de caractere, funcție assign().șir s1 = „site” ; șir s2; șir s3; char * ps = "site" ; s3 = s1; // s3 = "site" s2.assign(s1); // s2 = "site" s2.assign(s1, 0, 4); // s2 = "cel mai bun" s2.assign(ps, 8); // s2 = "cel mai bunprog"
9. Combinarea șirurilor. Funcția append(). Exemplu

Funcția append() este folosită pentru a concatena șiruri. De asemenea, puteți utiliza operația pentru a adăuga rânduri ‘+’ , De exemplu:

Șirul s1; șir s2; s1 = "abc" ; s2 = "def" ; s1 = s1 + s2; // s1 = "abcdef"

Cu toate acestea, funcția append() este bună dacă trebuie să adăugați o parte dintr-un șir.

Funcția are următoarele opțiuni de implementare:

String &append(const string & s, size_type start); șir de caractere &append(const char * s, size_type num);

În prima implementare, funcția primește o referință la un obiect șir s, care este adăugat la obiectul apelant. În a doua implementare, funcția primește un pointer către un șir de tip const char *, care se termină cu caracterul „\0”.

Exemplu. Demonstrarea funcției append().

String s1 = "abcdef" ; s2 = "1234567890" ; anexează(s2, 3, 4); // s1 = "abcdef4567" char * ps = "1234567890" ; s1 = "abcdef" ; s1.apend(ps, 3); // s1 = "abcdef123"

10. Inserarea caracterelor într-un șir. funcția insert(). Exemplu

Pentru a insera o linie la o anumită poziție a altei linii, trebuie să utilizați funcția insert(), care are mai multe opțiuni de implementare.

Prima versiune a funcției vă permite să introduceți întregul șir s la poziția de început specificată a liniei de apelare (obiectul apelant):

String & insert(size_type start, const string &s);

A doua versiune a funcției vă permite să inserați o parte (parametrii insStart , num ) din șirul s la poziția de început specificată a șirului de apelare:

String & insert(size_type start, const string &s, size_type insStart, size_type num);

În funcțiile de mai sus:

  • s – un șir care este introdus în linia de apelare;
  • start – poziție în linia de apel de la care este introdus șirul s;
  • insStart – poziția în șirul s din care are loc inserția;
  • num – numărul de caractere din șirul s care sunt inserate din poziția insStart.
șir s1 = "abcdef" ; șir s2 = "1234567890" ; s1.inserat(3, s2); // s1 = "abc"+"1234567890"+"def"="abc1234567890def" s2.inserat(2, s1, 1, 3); // s2 = "12bcd34567890"
11. Înlocuirea caracterelor dintr-un șir. funcția înlocuire(). Exemplu

Funcția înlocuiește() înlocuiește caracterele din șirul de apelare. Funcția are următoarele opțiuni de implementare:

String &replace(size_type start, size_type num, const string &s); string &replace(size_type start, size_type num, const string &s, size_type replStart, size_type replNum);

În prima implementare, șirul de apelare este înlocuit cu șirul s. Este posibil să specificați poziția (start) și numărul de caractere (num) din linia de apelare care trebuie înlocuite cu șirul s.

A doua versiune a funcției de înlocuire () diferă de prima prin faptul că permite doar înlocuirea unei părți a șirului de caractere cu șirul de apelare. În acest caz, sunt dați doi parametri suplimentari: poziția replStart și numărul de caractere din șirul s, care formează un subșir care înlocuiește șirul apelant.

Exemplu. Demonstrarea funcției replace().

String s1 = "abcdef" ; șir s2 = "1234567890" ; s2.inlocuire(2, 4, s1); // s2 = "12abcdef7890" s2 = "1234567890" ; s2.inlocuire(3, 2, s1); // s2 = "123abcdef67890" s2 = "1234567890" ; s2.inlocuire(5, 1, s1); // s2 = "12345abcdef7890" // înlocuirea caracterelor, funcția înlocuire().șir s1 = "abcdef" ; șir s2 = "1234567890" ; s2.inlocuire(2, 4, s1); // s2 = "12abcdef7890" s2 = "1234567890" ; s2.inlocuire(3, 2, s1); // s2 = "123abcdef67890" s2 = "1234567890" ; s2.inlocuire(5, 1, s1); // s2 = "12345abcdef7890" s2 = "1234567890" ; s2.inlocuire(5, 1, s1, 2, 3); // s2 = "12345cde7890" s2 = "1234567890" ; s2.inlocuire(4, 2, s1, 0, 4); // s2 = "1234abcd7890"

12. Eliminarea unui număr specificat de caractere dintr-un șir. funcția erase(). Exemplu

Pentru a elimina caractere din șirul de apelare, utilizați funcția erase():

String & erase(size_type index=0, size_type num = npos);

  • index – index (poziție) începând de la care doriți să eliminați caracterele din linia de apelare;
  • num – numărul de caractere care sunt eliminate.

Exemplu.

String s = "01234567890" ; s.stergere(3, 5); // s = "012890" s = "01234567890" ; s.stergere(); // s = ""

13. Căutați un caracter într-un șir. Funcțiile Find() și rfind(). Exemple

În clasa șir, căutarea unui șir într-un subșir se poate face în două moduri, care diferă în direcția căutării:

  • prin scanarea șirului de la început până la sfârșit folosind funcția find();
  • prin scanarea șirului de la sfârșit până la început cu funcția rfind().

Prototipul funcției find() arată astfel:

Size_type find(const string &s, size_type start = 0) const ;

  • s este subșirul care este căutat în șirul care apelează această funcție. Funcția caută prima apariție a șirului s. Dacă subșirul s este găsit în șirul care a apelat această funcție, atunci este returnată poziția primei apariții. În caz contrar, se returnează -1;

Prototipul funcției rfind() arată astfel:

Size_type rfind(const string &s, size_type start = npos) const ;

  • s este subșirul care este căutat în șirul de apelare. Căutarea unui subșir într-un șir se efectuează de la sfârșit până la început. Dacă subșirul s este găsit în șirul de apelare, atunci funcția returnează poziția primei apariții. În caz contrar, funcția returnează -1;
  • npos – poziția ultimului caracter al liniei de apelare;
  • start – poziția din care se efectuează căutarea.

Exemplul 1. Un fragment de cod care demonstrează rezultatul funcției find().

// tastați șir, funcția find()șir s1 = "01234567890" ; șir s2 = "345" ; șir s3 = „abcd” ; int pos; pos = s1.găsește(s2); // poz = 3 poz = s1.find(s2, 1); // pos = 3 pos = s1.find("jklmn" , 0); // poz = -1 poz = s1.find(s3); // pos = -1 pos = s2.fd(s1); // poz = -1

Exemplul 2. Demonstrarea funcției rfind().

// tip șir, funcții find() și rfind().șir s1 = "01234567890" ; șir s2 = "345" ; șir s3 = „abcd” ; șir s4 = "abcd---abcd" ; int pos; pos = s1.rfind(s2); // pos = 3 pos = s1.rfind(s2, 12); // pos = 3 pos = s1.rfind(s2, 3); // pos = 3 pos = s1.rfind(s2, 2); // pos = -1 pos = s2.rfind(s1); // pos = -1 pos = s1.rfind(s3, 0); // poz = -1 // diferența dintre funcțiile find() și rfind(). pos = s4.rfind(s3); // poz = 7 poz = s4.find(s3); // poz = 0
14. Comparația părților de șiruri. funcția compare(). Exemplu

Deoarece tipul șirului este o clasă, puteți utiliza operația pentru a compara două șiruri unul cu celălalt ‘= =’ . Dacă cele două șiruri sunt aceleași, atunci rezultatul comparației va fi adevărat. În caz contrar, rezultatul comparației va fi fals.

Dar dacă trebuie să comparați o parte dintr-un șir cu altul, atunci funcția compare() este furnizată pentru aceasta.

Prototipul funcției compare():

int compare(size_type start, size_type num, const string &s) const ;
  • s – șirul care este comparat cu șirul apelant;
  • start – poziție (index) în șirul s de la care începe vizualizarea șirului de caractere pentru comparație;
  • num este numărul de caractere din șirul s care sunt comparate cu șirul de apelare.

Funcția funcționează după cum urmează. Dacă șirul de apelare este mai mic decât șirul s, atunci funcția returnează -1 (o valoare negativă). Dacă șirul de apelare este mai mare decât șirul s , funcția returnează 1 (o valoare pozitivă). Dacă două șiruri de caractere sunt egale, funcția returnează 0.

Exemplu. Demonstrarea funcției compare():

// tip șir, funcție compară().șir s1 = "012345" ; șir s2 = "0123456789" ; int res; res = s1.compara(s2); // res = -1 res = s1.compare("33333" ); // res = -1 res = s1.compare("012345" ); // res = 0 res = s1.compare("345" ); // res = -1 res = s1.compare(0, 5, s2); // res = -1 res = s2.compare(0, 5, s1); // res = -1 res = s1.compare(0, 5, "012345" ); // res = -1 res = s2.compare(s1); // res = 1 res = s2.compare("456" ); // res = -1 res = s2.compare("000000" ); // res = 1
15. Primirea unui șir cu caracterul de final de linie „\0” (car * ). Funcția c_str() . Exemplu

Pentru a obține un șir care se termină cu caracterul ‘\0’ Este folosită funcția c_str().

Prototipul funcției:

const char * c_str() const ;

Funcția este declarată cu modificatorul const. Aceasta înseamnă că funcția nu poate modifica obiectul apelant (șir).

Exemplul 1. Conversia tipului șirului în const char * .

// tastați șir, funcție c_str()șir s = "abcdef" ; const char * ps; ps = s.c_str(); // ps = "abcdef"

Exemplul 2.

Mai jos este o demonstrație a conversiei unui șir din șir în tip System::String pentru a-l afișa într-un control Label

În această lecție vom discuta despre șiruri în stil C; este posibil să fi văzut deja aceste șiruri pe site-ul nostru web sau în orice alt manual. De fapt, șirurile C sunt doar matrice de caractere, dar, cu propriile lor specificități, știm întotdeauna unde se află sfârșitul liniei. În acest articol ne vom uita la mai multe funcții pentru lucrul cu șiruri, de exemplu, tu - copiați, concatenați, obțineți lungimea unui șir.

Ce sunt corzile?

Rețineți că, alături de șirurile de caractere în stil C, care sunt în esență matrice simple, există și literale de șir, cum ar fi acest „literal” . În realitate, atât șirurile, cât și literalele sunt pur și simplu seturi de caractere situate unul lângă altul în memoria computerului. Dar există încă o diferență între matrice și literale: literalele nu pot fi modificate, iar șirurile de caractere pot.

Orice funcție care ia un șir în stil C poate lua și un literal ca parametru. Există, de asemenea, unele entități în C care pot arăta ca șiruri de caractere, când de fapt nu sunt. Vorbesc acum despre caractere, sunt cuprinse între ghilimele simple, iată un exemplu - „a”, după cum puteți vedea, acesta nu este un șir. Un caracter poate fi, într-o anumită locație, să fie atribuit unui șir, dar caracterele nu pot fi procesate ca șir. Dacă vă amintiți, matricele funcționează ca indicatori, așa că dacă treceți un singur caracter într-un șir, acesta va fi considerat o eroare.

Din cele de mai sus, ar fi trebuit să realizezi că șirurile sunt matrice de caractere, iar literalele șiruri sunt cuvinte înconjurate de ghilimele duble. Iată un alt exemplu de literal:

„Acesta este un șir static”

Ai uitat de specificul corzilor, despre care s-a menționat ceva mai sus? Deci, șirurile C trebuie să se termine întotdeauna cu un caracter nul, literal „\0”. Prin urmare, pentru a declara un șir format din 49 de litere, trebuie să rezervați o celulă suplimentară pentru caracterul nul:

Char myString;

După cum puteți vedea din exemplu, lungimea matricei este de 50 de caractere, dintre care 49 va fi o linie și unul, ultimul va fi un caracter nul. Este important să ne amintim că trebuie să existe întotdeauna un caracter nul la sfârșitul liniilor C, la fel cum există un punct la sfârșitul fiecărei propoziții. Deși caracterul nul nu este afișat atunci când este scos șirul, totuși ocupă spațiu în memorie. Deci, din punct de vedere tehnic, într-o matrice de cincizeci de elemente, puteți stoca doar 49 de litere, deoarece ultimul caracter este necesar pentru a termina șirul. În plus, pointerii pot fi folosiți și ca șir. Dacă citești articolul despre , poți face așa ceva:

Char *myString; // tip char pointer myString = malloc(sizeof(*myString) * 64); // alocare de memorie

În acest exemplu, am alocat 64 de locații de memorie pentru matricea myString. Pentru a elibera memoria, utilizați funcția free().

Gratuit(myString);

Folosind șiruri

Șirurile sunt utile atunci când trebuie să efectuați diverse operații asupra informațiilor text. De exemplu, dacă doriți ca utilizatorul să introducă un nume într-un program, veți folosi un șir. Utilizarea funcției scanf() pentru a introduce un șir funcționează, dar poate duce la o depășire a memoriei tampon. La urma urmei, șirul de intrare poate fi mai mare decât dimensiunea șirului tampon. Există mai multe moduri de a rezolva această problemă, dar cea mai simplă este să utilizați , care este declarat în fișierul antet .

Când citește intrarea de la utilizator, acesta va citi toate caracterele, cu excepția ultimului. După aceea, un terminator zero va fi plasat la sfârșitul liniei de citire. Funcția fgets() va citi caractere până când utilizatorul apasă Enter. Să vedem un exemplu de utilizare a fgets():

#include int main() ( char myString; // long string printf("Introduceți un șir lung: "); fgets(myString, 100, stdin); // citiți șirul din fluxul de intrare printf("Ați introdus următorul șir: %s", myString); getchar(); )

Primul parametru pentru fgets() este un șir, al doilea parametru este dimensiunea șirului, iar al treilea parametru este un pointer către fluxul de date de intrare.

Rezultatul programului:

<ВВОД>...

După cum puteți vedea, din rezultatul programului, un caracter de linie nouă - "\n" - a intrat în linia de intrare. Acest lucru s-a întâmplat deoarece fgets() a numărat apăsarea butonului Enter în șirul myString și și-a finalizat munca. Acest lucru înseamnă că poate fi necesar să eliminați manual caracterul nou linie. O modalitate de a face acest lucru este enumerarea personaj cu caracter. Să modificăm programul și să eliminăm caracterul newline:

#include int main() ( char myString; // long string printf("Introduceți un șir lung: "); fgets(myString, 100, stdin); // citiți un șir din fluxul de intrare int i; for (i = 0; i< 100; i++) { if (myString[i] == "\n") { myString[i] = "\0"; break; } } printf("Вы ввели следующую строку: %s", myString); getchar(); }

Vă rugăm să rețineți că, dacă șirul de intrare conține mai puțin de 100 de caractere, atunci va fi inclus și un caracter newline în șir. Prin urmare, putem elimina acest personaj folosind forța brută simplă. Am adăugat o buclă la program în care trecem prin caracterele șirului, rândurile 12-19. Și când întâlnim un caracter de nouă linie, îl înlocuim cu un caracter nul, linia 16. Rezultatul programului:

Introduceți o linie lungă: Soarta își lasă amprenta Ați introdus următoarea linie: Soarta își lasă amprenta Pentru a închide această fereastră, faceți clic pe<ВВОД>...

Asta este tot pentru acum. În articolul următor vă voi spune despre funcții speciale pentru lucrul cu șiruri.

P.S.: Tuturor ne place să urmărim diferite înregistrări video, dar uneori se întâmplă să nu fie întotdeauna posibilă redarea unor formate de fișiere video. Deci, puteți rezolva această problemă folosind programul - xilisoft converter ultimate. Puteți converti rapid videoclipuri dintr-un format în altul. În plus, acest program poate converti și fișiere audio și imagini animate.

34

--- Ghid C# --- Strings

Din punct de vedere al programării obișnuite, șir tipul de date șir este una dintre cele mai importante din C#. Acest tip definește și acceptă șiruri de caractere. Într-un număr de alte limbaje de programare, un șir este o matrice de caractere. Și în C#, șirurile sunt obiecte. Prin urmare, tipul șir este un tip de referință.

Construirea corzilor

Cel mai simplu mod de a construi un șir de caractere este să utilizați un șir literal. De exemplu, următoarea linie de cod atribuie variabilei de referință șir str o referință la un literal șir:

String str = „Exemplu șir”;

În acest caz, variabila str este inițializată cu secvența de caractere „Example String”. Un obiect de tip șir poate fi creat și dintr-o matrice de tip char. De exemplu:

Char chararray = ("e", "x", "a", "m", "p", "l", "e"); șir str = șir nou (chararray);

Odată ce un obiect șir este creat, acesta poate fi folosit oriunde aveți nevoie de un șir de text cuprins între ghilimele.

Persistența șirului

În mod ciudat, conținutul unui obiect de tip șir nu poate fi modificat. Aceasta înseamnă că odată ce o secvență de caractere a fost creată, aceasta nu poate fi modificată. Dar această limitare contribuie la o implementare mai eficientă a șirurilor de caractere. Prin urmare, acest dezavantaj aparent evident se transformă de fapt într-un avantaj. Astfel, dacă un șir este necesar ca o variație a unui șir existent, atunci în acest scop ar trebui creat un șir nou care să conțină toate modificările necesare. Și, deoarece obiectele șir neutilizate sunt colectate automat ca gunoi, nici nu trebuie să vă faceți griji cu privire la soarta șirurilor inutile.

Trebuie subliniat, totuși, că referințele variabile la șiruri de caractere (adică obiecte de tip șir) sunt supuse modificării și, prin urmare, se pot referi la un alt obiect. Dar conținutul obiectului șir în sine nu se schimbă după ce este creat.

Să ne uităm la un exemplu:

Static void addNewString() ( șir s = „Acesta este accidentul vascular cerebral”; s = „Acesta este un accident vascular cerebral nou”; )

Să compilam aplicația și să încărcăm ansamblul rezultat în utilitarul ildasm.exe. Figura arată codul CIL care va fi generat pentru metoda void addNewString():

Rețineți că există numeroase apeluri la codul operațional ldstr (încărcare șir). Acest opcode CIL ldstr efectuează încărcarea unui nou obiect șir în heap-ul gestionat. Drept urmare, obiectul anterior care conținea valoarea „Acesta este lovitura mea” va fi în cele din urmă colectat de gunoi.

Lucrul cu șiruri

In clasa System.String este prevăzut un set de metode pentru determinarea lungimii datelor de caractere, căutarea unui subșir în șirul curent, conversia caracterelor din majuscule în litere mici și invers etc. În continuare ne vom uita la această clasă mai detaliat.

Proprietatea de clasă Field, Indexer și String

Clasa String definește un singur câmp:

Șir public static numai pentru citire Gol;

Câmpul Gol denotă un șir gol, de exemplu. un șir care nu conține niciun caracter. Aceasta este diferită de o referință String goală, care este pur și simplu făcută la un obiect inexistent.

În plus, clasa String definește un singur indexator numai pentru citire:

Public Char this ( obține; )

Acest indexator vă permite să obțineți un caracter la un index specificat. Indexarea șirurilor de caractere, ca și tablourile, începe de la zero. Obiectele String sunt persistente și nu se modifică, așa că are sens ca clasa String să accepte un indexator doar pentru citire.

În cele din urmă, clasa String definește o singură proprietate numai pentru citire:

Public int Lungime ( get; )

Proprietatea Length returnează numărul de caractere din șir. Exemplul de mai jos arată utilizarea indexatorului și a proprietății Length:

Utilizarea sistemului; Exemplu de clasă ( static void Main() ( string str = "Șir simplu"; // Obține lungimea șirului și al 6-lea caracter din linie folosind indexerul Console.WriteLine ("Lungimea șirului este (0), 6th caracterul este "(1)"" , str.Length, str); ))

Operatori de clasă șiruri

Clasa String supraîncarcă următorii doi operatori: == și !=. Operatorul == este folosit pentru a testa două șiruri de caractere pentru egalitate. Când operatorul == este aplicat referințelor la obiect, de obicei testează dacă ambele referințe sunt făcute la același obiect. Și când operatorul == este aplicat referințelor la obiecte de tip String, conținutul șirurilor în sine este comparat pentru egalitate. Același lucru este valabil și pentru operatorul !=. Când este aplicat referințelor la obiecte de tip String, conținutul șirurilor în sine este comparat pentru inegalitate. Cu toate acestea, alți operatori relaționali, inclusiv =, compară referințele la obiecte de tip String în același mod în care compară referințele la obiecte de alte tipuri. Și pentru a verifica dacă un șir este mai mare decât altul, ar trebui să apelați metoda Compare() definită în clasa String.

După cum va deveni clar, multe tipuri de comparații de șiruri de caractere se bazează pe informații culturale. Dar acest lucru nu se aplică operatorilor == și !=. La urma urmei, pur și simplu compară valorile ordinale ale caracterelor din șiruri. (Cu alte cuvinte, ei compară valorile binare ale caracterelor care nu au fost modificate de normele culturale, adică standardele locale.) Prin urmare, acești operatori efectuează comparații de șiruri într-o manieră insensibilă la majuscule și la cultură.

Metode ale clasei de șiruri

Următorul tabel listează unele dintre cele mai interesante metode din această clasă, grupate după scop:

Metode de lucru cu șiruri
Metodă Structură și supraîncărcări Scop
Comparație de șiruri
comparaţie() public static int Compare(șir strA, șir strB)

Public static int Compare (șir strA, șir strB, bool ignoreCase)

Public static int Compare(șir strA, șir strB, StringComparison comparisonType)

Public static int Compare (șir strA, șir strB, bool ignoreCase, cultură CultureInfo)

Metoda statică compară șirul strA cu șirul strB. Returnează o valoare pozitivă dacă strA este mai mare decât strB; negativ dacă strA este mai mic decât strB; și zero dacă șirurile strA și strB sunt egale. Comparațiile se fac pe baza registrului și a culturii.

Dacă ignoreCase este evaluat ca adevărat, comparația nu ia în considerare diferențele dintre literele mari și mici. În caz contrar, aceste diferențe sunt luate în considerare.

Parametrul comparisonType specifică modul specific în care sunt comparate șirurile. Clasa CultureInfo este definită în spațiul de nume System.Globalization.

public static int Compare (șir strA, int indexA, șir strB, int indexB, int lungime)

Public static int Compare (șir strA, int indexA, șir strB, int indexB, int lungime, bool ignoreCase)

Public static int Compare(șir strA, int indexA, șir strB, int indexB, int lungime, StringComparison comparisonType)

Public static int Compare (șir strA, int indexA, șir strB, int indexB, int lungime, bool ignoreCase, cultură CultureInfo)

Compară părți ale șirurilor strA și strB. Comparația începe cu elementele șir strA și strB și include numărul de caractere specificat de parametrul length. Metoda returnează o valoare pozitivă dacă o parte a șirului strA este mai mare decât o parte a șirului strB; valoare negativă dacă o parte din șirul strA este mai mică decât o parte din șirul strB; și zero dacă părțile șirurilor de caractere strA și strB care sunt comparate sunt egale. Comparațiile se fac pe baza registrului și a culturii.

CompareOrdinal() public static int CompareOrdinal(șir strA, șir strB)

Public static int CompareOrdinal(șir strA, int indexA, șir strB, int indexB, int număr)

Face același lucru ca metoda Compare(), dar fără a lua în considerare setările locale

Compara cu() public int CompareTo(valoarea obiectului)

Compară șirul de apelare cu reprezentarea șir a obiectului valoare. Returnează o valoare pozitivă dacă șirul de apelare este mai mare decât valoarea; negativ dacă șirul de apelare este mai mic decât valoarea; și zero dacă șirurile comparate sunt egale

public int CompareTo(string strB)

Compară șirul de apelare cu șirul strB

este egal() public override bool Equals(object object)

Returnează valoarea booleană adevărată dacă șirul de apelare conține aceeași secvență de caractere ca și reprezentarea șir a lui obj. Efectuează comparații ordinale ținând cont de majuscule, dar insensibile din punct de vedere cultural

public bool Egal (valoare șir)

Public bool Equals (valoare șir, StringComparison comparisonType)

Returnează valoarea booleană adevărată dacă șirul de apelare conține aceeași secvență de caractere ca și valoarea șirului. Se efectuează o comparație ordinală care ține cont de majuscule, dar nu ține cont de cultura. Parametrul comparisonType specifică modul specific în care sunt comparate șirurile

public static bool Egal (șir a, șir b)

Public static bool Equals (șir a, șir b, StringComparison comparisonType)

Returnează valoarea booleană adevărată dacă șirul a conține aceeași secvență de caractere ca șirul b. Se efectuează o comparație ordinală care ține cont de majuscule, dar nu ține cont de cultura. Parametrul comparisonType specifică modul specific în care sunt comparate șirurile

Concatenarea (conectarea) șirurilor
Concat() public static string Concat(string str0, string str1);

public static string Concat(params string values);

Combină instanțe individuale de șir într-un singur șir (concatenare)
Căutați într-un șir
Conține() public bool Conține (valoare șir) O metodă care vă permite să determinați dacă un șir conține un anumit subșir (valoare)
Incepe cu() public bool StartsWith(valoare șir)

Public bool StartsWith(valoare șir, Tip comparație șir de caractere)

Returnează valoarea booleană adevărată dacă șirul de apelare începe cu valoarea subșirului. În caz contrar, se returnează valoarea booleană false. Parametrul comparisonType specifică modul specific de a efectua căutarea

Se termină cu() public bool EndsWith(valoare șir)

Public bool EndsWith(valoare șir, tip de comparație StringComparison)

Returnează valoarea booleană adevărată dacă șirul de apelare se termină cu valoarea subșirului. În caz contrar, returnează valoarea booleană false. Parametrul comparisonType specifică metoda de căutare specifică

Index de() public int IndexOf(valoare caracter)

Public int IndexOf(valoare șir)

Găsește prima apariție a unui subșir sau caracter dat într-un șir. Dacă caracterul sau subșirul căutat nu este găsit, atunci valoarea -1 este returnată.

public int IndexOf(valoare caracter, int startIndex)

Public int IndexOf(valoare șir, int startIndex)

Public int IndexOf(valoare caracter, int startIndex, int număr)

Public int IndexOf(valoare șir, int startIndex, int număr)

Returnează indexul primei apariții a caracterului sau a valorii subșirului din șirul de apelare. Căutarea începe la elementul specificat de startIndex și se întinde pe numărul de elemente specificate de count (dacă este specificat). Metoda returnează -1 dacă caracterul sau subșirul căutat nu este găsit

LastIndexOf() Versiunile supraîncărcate sunt similare cu metoda IndexOf().

La fel ca IndexOf, dar găsește ultima apariție a unui caracter sau subșir, nu prima

IndexOfAny() public int IndexOfAny(char anyOf)

Public int IndexOfAny(char anyOf, int startIndex)

Public int IndexOfAny(char anyOf, int startIndex, int număr)

Returnează indexul primei apariții a oricărui caracter din tabloul anyOf găsit în șirul de apelare. Căutarea începe de la elementul specificat de startIndex și se întinde pe numărul de elemente specificate de count (dacă este specificat). Metoda returnează -1 dacă nu se potrivește niciun caracter din tabloul anyOf. Căutarea se efectuează în mod ordinal

LastIndexOfAny Versiunile supraîncărcate sunt similare cu metoda IndexOfAny().

Returnează indexul ultimei apariții a oricărui caracter din tabloul anyOf găsit în șirul de apelare

Împărțirea și unirea șirurilor
Despică șir public Split(params char separator)

Șir public Split(params char separator, int count)

O metodă care returnează o matrice de șiruri cu subșirurile prezente în această instanță în interior, care sunt separate unele de altele prin elemente din matricea de șiruri de caractere specificată.

Prima formă a metodei Split() împarte șirul de apelare în părțile sale componente. Rezultatul este un tablou care conține subșirurile obținute din șirul de apelare. Caracterele care delimitează aceste subșiruri sunt transmise în tabloul separator. Dacă matricea de separare este goală sau se referă la șirul gol, atunci un spațiu este folosit ca separator de subșir. Și în a doua formă a acestei metode, este returnat numărul de subșiruri determinat de parametrul count.

șir public Split (params char separator, opțiuni StringSplitOptions)

Split șir public (separator șir, opțiuni StringSplitOptions)

Split șir public (params char separator, int count, StringSplitOptions opțiuni)

Split șir public (separator șir, număr int, opțiuni StringSplitOptions)

În primele două forme ale metodei Split(), șirul de apelare este împărțit în părți și este returnat un tablou care conține subșirurile obținute din șirul de apelare. Caracterele care separă aceste subșiruri sunt transmise în tabloul separator. Dacă matricea de separare este goală, atunci un spațiu este folosit ca separator. Și în a treia și a patra formă a acestei metode, este returnat numărul de rânduri limitat de parametrul count.

Dar, în toate formele, parametrul opțiuni specifică o modalitate specifică de a gestiona liniile goale care sunt produse atunci când doi delimitatori sunt adiacenți. Enumerarea StringSplitOptions definește doar două valori: Nici unulȘi EliminațiEmptyEntries. Dacă opțiunile este None, atunci șirurile goale sunt incluse în rezultatul final al împărțirii șirului original. Și dacă parametrul opțiuni este setat la RemoveEmptyEntries, atunci liniile goale sunt excluse din rezultatul final al împărțirii șirului original.

A te alatura() Join string public static (separator șir, valoare șir)

Unire șir static public (separator șir, valoare șir, int startIndex, int număr)

Construiește un șir nou combinând conținutul unei matrice de șiruri.

Prima formă a metodei Join() returnează un șir format din subșiruri concatenate trecute în tabloul de valori. Cea de-a doua formă returnează, de asemenea, un șir format din subșiruri trecute în tabloul de valori, dar acestea sunt concatenate într-un anumit număr de număr, începând cu elementul de matrice value. În ambele forme, fiecare linie ulterioară este separată de linia anterioară printr-o linie separatoare specificată de parametrul separator.

Linii de umplere și tundere
Tunde() șir public Trim()

șir public Trim(params char trimChars)

O metodă care vă permite să eliminați toate aparițiile unui anumit set de caractere de la începutul și sfârșitul liniei curente.

Prima formă a metodei Trim() elimină spațiile de început și de final din șirul de apelare. Și a doua formă a acestei metode elimină aparițiile de început și de sfârșit ale șirului de caractere care apelează din tabloul trimChars. Ambele forme returnează șirul rezultat.

PadLeft() șir public PadLeft(int totalWidth)

Șir public PadLeft(int totalWidth, char paddingChar)

Vă permite să completați un șir cu caractere în stânga.

Prima formă a metodei PadLeft() introduce spații în partea stângă a șirului de apelare, astfel încât lungimea sa totală să devină egală cu valoarea parametrului totalWidth. Și în a doua formă a acestei metode, caracterele notate de parametrul paddingChar sunt introduse în partea stângă a șirului de apelare, astfel încât lungimea sa totală să devină egală cu valoarea parametrului totalWidth. Ambele forme returnează șirul rezultat. Dacă valoarea parametrului totalWidth este mai mică decât lungimea șirului de apelare, atunci este returnată o copie a șirului de apelare neschimbat.

PadDreapta() La fel ca PadLeft()

Vă permite să adăugați un șir cu caractere la dreapta.

Inserarea, ștergerea și înlocuirea rândurilor
Introduce() șir public Insert(int startIndex, valoare șir)

Folosit pentru a insera un rând în altul, unde valoarea denotă rândul care trebuie inserat în rândul apelant la startIndex. Metoda returnează șirul rezultat.

Elimina() șir public Remove(int startIndex)

Șir public Eliminare (int startIndex, int număr)

Folosit pentru a elimina o parte dintr-un șir. În prima formă a metodei Remove(), eliminarea începe în locația indicată de startIndex și continuă până la sfârșitul liniei. Și în cea de-a doua formă a acestei metode, numărul de caractere determinat de parametrul count este eliminat din șir, pornind de la locul indicat de indexul startIndex.

A inlocui() șir public Înlocuire(char oldChar, char newChar)

Șir public Înlocuire (șir vechiValoare, șir newValue)

Folosit pentru a înlocui o parte dintr-un șir. În prima formă a metodei Replace(), toate aparițiile caracterului oldChar din șirul de apelare sunt înlocuite cu caracterul newChar. Și în a doua formă a acestei metode, toate aparițiile șirului oldValue din linia de apelare sunt înlocuite cu șirul newValue.

Schimbă cazul
În sus() șir public ToUpper()

Scrie cu majuscule toate literele din șirul de apelare.

Pentru a reduce() șir public ToLower()

Toate literele mici din șirul de apelare.

Obținerea unui subșir dintr-un șir
subșir () șir public Subșir (int startIndex)

Șir public Subșir (int startIndex, int lungime)

În prima formă a metodei Substring(), subșirul este preluat pornind de la locația indicată de parametrul startIndex și terminând la sfârșitul șirului de apelare. Și în cea de-a doua formă a acestei metode, se extrage un subșir format din numărul de caractere determinat de parametrul lungime, pornind de la locul indicat de parametrul startIndex.

Următorul exemplu de program utilizează mai multe dintre metodele de mai sus:

Utilizarea sistemului; folosind System.Collections.Generic; folosind System.Linq; folosind System.Text; namespace ConsoleApplication1 ( clasa Program ( static void Main(string args) ( // Compara primele două linii șir s1 = „acesta este un șir"; șir s2 = „acesta este text și acesta este un șir"; if (String. CompareOrdinal(s1, s2) != 0) Console.WriteLine(„Șirurile s1 și s2 nu sunt egale”); if (String.Compare(s1, 0, s2, 13, 10, true) == 0) Console.WriteLine ("Totuși, acestea conțin același text"); // Concatenarea șirurilor de caractere Console.WriteLine(String.Concat("\n" + "One, two ","trei, patru")); // Căutare într-un șir / / Prima apariție a unui subșir dacă (s2. IndexOf(„this”) != -1) Console.WriteLine(„Cuvântul \”acest\” găsit în linie, acesta „+ ”este la: (0) poziția” , s2.IndexOf("this")); / / Ultima apariție a subșirului if (s2.LastIndexOf("this") != -1) Console.WriteLine("Ultima apariție a cuvântului \"this\" este " + "la (0) poziție", s2.LastIndexOf("this" )); // Căutare dintr-o matrice de caractere char myCh = ("ы","x","t"); if (s2.IndexOfAny (myCh) != -1) Console.WriteLine("Unul dintre caracterele din tabloul ch "+ "găsit în linia curentă la poziția (0)", s2.IndexOfAny(myCh)); // Determinați dacă linia începe cu subșirul dat if (s2.StartsWith("acesta este text") == true) Console.WriteLine("Subșir găsit!"); // Determinați dacă șirul conține un subșir // folosind exemplul de determinare a șirului de sistem de operare al utilizatorului myOS = Environment.OSVersion.ToString(); if (myOS.Contains ("NT 5.1")) Console.WriteLine ("Sistemul dvs. de operare este Windows XP"); else if (myOS.Contains ("NT 6.1")) Console.WriteLine ("Sistemul dvs. de operare este Windows 7"); Console.ReadLine(); ) ) )

Câteva despre compararea șirurilor în C#

Probabil cea mai comună dintre toate operațiunile cu șir de caractere este compararea unui șir cu altul. Înainte de a analiza orice metode de comparare a șirurilor, merită să subliniem următoarele: Comparațiile de șiruri pot fi făcute în .NET Framework în două moduri principale:

    În primul rând, comparația poate reflecta obiceiurile și normele unui anumit mediu cultural, care sunt adesea cadre culturale care intră în joc atunci când programul este implementat. Acesta este un comportament standard pentru unele metode de comparare, dar nu pentru toate.

    Și în al doilea rând, comparația se poate face indiferent de setările culturale doar prin valorile ordinale ale personajelor care alcătuiesc șirul. În general, comparațiile non-culturale ale șirurilor folosesc ordinea lexicografică (și caracteristicile lingvistice) pentru a determina dacă un șir este mai mare decât, mai mic sau egal cu un alt șir. În comparație ordinală, șirurile sunt pur și simplu ordonate pe baza valorii nemodificate a fiecărui caracter.

Din cauza diferențelor în modul în care diferă comparațiile de șiruri culturale și comparațiile ordinale și din cauza consecințelor fiecărei astfel de comparații, vă recomandăm insistent să urmați cele mai bune practici oferite în prezent de Microsoft. La urma urmei, alegerea unei metode greșite de comparare a șirurilor poate duce la funcționarea incorectă a programului atunci când acesta este operat într-un mediu diferit de cel în care a fost dezvoltat.

Alegerea modului de comparare a șirurilor de caractere este o decizie foarte importantă. Ca regulă generală și fără excepție, ar trebui să alegeți să comparați șirurile într-o manieră sensibilă din punct de vedere cultural dacă acest lucru este făcut în scopul de a afișa rezultatul utilizatorului (de exemplu, pentru a afișa o serie de șiruri sortate în ordine lexicografică). Dar dacă șirurile conțin informații fixe care nu sunt destinate să fie modificate pentru diferențele culturale, cum ar fi un nume de fișier, un cuvânt cheie, o adresă de site web sau o valoare de securitate, atunci ar trebui să alegeți compararea șirurilor ordinale. Desigur, caracteristicile aplicației particulare dezvoltate vor dicta alegerea unei metode adecvate pentru compararea șirurilor de caractere.

Clasa String oferă o varietate de metode de comparare a șirurilor, care sunt enumerate în tabelul de mai sus. Cea mai universală dintre ele este metoda Compare(). Permite compararea a două șiruri de caractere în întregime sau parțial, diferențiat de majuscule sau minuscule, într-un mod specificat de parametrul tip StringComparison, precum și informațiile culturale furnizate de parametrul tip CultureInfo.

Acele supraîncărcări ale metodei Compare() care nu includ un parametru de tip StringComparison efectuează o comparație a șirurilor de caractere care ține cont de majuscule și cultură. Și în acele variante supraîncărcate care nu conțin un parametru de tip CultureInfo, informațiile despre mediul cultural sunt determinate de mediul de rulare curent.

Tipul StringComparison este o enumerare care definește valorile prezentate în tabelul de mai jos. Folosind aceste valori, puteți crea comparații de șiruri care se potrivesc nevoilor aplicației dvs. specifice. Prin urmare, adăugarea unui parametru de tip StringComparison extinde capacitățile metodei Compare() și ale altor metode de comparare, cum ar fi Equals(). Acest lucru face, de asemenea, posibilă indicarea fără ambiguitate a modului în care se intenționează să fie comparate șirurile.

Din cauza diferențelor dintre comparațiile de șiruri sensibile din punct de vedere cultural și comparațiile ordinale, este important să fim cât mai precis posibil în acest sens.

Valori definite în enumerarea StringComparison
Sens Descriere
CurrentCulture Comparațiile de șiruri sunt făcute folosind setările actuale ale mediului cultural
CurrentCultureIgnoreCase Comparațiile de șiruri sunt făcute folosind setările curente de cultură, dar nu sunt sensibile la majuscule și minuscule
InvariantCulture Comparațiile de șiruri se fac folosind cele imuabile, adică date universale despre mediul cultural
InvariantCultureIgnoreCase Comparațiile de șiruri se fac folosind cele imuabile, adică date culturale universale și insensibile la majuscule și minuscule
Ordinal Comparațiile de șiruri se fac folosind valorile ordinale ale caracterelor din șir. În acest caz, ordinea lexicografică poate fi perturbată, iar convențiile adoptate într-un anumit mediu cultural sunt ignorate
OrdinalIgnoreCase Comparațiile de șiruri se fac folosind valorile ordinale ale caracterelor din șir, dar nu sunt sensibile la majuscule și minuscule

În orice caz, metoda Compare() returnează o valoare negativă dacă primul șir comparat este mai mic decât al doilea; pozitiv dacă primul șir comparat este mai mare decât al doilea; și, în final, zero dacă ambele șiruri comparate sunt egale. Deși metoda Compare() returnează zero dacă șirurile comparate sunt egale, în general este mai bine să folosiți metoda Equals() sau operatorul == pentru a determina dacă șirurile de caractere sunt egale.

Faptul este că metoda Compare() determină egalitatea șirurilor comparate pe baza ordinii lor de sortare. Astfel, dacă se face o comparație culturală între șiruri, ambele șiruri pot fi aceleași în ordinea lor de sortare, dar nu sunt egale în substanță. În mod implicit, egalitatea șirurilor este determinată în metoda Equals(), pe baza valorilor ordinale ale caracterelor și fără a ține cont de mediul cultural. Prin urmare, în mod implicit, ambele șiruri sunt comparate în această metodă pentru egalitate absolută, caracter cu caracter, similar cu modul în care se face în operatorul ==.

În ciuda versatilității mari a metodei Compare(), pentru comparații ordinale simple ale șirurilor de caractere este mai ușor să se folosească metoda CompareOrdinal(). În cele din urmă, rețineți că metoda CompareTo() efectuează doar comparații de șiruri sensibile din punct de vedere cultural.

Următorul program demonstrează utilizarea metodelor Compare(), Equals(), CompareOrdinal() și a operatorilor == și != pentru a compara șirurile de caractere. Rețineți că primele două exemple de comparație demonstrează în mod clar diferențele dintre comparațiile de șiruri sensibile din punct de vedere cultural și comparațiile ordinale într-un mediu vorbitor de limba engleză:

Utilizarea sistemului; Exemplu de clasă ( static void Main() ( șir str1 = "alfa"; șir str2 = "Alfa"; șir str3 = "Beta"; șir str4 = "alfa"; șir str5 = "alfa, beta"; rezultat int; / / Mai întâi, demonstrează diferențele dintre comparația de șiruri sensibilă la cultură // și rezultatul comparației ordinale = String.Compare(str1, str2, StringComparison.CurrentCulture); Console.Write("Comparație de șiruri sensibile la cultură: "); if (rezultat 0) ) Console.WriteLine(str1 + " mai mare decât " + str2); altfel Console.WriteLine(str1 + " egal cu " + str2); rezultat = String.Compare(str1, str2, StringComparison.Ordinal); Console.Write(" Linii de comparație ordinale: "); if (rezultat 0) Console.WriteLine(str1 + "mai mare decât " + str2); else Console.WriteLine(str1 + " egal cu " + str4); // Utilizați rezultatul metodei CompareOrdinal() = String.CompareOrdinal( str1, str2); Console.Write("Compararea șirurilor folosind metoda CompareOrdinal():\n"); if (rezultat 0) Console.WriteLine(str1 + " mai mare decât " + str2); else Console .WriteLine(str1 + " egal cu " + str4); Console.WriteLine(); // Determinați egalitatea șirurilor folosind operatorul == // Aceasta este o comparație ordinală a șirurilor de caractere if (str1 == str4) Console.WriteLine(str1 + " == " + str4); // Definiți inegalitatea liniilor folosind operatorul != if(str1 != str3) Console.WriteLine(str1 + " != " + str3); if(str1 != str2) Consola.WriteLine(str1 + " != " + str2); Console.WriteLine(); // Efectuați o comparație ordinală a șirurilor de caractere care nu ține seama de majuscule // folosind metoda Equals() if(String.Equals(str1, str2, StringComparison.OrdinalIgnoreCase)) Console.WriteLine("Comparație de șiruri folosind metoda Equals() cu " + "Parametrul OrdinalIgnoreCase: \n" + str1 + " este egal cu " + str2); Console.WriteLine(); // Comparați părți ale șirurilor de caractere if(String.Compare(str2, 0, str5, 0, 3, StringComparison.CurrentCulture) > 0) ( Console.WriteLine("Comparați șirurile ținând cont de mediul cultural actual:" + "\n3 primele caractere ale șirului " + str2 + " mai mult decât primele 3 caractere ale liniei " + str5); ) ) )

Rularea acestui program produce următorul rezultat:

Habra, salut!

Nu cu mult timp în urmă, mi s-a întâmplat un incident destul de interesant, în care a fost implicat unul dintre profesorii unei facultăți de informatică.

Conversația despre programarea Linux a progresat încet la această persoană, susținând că complexitatea programării sistemelor a fost de fapt foarte exagerată. Că limbajul C este la fel de simplu ca o potrivire, de fapt, ca nucleul Linux (în cuvintele lui).

Aveam cu mine un laptop cu Linux, care conținea un set de utilități gentleman pentru dezvoltare în limbajul C (gcc, vim, make, valgrind, gdb). Nu-mi amintesc ce obiectiv ne-am propus atunci, dar după câteva minute adversarul meu s-a trezit la acest laptop, complet gata să rezolve problema.

Și literalmente la primele rânduri a făcut o greșeală gravă când a alocat memorie la... o linie.

Char *str = (char *)malloc(sizeof(char) * strlen(buffer));
buffer - o variabilă de stivă în care au fost scrise datele de la tastatură.

Cred că vor exista cu siguranță oameni care se vor întreba: „Cum ar putea fi ceva în neregulă cu asta?”
Crede-mă, se poate.

Și ce anume - citiți despre pisică.

Puțină teorie - un fel de LikBez.

Dacă știți, derulați la următorul antet.

Un șir în C este o matrice de caractere, care ar trebui să se termine întotdeauna cu „\0” - caracterul de sfârșit de linie. Șirurile din stivă (statice) sunt declarate astfel:

Char str[n] = (0);
n este dimensiunea matricei de caractere, la fel ca lungimea șirului.

Atribuire ( 0 ) - „reducerea la zero” a șirului (opțional, îl puteți declara fără el). Rezultatul este același cu rularea funcțiilor memset(str, 0, sizeof(str)) și bzero(str, sizeof(str)). Este folosit pentru a preveni lăsarea gunoiului în variabilele neinițializate.

De asemenea, puteți inițializa imediat un șir pe stivă:

Char buf = "text tampon implicit\n";
În plus, un șir poate fi declarat ca un pointer și poate fi alocată memorie pentru el pe heap:

Char *str = malloc(dimensiune);
dimensiune - numărul de octeți pe care îi alocăm pentru șir. Astfel de șiruri sunt numite dinamice (datorită faptului că dimensiunea necesară este calculată dinamic + dimensiunea memoriei alocată poate fi mărită în orice moment folosind funcția realloc()).

În cazul unei variabile stive, am folosit notația n pentru a determina dimensiunea matricei; în cazul unei variabile heap, am folosit dimensiunea notației. Și aceasta reflectă perfect esența adevărată a diferenței dintre o declarație pe stivă și o declarație cu alocare de memorie pe heap, deoarece n este de obicei folosit când se vorbește despre numărul de elemente. Și dimensiunea este o cu totul altă poveste...

Valgrind ne va ajuta

În articolul meu anterior am menționat și asta. Valgrind ( , doi - o mică instrucțiune) este un program foarte util care ajută programatorul să urmărească scurgerile de memorie și erorile de context - exact lucrurile care apar cel mai des atunci când lucrează cu șiruri.

Să ne uităm la o scurtă listă care implementează ceva similar cu programul pe care l-am menționat și să o rulăm prin valgrind:

#include #include #include #define HELLO_STRING "Bună ziua, Habr!\n" void main() ( char *str = malloc(sizeof(char) * strlen(HELLO_STRING)); strcpy(str, HELLO_STRING); printf("->\t%s" , str); liber (str); )
Și, de fapt, rezultatul programului:

$ gcc main.c $ ./a.out -> Bună, Habr!
Nimic neobișnuit încă. Acum să rulăm acest program cu valgrind!

$ valgrind --tool=memcheck ./a.out ==3892== Memcheck, un detector de erori de memorie ==3892== Copyright (C) 2002-2015 și GNU GPL"d, de Julian Seward și colab. == 3892== Utilizând Valgrind-3.12.0 și LibVEX; reluați cu -h pentru informații despre drepturile de autor ==3892== Comanda: ./a.out ==3892== ==3892== Scriere nevalidă de dimensiunea 2 ==3892= = la 0x4005B4: principal (în /home/indever/prg/C/public/a.out) ==3892== Adresa 0x520004c are 12 octeți în interiorul unui bloc de dimensiunea 13 alloc"d ==3892== la 0x4C2DB9D: malloc (vg_replace_malloc.c:299) ==3892== de 0x400597: main (în /home/indever/prg/C/public/a.out) ==3892== ==3892== Citire nevalidă pentru dimensiunea 1 == 3892== la 0x4C30BC4: strlen (vg_replace_strmem.c:454) ==3892== de 0x4E89AD0: vfprintf (în /usr/lib64/libc-2.24.so) ==3892== prin 0x4E89AD0 (în /usr/lib64/libc-2.24.so) ==3892== prin 0x4E89AD0 lib64/libc-2.24.so) ==3892== de 0x4005CF: main (în /home/indever/prg/C/public/a.out) ==3892== Adresa 0x520004d este de 0 octeți după un bloc de dimensiunea 13 alloc"d ==3892== la 0x4C2DB9D: malloc (vg_replace_malloc.c:299) ==3892== prin 0x400597: main (în /home/inever/prg/C/public/a.out) ==3892== -> Bună, Habr! ==3892== ==3892== REZUMAT HEAP: ==3892== în uz la ieșire: 0 octeți în 0 blocuri ==3892== utilizare totală a heap: 2 alocări, 2 libere, 1.037 octeți alocați ==3892= = ==3892== Toate blocurile heap au fost eliberate -- nu sunt posibile scurgeri ==3892== ==3892== Pentru numărul erorilor detectate și suprimate, reluați cu: -v ==3892== REZUMAT ERORI: 3 erori din 2 contexte (suprimat: 0 din 0)
==3892== Toate blocurile heap au fost eliberate - nu sunt posibile scurgeri- nu există scurgeri și aceasta este o veste bună. Dar merită să-ți cobori ochii puțin mai jos (deși, vreau să remarc, acesta este doar rezumatul, informația principală este un loc puțin diferit):

==3892== REZUMAT ERORI: 3 erori din 2 contexte (suprimat: 0 din 0)
3 greseli. În 2 contexte. Într-un program atât de simplu. Cum!?

Da, foarte simplu. Întregul „lucru amuzant” este că funcția strlen nu ia în considerare caracterul de sfârșit de linie - „\0”. Chiar dacă îl specificați în mod explicit în linia de intrare (#define HELLO_STRING „Hello, Habr!\n\0”), va fi ignorat.

Chiar deasupra rezultatului execuției programului, linia -> Bună, Habr! există un raport detaliat despre ce și unde nu i-a plăcut prețiosului nostru valgrind. Vă sugerez să vă uitați singur la aceste rânduri și să trageți propriile concluzii.

De fapt, versiunea corectă a programului va arăta astfel:

#include #include #include #define HELLO_STRING „Bună ziua, Habr!\n” void main() ( char *str = malloc(sizeof(char) * (strlen(HELLO_STRING) + 1)); strcpy(str, HELLO_STRING); printf("->\ t%s", str); liber(str); )
Să o trecem prin valgrind:

$ valgrind --tool=memcheck ./a.out -> Bună, Habr! ==3435== ==3435== REZUMAT HEAP: ==3435== în uz la ieșire: 0 octeți în 0 blocuri ==3435== utilizare totală a heap: 2 alocări, 2 libere, 1.038 octeți alocați ==3435= = ==3435== Toate blocurile heap au fost eliberate -- nu sunt posibile scurgeri ==3435== ==3435== Pentru numărul erorilor detectate și suprimate, reluați cu: -v ==3435== REZUMAT ERORI: 0 erori din 0 contexte (suprimat: 0 din 0)
Grozav. Nu există erori, +1 octet de memorie alocată a ajutat la rezolvarea problemei.

Ceea ce este interesant este că, în majoritatea cazurilor, atât primul cât și cel de-al doilea program vor funcționa la fel, dar dacă memoria alocată pentru linia în care caracterul final nu se potrivea nu a fost pusă la zero, atunci funcția printf() la scoaterea unei astfel de linii , va scoate tot gunoiul după această linie - totul va fi tipărit până când un caracter de sfârșit de linie iese în calea printf().

Cu toate acestea, știți, (strlen(str) + 1) este o astfel de soluție. Ne confruntăm cu 2 probleme:

  1. Ce se întâmplă dacă trebuie să alocam memorie pentru un șir generat folosind, de exemplu, s(n)printf(..)? Nu susținem argumentele.
  2. Aspect. Linia de declarație variabilă arată îngrozitor. Unii băieți reușesc să atașeze (char *) la malloc, de parcă ar scrie sub plusuri. Într-un program în care trebuie să procesați în mod regulat șiruri, este logic să găsiți o soluție mai elegantă.
Să venim cu o soluție care să ne mulțumească atât pe noi, cât și pe valgrind.

snprintf()

int snprintf(char *str, size_t size, const char *format, ...);- o funcție - o extensie a lui sprintf, care formatează un șir și îl scrie în pointerul trecut ca prim argument. Diferă de sprintf() prin faptul că str nu va scrie un octet mai mare decât dimensiunea specificată.

Funcția are o caracteristică interesantă - în orice caz, returnează dimensiunea șirului generat (fără a lua în considerare caracterul de sfârșit de linie). Dacă șirul este gol, atunci este returnat 0.

Una dintre problemele pe care le-am descris cu utilizarea strlen este legată de funcțiile sprintf() și snprintf(). Să presupunem că trebuie să scriem ceva în șirul str. Linia finală conține valorile celorlalte variabile. Intrarea noastră ar trebui să fie cam așa:

Char * str = /* alocă memorie aici */; sprintf(str, „Bună ziua, %s\n”, „Habr!”);
Apare întrebarea: cum să determinați câtă memorie ar trebui alocată pentru șirul str?

Char * str = malloc(sizeof(char) * (strlen(str, "Bună ziua, %s\n", "Habr!") + 1)); - Nu va merge. Prototipul funcției strlen() arată astfel:

#include size_t strlen(const char *s);
const char *s nu implică faptul că șirul transmis la s poate fi un șir în format variadic.

Proprietatea utilă a funcției snprintf(), pe care am menționat-o mai sus, ne va ajuta aici. Să ne uităm la codul următorului program:

#include #include #include void main() ( /* Deoarece snprintf() nu ia în considerare caracterul de sfârșit de linie, adăugăm dimensiunea acestuia la rezultat */ size_t needed_mem = snprintf(NULL, 0, "Bună ziua, %s!\n", "Habr") + sizeof ("\0"); char *str = malloc(needed_mem); snprintf(str, needed_mem, "Bună ziua, %s!\n", "Habr"); printf("->\t %s", str); liber (str); )
Rulați programul în valgrind:

$ valgrind --tool=memcheck ./a.out -> Bună, Habr! ==4132== ==4132== REZUMAT HEAP: ==4132== în uz la ieșire: 0 octeți în 0 blocuri ==4132== utilizare totală a heap: 2 alocări, 2 libere, 1.041 octeți alocați ==4132= = ==4132== Toate blocurile heap au fost eliberate -- nu sunt posibile scurgeri ==4132== ==4132== Pentru numărul erorilor detectate și suprimate, reluați cu: -v ==4132== REZUMAT ERORI: 0 erori din 0 contexte (suprimat: 0 din 0) $
Grozav. Avem susținere a argumentelor. Datorită faptului că trecem null ca al doilea argument la funcția snprintf(), scrierea la un pointer nul nu va provoca niciodată un Seagfault. Cu toate acestea, în ciuda acestui fapt, funcția va returna în continuare dimensiunea necesară pentru șir.

Dar, pe de altă parte, a trebuit să introducem o variabilă suplimentară și designul

Size_t needed_mem = snprintf(NULL, 0, "Bună ziua, %s!\n", "Habr") + sizeof("\0");
arată chiar mai rău decât în ​​cazul lui strlen().

În general, + sizeof("\0") poate fi eliminat dacă specificați în mod explicit "\0" la sfârșitul liniei de format (size_t needed_mem = snprintf(NULL, 0, "Salut, %s!\n \0 ", "Habr");), dar acest lucru nu este întotdeauna posibil (în funcție de mecanismul de procesare a șirurilor, putem aloca un octet suplimentar).

Trebuie să facem ceva. M-am gândit puțin și am decis că acum este momentul să apelez la înțelepciunea anticilor. Să descriem o funcție macro care va apela snprintf() cu un pointer nul ca prim argument și nul ca al doilea. Și să nu uităm de sfârșitul firului!

#define strsize(args...) snprintf(NULL, 0, args) + sizeof("\0")
Da, poate fi o noutate pentru unii, dar macro-urile C acceptă un număr variabil de argumente, iar punctele de suspensie îi spun preprocesorului că argumentul funcției macro specificat (în cazul nostru, args) corespunde mai multor argumente reale.

Să verificăm soluția noastră în practică:

#include #include #include #define strsize(args...) snprintf(NULL, 0, args) + sizeof("\0") void main() ( char *str = malloc(strsize("Bună ziua, %s\n", "Habr! ")); sprintf(str, "Bună ziua, %s\n", "Habr!"); printf("->\t%s", str); liber(str); )
Să începem cu valgrund:

$ valgrind --tool=memcheck ./a.out -> Bună, Habr! ==6432== ==6432== REZUMAT HEAP: ==6432== în uz la ieșire: 0 octeți în 0 blocuri ==6432== utilizare totală a heap: 2 alocări, 2 libere, 1.041 octeți alocați ==6432= = ==6432== Toate blocurile heap au fost eliberate -- nu sunt posibile scurgeri ==6432== ==6432== Pentru numărul erorilor detectate și suprimate, reluați cu: -v ==6432== REZUMAT ERORI: 0 erori din 0 contexte (suprimat: 0 din 0)
Da, nu există erori. Totul este corect. Și valgrind este fericit, iar programatorul poate să se culce în sfârșit.

Dar, în sfârșit, voi mai spune un lucru. În cazul în care trebuie să alocăm memorie pentru orice șir (chiar și cu argumente), există deja soluție complet gata de funcționare.

Vorbim despre funcția asprintf:

#define _GNU_SOURCE /* Vezi feature_test_macros(7) */ #include int asprintf(char **strp, const char *fmt, ...);
Ia un pointer către un șir (**strp) ca prim argument și alocă memorie pointerului dereferențiat.

Programul nostru scris folosind asprintf() va arăta astfel:

#include #include #include void main() ( char *str; asprintf(&str, „Bună ziua, %s!\n”, „Habr”); printf(“->\t%s”, str); liber(str); )
Și, de fapt, în valgrind:

$ valgrind --tool=memcheck ./a.out -> Bună, Habr! ==6674== ==6674== REZUMAT HEAP: ==6674== în uz la ieșire: 0 octeți în 0 blocuri ==6674== utilizare totală a heap: 3 alocări, 3 libere, 1.138 octeți alocați ==6674= = ==6674== Toate blocurile heap au fost eliberate -- nu sunt posibile scurgeri ==6674== ==6674== Pentru contorizarea erorilor detectate și suprimate, rulați din nou cu: -v ==6674== REZUMAT ERORI: 0 erori din 0 contexte (suprimat: 0 din 0)
Totul este în regulă, dar, după cum puteți vedea, a fost alocată mai multă memorie și acum există trei alocări, nu două. Pe sistemele încorporate slabe, folosirea acestei funcții nu este de dorit.
În plus, dacă scriem man asprintf în consolă, vom vedea:

CONFORME CU Aceste funcții sunt extensii GNU, nu în C sau POSIX. Sunt disponibile și sub *BSD. Implementarea FreeBSD setează strp la NULL în caz de eroare.

Acest lucru arată clar că această funcție este disponibilă numai în sursele GNU.

Concluzie

În concluzie, vreau să spun că lucrul cu șiruri în C este un subiect foarte complex, care are o serie de nuanțe. De exemplu, pentru a scrie cod „sigur” atunci când se alocă dinamic memorie, se recomandă utilizarea funcției calloc() în loc de malloc() - calloc umple memoria alocată cu zerouri. Sau, după alocarea memoriei, utilizați funcția memset(). În caz contrar, gunoiul care a fost localizat inițial în zona de memorie alocată poate cauza probleme în timpul depanării și, uneori, atunci când lucrați cu șirul.

Mai mult de jumătate dintre programatorii C pe care îi cunosc (majoritatea dintre ei sunt începători) care au rezolvat problema alocării de memorie pentru șiruri la cererea mea, au făcut-o într-un mod care a dus în cele din urmă la erori de context. Într-un caz - chiar și la o scurgere de memorie (ei bine, o persoană a uitat să facă free(str), nu se întâmplă nimănui). De fapt, asta m-a determinat să creez această creație pe care tocmai ai citit-o.

Sper că acest articol va fi de folos cuiva. De ce fac atâta tam-tam - nici un limbaj nu este simplu. Peste tot are propriile sale subtilități. Și cu cât cunoști mai multe subtilități ale limbii, cu atât mai bine este codul tău.

Cred că după citirea acestui articol codul tău va deveni puțin mai bun :)
Succes, Habr!

Linii. Intrare/ieșire șir. I/O formatat. Procesarea șirurilor folosind funcții standard ale limbajului C. Lucrul cu memoria.

1.1. Declararea și inițializarea șirurilor de caractere.

Un șir este o matrice de caractere care se termină cu caracterul gol „\0”. Șirul este declarat ca o matrice obișnuită de caractere, de exemplu,

char s1; // șir lung de nouă caractere

char *s2; // pointer către șir

Diferența dintre pointerii s1 și s2 este că pointerul s1 este o constantă numită, iar pointerul s2 este o variabilă.

Constantele șirurilor sunt cuprinse între ghilimele duble, spre deosebire de caracterele, care sunt cuprinse între ghilimele simple. De exemplu,

„Acesta este un șir.”

Lungimea unei constante șir nu poate depăși 509 caractere conform standardului. Cu toate acestea, multe implementări permit lungimi mai mari ale șirurilor.

Când inițializați șirurile, este mai bine să nu specificați dimensiunea matricei; compilatorul va face acest lucru calculând lungimea șirului și adăugând unul la acesta. De exemplu,

char s1 = „Acesta este un șir.”;

În limbajul de programare C, există un număr mare de funcții pentru lucrul cu șiruri de caractere, ale căror prototipuri sunt descrise în fișierele de antet stdlib.h și string.h. Lucrul cu aceste funcții va fi discutat în paragrafele următoare.

1.2. Intrare/ieșire șir.

Pentru a introduce un șir din consolă, utilizați funcția

char* gets(char *str);

care scrie un șir la adresa str și returnează adresa șirului introdus. Funcția oprește introducerea dacă întâlnește un caracter „\n” sau EOF (sfârșitul fișierului). Caracterul newline nu este copiat. Un octet zero este plasat la sfârșitul liniei de citire. Dacă are succes, funcția returnează un pointer la linia citită, iar dacă nu are succes, NULL.

Pentru a scoate un șir în consolă, utilizați funcția standard

int pune (const char *s);

care, dacă are succes, returnează un număr nenegativ, iar dacă nu are succes, returnează EOF.

Prototipurile funcțiilor gets and puts sunt descrise în fișierul antet stdio.h.

#include

printf("Șir de intrare: ");

1.3. I/O formatat.

Pentru introducerea datelor formatate din consolă, utilizați funcția

int scanf (const char *format, ...);

care, dacă are succes, returnează numărul de unități de date citite, iar dacă nu are succes, returnează EOF. Parametrul format trebuie să indice șirul de formatat, care conține specificațiile formatului de intrare. Numărul și tipurile de argumente care urmează șirul de format trebuie să se potrivească cu numărul și tipurile de formate de intrare specificate în șirul de format. Dacă această condiție nu este îndeplinită, atunci rezultatul funcției este imprevizibil.

Un spațiu, „\t” sau „\n” într-un șir de format descrie unul sau mai multe caractere goale din fluxul de intrare, care includ caracterele: spațiu, „\t”, „\n”, „\v”, '\f'. Funcția scanf omite caracterele goale în fluxul de intrare.

Caracterele literale dintr-un șir de format, cu excepția caracterului %, necesită ca exact aceleași caractere să apară în fluxul de intrare. Dacă nu există un astfel de caracter, funcția scanf se oprește. Funcția scanf omite caracterele literale.

În general, specificația formatului de intrare arată astfel:

%[*] [lățime] [modificatoare].

Simbolul „*” denotă omisiune la introducerea unui câmp definit de această specificație;

- ‘lățime’ definește numărul maxim de caractere introduse conform acestei specificații;

Tipul poate lua următoarele valori:

c – matrice de caractere,

s – un șir de caractere, liniile sunt separate prin caractere goale,

d – întreg cu semn de 10 s/s,

i – întreg cu semn, sistemul numeric depinde de primele două cifre,

u – întreg fără semn la 10 s/s,

o – întreg fără semn în 8 s/s,

x, X – întreg fără semn la 16 s/s,

e, E, f, g, G – număr flotant,

p – pointer la pointer,

n – pointer către un număr întreg,

[…] – o serie de caractere scanate, de exemplu, .

În acest din urmă caz, din fluxul de intrare vor fi introduse numai caracterele cuprinse între paranteze drepte. Dacă primul caracter din paranteze pătrate este „^”, atunci sunt introduse numai acele caractere care nu sunt în matrice. Intervalul de caractere din matrice este specificat folosind simbolul „-”. Când introduceți caractere, sunt introduse și caracterele necompletate de început și octetul nul final al șirului.

Modificatorii pot lua următoarele valori:

h – număr întreg scurt,

l, L – întreg lung sau flotant,

și sunt folosite numai pentru numere întregi sau flotante.

Următorul exemplu arată utilizări ale funcției scanf. Rețineți că specificatorul de format, începând cu introducerea numărului flotant, este precedat de un caracter spațiu.

#include

printf("Introduceți un număr întreg: ");

scanf("%d", &n);

printf("Introduceți un dublu: ");

scanf(" %lf", &d);

printf("Introduceți un caracter: ");

scanf(" %c", &c);

printf("Introduceți un șir: ");

scanf(" %s", &s);

Rețineți că în acest program numărul în virgulă mobilă este inițializat. Acest lucru se face astfel încât compilatorul să includă biblioteca pentru a sprijini lucrul cu numere flotante. Dacă nu se face acest lucru, va apărea o eroare în timpul rulării la introducerea unui număr flotant.

Pentru ieșirea formatată a datelor către consolă, utilizați funcția

int printf (const char *format, ...);

care, dacă are succes, returnează numărul de unități de date de ieșire, iar dacă nu are succes, returnează EOF. Parametrul format este un șir de format care conține specificații pentru formatele de ieșire. Numărul și tipurile de argumente care urmează șirul de format trebuie să se potrivească cu numărul și tipurile de specificații de format de ieșire specificate în șirul de format. În general, specificația formatului de ieșire arată astfel:

%[steaguri] [lățime] [.precizie] [modificatoare].

- ‘steaguri’ sunt diferite simboluri care specifică formatul de ieșire;

- „lățimea” definește numărul minim de caractere ieșite conform acestei specificații;

- ‘.precision’ definește numărul maxim de caractere afișate;

- ‘modificatorii’ specifică tipul de argumente;

- „tip” specifică tipul argumentului.

Pentru a scoate numere întregi cu semn, se folosește următorul format de ieșire:

%[-] [+ | spațiu] [lățime] [l] d

- – aliniere stânga, implicit – dreapta;

+ – este afișat semnul ‘+’, rețineți că pentru numerele negative este afișat întotdeauna semnul ‘-’;

‘spațiu’ – un spațiu este afișat la poziția caracterului;

d – int tipul de date.

Pentru a scoate numere întregi fără semn, utilizați următorul format de ieșire:

%[-] [#] [lățime] [l]

# – 0 inițial este afișat pentru numerele din 8 c/c sau inițial 0x sau 0X pentru numerele din 16 c/c,

l – modificator de tip de date lung;

u – întreg în 10c/c,

o – întreg în 8 c/c,

x, X – întreg la 16 c/c.

Următorul format de ieșire este utilizat pentru a afișa numere în virgulă mobilă:

%[-] [+ | spațiu] [lățime] [.precizie]

„precizie” - indică numărul de cifre după virgulă pentru formatele f, e și E sau numărul de cifre semnificative pentru formatele g și G. Numerele sunt rotunjite. Precizia implicită este de șase cifre zecimale;

f – numărul punctului fix,

e – un număr în formă exponențială, exponentul este notat cu litera „e”,

E – un număr în formă exponențială, exponentul este notat cu litera „E”,

g – cel mai scurt dintre formatele f sau g,

G – cel mai scurt dintre formatele f sau G.

printf ("n = %d\n f = %f\n e = %e\n E = %E\n f = %.2f", -123, 12.34, 12.34, 12.34, 12.34);

// afișează: n = 123 f = 12,340000 e = 1,234000e+001 E = 1,234000E+001 f = 12,34

1.4. Formatarea șirurilor.

Există variante ale funcțiilor scanf și printf care sunt concepute pentru a formata șiruri și sunt numite sscanf și, respectiv, sprintf.

int sscanf (const char *str, const char *format, ...);

citește datele din șirul specificat de str, conform șirului de format specificat de format. Dacă are succes, returnează numărul de date citite, iar dacă nu are succes, returnează EOF. De exemplu,

#include

char str = "a 10 1.2 String Nicio intrare";

sscanf(str, „%c %d %lf %s”, &c, &n, &d, s);

printf("%c\n", c); // imprimă: a

printf("%d\n", n); // imprimări: 10

printf("%f\n", d); // imprimări: 1,200000

printf("%s\n", s); // imprimă: String

int sprintf (char *buffer, const char *format, ...);

formatează șirul în conformitate cu formatul specificat de parametrul format și scrie rezultatul rezultat în tamponul matricei de caractere. Funcția returnează numărul de caractere scrise în bufferul matricei de caractere, excluzând octetul nul final. De exemplu,

#include

char str = "c = %c, n = %d, d = %f, s = %s";

char s = "Acesta este un șir.";

sprintf(buffer, str, c, n, d, s);

printf("%s\n", buffer); // afișează: c = c, n = 10, d = 1,200000, s = Acesta este un șir

1.5. Convertiți șirurile de caractere în date numerice.

Prototipurile de funcții pentru conversia șirurilor de caractere în date numerice sunt date în fișierul antet stdlib.h, care trebuie inclus în program.

Pentru a converti un șir într-un număr întreg, utilizați funcția

int atoi (const char *str);

char *str = „-123”;

n = atoi(str); // n = -123

Pentru a converti un șir într-un număr întreg lung, utilizați funcția

long int atol (const char *str);

care, dacă are succes, returnează întregul în care este convertit șirul str, iar dacă nu are succes, returnează 0. De exemplu,

char *str = „-123”;

n = atol(str); // n = -123

Pentru a converti un șir într-un număr dublu, utilizați funcția

double atof(const char *str);

care, dacă are succes, returnează un număr flotant de tip double, în care este convertit șirul str, iar dacă nu are succes, returnează 0. De exemplu,

char *str = „-123.321”;

n = atof(str); // n = -123,321

Următoarele funcții îndeplinesc funcții similare cu atoi, atol, atof, dar oferă funcționalități mai avansate.

long int strtol (const char *str, char **endptr, int bază);

convertește șirul str într-un număr int lung, pe care îl returnează. Parametrii acestei funcții au următoarele scopuri.

Dacă baza este 0, atunci conversia depinde de primele două caractere ale str:

Dacă primul caracter este un număr de la 1 la 9, atunci se presupune că numărul este reprezentat în 10 c/c;

Dacă primul caracter este cifra 0 și al doilea caracter este o cifră de la 1 la 7, atunci se presupune că numărul este reprezentat în 8 c/c;

Dacă primul caracter este 0 și al doilea este „X” sau „x”, atunci se presupune că numărul este reprezentat în 16 c/c.

Dacă baza este un număr între 2 și 36, atunci acea valoare este considerată baza sistemului numeric și orice caracter din afara sistemului numeric încetează conversia. În sistemele numerice de la baza 11 la baza 36, ​​simbolurile „A” la „Z” sau „a” la „z” sunt folosite pentru a reprezenta cifre.

Valoarea argumentului endptr este stabilită de funcția strtol. Această valoare conține un indicator către caracterul care a oprit conversia șirului de caractere. Funcția strtol returnează numărul convertit dacă are succes și 0 dacă nu are succes. De exemplu,

n = strtol („12a”, &p, 0);

printf("n = %ld, %stop = %c, n, *p); // n = 12, stop = a

n = strtol ("012b", &p, 0);

printf("n = %ld, %stop = %c, n, *p); // n = 10, stop = b

n = strtol („0x12z”, &p, 0);

printf("n = %ld, %stop = %c, n, *p); // n = 18, stop = z

n = strtol („01117”, &p, 0);

printf("n = %ld, %stop = %c, n, *p); // n = 7, stop = 7

unsigned long int strtol (const char *str, char **endptr, int bază);

funcționează similar cu funcția strtol, dar convertește reprezentarea simbolică a unui număr într-un număr de tip unsigned long int.

dublu strtod (const char *str, char **endptr);

Transformă reprezentarea simbolică a unui număr într-un dublu.

Toate funcțiile enumerate în acest paragraf nu mai funcționează atunci când întâlnesc primul caracter care nu se potrivește cu formatul numărului în cauză.

În plus, dacă valoarea caracterului unui număr depășește intervalul de valori acceptabile pentru tipul de date corespunzător, atunci funcțiile atof, strtol, strtoul, strtod setează valoarea variabilei errno la ERANGE. Variabila errno și constanta ERANGE sunt definite în fișierul antet math.h. În acest caz, funcțiile atof și strtod returnează valoarea HUGE_VAL, funcția strtol returnează valoarea LONG_MAX sau LONG_MIN, iar funcția strtoul returnează valoarea ULONG_MAX.

Funcțiile non-standard itoa, ltoa, utoa, ecvt, fcvt și gcvt pot fi utilizate pentru a converti datele numerice în șiruri de caractere. Dar este mai bine să folosiți funcția standard sprintf în aceste scopuri.

1.6. Funcții standard pentru lucrul cu șiruri.

Această secțiune discută funcțiile pentru lucrul cu șiruri de caractere, ale căror prototipuri sunt descrise în fișierul antet string.h.

1. Comparație de șiruri. Funcțiile strcmp și strncmp sunt folosite pentru a compara șiruri.

int strcmp (const char *str1, const char *str2);

compară lexicografic șirurile str1, str2 și returnează –1, 0 sau 1 dacă str1 este, respectiv, mai mic, egal sau mai mare decât str2.

int strncmp (const char *str1, const char *str2, size_t n);

compară lexicografic cel mult primele n caractere din șirurile str1 și str2. Funcția returnează -1, 0 sau 1 dacă primele n caractere din str1 sunt, respectiv, mai mici, egale sau mai mari decât primele n caractere din str2.

// exemplu de comparare a șirurilor

#include

#include

char str1 = "aa bb";

char str2 = "aa aa";

char str3 = "aa bb cc";

printf("%d\n", strcmp(str1, str3)); // imprimă: -1

printf("%d\n", strcmp(str1, str1)); // imprimă: -0

printf("%d\n", strcmp(str1, str2)); // se imprimă: 1

printf("%d\n", strncmp(str1, str3, 5)); // imprimă: 0

2. Copierea liniilor. Funcțiile strcpy și strncpy sunt folosite pentru a copia șiruri.

char *strcpy (char *str1, const char *str2);

copiează șirul str2 în șirul str1. Întregul șir str2 este copiat, inclusiv octetul nul final. Funcția returnează un pointer către str1. Dacă liniile se suprapun, rezultatul este imprevizibil.

char *strncpy (char *str1, const char *str2, size_t n);

copiază n caractere din șirul str2 în șirul str1. Dacă str2 conține mai puțin de n caractere, atunci ultimul octet zero este copiat de câte ori este necesar pentru a extinde str2 la n caractere. Funcția returnează un pointer către șirul str1.

char str2 = "Copiați șirul.";

strcpy(str1, str2);

printf(str1); // imprimă: Copiați șirul.

4. Corzi de legătură. Funcțiile strcat și strncat sunt folosite pentru a concatena șiruri într-un singur șir.

char* strcat (char *str1, const char *str2);

adaugă șirul str2 la șirul str1, cu octetul zero final al șirului str1 șters. Funcția returnează un pointer către șirul str1.

char* strncat (char *str1, const char *str2, size_t n);

adaugă n caractere din șirul str2 la șirul str1, cu octetul zero de la urmă al șirului str1 șters. Funcția returnează un pointer către șirul str1. dacă lungimea șirului str2 este mai mică decât n, atunci sunt atașate numai caracterele incluse în șirul str2. După concatenarea șirurilor, un octet nul este întotdeauna adăugat la str1. Funcția returnează un pointer către șirul str1.

#include

#include

char str1 = „Șir”;

char str2 = "catenare";

char str3 = "Da Nu";

strcat(str1, str2);

printf("%s\n", str1); // printează: String catenation

strncat(str1, str3, 3);

printf("%s\n", str1); // imprimă: String catenation Da

5. Căutați un caracter într-un șir. Pentru a căuta un caracter într-un șir, utilizați funcțiile strchr, strrchr, strspn, strcspn și strpbrk.

char* strchr (const char *str, int c);

caută prima apariție a caracterului specificat de c în șirul str. Dacă are succes, funcția returnează un pointer la primul caracter găsit, iar dacă nu are succes, NULL.

char* strrchr (const char *str, int c);

caută ultima apariție a caracterului specificat de c în șirul str. Dacă are succes, funcția returnează un pointer la ultimul caracter găsit, iar dacă nu are succes, NULL.

#include

#include

char str = "Căutare Char";

printf("%s\n", strchr(str, "r")); // imprimă: r căutare

printf("%s\n", strrchr(str, "r")); // tipărituri: rch

size_t strspn (const char *str1, const char *str2);

returnează indexul primului caracter din str1 care nu este în str2.

size_t strcspn (const char *str1, const char *str2);

returnează indexul primului caracter din str1 care apare în str2.

char str = "123 abc";

printf ("n = %d\n", strspn (str, "321"); // afișează: n = 3

printf ("n = %d\n", strcspn (str, "cba"); // afișează: n = 4

char* strpbrk (const char *str1, const char *str2);

găsește primul caracter din șirul str1 care este egal cu unul dintre caracterele din șirul str2. Dacă are succes, funcția returnează un pointer la acest caracter, iar dacă nu are succes, NULL.

char str = "123 abc";

printf("%s\n", strpbrk(str, "bca")); // imprimă: abc

6. Comparație de șiruri. Funcția strstr este folosită pentru a compara șiruri.

char* strstr (const char *str1, const char *str2);

găsește prima apariție a lui str2 (fără octetul nul final) în str1. Dacă are succes, funcția returnează un pointer către subșirul găsit, iar dacă nu are succes, NULL. Dacă pointerul str1 indică un șir de lungime zero, atunci funcția returnează pointerul str1.

char str = "123 abc 456;

printf ("%s\n", strstr (str, "abc"); // print: abc 456

7. Analizarea unui șir în jetoane. Funcția strtok este folosită pentru a analiza un șir în token-uri.

char* strtok (char *str1, const char *str2);

returnează un pointer la următorul token (cuvânt) din șirul str1, în care delimitatorii jetonului sunt caractere din șirul str2. Dacă nu mai există jetoane, funcția returnează NULL. La primul apel la funcția strtok, parametrul str1 trebuie să indice un șir care este tokenizat, iar la apelurile ulterioare acest parametru trebuie setat la NULL. După găsirea unui token, funcția strtok scrie un octet nul după acest token în locul delimitatorului.

#include

#include

char str = "12 34 ab cd";

p = strtok(str, " ");

printf("%s\n", p); // tipărește valorile într-o coloană: 12 34 ab cd

p = strtok(NULL, " ");

8. Determinarea lungimii unui șir. Funcția strlen este utilizată pentru a determina lungimea unui șir.

size_t strlen (const char *str);

returnează lungimea șirului, ignorând ultimul octet nul. De exemplu,

char str = "123";

printf("len = %d\n", strlen(str)); // imprimă: len = 3

1.7. Funcții pentru lucrul cu memoria.

Fișierul antet string.h descrie, de asemenea, funcții pentru lucrul cu blocuri de memorie, care sunt similare cu funcțiile corespunzătoare pentru lucrul cu șiruri.

void* memchr (const void *str, int c, size_t n);

caută prima apariție a caracterului specificat de c în n octeți ai șirului str.

int memcmp (const void *str1, const void *str2, size_t n);

compară primii n octeți ai șirurilor str1 și str2.

void* memcpy (const void *str1, const void *str2, size_t n);

copiază primii n octeți din șirul str1 în șirul str2.

void* memmove (const void *str1, const void *str2, size_t n);

copiează primii n octeți de la str1 la str2, asigurându-se că șirurile care se suprapun sunt gestionate corect.

void* memset (const void *str, int c, size_t n);

copiază caracterul specificat de c în primii n octeți ai str.