ctype.h
ctype.h este fișierul antet care, în cadrul bibliotecii C standard , declară funcțiile utilizate pentru clasificarea caracterelor.
Istorie
Primii programatori de limbaj C de pe Unix au început rapid să dezvolte controale pentru a clasifica caracterele între diferite tipuri: număr , literă , caracter de control sau subseturi precum majuscule sau minuscule , terminându-se cu seturi mai mari, cum ar fi caracterele tipărite . Pentru a efectua aceste clasificări, au fost inițial concepute teste foarte simple; următorul exemplu arată cum să identificăm dacă caracterul conținut în variabila c
este o literă:
if ('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z')
Rezultatul acestei expresii este valid dacă c
reprezintă un caracter conform codificării ASCII : dimpotrivă, nu funcționează dacă setul de caractere utilizat pe mașină este, de exemplu, EBCDIC . Pe lângă faptul că nu este portabil , un program bazat în mare măsură pe teste precum acesta ar fi foarte greu de întreținut, având în vedere înțelegerea nu imediată a codului: acest lucru ar expune programatorul la erori logice mai mult sau mai puțin grave.
Implementare
Spre deosebire de cele de mai sus, funcțiile de clasificare a caracterelor nu sunt scrise sub formă de teste comparative. De fapt, în majoritatea bibliotecilor C acestea sunt implementate cu căutări în tabele alocate static .
De exemplu, tabelul poate fi implementat cu o matrice de 256 de numere întregi de câte 8 biți fiecare, organizat ca un câmp de biți , în care fiecare bit corespunde unei proprietăți particulare a caracterului: număr , literă și așa mai departe. Dacă bitul cel mai puțin semnificativ al întregului se potrivește cu proprietatea numărului , codul funcției (sau mai bine isdigit()
macro) isdigit()
ar putea fi scris simplu ca:
#define isdigit (x) (TABLE [x] & 1)
Cu toate acestea, primele versiuni de Linux au folosit o metodă similară cu următoarea, care ar putea expune codul la erori logice:
#define isdigit (x) ((x)> = '0' && (x) <= '9')
Această definiție ar putea cauza probleme dacă determinarea valorii lui x
avut efecte secundare, ca în isdigit(x++)
sau isdigit(esegui_qualcosa())
. În acest caz, expresia ar fi evaluată de două ori, ceea ce nu este imediat evident pentru programatorul distras. Pentru aceasta, metoda tabelului este utilizată mai mult (vezi și postarea lui Linus Torvalds în lista de corespondență a kernel-ului Linux de mai jos).
Funcții
Fișierul ctype.h
conține o duzină de funcții de clasificare a caracterelor: toate sunt dependente de localizare, cu excepția isdigit()
. În plus, funcțiile pot fi împărțite în două subgrupuri: cele utilizate pentru verificarea proprietăților caracterelor și cele utilizate pentru convertirea acestora.
Nume | Descriere |
---|---|
Funcții pentru verificarea proprietăților fontului Acestea returnează zero dacă este fals sau un număr diferit de zero dacă este adevărat. | |
isalnum | Verificați dacă caracterul trecut este alfanumeric . |
isalpha | Verificați dacă caracterul trecut este alfabetic . |
isblank | Verificați dacă caracterul trecut este alb , adică nu este vizibil pe ecran (spațiu sau filă). (introdus de C99) |
iscntrl | Verificați dacă caracterul trecut este controlat . |
isdigit | Verificați dacă caracterul trecut este numeric . (nu depinde de localizare) |
isgraph | Verificați dacă caracterul trecut este grafic , adică are un glif asociat. Caracterele spațiale, de exemplu, nu sunt considerate grafice . |
islower | Verificați dacă caracterul trecut este cu litere mici . |
isprint | Verificați dacă caracterul trecut este imprimabil . |
ispunct | Verificați dacă caracterul trecut este punctuație . |
isspace | Verificați dacă caracterul trecut este spațiu alb . |
isupper | Verificați dacă caracterul trecut este cu majuscule . |
isxdigit | Verificați dacă caracterul trecut este hexazecimal , adică este inclus în 0-9 sau af sau AF. |
Funcții pentru conversia personajelor Ele returnează personajul convertit. | |
tolower | Convertește caracterul trecut în potrivirea sa cu litere mici, dacă este cazul. |
toupper | Convertește caracterul trecut în majusculele corespunzătoare, dacă este cazul. |
Versiunea 3 a Specificației Single Unix adaugă caracteristici suplimentare suplimentare:
Nume | Descriere |
---|---|
isascii | Verificați dacă caracterul trecut este compatibil cu setul de caractere ASCII . |
toascii | Convertește caracterul trecut pentru a fi compatibil cu setul de caractere ASCII . |
Greșeli comune
Standardul C99 prevede clar (§7.4-1):
- În toate cazurile, argumentul este un int , a cărui valoare poate fi reprezentată ca un caracter nesemnat sau trebuie să fie egală cu valoarea EOF macro. Dacă argumentul are orice altă valoare, comportamentul este nedefinit.
In italiana:
- În toate cazurile [adică toți parametrii funcției, ndt] argumentele sunt ints , a căror valoare trebuie să fie reprezentabilă ca un caracter nesemnat sau trebuie să fie echivalentă cu valoarea macro-ului EOF . Dacă argumentul ia orice altă valoare, comportamentul este nedefinit.
Din păcate, mulți programatori uită că o variabilă de tip char poate fi semnată sau nesemnată, în funcție de implementare. Dacă tipul char este semnat, atunci conversia implicită din char în int ar putea duce la valori negative, rezultând un comportament nedefinit. În general, se întâmplă ca argumentul negativ să fie folosit ca index într-un tabel de căutare, accesând o zonă din afara mesei în sine și potențial în afara memoriei alocate de program, mergând chiar până la a genera o eroare de segmentare .
Modul corect de a utiliza parametrii char este, prin urmare, să aruncați un char nesemnat .
Alte proiecte
linkuri externe
- ( EN ) Explicația metodei tabelului de către Linus Torvalds