Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Pretrazivanje niske znakova u tekstualnom fajlu

[es] :: C/C++ programiranje :: C/C++ za početnike :: Pretrazivanje niske znakova u tekstualnom fajlu

[ Pregleda: 2470 | Odgovora: 4 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

sarizatatus

Član broj: 42686
Poruke: 13
*.beotel.net.



Profil

icon Pretrazivanje niske znakova u tekstualnom fajlu24.11.2006. u 14:09 - pre 211 meseci
Drugi dan pokusavam da nadjem greske ali bez uspeha. Cim otklonim jednu, nadje se na drugom mestu gde greske uopste ne bi trebalo da bude.
Da ne davim mnogo i da krenem redom:

Ovo je kod programa:

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

void ukljuci(char a, char *s, char d){
/*Funkcija ukljuci sluzi za ukljucivanje novog procitanog znaka u buffer*/
int i;
for (i=1;i<d;i++){
                  *(s+i-1)=*(s+i);
                  *(s+i)=a;}
}

void smanji(char *s){
/*Funkcija smanji sluzi za pretvaranje eventualnih velikih slova u niski u mala*/
char i,l;
for(i=0,l=0;i<strlen(s);i++){
                             l=0;
                             l=isupper(*(s+i));
                             if (l) *(s+i)+=32;}
};

void main (int bpar, const char *vpar[]){
/*Argumenti programa su niska karaktera koja se trazi, i fajl u kome se ta niska trazi */
int i,v,r=1;
char c, *rec, *buffer;
FILE *mf;

v=strlen(*vpar[1]);
rec=malloc(v);
rec=vpar[1]; smanji(rec);
buffer=malloc(v);
mf=fopen(vpar[2], "r"); /* C:\Mojfajl.txt */

while((c=fgetc(mf))!=EOF){
                          ukljuci(c,buffer,v);
                          smanji(buffer);
                          r=strcmp(rec, buffer);
                          if (!r) break;
                          }
if (!r) printf("U tekstualnom fajlu postoji niska znakova: %s !\n", vpar[1]);
else printf("U tekstualnom fajlu NE postoji niska znakova: %s !\n", vpar[1]);
free(buffer);
fclose(mf);
system("PAUSE");
}


Kompajler izbacuje sledece warninge:

Code:
27  warning: passing arg 1 of `strlen' makes pointer from integer without a cast
29  warning: assignment discards qualifiers from pointer target type
21  warning: return type of `main' is not `int'

Sad, prvi warning uopste ne kontam.
Drugi je pretpostavljam da mi ukaze da dodeljujem pointeru podatke koji su odredjenog tipa a nisam stavio konverziju tipa (???)
Treci warning kontam, o tome je vec bilo reci ovde na forumu.

Kada startujem program: proba beograd C:\Mojfajl.txt
izbaci mi poruku "proba.exe has encountered a problem and needs to close..."

Jos jednu stvar bih napomenuo. Posto sam dosta puta, kako bih uvideo gde je problem, ubacivao kod tipa:
Code:
printf("%s", rec); system("PAUSE");

kompajler bi izbacivao meni totalno nebulozne greske tipa: 'v' not defined, first used.... iako jeste definisano, a bez tog koda ne bi bilo nikakvih problema. Ovo mi se desavalo bar 50 puta dok sam pokusavao da trazim greske.

Koristim Bloodshed Dev-C++ v.4.0.

Ako imate bilo kakvih zamerki kako na algoritam, stil ili naravno kod, recite.
Edmondo
 
Odgovor na temu

Milan Aksic

Član broj: 412
Poruke: 1053
*.medianis.net.



Profil

icon Re: Pretrazivanje niske znakova u tekstualnom fajlu28.11.2006. u 08:09 - pre 211 meseci
Code:
#include <stdio.h>
#include <stdlib.h>
Za koriscenje "string" funkcija iz standardne biblioteke C-a, pravilno je da prethodno ukljucis i 'string.h' zaglavlje.
Code:
void ukljuci(char a, char *s, char d)
{
/*Funkcija ukljuci sluzi za ukljucivanje novog procitanog znaka u buffer*/
    int i;
    for (i = 1; i < d; i++) {
        *(s + i - 1) = *(s + i);
        *(s + i) = a;
    }
Ako je potrebno 'a' promenljivu dodati na kraj onda ona ne mora da se stalno dodaje u petlji vec moze izvan petlje (ispod 'for' bloka) da se napise ta dodela koja ce se izvrsiti samo jednom.
Code:
}

void smanji(char *s)
{
/*Funkcija smanji sluzi za pretvaranje eventualnih velikih slova u niski u mala*/
    char i, l;
    for (i = 0, l = 0; i < strlen(s); i++) {
    l = 0;
    l = isupper(*(s + i));
    if (l)
        *(s + i) += 32;
Umesto "konstante" 32, bolje koristi izraz ('a' - 'A')
Code:
    }
};

void main(int bpar, const char *vpar[])
{
/*Argumenti programa su niska karaktera koja se trazi, i fajl u kome se ta niska trazi */
    int i, v, r = 1;
Za duzinu niza u funkcijama iznad si koristio char (1 bajt) promenljivu dok ovde duzinu reci prosledjene programu cuvas u int (2-4 bajta) ovo nije dobra praksa jer nepaznjom moze doci do greske.
Code:
    char c, *rec, *buffer;
    FILE *mf;

    v = strlen(*vpar[1]);
Ovde funkciji 'strlen()' predajes prvi karakter druge reci, a ne drugu rec (niz). Trebao si dakle da napises:
v = strlen(vpar[1]);
Zapamti i da funkcija 'strlen()' vraca samo broj znakova u reci bez uracunatog nula terminirajuceg znaka.
Code:
    rec = malloc(v);
Ovde promenjvivoj 'v' trebas da dodas broj 1 kako bi rezervisao mesto i za nula terminirajuci znak.
Code:
    rec = vpar[1];
'vpar[1]' vraca pokazivac (vpar je pokazivac na pokazivace) tj, adresu, u liniji iznad ti si rezervisao memoriju za rec ali si ovim dodavanjem tu memoriju "ignorisao" i postavio si da 'rec' pokazuje (jer 'rec' je pokazivac) na istu onu memoriju na koju pokazuje i 'vpar[1]'. Ovde si trebao da kopiras sadrzaj iz jednoj niza u drugi ako si vec resio da koristis promenljivu 'rec'. Znaci npr ovako:
strncpy(rec, vpar[1], v + 1);
Obrati paznju da je promenjlivoj 'v' opet dodat broj 1 jer se bez toga nece kopirati i nula terminirajuci znak.
Code:
    smanji(rec);
    buffer = malloc(v);
U ovom konkretnom slucaju nije bitno jer se u funkciji 'ukljuci()' koju pozivas ispod, niz puni od kraja, ali ipak obrati paznju da clanovi niza 'buffer' nisu garantovano inicijalizovani, tj. mogu da sadrze bilo sta. Da bi inicijalizovao clanove niza na nulu, ispod linije iznad napisi:
memset(buffer, 0, v);
ili umesto funkcije 'malloc()' koristi funckiju 'calloc()' koja automatski vraca niz ciji su clanovi inicijalizovani na nulu:
buffer = calloc(v, sizeof(char));
Code:
    mf = fopen(vpar[2], "r");    /* C:\Mojfajl.txt */

    while ((c = fgetc(mf)) != EOF) {
        ukljuci(c, buffer, v);
        smanji(buffer);
Umesto sto koristis funkciju koja opet prolazi kroz ceo niz i proverava i one znakove koji su provereni i prevedeni u mala slova, mogao bi da napises funkciju koja bi smanjivala samo taj karakter koji si dobio iz datoteke. Funkcija bi npr. mogla da izgleda ovako:
char smanji(char c) {
if (isupper(c)) return c + 'a' - 'A';
else return c;
}

Code:
        r = strcmp(rec, buffer);
Kako 'buffer' ne sadrzi nula terminirajuci znak na kraju, na sta se oslanjaju mnoge funkcije za rad sa znakovnim nizovima iz standardne biblioteke C-a medju kojima je i funkcija 'strcmp()', ona ce u slucaju kada su u pitanju iste reci, u promenljivama 'rec' i 'buffer' porediti znakove dok ne naidje na nula terminirajuci znak u drugoj promenljivoj ili dok se ne pronadju razliciti karakteri, a niz 'buffer' nema na kraju nula terminirajuci znak. Umesto toga trebao bi da kao drugu promenljivu prosledis 'rec' ili jos bolje da koristis funkciju 'strncmp()' koja poredi samo naznaceni broj karaktera. Dakle:
r = strncmp(rec, buffer, v);
Code:
        if (!r)
            break;
    }
    if (!r)
        printf("U tekstualnom fajlu postoji niska znakova: %s !\n",
        vpar[1]);
    else
        printf("U tekstualnom fajlu NE postoji niska znakova: %s !\n",
        vpar[1]);
        
    free(buffer);
A promenljiva 'rec'? ;) Znaci trebalo je da se napise i:
free(rec);
Mada posto se izlazi iz programa nije ni mnogo bitno jer ce operativni sistem ionako sam da oslobodi svu zauzetu memoriju.
Code:
    fclose(mf);
    system("PAUSE");
Ovo ce ti raditi samo na Vindouz sistemu, ili na onim sistemima gde postoji komanda ljuske 'pause'.
Code:
}
U vaznijem programu bila bi potrebna provera vrednosti kako bi se izbegle greske tokom izvrsavanja programa. Na primer, trebalo bi da se proveri da li su programu prosledjeni onoliko i oni parametri koje ocekujes, da li 'mf' nakon poziva funkcije 'fopen()' sadrzi 'NULL', sto ukazuje na gresku pri otvaranju, da li pokazivaci 'rec' i 'buffer' sadrze 'NULL' nakon alociranja memorije, sto opet ukazuje na gresku i da li je funkcija 'fclose' vratila nulu ili 'EOF', sto pogadjas :) ponovo ukazuje na gresku pri zatvranju datoteke.

