Siruri de caractere si pointeri
10.1. Marcatorul "sfarsit de sir de caractere" \0
10.2. Folosirea pointerilor pentru procesarea
unui sir
10.3. Trimiterea argumentelor catre "main()"
10.4. Lucrul cu sirurile din biblioteca standard
10.5. Unde este eroarea ?
10.6. Exercitii propuse spre implementare
=========
Capitolul 10
=========
======================
Siruri de caractere si pointeri
======================
Un caracter dintr-un sir de caractere
"a" poate fi accesat folosind indexul sirului (a[i], de exemplu) sau
folosind pointeri la caracter.
-------- ----- ------ ----- ----- -----------
Marcatorul "sfarsit de sir de caractere" \0
-------- ----- ------ ----- ----- -----------
Prin conventie, un sir de caractere se termina
prin marcatorul (santinela, delimitator) \0, sau caracterul nul. De exemplu,
sirul "abc" este memorat pe 4 caractere,
ultimul fiind \0. Deci numarul de elemente al sirului este
3, iar dimensiunea 4.
-----------
Exemplu:
-----------
#define MAXWORD 100
void main()
Initializarea (citirea) unui sir se poate face in mai multe moduri:
1. Initializarea fiecarui
element cu cate un caracter:
w[0] = 'A';
w[1] = 'B';
w[2] = 'C';
w[3] = '\0';
2. Folosind functia "scanf()":
scanf("%s", w);
Formatul
"%s" este folosit pentru citirea unui sir de caractere. Distingem
trei pasi:
- pozitionare pe primul caracter al sirului;
- se citesc toate caracterele diferite de <Enter> si se introduc in
"w";
- citirea se face pana cand intalnim EOF; acum se plaseaza la sfarsitul sirului
'\0'.
Din moment
ce numele unui sir este un pointer la adresa de baza a sirului, expresia
"w" este echivalenta cu "&w[0]".
Daca sirul
citit are mai multe caractere decat cele rezervate, atunci se va obtine o eroare.
Atentie ! 'a' si "a" sunt
diferite. Prima este o
----- ------
"a" = | 'a' | '\0'
|
----- ------
3. Sirurile se pot initializa
la fel ca si caracterele
char s[] = "abc";
sau
echivalent
char s[] = ;
4. Putem folosi si un pointer catre un sir constant, dar interpretarea este
diferita:
char *p = "abc";
Va reamintim
ca numele unui sir poate fi tratat ca un pointer catre adresa de baza a sirului
din memorie.
Asadar, diferenta dintre un sir initializat cu o
-----------
Exemplu: Utilizarea sirurilor de caractere (ca vectori).
----------- Citim o linie de caractere
dintr-un sir, le tiparim in ordine inversa si adunam literele din sir.
#include <stdio.h>
#include <ctype.h>
#define MAXSTRING
main()
name[i] = '\0';
printf("\n%s%s%s\n%s",
"Ma bucur ca te-am
intalnit ",name,".",
"Numele tau scris
invers este ");
for (--i; i >= 0; --i)
putchar(name[i]);
printf("\n%s%d%s\n\n%s\n",
"si numele tau are
", sum," litere .",
"La revedere.
");
}
-------- ----- ------ ----- ----- -----------------
Folosirea pointerilor pentru procesarea unui sir
-------- ----- ------ ----- ----- -----------------
Vom discuta despre folosirea pointerilor pentru procesarea unui sir si
cum se pot folosi acestea pentru a fi transmise ca parametri unei functii. Vom
scrie un exemplu de program interactiv care citeste
intr-un sir o linie de caractere introdusa de utilizator. Programul va crea un nou sir si-l va tipari.
------------
Exemplu:
------------
#include <stdio.h>
#define MAXLINE 100
void main()
void citeste_in(char s[])
char *schimba(char *s)
else
*p++ = *s;
*p = '\0';
return sir_nou;
}
-----------
Intrebare: De ce vectorul "sir_nou" a fost declarat static ?
-----------
Deoarece numele "sir_nou" este tratat
ca un pointer catre adresa de baza a sirului. Fiind declarat
"static", acesta se pastreaza in memorie si dupa ce se iese din
functia "schimba()". Acest
lucru nu s-ar fi intamplat si daca, de exemplu, sirul ar fi fost declarat
"auto".
-----------
Exemplu: Functie C pentru numararea cuvintelor unui sir de caractere
-----------
#include <ctype.h>
int numarare_cuvinte(char *s)
}
return contor;
}
-------- ----- ------ ----- ----- ---------
Trimiterea argumentelor catre "main()"
-------- ----- ------ ----- ----- ---------
C pune la dispozitie siruri de orice tip, inclusiv siruri de pointeri.
Pentru scrierea de programe care folosesc argumente in linia de comanda,
trebuie sa folosim siruri de pointeri catre caractere.
Pentru aceasta, functia "main()" foloseste
doua argumente, numite generic "argc" si "argv".
-----------
Exemplu:
-----------
#include <stdio.h>
void main(int argc, char *argv[])
Variabila "argc" precizeaza numarul de argumente din linia de
comanda. Sirul "argv" este un sir de
pointeri catre caracter si poate fi gandit ca vector de siruri de caractere.
Deoarece elementul "argv[0]" contine
intotdeauna numele comenzii, rezulta ca valoarea lui "argc" va fi mai
mare sau egala cu 1.
Compilam programul de mai sus si obtinem executabilul
"prog1.exe". Daca dam comanda
prog1
atunci pe ecran se va afisa
argc = 1
argv[0] = prog1
Daca dam comanda
prog1 fisier1 fisier2
atunci pe ecran se va afisa
argc = 3
argv[0] = prog1
argv[1] = fisier1
argv[2] = fisier2
Parametrul "argv" s-ar fi putut declara si astfel
char **argv;
Acesta este un pointer catre pointer catre "char" si acesta
poate fi gandit ca un sir de pointeri catre "char", care la randul
lor pot fi ganditi ca vector de siruri de caractere. Observati
ca nu alocam spatiu in memorie pentru sirurile din linia de comanda.
Acest lucru este facut de insusi sistemul C cand
atribuie valori pentru argumentele "argc" si "argv".
-------- ----- ------ ----- ----- ----------
Lucrul cu sirurile din biblioteca standard
-------- ----- ------ ----- ----- ----------
Biblioteca standard <string.h> contine multe functii utile pentru
lucrul cu siruri de caractere. Sirurile ce sunt
argumente trebuie terminate cu '\0' si toate returneaza un intreg sau o valoare
a unui pointer catre "char".
Cateva functii utile pentru lucrul cu
siruri de caractere
-------- ----- ------ -------- ----- ------
- char *strcat(char
*s1, const char *s2);
Functia primeste doua
argumente, le concateneaza si pune rezultatul in "s1". Programatorul
trebuie sa verifice daca "s1"
are suficient spatiu pentru pastrarea rezultatului. Se returneaza sirul "s1".
- int
strcmp(const char *s1, const char *s2);
Sunt trimise doua siruri de
caractere si se returneaza un intreg care este mai mic strict, egal sau mai
mare strict
decat 0 dupa cum
"s1" este mai mic, egal sau mai mare lexicografic decat
"s2".
- char *strcpy(char
*s1, const char *s2);
Sirul "s2" este
copiat in "s1" pana cand se intalneste '\0'. Ceea ce
se gaseste in "s1" se suprascrie. Se presupune ca "s1"
are suficient spatiu pentru
pastrarea rezultatului. Se returneaza valoarea lui
"s1".
- unsigned
strlen(const char *s);
Pastreaza numarul de caractere
inaintea lui '\0'.
-------- ----- ------ ----- ----- --------- ----- -------
Aceste functii sunt scrise in C si sunt foarte scurte. Variabilele din
ele sunt de obicei declarate "register" pentru a face executia
mai rapida.
----------
Exemplu: Functia "strlen()" (o
varianta).
----------
unsigned strlen(const char *s)
-------- ----- ------ ----- ----- ----------------
|
Declaratii
si
initializari
|
-------- ----- ------ ----- ----- ----------------
| char s1[] = "tara noastra frumoasa si
bogata", |
| s2[] = "facultatea de
informatica";
|
-------- ----- ------ ----- ----- ----------------
|
Expresie
|
Valoare
|
-------- ----- ------ ----- ----- ----------------
|
strlen(s1)
|
31
|
| strlen(s2 +
8)
|
17
|
| strcmp(s1,
s2) | numar
pozitiv
|
-------- ----- ------ ----- ----- ----------------
|
Instructiune | Ce se va
tipari
? |
-------- ----- ------ ----- ----- ----------------
| printf("%s",
s1 + 13); | frumoasa si bogata |
| strcpy(s2 + 11, s1 +
25);|
|
| strcat(s2,
"\n"); |
|
| printf("%s",
s2); |
facultatea bogata |
-------- ----- ------ ----- ----- ----------------
----- ----- ---------------
Unde este eroarea ?
----- ----- ---------------
1.
char s[14];
strcpy(s, "Ce mai faci ?\n");
2.
char s[14];
scanf("%s", &s);
-------- ----- ------ ----- ----- ----
Exercitii propuse spre implementare
-------- ----- ------ ----- ----- ----
1. Folosind "argc" si "argv" (si
eventual optiunea -c) tipariti cu litere majuscule argumentele din
"argv".
2. Scrieti o functie proprie "strncmp()"
(extrageti din Help definitia si prototipul).
3. Presupunem ca avem declaratia si initializarea:
char *p[2][3]
= ;
Completati urmatorul tabel (incercati intai sa nu rulati
programul C).
-------- ----- ------ ----- ----- --------- ----- --------
|
Expresie
| Expresie echivalenta | Valoare |
-------- ----- ------ ----- ----- --------- ----- -------
|
***p
|
p[0][0][0]
| 'a' |
|
**p[1]
|
|
|
| **(p[1] +
2)
|
|
|
|*(*(p + 1) + 1)[7]
|
| eroare |
|(*(*(p + 1) +
1))[7]|
|
|
| *(p[1][2] +
2)
|
|
|
-------- ----- ------ ----- ----- --------- ----- --------
4. Folosind "scanf()" cititi 7 siruri
de caractere, dupa care folosind "strcmp()" sortati-le alfabetic
(eventual cu "bubble sort").
5. (*) Scrieti un program similar cu exercitiul
4 care sorteaza si afiseaza argumentele din linia de comanda.
|