STRINGOVI U JEZIKU C

String u jeziku C predstavlja niz podataka tipa char i služi za rad sa tekstom. Definišu se na sledeći način:


char tekst[] = "Ovo je neki tekst";
  

ili, može i ovako:


char tekst[] = {'O', 'v', 'o', ' ', 'j', 'e', 'n', 'e', 'k', 'i',
                ' ', 't', 'e', 'k', 's', 't', '\0'};
  

Objašnjenje null karaktera

U jeziku C, string je niz karaktera koji je uvek terminiran specijalnim karakterom '\0' (null karakter). Ovaj karakter označava kraj stringa, pa kada radimo sa stringovima u C-u, funkcije kao što su printf ili strlen prestaju da čitaju znakove kada naiđu na '\0'. Bez ovog karaktera, funkcije ne bi mogle ispravno odrediti gde string završava.

Na primer, ako definišemo niz karaktera bez '\0', funkcija printf može nastaviti da ispisuje podatke iz memorije, sve dok slučajno ne naiđe na neki '\0'. To može dovesti do nepredvidivih rezultata. Zato je veoma važno da stringovi uvek budu pravilno terminisani.

Preciznost u primerima

Kada definišemo string u C-u, možemo koristiti dve metode. Prva, jednostavna metoda je:


char tekst[] = "Ovo je neki tekst";
  

Ova definicija automatski dodaje null karakter '\0' na kraj stringa. Drugi način, ručno definisanje stringa kao niza karaktera, izgleda ovako:


char tekst[] = {'O', 'v', 'o', ' ', 'j', 'e', ' ', 'n', 'e', 'k', 'i',
                ' ', 't', 'e', 'k', 's', 't', '\0'};
  

Tip podatka char

Tip podatka char je sličan int podatku, tj. služi za opis celih brojeva, ali zauzima samo 8 bita memorije, za razliku od int-a, koji zauzima 16 ili 32 bita i može čuvati veći broj.

Tip char se obično koristi za čuvanje znakovnih podataka, odnosno njihovih kodova. Tako, na primer, ako želimo da sačuvamo slovo A u memoriji, čuvali bi zapravo kod slova A. Kodovi karaktera (znakova) su pridruženi brojevi, pomoću kojih razlikujemo karakter.

Npr. kod slova A je broj 65, kod slova B je 66 itd. Vrednost koda možemo dobiti ako karakter stavimo pod apostrofe, npr. 'A'.

Primer definisanja koda slova A i njegovo ispisivanje, zajedno sa ispisivanjem karaktera, bi bio:


char ch = 'A';
printf("Kod slova i slovo: %c %d\n", ch, ch);
  

Posle pokretanja:


Kod slova i slovo: A 65
  
Prikaz koda znaka u jeziku C-izvršenje
Slika 1: Prikaz koda znaka u jeziku C-izvršenje

Detaljno objašnjenje char tipa u C jeziku

Tip podatka char koristi se za predstavljanje pojedinačnih karaktera. Njegove glavne karakteristike su:

  • Veličina i vrednosti: Zauzima 1 bajt memorije (8 bita) i može sadržati vrednosti od -128 do 127 (za signed char) ili od 0 do 255 (za unsigned char).
  • Kodiranje: Obično koristi ASCII kod za mapiranje karaktera na brojeve. Na primer, 'A' je 65, 'a' je 97.
  • Operacije: Može se koristiti u aritmetičkim operacijama, jer se karakteri interno čuvaju kao numeričke vrednosti.

Praktični primer


#include <stdio.h>

int main() {
    char c = 'A';
    printf("Character: %c, ASCII value: %d\n", c, c);
    return 0;
}
  

Razlike između char i stringova: Pojedinačni karakter (char) i niz karaktera (string) se razlikuju – stringovi zahtevaju niz char-ova sa završnim karakterom \0.

Primer 1: Ispisivanje tablice ASCII kodova karaktera

Ispisaćemo kodove karaktera tako što, koristeći for petlju, menjamo kodove od 32 do 126 i te vrednosti ispisujemo koristeći konverziju "%c" za ispis karaktera, a "%d" za ispis koda odgovarajućeg karaktera.

