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);
}
/* 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);
}
70. NCP koji će kopirati sadržaj jedne tekstualne datoteke u drugu tekstualnu datoteku. Nazivi datoteka se zadaju kao parametri komandne linije.
/*copy 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") ) == NUL) 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;
}
71. 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;
}
72. NCP koji će obavljati čitanje binarne datoteke unazad (čije ime se zadaje u komandnoj liniji) i ispisati pročitan sadržaj na standardni izlaz u formi tabele sa 3 kolone čija su zaglavlja: ucitani karakter, vrednost karaktera, pozicija posle.
Bitna razlika između DOS-a i UNIX-a je u tretmanu kraju reda. U DOS-u su to 2 karaktera (CR LF ascii kodovi su: #13 #10), a u UNIX-u samo 1 (LF).
CR je Carriage Return (povratak na početak reda, vraćanje bubnja, tj. kolica na pisaćoj mašini ulevo).
LF je Line Feed (spuštanje za red niže).
ASCII (American Standard Code for International Interchange), DOS i kasniji OS-ovi koriste da je novi red CR LF.
Kod COMMODORE-u 64 je na primer novi red reprezentovan sa CR, dok u C-u i UNIX-u novi red je predstavljen sa LF.
Binarno prenošenje sadržaja je bit-po-bit. Ali ascii tekst tada ne bi bio dobro prenesen jer bi morao svaki LF da se zameni sa CR LF i obratno. Zato služi ascii prenos. Na primer, neki DOS fajl binarno ima 150 karaktera, a ascii 139.
ULAZ:
8abcd
PROVERITE IZLAZ OVOG zadatak za gore zadati ulaz pod DOS/Windows-om, pod UNIX/Linux-om. Uporedite sadržaje sve tri kolone. Ovaj zadatak ilustruje gore navedene razlike.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define BOF -2 /* marker pocetka datoteke */
FILE *fp;
int get_and_print( void ); /*popunjavanje jedne vrste tabele */
int get_previous_char( void ); /*ocitavanje karaktera pri citanju unazad */
main(int argc, char *argv[]){
if( (fp = fopen( argv[1], "rb")) == NULL ) {
fprintf( stderr, "Neuspeh pri otvaranje datoteke %s", argv[1]);
exit( 1 );
}
/* kreiranje "tabele" za ispis */
printf("\n ucitani\t vrednost\t pozicija");
printf("\n karakter\t karaktera\t posle\n");
fseek( fp, 0L, SEEK_END); /* pozicioniranje na kraj datoteke */
while( get_and_print( ) != BOF ) ; /*ucitavanje do korisnickog markera pocetka */
fclose( fp );
}
int get_and_print( void ){
int c; /*tekuci znak iz datoteke */
c = get_previous_char( );
if( isprint(c) ) printf("\t%c", c); /*"stampanje" ucitanog karaktera */
else if( c == '\n' ) printf("\tLF");
else if( c == '\r' ) printf("\tCR");
else if( c == EOF ) printf("\tEOF");
else if( c == BOF ) printf("\tBOF");
else if( c == 26 ) printf("\tALT26");
else printf("\t");
printf("\t %3d", c); /*vrednost karaktera */
printf("\t\t %2ld\n", ftell( fp ) ); /*pozicija */ return( c );
}
int get_previous_char( void )
{ int c;
if( ftell( fp ) > 0 )
{
fseek( fp, -1L, SEEK_CUR); /* pomeranje za jedan unazad */
c = getc( fp ); /* citanje */
fseek( fp, -1L, SEEK_CUR); /* pripremanje za sledece citanje */
return c;
}
else return BOF;
}
73. U svakoj liniji tekstualne datoteke cd.dat nalaze se podaci o prodaji komapkt diskova. Linija se sastojo od više kolona međusobno razdvojenih dvotačkom. U prvoj koloni sr nalazi naziv žanra CDa koji može biti jedna od niskiz skupa
{ inostrana, novokomponovana, decija, klasicna }. U drigoj 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. BROJ LINIJA U DATOTECI NIJE UNAPRED POZNAT. NCP koji će odštampati na standradni 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.
#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;
}
![]() | Jelena Grmusa | ![]() | Osnovi programiranja |