FizWeb

Porkoláb Zoltán - C programozás 2017.12.04. előadás jegyzet

10. előadás: Egy unix utility (pl. grep) implementálása, flagekkel.

kérdés: scanf-ben hogyan lehet beírni a macro méretet:
sprintf: összeállítja a stringet, ezután aszerint olvasunk be

ZH-ban: UNIX utility implementációja

most: $ grep

usage: grep PATTERN [file1 file2]
//kiírja a sort, ahol megtalálta a patternt
(egrep: lehet regexet is -> most nem kérik)

$grep blabla file1 file2 //2-esért ennyi: több fájlban keres
$grep -i blabla file1 file2 //case insensitive összehasonlítás
$grep -i -v blabla file1 file2 //reverz: azokat a sorokat írja ki, ahol nem volt a pattern

-iv/-vi/-i -v/-v -i : //ötösért: tetszőleges sorrend

MOST: lépésről lépésre GREP

1. jó-e a main-beli ciklusom
argv[] első paramétere: fájl, második: pattern --> kötelező!
többi: flagek


#include 
#include 

void usage();

int main(int argc, char *argv[]) {
  if (1==argc) usage(); //kiírja h hogy kell használni
  return 0;
}

////

#include 
#include 

void usage();
void gr(FILE*, FILE*, char*);  //hátha később máshonnan is be szeretnék olvasni

int main(int argc, char *argv[]) {
  if (1==argc) usage(); //kiírja h hogy kell használni
  else if(2==argc) gr(stdin, stdout, argv[1]);
  return 0;
}

//////////

#include 
#include 

void usage(char*);
void gr(FILE*, FILE*, char*);  //hátha később nem csak az stdoutra szeretnék írni

int main(int argc, char *argv[]) {
  if (1==argc) usage(argv[0]); //kiírja h hogy kell használni
  else if(2==argc) gr(stdin, stdout, argv[1]);
  else{
    int i;
    for (i = 0; i < argc; ++i) {
      FILE *fp = fopen(argv[i], "r");
      if(fp){
        gr(fp, stdout, argv[1]);
        fclose(fp);
      }
      else perror("can't open file");  //sima fprintf-fel is lehetne
    }
  }
  return 0;
}

//ha flagek kellenek: változtatni kell az else részt: kell egy utility, ami ellenőrzi h megvannak-e a paraméterek, melyik mi

kellenek a függvények:

void usage(char *n){  //n a fájl neve --> usage(argv[0])
 fprintf(stderr, "usage: %s minta [files...]\n", n); //bármilyen hibaüzenet
 exit(1);
}

void gr(FILE *in, FILE *out, char *pattern){ //Tfh. 1024-nél nem lesz nagyobb sor: BUFSIZE macro
  char buffer[BUFSIZE];
  while (fgets(buffer, BUFSIZE, in)) {
    if(NULL != strstr(buffer, pattern)){ //kell a string.h; a pointer a találat elejére mutat, különben NULL
      fputs(buffer, out);
    }
  }
}


///////

megvan a kettes, elmentem külön:


#include 
#include 
#include 
#define BUFSIZE 1024

void usage(char*);
void gr(FILE*, FILE*, char*);  //hátha később nem csak az stdoutra szeretnék írni

int main(int argc, char *argv[]) {
  if (1==argc) usage(argv[0]); //kiírja h hogy kell használni
  else if(2==argc) gr(stdin, stdout, argv[1]);
  else{
    int i;
    for (i = 0; i < argc; ++i) {  // 0 ???
      FILE *fp = fopen(argv[i], "r");
      if(fp){
        gr(fp, stdout, argv[1]);
        fclose(fp);
      }
      else perror("can't open file");  //sima fprintf-fel is lehetne
    }
  }
  return 0;
}

void usage(char *n){  //n a fájl neve --> usage(argv[0])
 fprintf(stderr, "usage: %s minta [files...]\n", n); //bármilyen hibaüzenet
 exit(1);
}

void gr(FILE *in, FILE *out, char *pattern){ //Tfh. 1024-nél nem lesz nagyobb sor: BUFSIZE macro
  char buffer[BUFSIZE];
  while (fgets(buffer, BUFSIZE, in)) {
    if(NULL != strstr(buffer, pattern)){ //kell a string.h; a pointer a találat elejére mutat, különben NULL
      fputs(buffer, out);
    }
  }
}

