#include <stdio.h> #include <stdlib.h> #include <string.h> #define UKUPAN_BROJ_LINIJA 1000 #define ZBIRNA_DUZINA 40000L struct datoteka { int rbr; char *s; } niz[UKUPAN_BROJ_LINIJA]; int brlin=0; /*broj linija <= UKUPAN_BROJ_LINIJA */ long ukupna_duzina=0; char heap[ZBIRNA_DUZINA+UKUPAN_BROJ_LINIJA]; char *rec=heap; int getline(FILE *f,char *line) /*ucitavanje linije iz datoteke i cuvanje '\n' u nisci line; vraca duzinu linije*/ {int c,i=0; while((c=fgetc(f))!=EOF && c!='\n') line[i++]=c; if(c=='\n') line[i++]=c; line[i]='\0'; return i; } void greska(int n) /*rutina za obradu greske u slucaju preobimnog ulaza */ {switch(n) {case 0 : fprintf(stderr,"prevelik ukupan broj linija\n"); exit(1); break; case 1 : fprintf(stderr,"prevelika ukupna duzina linija\n"); exit(1); break; } } void predstavi(char *imedat) /*predstavlja sadrzaj datoteke po imenu75.polju linija */ { FILE *f;int d; /*duzina tekuce linije */ /*pokusaj otvaranja datoteke za citanje */ if((f=fopen(imedat,"r"))==NULL) { fprintf(stderr,"greska : otvaranje fajla %s\n",imedat); exit(1); } /*ucitavanje linija do markera kraja i prekid ucitavanja u slucaju preobimnog ulaza */ while((d=getline(f,rec))>0) { if(brlin>=UKUPAN_BROJ_LINIJA) greska(0); niz[brlin].rbr=brlin+1; /*uvecava se redni broj linije */ niz[brlin++].s=rec; ukupna_duzina+=d; if(ukupna_duzina>=ZBIRNA_DUZINA) greska(1); rec+=strlen(rec)+1; } fclose(f); } int uporedi(const void *a,const void *b) { return strcmp( ((struct datoteka *)a)->s,((struct datoteka *)b)->s ); } void ucetiri(int n,char *s) { /*formiranje rednog broja linije sa vodecim nulama */ int i=0,j; /*brojaci u petljama */ while(n>0) { s[i++]=(n % 10) +'0'; n/=10; } for(j=i;j<4;j++,i++) s[i]='0'; /*dopuniti nulama*/ s[i]='\0'; strrev(s); ;} main(int argc,char *argv[]) { FILE *f; int i; /*brojac u petlji */ /*redni broj linije */ char broj[5]; //char *broj; /*imena datoteka se zadaju kao argumenti komandne linije */ if(argc!=3) { fprintf(stderr,"poziv : %s <ulazna dat> <izlazna dat> \n",argv[0]); exit(1); } if((f=fopen(argv[2],"w"))==NULL) { fprintf(stderr,"greska : otvaranje datoteke %s\n",argv[2]); exit(1); } predstavi(argv[1]); qsort(niz,brlin,sizeof(struct datoteka),uporedi); /*zeljeno sortiranje */ for(i=0;i<brlin;i++) { ucetiri(niz[i].rbr,broj); /*upisu sadrzaja linije prethodi redni broj */ fputs(broj,f); fputs(". ",f); /*znak tacka kao zavrsetak rednog broja linije */ fputs(niz[i].s,f); /*upis sadrzaja linije rednog broja broj */ } putchar('\n'); fclose(f);}
#include <stdio.h> #include <ctype.h> #include <string.h> double sr_duz_rec_1 (FILE *dat) { int br_rec=0, zb_duz=0, prvi=1, znak; /*brojac reci, brojac znakova u reci, indikator nailaska na pocetak reci, tekuci znak*/ fseek (dat, 0, SEEK_SET); /* pozicionirati se na pocetak tekstualne datoteke */ /* Citanje tekstualne datoteke znak po znak do nailaska na EOF */ while ((znak = fgetc (dat)) != EOF) { if (isspace (znak)) prvi = 1; /*van reci */ else { zb_duz++; if (prvi) { br_rec++; prvi = 0; } /*pocetak reci, uveca se brojac reci */ } } return (double) zb_duz / br_rec; /*srednja duzina reci = broj karaktera u recima/broj reci */ } double sr_duz_rec_2 (FILE *dat) { int br_rec=0, zb_duz=0; /*brojac reci, brojac karaktera u reci */ char rec[80]; /*tekuca rec*/ fseek (dat, 0, SEEK_SET); /* pozicionirati se na pocetak tekstualne datoteke */ /* Citanje tekstualne datoteke rec po rec do nailaska na EOF */ while ((fscanf (dat, "%s", rec)) != EOF) { zb_duz += strlen (rec); br_rec++; } return (double) zb_duz / br_rec; /*srednja duzina reci = broj karaktera u recima/broj reci */ } void main (int argc, char *argv[]) { FILE *dat = fopen (argv[1], "r"); if (dat) printf ("Srednja duzina reci u datoteci \"%s\" je %.2f (%.2f)\n", argv[1], sr_duz_rec_1(dat), sr_duz_rec_2 (dat)); else fprintf(stderr,"Nemoguce otvoriti datoteku %s za citanje\n", argv[1]); }76.
#include <stdio.h> #include <stdlib.h> int veci(int d1, int m1, int g1, int d2, int m2, int g2); /*vraca 1, ako je prvi datum d1.m1.g1 veci od drugog d2.m2.g2. vraca 2, ako je drugi datum veci vraca 0, ako su datumi jednaki */ void poruka(int d, int m, int g); /*stampa rezultat u formi d.m.g. */ main() { FILE *f; int d1,m1,g1; /* 1.datim d1.m1.g1. */ int d2,m2,g2; /* 2.datim d2.m2.g2. */ f=fopen("ulaz.txt", "r"); if (f==NULL) {fprintf(stderr, "Greska u citanju datoteke\n"); exit(1);} fscanf(f, "%d.%d.%d.", &d1, &m1, &g1); fscanf(f, "%d.%d.%d.", &d2, &m2, &g2); if (veci(d1,m1,g1,d2,m2,g2)==0) printf("Oba datuma su jednaka\n"); fclose(f); } void poruka(int d, int m, int g) { printf("\n%d.%d.%d.\n",d,m,g); } int veci(int d1, int m1, int g1, int d2, int m2, int g2) { int status; /* status = 0,1,2 u zavisnosti da li prvi datum je jednak drugom, veci od drugog, manji od drugog */ if (g1 > g2) status=1; /*jer prvi datum je tada veci od drugog*/ else if (g1 < g2) status=2; else /* ako su godine u oba datuma jednaka, porede se meseci */ if (m1 > m2) status=1; else if (m1 < m2) status=2; else /*porede se dani ako su meseci u oba datuma jednaki */ if (d1 > d2) status =1; else if (d1 < d2) status =2; else status=0; if (status < 2) poruka(d1,m1,g1); /* prvi datum se stampa ako je veci ili jednak od drugog */ else poruka(d2,m2,g2); return status; }77.
Napomena pre resavanja: U tekstu zadatka nisu date nikakve pretpostavke o ukupnom broju datuma u datoteci !!! Dakle, Vi kao programer ne znate da li ih ima 30 ili 300. Vodite racuna da ne upotrebite strukturu podataka koja cuva datume i zahteva od Vas da u programu navedete pretpostavljeni broj clanova strukture.
#include <stdio.h> #include <stdlib.h> int veci(int d1, int m1, int g1, int d2, int m2, int g2); /*vraca 1, ako je prvi datum d1.m1.g1 veci od drugog d2.m2.g2. vraca 2, ako je drugi datum veci vraca 0, ako su datumi jednaki */ void poruka(int d, int m, int g); /*stampa rezultat u formi d.m.g. */ main() { FILE *f; int d1,m1,g1; /* 1.datim d1.m1.g1. */ int maxd=0,maxm=0,maxg=0; /* najveci datum u obliku maxd.maxm.maxg. Polazna pretpostavka: 0.0.0. */ f=fopen("ulaz.txt", "r"); if (f==NULL) {fprintf(stderr, "Greska u citanju datoteke\n"); exit(1);} while (!feof(f)) { fscanf(f, "%d.%d.%d.", &d1, &m1, &g1); if (veci(d1,m1,g1,maxd,maxm,maxg)==1) { /* postavi nove vrednosti za najveci datum, jer je d1.m1.g1. novi najveci datum */ maxd=d1; maxm=m1; maxg=g1; } } poruka(maxd,maxm,maxg); fclose(f); } void poruka(int d, int m, int g) { printf("\n%d.%d.%d.\n",d,m,g); } int veci(int d1, int m1, int g1, int d2, int m2, int g2) { int status; /* status = 0,1,2 u zavisnosti da li prvi datum je jednak drugom, veci od drugog, manji od drugog */ if (g1 > g2) status=1; /*jer prvi datum je tada veci od drugog*/ else if (g1 < g2) status=2; else /* ako su godine u oba datuma jednaka, porede se meseci */ if (m1 > m2) status=1; else if (m1 < m2) status=2; else /*porede se dani ako su meseci u oba datuma jednaki */ if (d1 > d2) status =1; else if (d1 < d2) status =2; else status=0; return status; }78.
RESENJE:
Dakle, program mora da radi sa sledecom vrstom poziva iz komandne linije:
#include <stdio.h> #include <stdlib.h> typedef enum {GR1, GR2, GR3} kodGreske; char *greske[]= { "Nekorektno pokretanje programa. Morate navesti i opcije i konkretne brojeve\n", "Nekorektno zadavanje opcija -d ili -f\n", "Nekorektno slovo u opciji. MORATE uneti -d ili -f\n" }; void ispisGreske(kodGreske broj); main(int argc, char*argv[]) { int i; /*brojac u ciklusu*/ int s1=0; /*suma celih brojeva */ double s2=0; /*suma realnih brojeva*/ if (argc<2) ispisGreske(GR1); if(*argv[1]!='-') ispisGreske(GR2); /*analiza opcije, tj. slova iza - */ switch(*(argv[1]+1)) { case 'd': for (i=2;i<argc;i++) s1+=atoi(argv[i]); printf("\n Suma CELIH brojeva iz komandne linije: %d\n ", s1); break; case 'f': for (i=2;i<argc;i++) s2+=atof(argv[i]); printf("\n Suma REALNIH brojeva iz komandne linije: %f\n ", s2); break; default: ispisGreske(GR3); break; } } void ispisGreske(kodGreske j) { fprintf(stderr, greske[j]); exit(EXIT_FAILURE); }79.
Za cuvanje velike kolicine podataka cesto se koriste binarne datoteke (jer za istu kolicinu podataka zapis je <= zapisu u tekstualnoj datoteci.
Za otvaranje binarne datoteke za upis koristi se ista funkcija fopen kao kod tekstualne datoteke, ali rezim rada je "wb" (kod tekstualne datoteke "w", "wt").
Za upis podataka u binarnu datoteku koriste se standardna fukcija fwrite.
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
Uocite da velicina MAX nije poznata za vreme kompilacije. Niz brojeva cuvajmo u dinamickom nizu.
#include <stdio.h> #include <stdlib.h> main(int argc, char *argv[]) { FILE *f; int i; /*brojacka promenljiva*/ int MAX; /*broj clanova niza */ int *niz; /* dinamicki niz parnih brojeva */ if (argc < 2) {fprintf(stderr, "Nekorektan poziv programa: naziv MAX\n"); exit(1);} MAX=atoi(argv[1]); niz=(int *)malloc(MAX*sizeof(int)); /*niz=(int *)calloc(MAX, sizeof(int)); */ /* calloc ce sem alokacije izvrsiti i inicijalizaciju elemenata na 0 */ if (niz==NULL) {fprintf(stderr, "Nedovoljno memorije za malloc\n"); exit(2);} for(i=1; i<=MAX; i++) niz[i-1]=2*i; f=fopen("ulaz.bin", "wb"); /*pokusaj otvaranja binarne datoteke za upis */ if(f==NULL) {fprintf(stderr, "Greska pri otvaranju datoteke za upis\n"); exit(3);} fwrite(niz, sizeof(int), MAX, f); free(niz); fclose(f); }80.
Za citanje iz binarne datoteke koristi se <stdio.h> funkcija fread.
size_t fread(
void *buffer,
size_t size,
size_t count,
FILE *stream
);
je funkcija koja
iz datoteke na koju pokazuje stream ucitava count elemenata (svaki veličine size bajtova) i upisuje u operativnu memoriju počev od adrese buffer. Povratna vrednost funkcije je broj uspešno učitanih podataka.
Funkcije iz <stdio.h> fseek, ftell, rewind koriste se za pozicioniranja u datoteci. Kao što je već ilustrovano u primerima iz glave VII (sa vezbi, u knjzi K&R):
#include <stdio.h> #include <stdlib.h> main(int argc, char *argv[]) { FILE *f; int N; /*redni broj clanova niza iz prethodnog zadatka, N=1,2,3,.... iako je niz indeksiran pocev od 0 */ int broj; /*trazeni element sa rednim brojem N*/ if (argc < 2) {fprintf(stderr, "Nekorektan poziv programa: naziv N\n"); exit(1);} N=atoi(argv[1]); f=fopen("ulaz.bin", "rb"); /*pokusaj otvaranja binarne datoteke za citanje */ if(f==NULL) {fprintf(stderr, "Greska pri otvaranju datoteke za citanje\n"); exit(2);} if ( (fseek(f, (long)(N-1)*sizeof(int), SEEK_SET)) !=0) {fprintf(stderr, "Nekorektna pozicija %d u datoteci\n", N); exit(3);} fread(&broj, sizeof(int), 1, f); if (broj < 0) {fprintf(stderr, "Nekorektna pozicija %d u datoteci\n", N); exit(3);} printf("\n%d. clan niza je %d\n",N, broj); fclose(f); }81.
#include <stdio.h> #include <stdlib.h> void greska(char *s); /*ispisuje nisku s na standardan izlaz za poruke o gresci */ main() { FILE *ulaz, *izlaz; char znak; /*tekuci karakter ulazne datoteke koji ce se sifriran ispisati u izlaznu datoteku */ unsigned short bit1; /* sifriran znak */ unsigned short pom; /* pomocna promenljiva koja ce cuvati bit najmanje tezine u ASCII kodu znaka, znacajan pri rotaciji udesno*/ ulaz=fopen("ulaz.txt", "r"); if(ulaz==NULL) greska("\nGreska u otvaranju datoteke ulaz.txt"); izlaz=fopen("tajna.txt", "w"); if(izlaz==NULL) greska("\nGreska u otvaranju datoteke tajna.txt"); /*ucitavanje karaktera po karakter ulazne datoteke sve do EOF i sifriranje svakog karaktera i upis u izlaznu datoteku */ while ( (znak=fgetc(ulaz)) != EOF) { bit1=znak; pom=1; /*maska za izdvajanje bita najmanje tezine */ pom=bit1&pom; /* pom cuva bit najmanje tezine */ bit1=bit1>>1; /* pomeranje ASCII bitova (sem bita najmanje tezine) udesno za 1 mesto */ pom=pom<<7; bit1=bit1|pom; /*pom bit postavljen u bit1 na mesto najvece tezine */ znak=bit1; fputc(znak, izlaz); } fclose(ulaz); fclose(izlaz); } void greska(char *s) { printf("%s\n", s); exit(EXIT_FAILURE); }82.
IDEJA:
svaki znak datoteke tajna.txt se zameniti znakom čiji ASCII kôd je rotaciono pomeran ulevo za 1 bit.
Npr. znak = sa ASCII kôdom (dekadno) 61 se transformiše u znak z sa ASCII kôdom (dekadno) 122, jer rotacijom ulevo za 1 bit ôda 00111011 dobija se kôd 01111010 (bit najvećlje težine prelazi na poziciju najmanje težine, a ostali bitovi pomeraju se ulevo za 1 mesto).
UPOREDITE datoteke ulaz.txt (prethodni zadatak) i provera.txt
#include <stdio.h> #include <stdlib.h> void greska(char *s); /*ispisuje nisku s na standardan izlaz za poruke o gresci */ main() { FILE *ulaz, *izlaz; char znak; /*tekuci karakter ulazne datoteke koji ce se desifriran ispisati u izlaznu datoteku */ unsigned short bit1; /* desifriran znak */ unsigned short pom; /* pomocna promenljiva koja ce cuvati bit najvece tezine u ASCII kodu znaka, znacajan pri rotaciji ulevo*/ ulaz=fopen("tajna.txt", "r"); if(ulaz==NULL) greska("\nGreska u otvaranju datoteke tajna.txt"); izlaz=fopen("provera.txt", "w"); if(izlaz==NULL) greska("\nGreska u otvaranju datoteke provera.txt"); /*ucitavanje karaktera po karakter ulazne datoteke sve do EOF i desifriranje svakog karaktera i upis u izlaznu datoteku */ while ( (znak=fgetc(ulaz)) != EOF) { bit1=znak; pom=1; pom=pom<<7; /*maska za izdvajanje bita najvece tezine */ pom=bit1&pom; /* pom cuva bit najvece tezine */ bit1=bit1>>1; /* pomeranje ASCII bitova (sem bita najvece tezine) ulevo za 1 mesto */ pom=pom>>7; bit1=bit1|pom; /*pom bit postavljen u bit1 na mesto najmanje tezine */ znak=bit1; fputc(znak, izlaz); } fclose(ulaz); fclose(izlaz); } void greska(char *s) { printf("%s\n", s); exit(EXIT_FAILURE); }83.
#include <stdio.h> #include <stdlib.h> #include <string.h> struct student{ char imePrezime[40]; long maticniBroj; int godinaStudija; char srednjaSkola[50]; double poeni; }; struct licniDosije{ long maticniBroj; char adresa[50]; char grad[40]; long FiksniTelefon; long MobilniTelefon; char drzavljanstvo[20]; }; struct izlazniPodaci{ char imePrezime[40]; char adresa[50]; char srednjaSkola[50]; double poeni; }; void greska(char *s); /*ispisuje nisku s na standardan izlaz za poruke o gresci */ main(int argc, char *argv[]) { FILE *izlaz, *ulaz1, *ulaz2; struct student slog1; /*slog prve ulazne datoteke */ struct licniDosije slog2; /*slog sa podacima iz druge ulazne datoteke */ struct izlazniPodaci slog; /* slog koji ce biti upisan u izlaznu datoteku */ if (argc!=2) greska("Nekorektan poziv programa: nazivPrograma nazivGrada"); ulaz1=fopen("studiranje.bin", "rb"); ulaz2=fopen("licno.bin", "rb"); izlaz=fopen("izlaz.bin", "wb"); if (!ulaz1 || !ulaz2 || !izlaz) greska("Nekorektno otvaranje ili ulaznih ili izlazne datoteke"); while (!feof(ulaz1)) /*sve dok ima slogova u studiranje.bin (tj. licno.bin) traziti polja koja se odnose na studente iz zadatog grada */ { /*citanje tekuceg sloga iz studiranje.bin */ if (fread(&slog1, sizeof(struct student), 1, ulaz1) !=1) greska("Greska pri citanju sloga iz studiranje.bin"); /*citanje tekuceg sloga iz licno.bin */ if (fread(&slog2, sizeof(struct licniDosije), 1, ulaz2) !=1) greska("Greska pri citanju sloga iz licno.bin"); /*poredjenje zadatog grada sa vrednoscu polja grad u tekucem slogu iz datoteke licno.bin */ if (strcmp(argv[1], slog2.grad)==0) { strcpy(slog.imePrezime, slog1.imePrezime); strcpy(slog.srednjaSkola, slog1.srednjaSkola); slog.poeni=slog1.poeni; strcpy(slog.adresa, slog2.adresa); /*upis slog(a) u izlaznu datoteku izlaz.bin */ if (fwrite(&slog, sizeof(struct izlazniPodaci), 1, izlaz) != 1) greska("Greska pri upisu sloga u datoteku izlaz.bin"); } } fclose(ulaz1); fclose(ulaz2); fclose(izlaz); } void greska(char *s) { printf("%s\n", s); exit(1); }84.
IDEJA:
Dakle, ako je program pozvan sa
zumiraj ulaz.bmp 3 izlaz.bmp
i ako je polazna slika bila dimenzije 10 x 20, onda će izlazna slika biti dimenzije 30 x 60.
#include <stdio.h> #include <stdlib.h> #define MAX 1024 int uzmipixel(FILE *f); /*za svaki pixel ucitava 8+4 bita (bajt i polubajt) iz datoteke na koju pokazuje f i vraca brojcanu 12-bitnu vrednost */ void pisipixel(short p, FILE *f); /*upis pixela p u datoteku na koju ukazuje f */ void greska(char *s); /*ispisuje nisku s na standardan izlaz za poruke o gresci */ main(int argc, char *argv[]) { FILE * ulaz, *izlaz; short niz_pixela[MAX]; /*pixeli jednog reda u datoteci */ short faktor, duzina, sirina; /*faktor uvecanaj slike, duzina polazne slike, sirina polazne slike */ short i,j,k,n; /*brojacke promenljive */ if (argc!=4) greska("Greska u pozivu programa:zumiraj ulaz faktor izlaz"); ulaz=fopen(argv[1],"rb"); if (!ulaz) greska("Nekorektno otvaranje binarne ulazne datoteke za citanje"); izlaz=fopen(argv[3],"wb"); if (!ulaz) greska("Nekorektno otvaranje binarne izlazne datoteke za upis"); faktor=atoi(argv[2]); if (faktor <0) greska("Nekorektna vrednost faktora"); /*ucitavanje dimenzije slike iz ulazne datoteke */ if (fread(&duzina, 2, 1, ulaz) !=1) greska("Nekorektna vrednost za duzinu slike u ulaznoj datoteci"); if (fread(&sirina, 2, 1, ulaz) !=1) greska("Nekorektna vrednost za sirinu slike u ulaznoj datoteci"); /*upis dimenzije slike u izlaznu datoteku */ i=duzina*faktor; j=sirina*faktor; if (fwrite(&i, 2, 1, izlaz) !=1) greska("Nekorektno upisivanje vrednosti za duzinu slike u izlaznoj datoteci"); if (fwrite(&j, 2, 1, izlaz) !=1) greska("Nekorektno upisivanje vrednosti za sirinu slike u izlaznoj datoteci"); /*za svaku vrstu slike */ for(i=0;i<duzina;i++) { /*ucitava se vrsta u niz*/ for(j=0;j<sirina;j++) niz_pixela[j]=uzmipixel(ulaz); /*u izlaznu datoteku se faktor puta ispisuje prosirena vrsta, tj. vrsta u kojoj je svaki pixel umnozen uzastopno faktor puta */ for (k=0;k<faktor; k++) for (j=0;j<sirina;j++) for (n=0; n<faktor; n++) pisipixel(niz_pixela[j], izlaz); } fclose(ulaz); fclose(izlaz); } int uzmipixel(FILE *f) { static int stao_na_pola_bajta=0; /*indikator koji govori da li jeste ili nije zaostao polubajt na ulazu */ static short pom; /*sadrzi pixel i deo drugog pixel-a */ if (stao_na_pola_bajta){ stao_na_pola_bajta=!stao_na_pola_bajta; /*uzet je zaostali polubajt */ return ( (getc(f) <<4) | (pom >> 12) ); } else { pom=getc(f) | ( getc(f) << 8); stao_na_pola_bajta=!stao_na_pola_bajta; /*ostao je polubajt */ return (pom & 0xfff); /*vraca nizih 12 bita iz pom */ } } void pisipixel(short c, FILE *f) { static int stao_na_pola_bajta=0; /*indikator pristupa donjem ili gornjem polubajtu tekuceg bajta */ static char pom2; /* sadrzi deo pixel-a */ if (stao_na_pola_bajta) { stao_na_pola_bajta=!stao_na_pola_bajta; putc( ((c << 4) | pom2) & 0xff, f); putc( c >> 8, f); /*nakupilo se 16 bitova (4 od ranije i novih 12 bitova) */ } else { stao_na_pola_bajta=!stao_na_pola_bajta; putc (c & 0xff, f); /*upisuje donji bajt i ostaje jos 4 bita za upis */ pom2=c >> 8; /*koji se pamte u donja 4 bita promenljive pom2, zato je staticka*/ } } void greska(char *s) { printf("%s\n", s); exit(1); }85.
Pogledajmo formiranje prvih n članova skupa M za neke vrednosti promenljive n:
#include <stdio.h> #define MAX 100 main() { FILE *f; int i2; /* indeks clana niza koji se generise granom 2k+1 */ int i3; /*indeks clana niza koji se generise granom 3m +1 */ int n; /* broj clanova podskupa skupa M koji se ispisuje na stdout */ int x[MAX]; /*niz koji sadrzi n <= MAX clanova skupa M */ int i; /*indeks tekuceg clana niza x*/ int ind; /*razlika vrednosti dva clana generisanog granom 2k+1, 3m +1 za tekuce k,m */ f=fopen("ulaz.txt", "r"); /*ucitavanje broja n sa proverom korektnosti*/ do { fscanf(f, "%d", &n); } while (n < 1 || n > MAX); /*inicijalizacije*/ i2=i3=0; x[0]=1; /* prvi clan skupa M */ /*generisanje clanova podskupa na osnovu zakona */ for (i=1; i <n; i++) { ind=x[i2]*2 - 3*x[i3]; /*razlika vrednosti dva clana generisanog granom 2k+1, 3m +1 za tekuce k,m da bi se odlucilo koja grane daje manji clan*/ if (ind < 0) /*ako se generisanje vrsi granom 2k+1 */ { x[i]=x[i2]*2+1; i2++; } else if (ind > 0) /*ako se generisanje vrsi granom 3k+1 */ { x[i]=x[i3]*3+1; i3++; } else /*ako se isti clan dobija u obe grane */ { x[i]=x[i2]*2 +1; i2++; i3++; } } printf("\nClanovi skupa M su:\n"); for (i=0; i < n; i++) printf("%d", x[i]); fclose(f); }86.
IDEJA:
Program treba da n puta ispise
ULAZ program 12
IZLAZ
10 14 20 28 30 35 40 42 50 56 60 80
Uociti da broj 70=2*5*7 nije na izlaznom spisku
#include <stdio.h> #include <stdlib.h> /* p1, p2, p3 su brojevi za koje proveravamo deljivost */ #define p1 2 #define p2 5 #define p3 7 int check (int a, int p); /* funkcija koja vraca negativnu vrednost ako a nije deljivo sa p, ili 0 ako a jeste deljivo sa p*/ main (int argc, char * argv[]) { FILE *f; int j, k, l; /* u ove tri promenljive smestamo isti broj i posebno proveramo da li je neki od njih deljiv sa 2, 5, 7 */ int i; /* brojac u petlji koji se uvecava za jedan i inicijalizuje j, k, l pri svakom prolazu kroz petlju */ int n; f=fopen("izlaz.txt", "w"); n=atoi(argv[1]); /* prvi kandidat je broj i=10=2*5; ispisuje se n brojeva koji ispunjavaju formulisanu uslov deljivosti */ for(i=10;n>0; i++) { j=k=l=i; /*inicijalizacija kandidata j,k,l*/ j=check(j,p1); /*ako je broj i deljiv sa 2 bice j==0 nakon poziva funkcije check */ k=check(k,p2); /*ako je broj i deljiv sa 5 bice k==0 nakon poziva funkcije check */ l=check(l,p3); /*ako je broj i deljiv sa 7 bice l==0 nakon poziva funkcije check */ /*provera da li za vrednost promenljive i vazi broj je deljiv sa 2 (j==0) i deljiv sa 5 (k==0) i nije deljiv sa 7 (l!=0) ili broj je deljiv sa 2 (j==0) i deljiv sa 7 (l==0) i nije deljiv sa 5 (k!=0) ili broj je deljiv sa 5 (k==0) i deljiv sa 7 (l==0) i nije deljiv sa 2 (j!=0) */ if ( (j==0 && k==0 && l!=0) || (j==0 && l==0 && k!=0) || (k==0 && l==0 && j!=0) ) { fprintf(f, "%d ", i); /*upis u datoteku broja i koji ispunjavaju formulisanu uslov deljivosti */ n--; /* kolicina brojeva za upis u datoteku je manja za jedan broj */ } /*if*/ } /*for*/ fclose(f); }/*main*/ int check (int a, int p) { do { /*od promenljive a oduzimamo p sve dok je a strogo vece od nula, funkcija vraca kao rezultat poslednje izracunatu vrednost promenljive a. Ta vrednost ce biti tacno nula ako a deli p bez ostatka.*/ a=a-p; } while (a>0); return a; }87.
gcc zad87.c -o zad87
POKRETANJE PROGRAMA: zad87 10 40
daje u izlaznoj datoteci prosti.txt IZLAZ
37 31 19 17 13
jer broj 37 je prost, a zbir cifara 3+7=10 je slozen broj
...
#include <stdio.h> #include <stdlib.h> int prost (int n); /*testira da li je broj n prost broj */ /*Prirodni brojevi (sem 1) imaju najmanje dva delioca:jedinicu i samog sebe. Brojevi koji nemaju drugih delioca,sem ova dva, nazivaju se prostim */ int zbirCifara (int n); /*vraca zbir cifara broja n */ main(int argc, char **argv) { int donja,gornja; /*granice intervala */ int i; /*brojac u petlji */ int pom; /*posrednik u eventualnoj trampi granica intervala*/ FILE *f; f=fopen("prosti.txt", "w"); /* "ucitavanje" granica intervala iz niski argv[1], argv[2] u komandnoj liniji i konverzija u cele brojeve*/ sscanf(argv[1], "%d", &donja); /*donja=atoi(argv[1]) */ sscanf(argv[2], "%d", &gornja); /*gornja=atoi(argv[2]) */ if (donja > gornja) /*obezbedjivanje relacije: donja <=gornja */ { pom=donja; donja=gornja; gornja=pom; } /*brojevi ce se upisivati u datoteku u opadajucem poretku gornja - > donja*/ for(i=gornja;i>=donja; i--) if (prost (i) && !prost(zbirCifara(i) ) ) fprintf(f, "%d ",i); fclose(f); } int prost(int n) /*Ispituje se da li je broj n prost tako to se proverava da li ima delioce medju brojevima od 2 do n/2. Pri implementaciji se koristi tvrdjenje da je broj prost ako je jednak 2, ili ako je neparan i ako nema delitelja medju neparnim brojevima od 3 do n/2 */ { int prost; /*indikator slozenosti broja n */ int i; /*potencijalni delitelj broja n */ if (n==1) return 0; prost= (n%2!=0) || (n==2); /*parni brojevi razliciti od od dva nisu prosti brojevi */ i=3; /*najmanji potencijalni kandidat za delitelje medju neparnim brojevima razlicitim od jedan */ while ( (prost) && (i<=n/2) ) { prost=n%i != 0; i=i+2; /*proveravamo kandidate za delitelje samo medju neparnim brojevma */ } return prost; } int zbirCifara (int n) { int Suma=0; while (n>0) { Suma+= n%10; /*dodavanje cifre tekuceg razreda,pocev od razreda jedinica , a iduci ka visim razredima cifara */ n=n/10; /*prelaz ka visem razredu */ } return Suma; }88.
#include <stdio.h> #include <ctype.h> int malisamogl(int znak); /* ako znak je malo slovo a,e,i,o,u funkcija vraca 1, inace 0 */ main(int argc, char *argv[]) { int znak; /*tekuci znak ulazne datoteke koji se kopira u izlaznu datoteku */ FILE *ulaz, *izlaz; ulaz=fopen(argv[1], "r"); izlaz=fopen(argv[2], "w"); /* kopirati sadrzaj ulazne datoteke u izlazne citanjem ulaza do markera kraja EOF i konvertovanjem malih samoglasnika */ while( (znak=getc(ulaz)) != EOF) { if (malisamogl(znak)) znak=toupper(znak); /*mali samoglasnik postaje veliki samoglasnik */ else /*veliko slovo koje nije samoglasnik postaje malo slovo; veliko slovo koje jeste samoglasnik se ne transformise */ if( isupper(znak) && !malisamogl(znak + 'a'- 'A')) znak=tolower(znak); putc(znak, izlaz); } } int malisamogl(int znak) { if (znak=='a' || znak=='e' || znak=='i' || znak=='o' || znak=='u') return 1; else return 0; }89.
ULAZ Marko Markovic ml020888 Branka Brankovic mr050012 Ana Petrovic mm040088 Petar Andric mv050700 Mika Lazic mn050701 Sanja Petrovic aa040500 IZLAZ Generacija05.htm
Ime | Prezime | Username |
---|---|---|
Branka | Brankovic | mr050012 |
Petar | Andric | mv050700 |
Mika | Lazic | mn050701 |
IDEJA i DISKUSIJA:
Ucitava se rec po rec datoteke i nakon svake tri ucitane reci, proverava se vrednost niske username i njeni karakteri na drugoj i trecoj poziciji (jer
nulta i prva pozicija cuvaju oznake smera, a druga i treca pozicija oznaku godine upisa u obliku poslednje dve cifre godine ).
Kako niske ime, prezime, username za svakog studenta ne sadrze beline, a kako separatori među niskama su blanko,
a separator među podacima o studentima je znak za prelaz u novi red, to možemo koristiti bibliotečki funkciju
formatiranog ulaza fscanf (tj. nije nužno da implementiramo korisničku funkciju za učitavanje reči).
Uočite da implementacija korisničke funkciju za učitavanje reči sa ulaza je bilo potrebno kad god su te reči bile specifične forme (npr. tagovi - niske između uglastih zagrada ili alfanumeričke niske-niske koje sadrže samo slova ili cifre
ili tagovi bez atributa - niske između uglastih zagrada i/ili belina,...)
#include <stdio.h> #include <ctype.h> #include <string.h> #include <stdlib.h> #define MAXIME 20 #define MAXU 9 int main(int argc, char ** argv) { FILE *ulaz, *izlaz; char ime[MAXIME], prezime[MAXIME], username[MAXU]; ulaz=fopen(argv[1], "r"); izlaz=fopen("generacija05.htm", "w"); /*formiranje HTML zaglavlja i tela u izlaznoj datoteci generacija05.htm */ fprintf(izlaz,"<HTML><HEAD><TITLE>Generacija upisana 2005/06</TITLE></HEAD><BODY>"); fprintf(izlaz, "<TABLE><TR><TH>Ime</TH><TH>Prezime</TH><TH>Username</TH>"); while(!feof(ulaz)) { /* Ucitavanje imena iz ulazne datoteke*/ fscanf(ulaz, "%s", ime); /* Ucitava se prezime iz datoteke */ fscanf(ulaz, "%s", prezime); /* Ucitava se username*/ fscanf(ulaz, "%s", username); /* provera da li ucitan potpun sadrzaj za sve tri niske */ if(strlen(ime) && strlen(prezime) && strlen(username)) /* provera da li korisnicko ime sadrzi cifre 05 na pozicijama godina upisa*/ if((username[2]=='0') && (username[3]=='5') ) /* upisi podataka u tabelu datoteke generacija05.htm */ fprintf(izlaz,"<TR><TD>%s</TD> <TD>%s</TD> <TD>%s</TD></TR>", ime, prezime, username ); } /*Upis tagovi za kraj tabele i HTML datoteke*/ fprintf(izlaz,"</TABLE></BODY></HTML>"); fclose(ulaz); fclose(izlaz); }
Jelena Grmuša | Osnovi programiranja |