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