E da, ako vec nameravas da koristis srpske nazive za imena promenljivih i funkcija onda ostani dosledan :)

Srecno :)
 
Odgovor na temu

sarizatatus

Član broj: 42686
Poruke: 13
*.beotel.net.



Profil

icon Re: Pretrazivanje niske znakova u tekstualnom fajlu28.11.2006. u 12:17 - pre 211 meseci
Prvo da se zahvalim na vanserijskom odgovoru! Mogu ti reci da si mi ulepsao dan :)

Drugo da kazem da je program proradio :)

E sad samo da da napomenem par stvari:

Code:
void ukljuci(char a, char *s, char d)
{
/*Funkcija ukljuci sluzi za ukljucivanje novog procitanog znaka u buffer*/
    int i;
    for (i = 1; i < d; i++) {
        *(s + i - 1) = *(s + i);
        *(s + i) = a;
    }
}

Posle for petlje moralo je da ide

*(s+i-1) jer pre nego sto se for petlja zavrsi on dodatno uveca i za jedan pa mora da ide '-1' dodatno.

Onu moju funkciju smanji bi mogao da zamenim sa
char smanji(char c) {
if (isupper(c)) return c + 'a' - 'A';
else return c;
}
ali mi treba i za smanjivanje karaktera u niski 'rec' a ne samo za karaktere iz datoteke. Ili je mozda brze da idu dve funkcije, posto se ova jedna izvrsava samo jednom a za citanje karaktera iz datoteke stalno???

