Mala škola C-a
Milan GOLUBOVIĆ milang@iname.com



Argumenti komandne linije i pristup datoteci

Lijepo je kada programi rade u GUI okruženju, ali je nekada korisnije kada se pozivaju i kada im se argumenti zadaju iz komandne linije DOS-a: CLI-ja. Da vidimo kako se to radi.

Pošto po startanju programa izvršavanje počinje od funkcije main, a pošto je ona funkcija kao i svaka druga potrebno je definirati koje će parametre primiti od DOS-a. Dakle, vi u main-u kao parametre dobijate jedan podatak int tipa koji se može zvati kako hoćete, ali je ustaljen naziv za njega "argc" (argument counter). On pokazuje s koliko argumenata je pozvan vaš program. Recimo da želite napisati program koji jednostavno ispisuje argumente s kojima je pozvan. Tako nešto radi DOS komanda "echo", ali ćemo, da bi bilo jasnije, ispisati i ime pod kojim je program pozvan. Na primjer, ako se program zove "argumenti" i ako smo ga pozvali iz DOS-a sa:

argumenti prvi drugi treći

argc će sada biti 4, što znaci da se pored argumenata računa i samo ime programa. Pretpostavljam da znate da se argumenti od imena programa, kao i jedni od druge odvajaju samo razmakom, a ne recimo zarezom i sl. argc znači može biti najmanje 1. Specijalno, kod Amige, ako je program startan iz Workbencha (preko ikone) argc je 0.

Drugi parametar koji main prima je sam niz stringova (pointera na nizove tipa char sa \0 na kraju) s imenom programa, a zatim sa argumentima. On se, po konvenciji, zove argv. Za isti primer niz argv[] bi sadržavao stringove:

"argumenti" , "prvi", "drugi", "treći" , ""

argv[0] će biti pointer na ime pod kojim je vaš program startan ("argumenti"), dok će zadnji string imati indeks argc-1 (argv[4-1]). argv[argc] je uvijek 0 (NULL). Da vidimo na primjeru kako bi to izgledalo.

#include <stdio.h>
main (int argc, char *argv[])
{
     int i;
     printf("Ispisano je %d riječi i to su:\n",argc); // Koliko je argc?
     for (i=0;i<argc;i++) // Treba ispisati sve članove niza
     {
          printf("%s",argv[i]); // Ispiši trenutni string
          if(i<argc-1) // Ako nije zadnji
               printf(" "); // Odvoji ga od slijedećeg razmakom
          else // A ako jeste
               printf("\n"); // Prijeđi u novi red
     }
}

Mislim da je program sasvim jasan. Ispiše se prvo argc, a zatim redom svi članovi niza argv[].


Da vidimo sada kako se pristupa datoteci. Naravno u AmigaDOS-u postoji više funkcija za pristupanje fajlovima, ali mi ćemo obraditi C funkciju za otvaranje datoteke fopen uz pomoć koje "otvaramo" fajl i getc i putc kojima ćemo učitavati i snimati bajt po bajt. Cijeli "mehanizam" (definicije) za ovakav način pristupanja fajlu nalazi se u stdio.h biblioteci, pa kako je obično uvijek koristimo, izvršni fajlovi naših programa neće biti znatno duži. Tu se nalazi i definicija tipa FILE. Funkcija fopen je tipa FILE, ali da vas ovaj novi tip ne bi dodatno zbunjivao ovdje će biti objašnjen samo postupak njegovog korištenja. To što on ustvari predstavlja uopće nije ni bitno. Funkciji fopen je potrebno proslijediti dva argumenta: pointer na ime fajla koji otvaramo i pointer na string koji određuje što ćemo raditi s fajlom. Ako string ima vrijednost "r" iz fajla ćemo čitati, ako je "w" u fajl ćemo pisati, a ako je "a" fajlu cemo dodavati podatke.