Napomena: Kod 127 i kodovi od 0–32 postoje i odnose se na neštampajuće znake, kontrolne i bele znakove. Postoje i znaci sa kodovima većim od 127 a manjim ili jednakim 255 i oni zavise od lokalnih podešavanja (npr. ćirilična slova u određenim područjima).


#include <stdio.h>
#include <stdlib.h>

int main() {
    for(int ch = 32; ch <= 126; ch++) {
        printf("%c %d\n", ch, ch);
    }
    return 0;
}
  

Posle izvršenja programa vidimo sledeće:


! 33
" 34
# 35
$ 36
% 37
...
~ 126
  
Prikaz tablice ASCII znakovnih kodova  u jeziku C-izvršenje
Slika 2: Prikaz tablice ASCII znakovnih kodova u jeziku C-izvršenje

Učitavanje znakova sa tastature

Učitavanje jednog karaktera (znaka) sa tastature, uključujući i beli znak, može se izvršiti pomoću funkcije getchar() iz zaglavlja <stdio.h>.

U istom zaglavlju se nalazi i funkcija koja će ispisati ovaj znak – putchar(ch), gde je ch taj znak.

Funkcije poput getchar(), putchar() i funkcije iz zaglavlja <ctype.h> omogućavaju jednostavno upravljanje ulazom i izlazom podataka, kao i ispitivanje karaktera:

  • getchar() – omogućava unos jednog karaktera sa tastature.
  • putchar() – omogućava ispis jednog karaktera na ekranu.
  • <ctype.h> – sadrži funkcije za proveru tipa karaktera (da li je slovo, cifra, beli znak, itd.), što pomaže u validaciji i obradi unosa.

Ispitivanje znakova pomoću funkcija iz <ctype.h>

Najčešće korišćene funkcije su:

  • isalnum(ch) – da li je ch slovo ili cifra?
  • isalpha(ch) – da li je ch slovo?
  • islower(ch) – da li je ch malo slovo?
  • isupper(ch) – da li je ch veliko slovo?
  • isdigit(ch) – da li je ch decimalna cifra?
  • isspace(ch) – da li je ch beli znak?
  • ispunct(ch) – da li je ch znak interpunkcije?
  • iscntrl(ch) – da li je ch upravljački znak?

Rezime:

  • ispunct(ch) vraća true ako je karakter interpunkcijski znak (npr. tačka, zarez, upitnik).
  • isdigit(ch) vraća true ako je karakter cifra (0–9).
  • isalpha(ch) vraća true ako je karakter slovo.
  • islower(ch) vraća true ako je malo slovo.
  • isupper(ch) vraća true ako je veliko slovo.

Ove funkcije omogućavaju jednostavno prepoznavanje vrste karaktera, što je ključno za analizu unosa u mnogim programima.

Primer 2: Analiza unete šifre

Napraviti program koji od korisnika zahteva da unese šifru i ispisuje na ekranu koliko ima malih, velikih slova, cifara i znakova interpunkcije u toj šifri.

Za unos šifre koristićemo do-while petlju i funkciju getchar(), a za ispitivanje vrste znaka funkcije iz zaglavlja <ctype.h>.


#include <stdio.h>
#include <ctype.h>

int main() {
    int sc = 0; // broj znakova interpunkcije
    int nd = 0; // broj cifara
    int uc = 0; // broj velikih slova
    int lc = 0; // broj malih slova
    char ch;

    printf("Unesite šifru!\n");

    do {
        ch = getchar();

        if (ispunct(ch)) {
            sc++;
        }
        if (isdigit(ch)) {
            nd++;
        }
        if (isupper(ch)) {
            uc++;
        }
        if (islower(ch)) {
            lc++;
        }

    } while (ch != EOF && (!isspace(ch) && !iscntrl(ch)));

    printf("Šifra ima %d malih slova, %d velikih slova, %d cifru/cifre i %d specijalnih znakova.\n",
           lc, uc, nd, sc);

    return 0;
}
  

Učitavanje se vrši sve dok se ne unese beli znak ili neki upravljački znak (npr. novi red), ili se ne unese znak za kraj datoteke (Ctrl+Z).

