#include #include #include struct niz { int d; /* dolzina niza */ char * n; /* niz */ }; /* funkcija odvrne 0, ce sta niza enako dolga, -1, ce je prvi krajsi od drugega in 1, ce je prvi daljsi od drugega */ int primerjaj_niza (const void * a, const void * b) { const struct niz * sna = (const struct niz *) a; /* Cjeva carovnija vlivanja */ const struct niz * snb = (const struct niz *) b; return (sna->d > snb->d) - (sna->d < snb->d); /* preprosto primerjanje dveh stevilk */ } struct niz * podprogram ( struct niz * n, /* seznam nizov */ int nizov, /* stevilo nizov */ struct niz * p /* prejsnji niz za rekurzijo */ ) { int i = 0; /* iteracijski decek */ int j = 0; /* iteracijski decek, ki je potopljen v 1. globino vgnezdene zanke */ int o = 0; /* oddaljenost prvega niza, ki ima vecjo dolzino */ int s = 0; /* ali smo ze en znak izpustili */ int a = 1; /* niz je aplikatibilen */ struct niz * od = p; /* kazalec na odgovor, nastavljen na prejsnji niz, ce nizi te velikosti niso vec aplikatibilni */ struct niz * op; /* kazalec na prihodnji morebitni odgovor, seveda zgolj, ce je daljsi */ int zadnja_runda = 0; /* samoumevno */ for (o = 0; n[o].d == n[0].d; o++) /* za vsak niz najkrajse dolzine */ if (o+1 >= nizov) { /* ce smo pri koncu seznama nizov */ zadnja_runda = 1; /* pri koncu seznama nizov smo, to si zabelezimo */ o++; /* ker se pri break tretji stavek for zanke ne izvede na koncu */ break; } for (i = 0; i < o; i++) { /* podobno kot prejsnja zanka, le da jnam je sedaj o znan */ s = 0; /* ponastavimo */ a = 1; /* ponastavimo */ for (j = 0; j < p->d; j++) { /* za vsak znak prejsnjega niza */ if (p->n[j] != n[i].n[j+s]) /* ce se nas niz za en znak vec ne ujema s prejsnjim */ s++; if (s > 1) { /* ce se je prejsen ce stavek ze zgodil, smo izpustili ze dva znaka, kar ni dovoljeno */ a = 0; /* ta niz ni aplikatibilen */ break; } } if (a && zadnja_runda) /* ce smo pri koncu in smo nasli aplikatibien niz - super, vrnemo ga skozi rekurzicno verigo, to je niz, ki ga iscemo (;:! */ return &n[i]; /* ja, spet bi lahko uporabil n+i ampak se mi tole zdi lepše */ if (a) { op = podprogram(n+o, nizov-o, &n[i]); /* poklicemo podprogram z mnozico nizov zgolj vecjih velikosti, kot ta velikost - zato potrebujemo o (: */ if (op != NULL && op->d > od->d) /* ce je odgovor boljsi od do sedaj znanega */ od = op; /* kazalec na starega prepisemo */ } } return od; } /* argv+1 je seznam nizov. * */ #if __INCLUDE_LEVEL__ == 0 int main (int argc, char ** argv) { if (argc < 1+1) { fprintf(stderr, "uporaba: %s splatters splatter platter latter later late ate at a (nenujno po velikosti)\n", argv[0]); return 1; } struct niz * n = malloc(sizeof(struct niz)*argc); /* prostor za nize */ size_t i = 0; /* iteracijski decek */ struct niz * o; /* odgovor */ struct niz p = { /* virtualen prejsnji niz, ki ga damo v rekurzicno funkcijo */ .d = 0, .n = "", }; /* zato, da ni treba delati dodatnega preizkusa, ce je funkcija podprogram pognana iz funkcije podprogram ali iz uporabnkove funkcije, recimo main */ for (i = 0; i < argc-1; i++) { /* pridobimo velikosti nizov */ n[i].d = strlen(argv[1+i]); /* predpomnimo dolzino niza */ n[i].n = argv[i+1]; /* zapisemo kazalec do konstantnega niza iz argv */ } /* sedaj pa nize razvrstimo po velikosti s funkcijo iz STANDARDNE KNJIZNICE qsort */ qsort(n, argc-1, sizeof(struct niz), primerjaj_niza); /* sedaj pa lahko zacnemo z nasim skriptom */ o = podprogram(n, argc-1, &p); fprintf(stdout, "%s\n", o->n); free(n); n = NULL; return 0; } #endif