I jos jedna sitnica koja me kopka. Posto sam umetnuo kod da vidim stanje 'rec'-i i 'buffer'-a:
Code:
r=strncmp(rec, buffer, v);
                          printf("rec %s , buffer %s    ",rec,buffer);
                          system("PAUSE");
                          if (!r) break;

Kao sto se vidi sa slike:

Na kraju 'buffer'-a postoji jedan apostrof. Odakle on?
Evo ga ceo kod kako sada izgleda:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void ukljuci(char a, char *s, char d){
/*Funkcija ukljuci sluzi za ukljucivanje novog procitanog znaka u buffer*/
int i;
for (i=1;i<d;i++){
                  *(s+i-1)=*(s+i);
                  }   *(s+i-1)=a;
}

void smanji(char *s){
/*Funkcija smanji sluzi za pretvaranje eventualnih velikih slova u niski u mala*/
char i,l;
for(i=0,l=0;i<strlen(s);i++){
                             l=0;
                             l=isupper(*(s+i));
                             if (l) *(s+i)+=('a'-'A');}
}

void main (int bpar, const char *vpar[]){
/*Argumenti programa su niska karaktera koja se trazi, i fajl u kome se ta niska trazi */
int i,r=1;
char v, c, *rec, *buffer;
FILE *mf;

v=strlen(vpar[1]);
rec=malloc(v+1);
strncpy(rec, vpar[1], v + 1); smanji(rec);
buffer=malloc(v);
memset(buffer, 0, v);
mf=fopen(vpar[2], "r"); /* C:\Mojfajl.txt */

while((c=fgetc(mf))!=EOF){
                          ukljuci(c,buffer,v);
                          smanji(buffer);
                          r=strncmp(rec, buffer, v);
                          printf("rec %s , buffer %s    ",rec,buffer);
                          system("PAUSE");
                          if (!r) break;
                          }
if (!r) printf("U tekstualnom fajlu postoji niska znakova: %s !\n", vpar[1]);
else printf("U tekstualnom fajlu NE postoji niska znakova: %s !\n", vpar[1]);
free(buffer);
free(rec);
fclose(mf);
system("PAUSE");
}