Izvršenje primera: Na ekranu se vidi broj malih i velikih slova, cifara i interpunkcijskih znakova u šifri koju je korisnik uneo.

Analiza unete šifre, primer u C jeziku-izvršenje
Slika 3: Analiza unete šifre, primer u C jeziku-izvršenje

EOF i rad sa stringovima i pokazivačima

EOF (End of File) označava signal koji se koristi u programiranju da označi kraj unosa podataka. U kontekstu funkcije getchar(), kada korisnik unese karaktere, EOF signalizira kraj unosa. Na primer:

  • Ctrl+Z na Windows-u
  • Ctrl+D na Unix/Linux sistemima

while petlja u ovom kontekstu omogućava kontinuirani unos dok se ne unese EOF ili beli znak. Petlja stalno poziva funkciju getchar() i proverava vrednost koju je uneo korisnik, čime omogućava unos više znakova sve dok se ne postigne kraj unosa.

Stringovi i pokazivači

Stringovi u C jeziku predstavljaju nizove podataka tipa char, koji se mogu kreirati i dinamički (pomoću pokazivača) ili statički (kao nizovi).

Definicija dva stringa:


char* pTekst = "Danas je lep dan"; 
char tekst2[19] = {'A','n','a',' ','v','o','l','i',' ',
                   'M','i','l','o','v','a','n','a','\0'};
  • Dinamičko kreiranje: koristi pokazivač koji pokazuje na konstantni string u memoriji.
  • Statičko kreiranje: koristi niz sa unapred određenom veličinom, koji se nalazi na stogu (stack).

Statički string primer: char tekst2[19] = "Ana voli Milovana"; Ovaj niz zauzima fiksnu memoriju i veličina mu mora biti poznata tokom kompajliranja.

Dinamički string primer: char* pTekst = "Danas je lep dan"; String se nalazi u memoriji za konstante, a pokazivač pokazuje na njegov prvi karakter.

Pomeranje pokazivača kroz string

Pokazivač pokazuje na određeni element niza. Ako želimo da pređemo na sledeći element, možemo jednostavno uvećati vrednost pokazivača:


pTekst++; // sada pokazuje na sledeći karakter

Više o tome pogledaj u članku: String Pointer in C (Scaler)

Da bismo imali pokazivač na drugi string, možemo dodati sledeći red:


char* pch2 = tekst2; // pokazivač pch2 pokazuje na prvi element niza tekst2

Kompletan kod


#include <stdio.h>

int main() {
    // Dinamičko kreiranje stringa pomoću pokazivača
    char* pTekst = "Danas je lep dan"; 
    // Pokazivač pokazuje na konstantni string u memoriji.

    // Statičko kreiranje stringa pomoću niza
    char tekst2[19] = {'A','n','a',' ','v','o','l','i',' ',
                       'M','i','l','o','v','a','n','a','\0'};

    // Ispis stringa kreiranog dinamički
    printf("tekst 1:\t");
    while (*pTekst != '\0') { 
        printf("%c", *pTekst); // Ispis trenutnog karaktera
        pTekst++;              // Pomeri pokazivač na sledeći karakter
    }
    printf("\n");

    // Povezivanje pokazivača sa statičkim nizom
    char* pch2 = tekst2; 
    printf("tekst 2:\t");
    while (*pch2 != '\0') {
        printf("%c", *pch2);  // Ispis karaktera
        pch2++;               // Pomeri pokazivač na sledeći karakter
    }

    printf("\n");
    return 0;
}

Ciklus se prekida kada se naiđe na karakter '\0'. Nakon pokretanja programa ispisuju se oba stringa.

 Stringovi i pokazivači-primer u C jeziku-izvršenje
Slika 4: Stringovi i pokazivači-primer u C jeziku-izvršenje

Učitavanje stringova u jeziku C

Učitavanje stringa može se izvršiti na više načina:

  • Pomoću getchar() funkcije, znak po znak (kao u prethodnom primeru).
  • Pomoću scanf funkcije – učitava se tekst do prvog belog znaka.
  • Pomoću fgets() – preporučeni način, jer omogućava bezbedno učitavanje cele linije.