//////////////////

jobb jegyért: a flagek beolvasása nehezebb feladat -> írjuk meg külön függvényként
akarunk csinálni egy térképet, hogy milyen paramétereket adtak meg:
struct: van-e param, ha van mi az


#include 
#include 
#include 
#define BUFSIZE 1024

typedef struct PARAM{ //PARAM elhagyható, szokás
  int iflag;
  int vflag;
  char *p;   //pattern
} param_t;  //erre sok helyen szükség lesz --> globális változóként

param_t params; //globális

int procargs(int argc,char *argv[]);  //ez a fv dolgozza fel az adatokat
//int: adja vissza azt az i-t, ahonnan a fájlnevek jönnek
//lehetne: -- paraméter (flag), ahonnan a fájlneveke következnek

int main(int argc, char *argv[]) {
  int i = procargs(argc, argv);
  /* code... */
  return 0;
}

int procargs(int argc, char *argv[i]){ //konvenció: ha mínusszal kezdődik, akkor flag
  int i = 1;
  while (i=argc) usage(argv);
  //params.p = (char*)malloc(strlen(argv[i]+1)); --> ehelyett elég az argv[i], az már a patternre mutat
  params.p = argv[i];
  ++i;
  return i;
}
// ezzel ha többszöt adja meg ugyanazt a flaget, akkor az 1-et felülírja 1-gyel

//Mi van. ha elfogynak a mínusz flagek??
//BAJ: ha nem létezik utána file1... paraméter: ellemőrizni kell h létezik-e argv[i]
i mindig ellenőrizni

//////////

#include 
#include 
#include 
#define BUFSIZE 1024

typedef struct PARAM{ //PARAM elhagyható, szokás
  int iflag;
  int vflag;
  char *p;   //pattern
} param_t;  //erre sok helyen szükség lesz --> globális változóként

param_t params; //globális

int procargs(int argc,char *argv[]);

int main(int argc, char *argv[]) {
  int i = procargs(argc, argv);
  if(i>=argc) gr(stdin, stdout);
  else{
    for ( ; i=argc) usage(argv);
  //params.p = (char*)malloc(strlen(argv[i]+1)); --> ehelyett elég az argv[i], az már a patternre mutat
  params.p = argv[i];
  ++i;
  return i;
}

//át kell írni a gr függvény is: lehet -i !!!

void gr(FILE *in, FILE *out){
  char buffer[BUFSIZE];
  while (fgets(buffer, BUFSIZE, in)) {
    if (params.iflag) {
      char upper[BUFSIZE];
      conv2upper(upper, buffer);
      /*...*/
    }
  }
}

//más ötlet, a paramfeldolgozásnál az egészet uppercase-zé alakíthatom

mégis kell új tárterület a *p-hez, mert az argv[i]-t nem írhatjuk át

int procargs(int argc, char *argv[i]){ //konvenció: ha mínusszal kezdődik, akkor flag
  int i = 1;
  while (i=argc) usage(argv);
  params.p = argv[i];
  ++i;
  if (params.iflag) {
    char *s = (char *)malloc(strlen(params.p)+1);
    conv2upper(s, params.p);
    params.p=s;
  }
  return i;
}

//befejezzük a gr fv-t

void gr(FILE *in, FILE *out){
  char buffer[BUFSIZE];
  while (fgets(buffer, BUFSIZE, in)) {
    int m = 0;
    if (params.iflag) {
      char upper[BUFSIZE];
      conv2upper(upper, buffer);
    }
    m = (strstr(params.iflag?upper: buffer, params.p) != NULL);     //???
    if(params.vflag){
      m=!m;                                                         //???
      if(m) fputs(buffer, out);   //nem a buffert írtam át, mert azt ki akarom írni
    }
  }
}

//kell még a conv2upper:

void conv2upper(char *t, char *s){
  char *p=s;
  while ("\0" != *p) {
    *t++ = toupper(*p++);  //a toupper benne van a  headerben
  }
}

//programozási nyelvek labor