Hvala jos jednom!

[Ovu poruku je menjao sarizatatus dana 28.11.2006. u 13:32 GMT+1]
Edmondo
Prikačeni fajlovi
 
Odgovor na temu

Milan Aksic

Član broj: 412
Poruke: 1053
*.medianis.net.



Profil

icon Re: Pretrazivanje niske znakova u tekstualnom fajlu28.11.2006. u 13:06 - pre 211 meseci
Citat:
Posle for petlje moralo je da ide

*(s+i-1) jer pre nego sto se for petlja zavrsi on dodatno uveca i za jedan pa mora da ide '-1' dodatno.
Da :) U drugoj datoteci koju sam paralelno prepravljao da bih proverio da li je sve u redu, nakon 'for' bloka sam dodao:
*(s + (i-1)) = a;
Citat:
I jos jedna sitnica koja me kopka. Posto sam umetnuo kod da vidim stanje 'rec'-i i 'buffer'-a:
Koliko vidim ti si kao rec za pretragu uneo "pisalo", tako da niz 'rec' sadrzi 7 clana (6 za rec i 1 za nula terminirajuci znak) a niz 'buffer' koji ne treba da sadrzi nula terminirajuci znak ima 6 clana. Znak ' ' ' (jednostruki apostrof) koji se prikazuje bi bio sedmi clan, ali on nije u sastavu niza 'buffer' to je iza njega, znaci nedefinisano. Ako budes pokrenuo program jos koji put to ce se promeniti i mozda ce se prikazati nesto drugo. A zasto se taj sedmi clan uopste prikazuje? Pa zato sto si ovako pozvao funkciju 'printf()':
printf("rec %s , buffer %s ",rec,buffer);
To znaci da ce funkcija 'printf()' ispisivati slovo po slovo iz niza 'buffer' dok ne naidje na nulu a niz 'buffer' nema na kraju nula terminirajuci znak.
Citat:
Onu moju funkciju smanji bi mogao da zamenim sa
char smanji(char c) {
if (isupper(c)) return c + 'a' - 'A';
else return c;
} ali mi treba i za smanjivanje karaktera u niski 'rec' a ne samo za karaktere iz datoteke. Ili je mozda brze da idu dve funkcije, posto se ova jedna izvrsava samo jednom a za citanje karaktera iz datoteke stalno???
Evo saljem ti onaj prepravljeni program koji sam spomenuo iznad pa uporedi:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void ukljuci(char a, char *s, int d) {
    int i;
    for (i = 1; i < d; i++) {
        *(s + i - 1) = *(s + i);
    }
    
    *(s + (i-1)) = a;
}

char smanji(char c) {
    if (isupper(c)) return c + 'a' - 'A';
    else return c;
}

int main(int bpar, const char *vpar[]) {
    int i, v, r = 1;
    char c, *rec, *buffer;
    FILE *mf;

    if (bpar != 3) return 1;

    v = strlen(vpar[1]);
    
    rec = malloc(v + 1);
    strncpy(rec, vpar[1], v + 1);
    
    for (i = 0; i < v; i++)
        rec[i] = smanji(rec[i]);

    buffer = malloc(v);
    memset(buffer, 0, v);
 
    if ((mf = fopen(vpar[2], "r")) == NULL) return 1;

    while ((c = fgetc(mf)) != EOF) {
        c = smanji(c);
        ukljuci(c, buffer, v);
        
        r = strncmp(rec, buffer, v);
        if (!r)
            break;
    }
    
    if (!r)
        printf("U tekstualnom fajlu postoji niska znakova: %s !\n",
        vpar[1]);
    else
        printf("U tekstualnom fajlu NE postoji niska znakova: %s !\n",
        vpar[1]);

    free(rec);
    free(buffer);
    fclose(mf);
}

Pokusaj sada :)
 
Odgovor na temu

sarizatatus

Član broj: 42686
Poruke: 13
*.beotel.net.



Profil

icon Re: Pretrazivanje niske znakova u tekstualnom fajlu28.11.2006. u 16:56 - pre 211 meseci
Sada je perfektno :)
Edmondo
 
Odgovor na temu

[es] :: C/C++ programiranje :: C/C++ za početnike :: Pretrazivanje niske znakova u tekstualnom fajlu

[ Pregleda: 2470 | Odgovora: 4 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.