Korišćenje scanf funkcije


char rec[10];
scanf("%s", rec);

Problem sa scanf("%s") je što može doći do prelivanja bafera ako korisnik unese više karaktera nego što niz može da primi. Da bismo to izbegli, unos treba ograničiti:


scanf("%9s", rec); // Maksimalno 9 karaktera + '\0'

Korišćenje gets i puts funkcija

Funkcija gets() je ranije korišćena za učitavanje celog reda, ali je zastarela i nesigurna, jer može izazvati prelivanje bafera. Funkcija puts() služi za ispisivanje stringa.

Umesto gets(), preporučuje se upotreba fgets():


fgets(tekst2, sizeof(tekst2), stdin); 

Primer 3: Učitavanje stringa

Učitati dva stringa:

  1. Prvi string – do belog znaka (jedna reč).
  2. Drugi string – ceo red teksta, sve do znaka za novi red.

#include <stdio.h>
#include <stdlib.h>

int main() {
    char tekst1[10], tekst2[50]; // prvi niz manji, drugi veći

    // Učitavanje jedne reči pomoću scanf
    printf("Unesi tekst (jedna rec):\n");
    scanf("%9s", tekst1); // sigurno učitavanje do 9 karaktera
    printf("Ucitano: %s\n", tekst1);

    getchar(); // da "pojede" Enter sa tastature

    // Učitavanje celog reda pomoću fgets
    printf("Unesi ceo red teksta:\n");
    fgets(tekst2, sizeof(tekst2), stdin);
    printf("Ucitano: %s\n", tekst2);

    return 0;
}

□ Napomena: - scanf("%s") se koristi samo za učitavanje jedne reči (do belog znaka). - fgets() je sigurniji jer omogućava ograničenje broja karaktera i učitava ceo red teksta. - Funkcija puts() je praktičan način za ispisivanje stringa.

Problemi sa učitavanjem stringova

Problemi koji se javljaju pri učitavanju:

1. Zaostali karakter u ulaznom baferu

Kada scanf() pročita unos, ostavlja novi red (\n) u ulaznom baferu nakon unete vrednosti. Ako odmah nakon scanf() koristite funkciju koja čita ceo red, poput fgets(), ona će pročitati preostali \n, što može izgledati kao da korisnik nije uneo ništa.

Rešenje: pozvati getchar() nakon unosa sa scanf(). Poziv getchar() uklanja taj preostali \n iz bafera, omogućavajući pravilno učitavanje sledećeg reda teksta.

a. Korišćenje modifikatora za scanf()

scanf("%s", ime);

b. Korišćenje fgets() i sscanf()

#include <stdio.h>
#include <string.h>

int main() {
    char unos[30];
    char ime[30];

    // Učitava ceo unos
    fgets(unos, sizeof(unos), stdin);
    sscanf(unos, "%s", ime); // Ekstraktuje prvu reč iz unosa

    printf("Prva reč: %s\n", ime);
    return 0;
}

c. Ručno uklanjanje znakova iz bafera

int ch;
while ((ch = getchar()) != '\n' && ch != EOF);

d. Upotreba fgets() i obrade stringova

d.1 Primer sa sscanf()

#include <stdio.h>

int main() {
    char unos[100];
    char ime[30];

    printf("Unesite tekst: ");
    fgets(unos, sizeof(unos), stdin); // Učitava ceo red, uključujući razmake

    if (sscanf(unos, "%s", ime) == 1) {
        printf("Prva reč: %s\n", ime);
    } else {
        printf("Nije uneta validna reč.\n");
    }

    return 0;
}

d.2 Primer sa strtok()

#include <stdio.h>
#include <string.h>

int main() {
    char unos[100];

    printf("Unesite tekst: ");
    fgets(unos, sizeof(unos), stdin);

    unos[strcspn(unos, "\n")] = '\0'; // uklanjanje '\n'

    char* token = strtok(unos, " ");
    while (token != NULL) {
        printf("Reč: %s\n", token);
        token = strtok(NULL, " ");
    }

    return 0;
}

2. Problem sa prelivanjem bafera