Funkcjia fopen vraća vrijednost tipa FILE* koja se kasnije proslijeđuje getc i putc funkcijama pri čitanju i pisanju.

Sve otvorene fajlove potrebno je prije izlaska iz programa zatvoriti funkcijom fclose.

Evo i primjera koji, usput, radi i nešto korisno - konvertira tekstove s pc-ja u Amigin format. Naime, kod pc-a se na kraju reda osim "linefeed" znaka (ima kod 10) nalazi i "cr" (kod 13), kojeg kod Amige nema. Da bi "izfiltrirali" tekst potrebno je jednostavno čitati bajt po bajt, provjeriti da li je 13 i ako nije snimiti ga. Jednostavno!

#include <stdio.h>
main (int argc, char *argv[]) // Ovo više ne treba objašnjavati.
{
     FILE *in; // 2 pointera na varijablu tipa FILE
     FILE *out; // Jer treba otvoriti 2 fajla
     char c; // Pomoćna varijabla za privremeni smještaj podataka
     if (argc!=3) // Da li je pogrešno pozvan program?
     {
          printf("Usage: convert pcfile amigafile\n");
          return(0); // Ako jeste izađi iz programa.
     }
     in=fopen(argv[1],"r"); // Otvaramo fajl za čitanje - "r"
     if (in==NULL) // Jel' fajl pronadjem ?
     {
          printf("Can't open file %s.\n",argv[1]);
          return(1); // Ako nije, opet je greška posrijedi
     }
     out=fopen(argv[2],"w"); // otvori fajl za snimanje - "w"
     if(out==NULL) // Jel' to uspješno obavljeno?
     {
     fclose(in); // Ako nije potrebno je zatvoriti predhodno otvoreni,
     printf("Can't save file.\n"); // ispisati prigodnu poruku
     return(2); // i izaći iz programa
     }
     printf("Converting %s to %s.\n",argv[1],argv[2]); // Najzad je sve OK!!

     while ((c=getc(in))!=EOF) // Char-ovi se uzimaju dok se ne naiđe na EOF
     {
          if (c!=13) // Ako c nije 13 (CR)
               putc(c,out); // treba ga snimiti
     }
     fclose(in); // Sve što je otvoreno
     fclose(out); // mora se uvijek i zatvoriti.
     printf("Finished!\n"); // Gotovo (napokon)
}

Prvi argument koji se proslijeđuje fopen funkciji je, kao što rekosmo, ime fajla, a to upravo sadrži argv[1], a u slijedećem otvaranju argv[2].

Ovaj program uz vrlo male prepravke može raditi bilo šta. Probajte, recimo, da ga "natjerate" da šifrira fajl. Dovoljno je svaki bajt EOR-ovati sa slovima neke šifre i uraditi još po nešto s njim, pa ga snimiti. Pazite samo da ta operecija bude obostrano jednoznačna, da bi se dešifriranjem dobilo ono što je šifrirano.

Možete konvertirati mala u velika slova i obratno, "loviti" i ispravljati neke riječi, napraviti obrnutu konverziju ( Amiga2PC ) i sve što vam pada na pamet.

Pored ovih funkcija postoje i funkcije read, write za neformatiran ulaz/izlaz, zatim fscanf i fprintf za formatiran ulaz/izlaz vrlo sličan običnim prinf i scanf, fseek i mnoge druge. Međutim, za sada će vam čitanje s FILE tipom biti dovoljno, a ako vam pritrebaju neke druge - sve one su dobro objašnjene u SAS C help-u.


Iz "tehničkih razloga" ovaj nastavak Male škole C-a je zaista mali. U planu je bilo obraditi pozive AmigaOS funkcija, ali to ćemo ostaviti za slijedeći put. No, ne očajavajte - ako vam je sve do sada napisano jasno onda posjedujete dovoljno znanja da pišete sasvim upotrebljive programe i to ne samo na Amigi, već na bilo kojoj platformi! Zato, bacite se na posao i programirajte!!!!