115. NCP koji u datoteku podaci.txt upisuje prvih 10 prirodnih brojeva, a zatim se iz iste datoteke citaju brojevi dok se ne stigne do kraja i ispisuju se na standardni izlaz .
/* Program demonstrira otvaranje datoteka ("r" - read i "w" - write mod) i osnovne tehnike rada sa datotekama */
#include <stdio.h>
/* Zbog funkcije exit */
#include <stdlib.h>
main()
{
int i; /* brojac u ciklusu */
int br; /* broj iz ulazne datoteke */
/* Otvaramo datoteku sa imenom podaci.txt za pisanje */
FILE* f = fopen("podaci.txt", "w");
/* Ukoliko otvaranje nije uspelo, fopen vraca NULL. U tom slucaju, prijavljujemo gresku i zavrsavamo program */
if (f == NULL)
{
printf("Greska prilikom otvaranja datoteke podaci.txt za pisanje\n");
exit(1);
}
/* Upisujemo u datoteku prvih 10 prirodnih brojeva (svaki u posebnom redu) */
for (i = 0; i<10; i++) fprintf(f, "%d\n", i);
/* Zatvaramo datoteku */
fclose(f);
/* Otvaramo datoteku sa imenom podaci.txt za citanje */
f = fopen("podaci.txt", "r");
/* Ukoliko otvaranje nije uspelo, fopen vraca NULL. U tom slucaju, prijavljujemo gresku i zavrsavamo program */
if (f == NULL)
{
printf("Greska prilikom otvaranja datoteke podaci.txt za citanje\n");
exit(1);
}
/* Citamo brojeve iz datoteke dok ne stignemo do kraja i ispisujemo ih na standardni izlaz */
/* Pokusavamo da procitamo broj */
while(fscanf(f, "%d", &br) == 1)
/* Ispisujemo procitani broj */
printf("Procitano : %d\n", br);
/* Zatvaramo datoteku */
fclose(f);
}
NAPOMENA:
Citanje brojeve iz datoteke do kraja datoteke i ispis tih brojeva na standardni izlaz
odvija se u fragmentu:
while(fscanf(f, "%d", &br) == 1)
printf("Procitano : %d\n", br);
II nacin za citanje brojeve iz datoteke do kraja datoteke i ispis tih brojeva na standardni izlaz:
while(1)
{
fscanf(f, "%d", &br);
/* Ukoliko smo dosli do kraja datoteke (poziv f-je feof(f) ), prekidamo ciklus*/
if (feof(f)) break;
/* Ispisujemo procitani broj */
printf("Procitano : %d\n", br);
}
OPREZ:
/* Ako je datoteka iz koje se vrsi ucitavanja mozda i prazna, onda
funkciju feof ne bi trebalo pozivati pre pokusaja citanja.
Sledeci kod moze dovesti do greske:
while (!feof(f))
{
fscanf(f, "%d",&br);
printf("Procitano : %d\n", br);
}
*/
116. NCP koji demonstrira rad sa datotekom u rezimu "a" - append mod datoteka tj. nadovezivanje sadrzaja na kraj datoteke.
#include <stdio.h>
main()
{
FILE* datoteka;
/* Otvaramo datoteku za nadovezivanje i proveravamo da li je doslo do greske */
if ( (datoteka=fopen("dat.txt","a"))==NULL)
{
fprintf(stderr,"Greska : nisam uspeo da otvorim dat.txt\n");
return 1;
}
/* Upisujemo sadrzaj u datoteku */
fprintf(datoteka,"Zdravo svima\n");
/* Zatvaramo datoteku */
fclose(datoteka);
}
117. NCP koji kopira datoteku ulaz.txt u datoteku izlaz.txt. Uz svaku liniju se zapisuje i njen broj
#include <stdio.h>
#include <string.h>
#define MAX_LINE 256
/* Korisnicka funkcija getline iz K&R jednostavno realizovana preko bibliotecke funkcije fgets (iz stdio.h) */
int getline(char s[], int lim)
{
char* c = fgets(s, lim, stdin);
return c==NULL ? 0 : strlen(s);
}
main()
{
char line[MAX_LINE]; /* linija datoteke */
FILE *in, *out; /*tokovi: ulaz, izlaz*/
int line_num; /*redni broj linije */
if ((in = fopen("ulaz.txt","r")) == NULL)
{
fprintf(stderr, "Neuspesno otvaranje ulazne datoteke %s\n", "ulaz.txt");
return 1;
}
if ((out = fopen("izlaz.txt","w")) == NULL)
{
fprintf(stderr, "Neuspesno otvaranje datoteke %s\n","izlaz.txt");
return 1;
}
/* Prepisivanje karakter po karakter je moguce ostvariti preko sledeceg fragmenta:
int c;
while ((c=fgetc(in)) != EOF) putc(c,out);
*/
line_num = 1; /*redni broj polazne linije */
/* Citamo liniju po liniju sa ulaza*/
while (fgets(line, MAX_LINE, in) != NULL)
{
/* Ispisujemo broj linije i sadrzaj linije na izlaz */
fprintf(out, "%-3d :\t", line_num++);
fputs(line, out);
}
/* Zatvaramo datoteke */
fclose(in);
fclose(out);
}
118. U svakoj liniji tekstualne datoteke cd.dat nalaze se podaci o prodaji kompakt diskova. Linija se sastoji od više kolona međusobno razdvojenih dvotačkom.
U prvoj koloni se nalazi naziv žanra CDa koji može biti jedna od niski iz skupa { inostrana, novokomponovana, decija, klasicna }.
U drugoj koloni je zadat broj prodatih primeraka za tekuću prodaju.
U trećoj koloni dat je datum prodaje u obliku rednog broja između 1 (početni dan intervala prodaje) i 30 (dan obrade podataka).
Potom slede podaci o nabavnoj ceni. Ti podaci se sastoje od: cene po primerku, ali za inostranu muziku dodatno se zadaje i iznos carine PO UKUPNOJ KOLIČINI, dok za novokomponovanu muziku dodatne se PO PRIMERKU zadaje i iznos poreza na šund.
Potom slede podaci o prodajnoj ceni
BROJ LINIJA U DATOTECI NIJE UNAPRED POZNAT.
NCP koji će odštampati na standardni izlaz ukupne prihode od prodaje u intervalima od 15 dana i formirati datoteku podaci.dat koja će biti u istom formatu kao datoteka cd.dat, ali će sadržati podatke o prodaju diskova koji nisu iz žanra novokomponovane muzike.
TEST PRIMER
cd.dat |
standardni izlaz |
podaci.dat |
---|---|---|
inostrana:20:1:400:20:500 novokomponovana:100:1:200:80:500 decija:5:1:100:200 klasicna:1:1:200:250 novokomponovana:100:2:200:80:500 inostrana:10:2:400:20:500 decija:3:2:100:200 novokomponovana:120:3:200:80:500 inostrana:28:3:400:20:500 inostrana:12:4:400:20:500 novokomponovana:80:4:200:80:500 decija:8:4:100:200 klasicna:3:4:200:250 |
Prihodi po intervalima dana: [1,15]: 96720.00 [16,30]: 0.00 |
inostrana:20:1:400.000000:20.000000:500.000000 decija:5:1:100.000000:200.000000 klasicna:1:1:200.000000:250.000000 inostrana:10:2:400.000000:20.000000:500.000000 decija:3:2:100.000000:200.000000 inostrana:28:3:400.000000:20.000000:500.000000 inostrana:12:4:400.000000:20.000000:500.000000 decija:8:4:100.000000:200.000000 klasicna:3:4:200.000000:250.000000 |
#include <stdio.h> #include <stdlib.h> #include <string.h> main () { int i; /*brojac u petlji */ FILE *cd; /*podaci o prodaji kompakt diskova se cuvaju u datoteci tako da svaka linija sadrzi podatke o jednoj prodaji; Unutar linje kolone se razdvajaju dvotackama*/ FILE *podaci; /*podaci o zanru inostrana, decija, klasicna */ char naziv[17]; /* zanr CD-a moze biti: inostrana, novokomponovana, decija, klasicna*/ int komada_prodato; /* broj prodatih diskova pri tekucoj prodaji */ int datum_prodaje; /* datum prodaje za tekucu prodaju (1..30) */ float nabavna_cena; /* nabavna cena po jedinici za tekucu prodaju. */ float iznos_carine; /*iznos carine za tekucu prodaju. */ float iznos_poreza; /* porez po jedinici za novokonponovanu muziku */ float prodajna_cena; /* prodajna cena za tekucu prodaju. */ float prihod_1_15, prihod_16_30; /*prihod po svakom od intervala od po 15 dana*/ float prihod; /*prihod od tekuce prodaje. */ cd = fopen ("cd.dat", "r"); podaci = fopen ("podaci.dat", "w"); if ( (cd==NULL) || (podaci==NULL) ) {fprintf(stderr,"Greska pri otvaranju neke od datoteka\n"); exit(1); } /* Inicijalizacije. */ prihod_1_15 = prihod_16_30 = 0; /* Obradjuje se jedna po jedna linija datoteke o svim prodajama, pazeci na dvotacku */ for (; !feof (cd);) { /* Ucitava se naziv zanra */ for (i = 0; (naziv[i] = fgetc (cd)) != ':'; i++) ; naziv[i] = '\0'; /* Ucitavaju se broj prodatih jedinica :datum prodaje:nabavna cena za tekucu prodaju */ fscanf (cd, "%d:%d:%f:", &komada_prodato, &datum_prodaje, &nabavna_cena); /* Za inostrani cd ucitava se iznos carine. */ if (!strcmp (naziv, "inostrana" )) fscanf (cd, "%f:", &iznos_carine); else iznos_carine = 0; /* Za cd novokomponovane muzike ucitava se iznos poreza. */ if (!strcmp (naziv, "novokomponovana")) fscanf (cd, "%f:", &iznos_poreza); else iznos_poreza = 0; /* Ucitava se prodajna cena po primerku */ fscanf (cd, "%f\n", &prodajna_cena); /* Izracunava se prihod od tekuce prodaje. */ prihod = komada_prodato * (prodajna_cena - nabavna_cena - iznos_poreza) - iznos_carine; /* Uvecava se prihod u intervalu kome pripada prodaja. */ if (datum_prodaje <= 15) prihod_1_15 += prihod; else if (datum_prodaje <= 30) prihod_16_30 += prihod; /* Ako zanr cd nije novokomponovana muzika, prepisuje se tekuca prodaja u datoteku sa podacima o prodaji */ if (strcmp (naziv, "novokomponovana") !=0) { fprintf (podaci, "%s:%d:%d:%f:", naziv, komada_prodato, datum_prodaje, nabavna_cena); if (!strcmp (naziv, "inostrana")) fprintf (podaci, "%f:", iznos_carine); fprintf (podaci, "%f\n", prodajna_cena); } } /* Zatvaraju se datoteke. */ fclose (cd); fclose (podaci); /* Ispisuje se izvestaj o prodaji cd-a po intervalima */ printf ("Prihodi po intervalima dana:\n"); printf ("%s: %.2f\n", "[1,15]", prihod_1_15); printf ("%s: %.2f\n", "[16,30]", prihod_16_30); return 0; }
119. NCP koji ispisuje na standardni izlaz spojeni sadržaj nekoliko datoteka čiji nazivi su dati kao parametri komandne linije. Ako se u komandnoj liniji ne nalazi naziv niti jedne datoteke, onda ispisati tekući sadržaj sa standardnog ulaza.
IDEJA:
U ovom zadatku potrebno je otvoriti datoteke čiji
nazivi su sadržani u niskama argv[1], argv[2],..., argv[argc-1]
Ako
otvaranje pojedinačne datoteka bude uspešno (fopen(...)
!= NULL), onda pozvati f-ju pisi(f,stdout) koja sadrzaj datoteke na
koji pokazuje f ispisuje na stdout (standardni izlaz, tj. ekran dok
ga ne preusmerimo komandom operativnog sistema)
Ako otvaranje
datoteke ne uspe, potrebno je ispisati poruku o gresci na
stderr(standardni tok za poruke o grešci) i prekinuti dalje
izvršvanje programa (exit(1);)
U f-ju pisi(f,stdout) čita
se karakter po karakter (sve do EOF) iz datoteke na koju pokazuje f
(getc(f)) i ispisuje na standardni izlaz (putc(c,stdout)).
Nakon
završetka ispisa sadržaja datoteke, datoteka se zatovori.
(fclose(f))
#include <stdio.h> void pisi(FILE *ulaz,FILE *izlaz); /*prepisuje ulaznu datoteku u izlaznu datoteku */ main(int argc, char *argv[ ]) { FILE *f; /* za citanje */ int i; /*brojac u petlji */ char *imeprog=argv[0]; /*ime programa; nije obavezno pri ispisu*/ if(argc==1) pisi(stdin,stdout); /* kada se prenosi tekst sa glavnog ulaza,jer u komandnoj liniji nema imena ostalih datoteka */ else /*inace ispisati "spojeni" sadrzaj (ako je moguce) onih datoteka cija se imena cuvaju kao argv[1]...argv[argc-1] */ for(i=1; i < argc;i++) /*pokusaj otvranja datoteke za citanje */ if( (f=fopen(argv[i],"r") ) ==NULL) { fprintf(stderr, "%s: Ne mogu otvoriti fajl sa imenom %s\n",imeprog, argv[i]); exit(1); } else /*ispis sadrzaja upravo otvorene datoteke na standardni izlaz */ { pisi(f,stdout); fclose(f);} if (ferror(stdout) ) { fprintf(stderr, "%s: greska pisanja u stdout\n",imeprog); exit(2);} exit ( 0 ); } void pisi(FILE *ulaz,FILE *izlaz) /*kopira ulaz na izlaz */ { int c; while( (c=getc(ulaz) ) != EOF) putc(c,izlaz); }
120. NCP koji ce odštampati na standardni izlaz izveštaj o broju redova, reči, karaktera u datoteci PROVERA.C. Pretpostaviti da tip long je dovoljan za sve tri karakteristike iz izveštaja. Smatrati da reč je ma koja niska znakova koja ne sadrži znak razmak, horizontalni tabulator, znak za prelaz u novi red.
/* word count (UNIX komanda wc) za file "PROVERA.C", pogledati sličan zadatak u I glavi Kernighan-Ritchie */ #include <stdio.h> #include <stdlib.h> typedef enum {VAN, UNUTAR} STANJE; main (){ STANJE ureci; /*svojom vrednoscu signalizira VAN/UNUTAR reci */ long red_broj, rec_broj, znak_broj; /*ukupan broj redova,reci,znakova */ int zn; /*tekuci ucitani znak */ char ime[]="PROVERA.C" ; /*ime datoteke koja se analizira */ FILE *pf; pf = fopen(ime, "r"); if (pf == NULL) { fprintf(stderr, "Otvaranje %s nije uspelo.\n", ime);exit (EXIT_FAILURE); } /* analiza sadrzaja fajla i prebrojavanje karaktera, reci, prelazaka u novi red*/ red_broj = rec_broj = znak_broj = 0;ureci = VAN; while (( zn = fgetc(pf)) != EOF) { ++znak_broj; if (zn == ' ' || zn == '\t' || zn == '\n') ureci = VAN; else if (ureci == VAN) { ++rec_broj; ureci = UNUTAR; } if (zn == '\n')++red_broj; } if (ferror(pf) != 0) {fprintf(stderr, "GRESKA PRI CITANJU: %s\n", ime); exit (EXIT_FAILURE); } /* prikazati rezultate analize */ printf("%s: %ld %ld %ld\n",ime, red_broj, rec_broj, znak_broj); return (EXIT_SUCCESS); }
121. NCP koji će kopirati sadržaj jedne tekstualne datoteke u drugu tekstualnu datoteku. Nazivi datoteka se zadaju kao parametri komandne linije.
/* POZIV programa: kopiraj dat1 dat2 */ #include <stdio.h> main( int argc, char *argv[]){ int znak; /*tekuci znak ulazne datoteke koji se kopira u izlaznu datoteku */ FILE *ulaz, *izlaz; if (argc !=3) printf("\nOblik komande je: %s ulaz izlaz\n", argv[0]); else if ( (ulaz=fopen(argv[1],"r") ) == NULL) printf("Datoteka %s se ne moze otvoriti za citanje\n",argv[1]); else if ( (izlaz=fopen(argv[2],"w") ) == NULL) printf("Datoteka %s se ne moze otvoriti za pisanje\n",argv[2]); else { /*izvrsiti kopiranje sadrzaja ulazne datoteke u izlaznu iscitavanjem ulaza do markera kraja */ while ( (znak=getc(ulaz) ) != EOF) putc(znak, izlaz); printf("\n"); } return 0; }
122. NCP koji će prepisati sadržaj tekstualne datoteke (čije ime se zadaje kao argument komandne linije) na standardni izlaz tako da se učitava do 80 karaktera po liniji.
/* type datoteka */ #include <stdio.h> #define LINE_LENGTH 81 main(int argc, char *argv[]){ char linija[LINE_LENGTH]; /*sadrzaj tekuce linije datoteke */ FILE *ulaz; if (argc !=2) printf("\nFormat poziva: %s imeUlazneDatoteke\n",argv[0]); else if ( (ulaz=fopen(argv[1],"r") ) == NULL) printf("Datoteka %s se ne moze otvoriti \n", argv[1]); else /*ispis teksta */ while (fgets(linija,LINE_LENGTH,ulaz) != NULL) printf("%s",linija); return 0; }
123.
NCP koji iz datoteke ulaz.txt ucitava
datume u obliku dd.mm.gggg. (do nailaska na oblezje kraja datoteke) i
ispisuje na standardni izlaz najveci datum. U slucaju da postoji vise
takvih ispisati tacno jedan od njih.
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; }
124.
NCP koji ulaznu datoteku ulaz.txt
šifrira i prepisuje u datoteku tajna.txt tako da svaki znak
datoteke se zameni znakom čiji ASCII kôd je rotaciono
pomeran udesno za 1 bit.
Npr. znak z sa ASCII kôdom
(dekadno) 122 se transformiše u znak = sa ASCII kôdom
(dekadno) 61, jer rotacijom udesno za 1 bit ôda 01111010 dobija
se kôd 00111011 (bit najmanje težine prelazi na poziciju
najveće težine, a ostali bitovi pomeraju se udesno za 1 mesto).
#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); }
125.
NCP koji ulaznu datoteku tajna.txt
(koja je dobijena šifriranjem ako u prethodnom zadatku)
dešifrira i prepisuje u datoteku provera.txt .
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); }
126.
NCP koji ucitava
iz (tekstualne) ulazne datoteke ulaz.txt prirodan broj n (manji ili
jednak od 100), proverava korektnost učitane vrednosti i
generiše prvih n članova skupa M koji se formiraju po
zakonu
1 pripada M
ako k pripada M, onda i 2k+1 i 3k+1 pripadaju skupu M
Ispisati prvih na članova skupa M na standardni izlaz. (NAPOMENA: M je skup, dakle nema duplikata među članovima).
Pogledajmo formiranje prvih n članova skupa M za neke vrednosti promenljive n:
n=3: 1, 3, 4 (formirani po zakonu 1, zakonu 2, jer 3=2*1+1, 4=3*1+1)
n=8: 1, 3, 4, 7, 9, 10, 13, 15 (formirani po zakonu 1 i naizmenicnoj primeni zakona 2 i po grani 2k+1 i po grani 3k+1)
n=15: 1, 3, 4, 7, 9, 10, 13, 15, 19, 21, 22, 27, 28, 31, 39
Ako pogledamo drvo formiranja onda "preti opasnost" da
31 bude duplikat u skupu jer se dobija dvojako i preko grane zakon
2k+1 i preko grane zakona 3k+1, tj. i kao 31=2*15+1 i kao 31=3*10 +1
Zato se u svakom koraku primene upoređuju poslednje
formirani elementi i po zakonu 2k+1 i po zakonu 3m+1. Izabere se
manji clan i smesti u skup M, a grana koja ga je generisala "ima
pravo" da primeni zakon za novu vrednost broja k ili m. Ako se
po obe grane dobije isti clan, onda obe grane primenjuju zakon za
nove vrednosti k,m.
#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); }
127.
NCP koji u datoteku izlaz.txt upisuje n
najmanjih prorodnih brojeva deljivih sa tačno dva broja iz skupa
{2, 5, 7}. Proveru izvršiti bez upotrebe operatora / ili
operatora %. Broj n se zadaje iz komandne linije.
IDEJA:
Program treba da n puta ispise
ili broj koji je deljiv sa 10(2*5), ali ne i sa 70 (2*5*7)
ili broj koji je deljiv sa 14(2*7), ali ne i sa 70 (2*5*7)
ili broj koji je deljiv sa 35(5*7), ali ne i sa 70 (2*5*7)
Kako poredak treba da bude rastući, onda proveru treba započeti od prvog kandidata i za svaki sledeći veći broj proveriti gore navedene uslove deljivosti. Prvi kandidat je 10=2*5 (i nema potrebe proveru uslova deljivosti vršiti za manje brojeve), a sledeći kandidati su 11, 12, 13,... Program okončava rad kada pronađe n brojeva počev od 10 koji zadovoljavaju uslov.
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; }
128.
NCP koji u datoteku prosti.txt upisuje
proste brojeve zadatog intervala kojima je zbir cifara složen broj.
Interval se zadaje učitavanjem gornje i donje granice (dva
prirodna broja) u komandnoj liniji. Brojeve upisivati u datoteku u
opadajućem poretku. U programu nije potrebno predvideti obradu
greski nastalih usled nekorektnog pozivanja programa u komandnoj
liniji ili greske u otvaranju datoteke...
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; }
129.
NCP koji će ulaznu datoteku
prepisati u izlaznu tako da samo samoglasnici (a, e, i, o, u) budu
prikazani velikim slovima. Nazivi ulazne i izlazne datoteke se zadaju
u komandnoj liniji. U programu nije neophodno predvideti obradu
greski nastalih usled nekorektnog pozivanja programa u komandnoj
liniji ili greske u otvaranju datoteka...
#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; }
Zadaci za vezbu (zadaci su poredjani po tezini u rastucem poretku):
Zadatak 1. NCP koji iz komandne linije ucitava imena dve datoteke i ispisuje na standardni izlaz da li su jednake prva rec prve datoteke i prva rec druge datoteke. Smatrati da reci nemaju vise od 20 karaktera. U slucaju greske u otvaranju datoteka, prijaviti odgovarajuci komentar na stderr.
TEST primer
DAT1. txt
Programiranje 1 je moj omiljeni predmet.
DAT2.txt
Programiranje 1 nije moj omiljeni predmet.
IZLAZ
Prva rec 1. datoteke je Programiranje, prva rec 2. datoteke je Programiranje i te dve reci su jednake.
Zadatak 2. NCP koji iz komandne linije ucitava imena dve datoteke (ulazna i izlazna datoteka) i sabira sve realne brojeve u ulaznoj datoteci i ispisuje njihov zbir u izlaznu datoteku. U slucaju greske u otvaranju datoteka, prijaviti odgovarajuci komentar na stderr.
TEST primer
ULAZ.txt
1 5 8.3 -2.3
8
0
-6
IZLAZ.txt
Suma brojeva datoteke ULAZ.txt je 14.
Zadatak 3. NCP koji iz komandne linije ucitava imena dve datoteke (ulazna i izlazna datoteka) i iz ulazne datoteke kopira u izlaznu svaki drugi karakter polazeci od drugog procitanog karaktera. U slucaju greske u otvaranju i zatvaranju datoteka, prijaviti odgovarajuci komentar na stderr.
TEST primer
DAT1. txt
Programiranje.
IZLAZ
rgaiaj.
Zadatak 4. Napisati program koji broji pojavljivanja za svako od slova engleske abecede u datoteci ulaz i stampa rezultat na standardni izlaz.
TEST primer
ULAZ. txt
FE9 + 1 = FEA.
IZLAZ
Slovo A: 1
Slovo B: 0
Slovo C: 0
Slovo D: 0
Slovo E: 2
Slovo F: 2
Slovo G:0
....
Slovo Z: 0
Zadatak 5. NCP koji iz komandne linije ucitava naziv datoteke i ispisuje na standardni izlaz najduzu liniju. Ako ima vise linija najvece duzine, ispisati onu koja se najpre pojavila. Pretpostaviti da svaka linija datoteke nema vise od 80 karaktera. Broj linija datoteke NIJE unapred poznat!!! U slucaju greske u otvaranju datoteke, prijaviti odgovarajuci komentar na stderr.
TEST primer
DAT1. txt
Programiranje 1 je
moj omiljeni predmet. Ako
ne polozim
programiranje 1,
bice mi tesko da
savladam gradivo
na predmetu
Programiranje 2.
IZLAZ
moj omiljeni predmet. Ako
Zadatak 6. Opisati sve greške u sledećem C programu.
include
<stdio.h>
define OFFSET 3;
define greska(msg)
fprintf(stderr,#msg" %s\n",argv);
void
processFile(pd1,pd2); /ucitavanja iz datoteke i obrada/
int
length, width;
long area;
struct coord_p
{ int x,
int
y }mypt
struct rectangle
{ coord_p topleft,
coord_p
bottomrt } mybox
main(int argc, char argv**) {
FILE
pd1, pd2;
if( argv = 3 ) /korektan broj argumenata /
if( pd1 =
fopen( **++argv, 'r')== NULL ) {
greska(Ne moze da se
otvori)
exit(1)
} else if( pd2 = fopen( **++argv, 'r')= NULL )
{
greska(Ne moze da se otvori)
exit(1)
} else { /ucitavanje
koordinata/
processFile( pd1, pd2 ); free( pd1 ); free( pd2
);
exit(2)
}
return 3;
}
void processFile(pd1,pd2);
{boolean coord_test;
fscanf(pd1, "%d",
mybox.topleft.x, mybox.topleft.y);
fscanf(pd1, "%d",
mybox.bottomrt.x); fscanf(pd1, "%d", mybox.bottomrt.y);
coord_test=(bottomrt.x - topleft.x)*(bottomrt.y - topleft.y) >
0;
if (coord_test){ / izracunavanje duzine, visine i povrsine /
width = OFFSET+ bottomrt.x - topleft.x; length = OFFSET +
bottomrt.y - topleft.y; Area = width * length;
printf(pd2,"\nPovrsina je %l\n", area); }
}
RESENJE:
#include
<stdio.h>
#include <stdlib.h>
#define OFFSET
3
#define greska(msg) fprintf(stderr,#msg" %s\n",
*argv);
void processFile( FILE * pd1, FILE *pd2 );
/*ucitavanje iz datoteke i obrada */
int length, width;
long
area;
struct coord{
int x;
int y;
};
struct rectangle{
struct coord topleft;
struct
coord bottomrt;
} mybox;
main(int argc, char **argv)
{
FILE *pd1, *pd2;
if( argc == 3 ) /*
korektan broj argumenata */
if( (pd1 = fopen( *++argv,
"r" ) ) == NULL ) {
greska(Ne moze da se
otvori)
exit(1);
} else if( ( pd2 = fopen( *++argv, "w"
) ) == NULL ) {
greska(Ne moze da se otvori)
exit(1);
}
else { /* ucitavanje koordinata */
processFile( pd1, pd2
);
fclose( pd1 );
fclose( pd2 );
exit( 2 );
}
}
void processFile( FILE
* pd1, FILE *pd2 ) {
int coord_test;
fscanf(pd1, "%d
%d", &mybox.topleft.x, &mybox.topleft.y);
fscanf(pd1, "%d", &mybox.bottomrt.x);
fscanf(pd1, "%d", &mybox.bottomrt.y);
coord_test=(mybox.bottomrt.x -
mybox.topleft.x)*(mybox.bottomrt.y - mybox.topleft.y)
> 0;
if (coord_test) { /*izracunavanje duzine, visine i
povrsine */
width = OFFSET + mybox.bottomrt.x -
mybox.topleft.x;
length = OFFSET + mybox.bottomrt.y -
mybox.topleft.y;
area = width * length;
}
fprintf(pd2,"\nPovrsina je %ld \n",
area);
}
Zadatak 7*. Datoteka cije se ime unosi sa standardnog ulaza sadrzi podatke o proizvodima koji se prodaju u okviru odredjene prodavnice.
Svaki proizvod se odlikuje sledecim podacima :
bar-kod - petocifreni pozitivan broj
ime - niska karaktera
cena - realan broj zaokruzen na dve decimale
pdv - stopa poreza - realan broj zaokruzen na dve decimale
Pretpostavljamo da su podaci u datoteci korektno zadati.
Pretpostavljamo da se u prodavnici ne prodaje vise od 1000 razlicitih artikala. Na standardni izlaz ispisati podatke o svim proizvodima koji se prodaju.
Zadatak
8**. NCP koji iz komandne linije
prihvata naziv grada i formira datoteku izlaz.txt koja sadrzi podatke
o studentima iz tog grada. Izlazna datoteka treba da sadrzi ime i
prezime studenta, naziv zavrsene srednje skole, broj pena na
prijemnom i adresu. Ovi podaci se vec nalaze u datotekama
studiranje.txt kao delovi strukture
struct student{ char
imePrezime[40]; long maticniBroj; int godinaStudija; char
srednjaSkola[50]; double poeni; }
i datoteci licno.txt kao delovi
strukture
struct licniDosije{ long maticniBroj; char adresa[50];
char grad[40]; long FiksniTelefon; long MobilniTelefon; char
drzavljanstvo[20]; }
Zadatak
9**.
Svaki red datoteke, čije
se ime unosi kao argument komandne linije, sadrži ime, prezime i
korisničko ime studenta (Matematičkog fakulteta u Beogradu)
na serveru ALAS. Iza imena i prezimena nalazi se po jedan blanko
karakter, a korisnička imena su zapisana u formatu: dvoslovna
oznaka smera, poslednje dve cifre godine upisa, četvorocifren
broj indeksa. (npr. mr050007, ml040950, aa030034). Napisati program
koji generiše datoteku generacija05.txt koja sadrži tabelu sa
podacima o studentima koji su upisani 2005. godine na Matematički
fakultet. Zaglavlje tabele treba da sadrži polja: ime, prezime,
username. Pretpostavka da ulazna datoteka je bez sintaksnih i
semantičkih greški.
ULAZ Marko Markovic ml020888 Branka Brankovic mr050012 Ana Petrovic mm040088 Petar Andric mv050700 Mika Lazic mn050701 Sanja Petrovic aa040500 IZLAZ generacija05.txt
Ime |
Prezime |
Username |
---|---|---|
Branka |
Brankovic |
mr050012 |
Petar |
Andric |
mv050700 |
Mika |
Lazic |
mn050701 |
IDEJA:
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).