Kada se koristi zastarela funkcija gets, dolazi do rizika prelivanja bafera jer funkcija ne ograničava broj učitanih karaktera.

#include <stdio.h>

int main() {
    char ime[10]; 
    printf("Unesite ime: ");
    gets(ime); // Potencijalno prelivanje bafera
    printf("Uneto ime: %s\n", ime);
    return 0;
}

Rešenje: koristiti fgets() umesto gets().

fgets(ime, sizeof(ime), stdin);

Poboljšana verzija koda

#include <stdio.h>
#include <string.h>

int main() {
    char tekst1[10];
    printf("Unesi tekst (do belog znaka):\n");
    scanf("%9s", tekst1);
    printf("Unesena reč: %s\n", tekst1);

    char tekst2[10];
    getchar(); 
    printf("Unesi ceo red teksta:\n");
    fgets(tekst2, sizeof(tekst2), stdin);
    printf("Uneseni tekst: %s\n", tekst2);

    char tekst[] = "Priprema za takmičenje iz programiranja";
    int poz = 12;
    int duzPodstr = 10;

    char podstring[duzPodstr + 1];
    strncpy(podstring, tekst + poz, duzPodstr);
    podstring[duzPodstr] = '\0';
    printf("Izdvojeni podstring: %s\n", podstring);

    return 0;
}

Određivanje dužine teksta

char tekst[] = "Priprema za takmičenje iz programiranja";
int duzina = strlen(tekst);
printf("Dužina teksta je %d\n", duzina);

Izdvajanje dela teksta iz teksta (Izdvajanje podstringa)

Deo teksta se može izdvojiti iz celog teksta tako što se, upotrebom petlje, prolazi kroz niz podataka tipa char od pozicije u tekstu odakle treba izdvojiti podstring, pa sve do krajnje željene pozicije. Tada se tekući znak dodaje u novi niz char podataka, tj. u podstring.

Primer 4: Izdvajanje podstringa

Neka je zadat tekst: "Priprema za takmičenje iz programiranja". Izdvojiti deo teksta od pozicije 12, dužine od 10 karaktera i ispisati ga na ekranu.

Rešenje sa petljom

#include <stdio.h>
#include <string.h>

int main()
{
    char tekst[] = "Priprema za takmičenje iz programiranja";
    int duzina = strlen(tekst);
    int poz = 12; // podstring počinje od pozicije 12
    int duzPodstr = 10;

    char podstring[duzina];
    for (int c = poz, i = 0; c <= poz + duzPodstr; c++, i++) {
        char ch = tekst[c];
        podstring[i] = ch;
    }
    podstring[duzPodstr] = '\0'; // terminator stringa
    printf("%s\n", podstring);

    return 0;
}

Pozicija c predstavlja poziciju tekućeg karaktera unutar zadatog teksta, a i je pozicija tekućeg elementa u nizu podstring.


Rešenje pomoću funkcije strncpy()

Zadatak je moguće rešiti i pomoću funkcije strncpy() iz zaglavlja <string.h>. Ova funkcija kopira deo jednog stringa u drugi, koji je po dužini manji ili jednak prvom.

#include <stdio.h>
#include <string.h>

int main()
{
    char tekst[] = "Priprema za takmičenje iz programiranja";
    int duzina = strlen(tekst);
    int poz = 12; // podstring počinje od pozicije 12
    int duzPodstr = 10;

    char podstring[duzina];
    strncpy(podstring, tekst + poz, duzPodstr);
    podstring[duzPodstr] = '\0'; // dodavanje terminatora
    printf("%s\n", podstring);

    return 0;
}

Parametri funkcije strncpy():

➡ Ostale funkcije iz zaglavlja <string.h> možete pogledati ovde: cplusplus.com/reference/cstring/


Rešenje sa posebnom funkcijom

Još bolji pristup je da se napravi posebna funkcija za izdvajanje podstringa, koju možemo pozivati više puta za različite delove teksta.

#include <stdio.h>
#include <string.h>

void izdvojiPodstring(char* izvor, char* cilj, int poz, int duzina) {
    strncpy(cilj, izvor + poz, duzina);
    cilj[duzina] = '\0'; // dodavanje terminatora
}

