Materijali/Čas 13

Čas 13 · nul znak, unos reda i obrada teksta

Stringovi: tekst kao niz znakova

String povezujemo sa već poznatim nizovima: pratimo znakove do završnog nul znaka, bezbedno učitavamo ceo red, ručno prolazimo kroz tekst i tek zatim koristimo funkcije iz string.h.

MAPA ČASA

Od ideje do prvog C programa

1
program
2
podaci
3
promenljiva
4
pseudokod
5
C program

Na kraju je dovoljno da:

  • Razlikuj jedan char od stringa i objasni ulogu nul znaka.
  • Učitaj ceo red funkcijom fgets i ukloni završni novi red.
  • Prođi kroz string petljom i prebroj ili promeni izabrane znakove.
  • Kopiraj i poredi stringove ručno i funkcijama iz string.h.

01 · KORAK

Jedan znak nije isto što i string

Promenljiva char slovo = 'A'; čuva jedan znak. Deklaracija char rec[] = "A"; pravi niz sa dva elementa: slovom A i završnim nul znakom '\0'.

C ne pamti dužinu stringa posebno. Funkcije i petlje prepoznaju kraj kada naiđu na prvi '\0'. Zbog toga niz mora imati mesto i za taj završni element.

char slovo = 'A';
char rec[] = "A";       /* 'A', '\0' */
char grad[4] = "Nis";  /* tri slova i '\0' */
Promena kraja stringaZa char s[] = "C je tu" odredi prikaz posle s[2] = 'J';, a zatim posle s[4] = '\0';. Objasni zašto znaci iza novog nul znaka više nisu deo prikazanog stringa.
Kapacitet nije isto što i dužinaNiz char s[20] ima kapacitet 20 elemenata, ali string u njemu može biti kraći. Ako s sadrži "kod", dužina je 3, a četvrti element je '\0'.

02 · KORAK

fgets čita ceo red, uključujući razmake

Format %s funkcije scanf staje na prvom razmaku. Za rečenicu zato koristimo fgets, proveravamo da li je čitanje uspelo i ostavljamo joj podatak o kapacitetu niza.

Ako u nizu ima mesta, fgets obično sačuva i znak novog reda nastao pritiskom na Enter. Taj znak tražimo i menjamo u '\0' pre poređenja ili dalje obrade.

char s[100];
if (fgets(s, sizeof s, stdin) == NULL) return 1;

int i = 0;
while (s[i] != '\0' && s[i] != '\n') i++;
if (s[i] == '\n') s[i] = '\0';
Prati stvarni sadržaj nizaZa unos Ana voli C odredi indeks znaka novog reda, element koji postaje '\0' i konačan string. Zatim objasni šta bi učitao scanf sa formatom %99s.
Provera rezultata nije ukrasAko fgets vrati NULL, nema ispravno učitanog reda koji bi program smeo dalje da obrađuje.

03 · KORAK

Petlja ide do prvog nul znaka

Obrada stringa liči na obradu niza, ali granicu ne daje posebna promenljiva n. Uslov s[i] != '\0' vodi petlju do kraja važećeg teksta.

Isti obrazac može da odredi dužinu, prebroji pojavljivanja jednog znaka, pronađe prvi znak ili promeni sve odgovarajuće elemente.

int broj_znaka(const char s[], char trazeni) {
    int broj = 0;
    for (int i = 0; s[i] != '\0'; i++)
        if (s[i] == trazeni) broj++;
    return broj;
}
Čitanje ili promenaUporedi funkciju koja samo broji znakove sa funkcijom koja menja svako 'a' u 'o'. Objasni zašto prva može da primi const char s[], a druga ne može.
Veliko i malo slovo nisu isti znakPoređenje s[i] == 'a' ne prihvata 'A'. Ako zadatak traži oba oblika, uslov to mora izričito da obuhvati ili treba koristiti odgovarajuću funkciju iz ctype.h.

04 · KORAK

Jednim prolaskom rešavamo više brojanja

Za svaki znak možemo proveriti kojoj grupi pripada: 'a' do 'z', 'A' do 'Z', '0' do '9' ili razmak. Lanac if/else if sprečava da isti znak uđe u više međusobno isključivih grupa.

Znakovi cifara nisu brojevi koji se računaju. U stringu su to karakteri '0' do '9', pa ih proveravamo kao znakove.

if (s[i] >= 'a' && s[i] <= 'z') mala++;
else if (s[i] >= 'A' && s[i] <= 'Z') velika++;
else if (s[i] >= '0' && s[i] <= '9') cifre++;
else if (s[i] == ' ') razmaci++;
Proveri graniceZa red AiP 2026 izračunaj sva četiri broja, zatim proveri red sa znakovima na granicama: A, Z, a, z, 0 i 9.
Novi red se ne brojiAko obrada ide direktno posle fgets, petlja može da stane i na '\n', ili se novi red prethodno uklanja. Tako Enter ne ulazi ni u jednu grupu.

05 · KORAK

Kopiranje i poređenje rade element po element

Nizovi se posle deklaracije ne kopiraju operatorom =. Ručna funkcija za kopiranje prenosi svaki vidljivi znak i na kraju obavezno upisuje '\0'. Odredište mora biti dovoljno veliko.

Pri poređenju se proveravaju znakovi na istim indeksima. Ako nema razlike pre kraja, stringovi su jednaki samo ako se oba završe na istom indeksu.

int jednaki(const char a[], const char b[]) {
    int i = 0;
    while (a[i] != '\0' && b[i] != '\0') {
        if (a[i] != b[i]) return 0;
        i++;
    }
    return a[i] == b[i];
}
Isti početak nije dovoljanPrati poređenje parova kod/kod, kod/kodovi i Ana/ana. Za svaki par napiši indeks na kome je odluka donesena.
Ne zaboravi završetakPetlja koja kopira samo dok izvor[i] != '\0' mora posle petlje posebno da upiše odrediste[i] = '\0'. Bez toga odredište nije pouzdan string.

06 · KORAK

string.h skraćuje kod, ali ne proverava kapacitet umesto nas

strlen vraća dužinu bez nul znaka. strcpy kopira, strcat dodaje, strcmp poredi, a strstr traži podstring. Sve su deklarisane u zaglavlju string.h.

Kod strcmp je važan znak rezultata: 0 znači jednaki, negativno da je prvi string leksikografski pre drugog, a pozitivno da je posle. Standard ne obećava baš -1 ili 1.

char s[20] = "pro";
strcat(s, "gram");       /* program */
printf("%zu", strlen(s)); /* 7 */

if (strcmp(a, b) == 0)
    puts("Jednaki");
Izaberi pravu funkcijuZa svaku nameru izaberi funkciju: napravi kopiju teksta, dodaj nastavak, proveri jednakost, pronađi gram u programiranje i odredi dužinu.
Biblioteka ne proširuje nizstrcpy i strcat ne znaju kapacitet odredišta. Program mora unapred da obezbedi dovoljno mesta za ceo rezultat i završni nul znak.

ZATVARANJE

Brza provera pre domaćeg

  1. Koja je razlika između algoritma i programa?
  2. Šta je ime, a šta vrednost promenljive?
  3. Kako svojim rečima čitaš x = x + 1?
  4. Koji red prvog programa računa, a koji prikazuje rezultat?