Professional Documents
Culture Documents
Argumenti Komandne Linije
Argumenti Komandne Linije
Prilikom pozivanja programa iz komandne linije moguće je navesti određene opcije i argumente,
koje program koristi u svom radu. Npr, možemo pozvati program na sledeći način:
./izvrsni ulaz.txt izlaz.txt
zeleci da program izvrsni iskopira fajl ulaz.txt u fajl izlaz.txt.
Potrebno je da postoji mehanizam da program iznutra pristupi stringovima koje je korisnik naveo
prilikom poziva programa.
U C-u se to ostvaruje na sledeći način:
Definišemo parametre funkcije main:
int argc
ovaj parametar prilikom pokretanja programa dobija vrednost broja argumenata koje je korisnik prilikom
poziva naveo. Pri tom se i ime programa broji kao argument komandne linije. U
gornjem primeru će argc biti postavljeno na 3.
char **argv
pokazivač na pokazivač na char koji sadrži adresu prvog u nizu pokazivača na karaktere. Svaki od tih
pokazivača na karaktere sadrži adresu odgovarajućeg stringa koji sadrži argument komandne linije. Npr. u
gornjem primeru, argv[0] će nam pokazivati na string "./primer", argv[1] će nam pokazivati na
string "ulaz.txt", argv[2] će nam pokazivati na string "izlaz.txt". Dakle, niz pokazivača na čiji prvi član
pokazuje argv je dužine upravo argc.
1. NCP koji ispisuje broj argumenata komandne linije i parametre komandne linije.
#include <stdio.h>
typedef struct {
....
} FILE;
koja sadrzi sve informacije vezane za otvoreni fajl. Ove informacije su platformski zavisne, i nama nisu od znacaja.
Ova funkcija prihvata string sa putanjom do fajla (ime), kao i string (nacin) koji definise način rada sa fajlom. Može
biti:
"w" fajl se otvara za pisanje (kreira se ako ne postoji, a ako postoji, njegov sadržaj se briše)
"a" fajl se otvara za dopisivanje (kreira se ako ne postoji. Prilikom svakog pisanja sadržaj se dodaje na kraj fajla).
Funkcija fopen() vraca pokazivač na FILE strukturu koja je povezana sa otvorenim fajlom. Od tog trenutka se
baratanje sa otvorenim fajlom sastoji u tome da se funkcijama standardne biblioteke prosledi ovaj pokazivač kao
argument. Ostalo obavlja biblioteka za nas.
● Dakle, u pitanju je nula. Uobičajeno je da se ova konstanta koristi za pokazivače koji imaju vrednost nula (tj. ne
pokazuju ni na šta).
Prilikom svakog otvaranja fajla, treba proveriti da li je nastupila greška, tj. da li je povratna vrednost funkcije bila
NULL. Ako jeste, treba nekako obraditi tu grešku. Najčešći način za to je obavestiti korisnika o tome šta se desilo i
prekinuti program.
fclose(f);
● Prilikom završetka rada programa, svi fajlovi se automatski zatvaraju. Mi se nećemo oslanjati na ovo, već kad god
nam otvoreni fajl više ne treba, eksplicitno ćemo ga zatvarati.
Standardni ulaz i izlaz se u C-u takođe svodi na ulaz i izlaz fajova. Prilikom pokretanja programa se automatski
otvaraju tri fajla, kojima se dodeljuju sledeći globalni FILE pokazivači:
Učitava jedan karakter iz fajla na koji pokazuje f, i vraća njegov ASCII kod kao povratnu vrednost. Ako je nastupio
Učitava celu liniju karaktera iz fajla na koji pokazuje f u string s, ali ne više od size karaktera (što treba da bude
veličina stringa s). Eventualni '\n' sa kraja linije se čuva u stringu s, koji se ovom fjom i terminira nulom. Fja vraća
NULL ako se desila greška pri učitavanju.
Upisuje string s u fajl na koji pokazuje f bez terminirajuće nule. Vraća EOF za grešku.
Ove dve funkcije rade isto što i scanf i printf, osim toga što ne rade sa standardnim ulazom, tj. sa standardnim
izlazom već rade sa fajlom na koga pokazuje f.
Ova fja vraća tekuću poziciju datoteke f ili -1L u slučaju greške.
Funkcija fseek podešava poziciju datoteke f. Narednim čitanjem ili pisanjem pristupa se podacima na početku nove
pozicije. Nova pozicija se postavlja na offset znakova od mesta origin, koje može biti SEEK_SET (početak datoteke),
SEEK_CUR (tekuća pozicija) ili SEEK_END (kraj datoteke).
Za tekstualnu datoteku, offset mora biti nula ili vrednost koju je
vratila funkcija ftell i u tom slučaju origin mora biti SEEK_SET.
Primer: fseek(f, 0, SEEK_END) postavlja datoteku na 0 bajtova od kraja datoteke, tj. na kraj datoteke.
2. Napisati program koji kopira fajl koji se zada kao prvi argument komandne linije u fajl koji se zada kao drugi
argument komandne linije.
#include <stdio.h>
if (argc != 3) {
fprintf(stderr, "Koriscenje programa: ./copy ulaz izraz\n");
return 1;
}
/* Zatvaramo fajlove */
fclose(in);
fclose(out);
return 0;
}
3. Napisati program koji prepisuje datoteku cije se ime navodi kao prvi argument komandne linije u datoteku ciji se
argument navodi kao drugi argument komandne linije programa. Ukoliko je navedena opcija -u program prilikom
prepisivanja treba da zamenjuje sva mala slova velikim, a ukoliko je navedena opcija -l sva velika slova se zamenjuju
malim.
(Koliko se ovaj problem teze implementira u odnosu na problem kod koga su fiksirana imena datoteka. Diskutovati
varijantu u kojoj je fiksiran polozaj opcije u listi argumenata, kao i varijantu u kojoj se opcija moze navesti na
proizvoljnom mestu u listi argumenata.)
#include <stdio.h>
#include <ctype.h>
return 0;
}
4. /* find_str [-n|-x] pattern */
Argumenti komandne linije su: poziv programa, opcioni argumenti (-n, -x), obrazac.
NCP koji čita linije sa standardnog ulaza do markera kraja i štampa sve linije koje sadrže obrazac(sem ako se među
argumentima komandne linije ne nalazi opcija -x). Ukoliko se među opcionim argumentima nalazi -n ispisuje redni
broj linije ispred sadržaja linije. Predvideti mogućnost pojavljivanja oba opciona argumenta u formi -nx, -xn.
Pretpostaviti da ukupan broj linija je strogo manji od LONG_MAX.
Test primer 1: ispisati sve linije teksta sa ulaza koje ne sadrže (opcija: -x) nisku HTML. Uz sadrzaj ispisati i
redne brojeve linija. (opcija -n)
Test primer 2: isto kao primer 1, ali ilustruje prisustvo i kombinaciju oba opciona argumenta
Test primer 3: poziv sa nekorektnom opcijom -z koja je zadata kao argument komandne linije
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLEN 1000 /*max duzina linije */
5. Napisati C program koji ce ispisati argumente komandne linije. Predvideti mogucnost ispisa:
a) argumenata komandne linije u novom redu ako je zadata opcija –n u komandnoj liniji
b) argumenata komandne linije sa tabom ako je zadata opcija –t u komandnoj liniji
c) argumenata komandne linije sa navodnicima ako je zadata opcija –q u komandnoj liniji
/*pretraga flegova -n, -q, -t u komandnoj liniji - videti slican zadatak - zadatak 51*/
/*ispis u zeljenom obliku,pri cemu deo petlje zaduzen inicijalizaciju je prazan jer je vazno pristupiti tekucoj nisci
*argv.
Uociti da argc se smanjuje u svakoj iteraciji */ */
for(; argc>0; argc--, argv++)
printf("%s%s%s", start? "\"" : "" , *argv, ispisFormat );
printf("\n");
return 0;
}
U datoteci rec.txt čuva se sadržaj reči koju pogađa korisnik. Pretpostaviti da reč se sastoji isključivo od malih slova
(do 20 karaktera). NCP koji od strane korisnika učitava jedno po jedno slovo koje unosi korisnik pogađajući reč. Pri
učitavanju svakog slova, program treba da ispiše ona slova u reči koja su do tada pogođena. Na mestima nepogođenih
slova treba da stoje zvezdice (*). Predvideti da korisnik može da unese nešto što nije slovo u kom slučaju program i
ne mora da mu ispiše trenutni status pogođenih slova (jer se ništa nije promenilo). Predvideti i mogućnost da se
korisniku uvaži unos velikog slova, tj. tretirati ga kao odgovarajuće malo slovo. Ispisati broj pokušaja nakon
pogađanja reči. Jednostavnosti radi, pretpostaviti da izvršna verzija programa se nalazi u istom direktorijumu gde je i
ulazna datoteka rec.txt.
a
*****
e
*e***
O
*e**o
2
5
h
he**o
l
hello
Imali ste ukupno pokusaja: 7
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
main( )
{
FILE *f; /*pristup proizvoljnoj datoteci, pokazivac na strukturu FILE */
char rec[21]; /*rec koja se pogadja */
int duzina; /*duzina reci */
char slovo; /*tekuce slovo pri pogadjanju */
char *ispis; /*rec koja ce se ispisivati tokom pogadjanja stavljajuci * na mesta nepogodjenih slova*/
int pogodjeni; /*broj trenutno pogodjenih slova*/
int pokusaji; /*broj pokusaja; pretpostavka da je tip int dovoljan */
int i; /*brojac u petljama */
/*odredjivanje da li se slovo pojavljuje u reci: ako se pojavljuje i ukoliko ranije nije pogodjeno,onda ga ukljuciti
kao pogodjeno slovo u ispis i uvecati broj pogodjenih */
for (i=0; i< duzina; i++ )
if (rec[i]==slovo && ispis[i] =='*')
{ ispis[i]=slovo;
pogodjeni ++;
}
exit (EXIT_SUCCESS);
7. NCP koji će sabrati dva broja koji se zadaju kao dva parametra komandne linije
/*inicijalizacije */
nzbir= (n>m ? n : m) +1; /*nzbir=max(n,m)+1 */
if(argc !=3)
{ fprintf(stderr,"\nNekorektan broj argumenata komandne linije u pozivu programa\n");
exit(1);
}
/*sabiranje */
zbir=(char *)malloc(nzbir*sizeof(char) );
saberi( reverse(argv[1]) ,n, reverse(argv[2]),m,zbir,&nzbir);
printf("\n%s+%s= %s\n\n", reverse(argv[1]),reverse(argv[2]), reverse(zbir));
free(zbir);
return 0;
}
void saberi(char *a1, int n, char *a2, int m, char *s, int *ns)
{
int prenos; /*prenos u susedni razred cifara, a koji je nastao
pri sabiranju cifri oba broja tekuceg razreda */
int c; /*rezultat sabiranja tekuce cifre prvog broja i tekuce cifre drugog broja*/
int i; /*brojac u petlji */
prenos=0;
/*sabiranje velikih brojeva se odvija implementacijom algoritma naucenom u mladjim razredima osnovne skole */
/*Sabiraju se cifre oba broja iz tekuceg razreda, pocev od razreda jedinica ,ka razredima vece tezine. */
/*Vodi se racuna o eventualnom nastalom prenosu u sledeci razred cifara, /*
/*kao i da ako je neki od brojeva "kraci", postavljaju mu se zamisljene nule kao cifre tekuceg razreda .*/
/*Te zamisljene nule su vodece nule, i zato ne uticu na izmenu vrednosti broja */
if(prenos > 0) {
s[*ns]=znak(prenos);
*ns=*ns+1;
}
s[*ns]='\0'; /*zbog rada sa niskom cifara */
} //kraj potprograma
8. NCP koji će pomnožiti dva broja koji se zadaju kao dva parametra komandne linije
/*vaze napomene iz 5. zadatka */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define znak(cifra) ((cifra) +'0')
#define cifra(x) ((x)-'0')
void mnozi(char *a1, int n1, char *a2, int n2, char *p, int *np); /*a1 * a2 -> p*/
char* reverse( char s[] );
int main(int argc, char *argv[])
{
int n=strlen(argv[1]); /*br.cifra prvog "broja" */
int m=strlen(argv[2]); /*br.cifara drugog "broja" */
int nproizvod; /*br.cifara proizvoda */
char *proizvod; /*proizvod oba broja */
/*inicijalizacije */
nproizvod=n+m;
if(argc !=3)
{ fprintf(stderr,"\nNekorektan broj argumenata komandne linije u pozivu programa\n");
exit(1);
}
/*mnozenje */
proizvod=(char *)malloc(nproizvod*sizeof(char)) ;
mnozi(reverse(argv[1]),n,reverse(argv[2]),m,proizvod,&nproizvod);
printf("\n%s\n*\n%s=\n%s\n", reverse(argv[1]),reverse(argv[2]), reverse(proizvod));
free(proizvod);
return 0;
}
void mnozi(char *a1, int n1, char *a2, int n2, char *p, int *np)
{
int prenos; /*prenos u susedni razred i+j+1;voditi racuna kada j==n2*/
int c; /*rezultat sabiranja proizvoda cifara koje ucestvuju u forimranju (i+j).te cifre rezultata */
int i, j; /*brojaci u petljama */
/*inicijalizacije */
for(j=0; j<*np; ++j)
p[j]=znak(0);
p[j]='\0';
/*mnozenje: (i+j).-ta cifra rezultata je jednaka sumi a1[i]*a2[j] */
for(i=0; i<n1; ++i) {
prenos=0; /*resetovanje prenosa pre formiranja (i+j)-te cifre rezultata */
for(j=0; j<n2; ++j) {
c= cifra(a1[i]) * cifra(a2[j]) + cifra(p[i+j]) + prenos;
p[i+j]= znak(c%10);
prenos= c/10;
} //unutrasnji for
p[i+n2]= znak(prenos);
} //spoljasnji for