int main()
{
    char tekst[] = "Priprema za takmičenje iz programiranja";

    char pod1[20];
    char pod2[20];

    // Izdvajamo deo od pozicije 12 dužine 10
    izdvojiPodstring(tekst, pod1, 12, 10);
    printf("Podstring 1: %s\n", pod1);

    // Izdvajamo deo od pozicije 0 dužine 9
    izdvojiPodstring(tekst, pod2, 0, 9);
    printf("Podstring 2: %s\n", pod2);

    return 0;
}

Ova funkcija izdvojiPodstring() je univerzalna i može se koristiti za izdvajanje bilo kog dela teksta, što čini kod preglednijim i fleksibilnijim.

Prvi parametar funkcije strcpy() je podstring koji treba dobiti(odredište), drugi je pokazivač na znak iz polaznog teksta(izvor) na poziciji "poz", dok je treći parametar dužina podstringa.
​Posle pokretanja:
Izdvajanje podstringa, primer u C jeziku-izvršenje
Slika 5: Izdvajanje podstringa, primer u C jeziku-izvršenje

Pretraga dela teksta unutar većeg teksta

Često je potrebno ispitati da li se neka reč ili neki tekst nalazi u zadatom tekstu i, ako se nalazi, pronaći na kojim pozicijama. Sledeći primer pokazuje jedan način da se ovo uradi.

Primer 5: Pretraga stringa

Proveriti da li i na kojim pozicijama se zadate reči (ana i pera) nalaze u datom tekstu. Ispisati koliko puta se ponavljaju i na kojim pozicijama, ili ispisati "nije se pojavila" ako se reč ne nalazi u tekstu.

Linearna pretraga za jednu reč

Jedan način je korišćenjem linearne pretrage: prolazi se kroz kompletan tekst znak po znak i poredi se tekući znak sa prvim znakom reči koja se traži. Ako se naiđe na podudaranje prvog znaka, proveravaju se i ostali znakovi. Ako svi znakovi reči odgovaraju, konstatuje se pozicija početka podstringa u tekstu.

#include <stdio.h>
#include <string.h>

int main()
{
    char tekst[] = {'a','n','a','v','o','l','i','M','i','l','o','v','a','n','a','\0'};
    char rec1[] = "ana";
    int brPoj = 0;
    int duzTeksta = strlen(tekst);
    int duzReci = strlen(rec1);
    int poz1 = -1;
    int pronasao = 0;
    int j = 0;

    for(int i = 0; i < duzTeksta; i++) {
        char chT = tekst[i];
        char ch = rec1[j];

        if(!pronasao && chT != ch) {
            continue;
        }
        else if(!pronasao && chT == ch) {
            pronasao = 1;
            poz1 = i;

            while(chT == ch && i < duzTeksta && j < duzReci) {
                i++;
                j++;
                chT = tekst[i];
                ch = rec1[j];
            }

            if(j == duzReci) {
                pronasao = 0;
                j = 0;
                brPoj++;
                printf("Pronadjena na %d poz\n", poz1);
            }
            else {
                pronasao = 0;
                j = 0;
            }
        }
    }

    if(brPoj > 0) {
        printf("Rec se pojavila %d puta u tekstu\n", brPoj);
    } else {
        printf("Ne\n");
    }

    return 0;
}

U prethodnom kodu se pretraga izvršava samo za reč "ana", a ne za "pera". U sledećem primeru se koristi dvodimenzioni niz reči i posebna funkcija za pretragu koja vraća poziciju ili -1 ako reč nije nađena.

Pretraga više reči pomoću funkcije

#include <stdio.h>
#include <string.h>

// Funkcija koja vraća poziciju reči u tekstu, ili -1 ako nije pronađena
int pozicijaUTekstu(int poz, char txt[], char rec[]) {
    int duzTeksta = strlen(txt);
    int duzReci = strlen(rec);
    int pronasao = 0;

    for(int i = poz + 1, j = 0; i < duzTeksta; i++) {
        char chT = txt[i];
        char ch = rec[j];

        if(!pronasao && chT != ch) {
            continue;
        }
        else if(!pronasao && chT == ch) {
            pronasao = 1;
            poz = i;
            while(chT == ch && i < duzTeksta && j < duzReci) {
                i++;
                j++;
                chT = txt[i];
                ch = rec[j];
            }
            if(j == duzReci) {
                break;
            } else {
                pronasao = 0;
                j = 0;
                if(i >= duzTeksta) {
                    poz = -1;
                    break;
                }
            }
        }
    }
    return poz;
}

int main() {
    char tekst[] = {'a','n','a','v','o','l','i','M','i','l','o','v','a','n','a','\0'};
    char rec[2][10] = {"ana", "pera"};
    int brPoj = 0;
    int poz = -1;

    for(int i = 0; i < 2; i++) {
        do {
            poz = pozicijaUTekstu(poz, tekst, rec[i]);
            if(poz != -1) {
                brPoj++;
                printf("Rec %s Pronadjena na %d poz\n", rec[i], poz);
            }
        } while(poz != -1);

        if(brPoj > 0) {
            printf("Rec %s se pojavila %d puta u tekstu\n", rec[i], brPoj);
        } else {
            printf("Rec %s se nije pojavila u tekstu nijednom\n", rec[i]);
        }
        brPoj = 0;
        poz = -1; // resetuje poziciju pre prelaska na sledeću reč
    }

    return 0;
}

U ovom kodu:

Posle izvršenja programa:Pretraga stringa, primer u C jeziku-izvršenje
Slika 6: Pretraga stringa, primer u C jeziku-izvršenje

Pretraga reči u tekstu – logika i optimizacija

U glavnoj funkciji (main) je zadat dvodimenzionalni niz znakova sa rečima za pretragu i definisani su:

U do-while petlji poziva se funkcija pozicijaUTekstu(), kojoj se prosleđuju: pozicija, tekst i reč za pretragu. Funkcija vraća prvu poziciju veću od prethodno pronađene na kojoj se nalazi reč, ili -1 ako reč nije pronađena.

Objašnjenje logike

Zašto se koristi pronasao: Promenljiva pronasao signalizira trenutak kada se prvi znak reči poklapa sa znakom u tekstu. Ona omogućava praćenje početka potencijalnog podudaranja i prelazak na detaljnije poređenje narednih znakova.

Kako funkcioniše upoređivanje: Kada se otkrije podudaranje prvog znaka, algoritam koristi petlju za poređenje narednih znakova. Ako se svi znakovi poklope, reč je pronađena. Ako se pojavi razlika, algoritam se resetuje i nastavlja pretragu.

Optimizacija algoritma

Alternativna metoda: KMP algoritam (Knuth-Morris-Pratt). KMP koristi preprocesiranje reči za kreiranje "prefix-suffix" tabele, što omogućava preskakanje nepotrebnih poređenja, značajno ubrzavajući pretragu, posebno za velike tekstove i česte ponavljajuće šablone.

Problemi sa memorijom i dinamička alokacija stringova u C-u

Nepravilno rukovanje stringovima može dovesti do curenja memorije ili prepunjavanja bafera.

Alokacija i promena veličine stringova

char *str = (char *)malloc(50 * sizeof(char));
if (str == NULL) {
    printf("Alokacija memorije nije uspela");
    return 1;
}

str = (char *)realloc(str, 100 * sizeof(char));

Izbegavanje prepunjavanja bafera

strncpy(str, "Siguran string", 49);
str[49] = '\0';  // Osigurajte završni null karakter

Oslobađanje memorije

free(str);
str = NULL;

Napredni primer: Dinamička konkatenacija stringova

Primer funkcije koja dinamički spaja stringove:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *concat(const char *s1, const char *s2) {
    size_t len1 = strlen(s1), len2 = strlen(s2);
    char *result = (char *)malloc((len1 + len2 + 1) * sizeof(char));
    if (!result) {
        printf("Alokacija memorije nije uspela");
        exit(1);
    }
    strcpy(result, s1);
    strcat(result, s2);
    return result;
}

int main() {
    char *pozdrav = concat("Zdravo, ", "Svete!");
    printf("%s\n", pozdrav);
    free(pozdrav);
    return 0;
}

U ovom primeru: