Staonův svět - Zápočty z C/C++ - pár hintů

Pořád čtu, jak zápasíte s Cčkem (dobře já vím, měl jsem kliku :) ), přidal jsem vám sem pár drobností, které snad trochu pomohou.

Protože se občas vyskytuje zákaz prvků C++, tak všechny následující kousky kódů jsou v Cčku. Napsal jsem to jen tak hodně narychlo, takže to rozhodně není žádná ukázka jak správně programovat.

V písemkách se často objevuje nějaké zpracování vstupních textových souborů. Velmi často se vyskytuje případ, že nějaká řádka či něco jiného nemá omezenou velikost. Přitom ošetřit tuto eventualitu je práce na pár řádek. Chce si to jen udělat inteligentní funkci, která dynamicky alokuje buffer dle nutnosti. Např. takhle:

  1. #define BUFFER_SIZE 16
  2.  
  3. char * my_fgets(FILE * fi) {
  4.   char * buffer, * nbuff;
  5.   int len, fr;
  6.   int znak;
  7.  
  8.   /* -- prvni buffer */
  9.   buffer = (char *) malloc(sizeof(char) * BUFFER_SIZE);
  10.   len = 0; fr = BUFFER_SIZE - 1;
  11.   buffer[0] = 0;
  12.  
  13.   while(1) {
  14.     znak = fgetc(fi);
  15.     if(znak == '\n' || znak == EOF) break;
  16.     if(fr <= 1) {
  17.       /* -- naalokuji novy buffer */
  18.       nbuff = (char *) malloc(sizeof(char) * (len + 1 + BUFFER_SIZE));
  19.       strcpy(nbuff, buffer);
  20.       fr = BUFFER_SIZE;
  21.       free(buffer);
  22.       buffer = nbuff;
  23.     }
  24.  
  25.     buffer[len++] = znak;
  26.     buffer[len] = 0;
  27.     -- fr;
  28.   }
  29.  
  30.   return buffer;
  31. }

Určitě byste to dokázali ještě elegantněji, ale o to v zápočtu Cčka nejde, že? Funkce si naalokuje nějaký buffer a v případě, že z něj vyteče, tak si naalokuje větší a do něho překopíruje původní již načtený text.

Další funkce, která se pravděpodobně může hodit, je kopie řetězce.

  1. char * strndup(const char * string, int len) {
  2.   char * buff;
  3.  
  4.   if(len < 0) len = strlen(string);
  5.   buff = (char *) malloc(sizeof(char) * (len + 1));
  6.   strncpy(buff, string, len);
  7.   buff[len] = 0;
  8.   return buff;
  9. }

Pokud se jí jako len zadá něco menšího než nula, očekává NULL-terminated string, který zkkopíruje celý. V opačném případě zkopíruje jen zadaný počet znaků. Řetězec na výstupu je vždy ukončen nulou.

Možnost zadat počet znaků se může hodit např. pro pársování vstupních řádek, kde jsou položky oddělené nějakým oddělovačem:

  1. char * last, * next;
  2. char * part;
  3.  
  4. next = last;
  5. while(* next != ':' && * next != 0) ++ next;
  6. part = strndup(last, next - last);

Při parsování mám ukazatel na první znak za posledním oddělovačem, druhým ukazatelem si najdu další oddělovač a pak pomocí strndup si vyseknu tu jednu položku.

Většina úloh byla nějakým způsobem na to, si udělat nějaké spojové seznamy s texty. Ukázku, jak vyhledat text ve spojovém seznamu máte zde:

  1. struct _ONode {
  2.   char * text;
  3.   struct _ONode * next;
  4. };
  5. typedef struct _ONode ONode;
  6.  
  7. ONode * find_node(ONode * list, const char * text) {
  8.   while(list) {
  9.     if(strcmp(text, list -> text) == 0) break;
  10.     list = list -> next;
  11.   }
  12.   return list;
  13. }

Prostě jdu položku po položce a jednoduše pomocí strcmp porovnávám. Nic složitého.

Další evergreen je práce se soubory. Na tom opravdu není nic složitého:

  1. FILE * fi;
  2.  
  3. fi = fopen("vstup.txt", "r");
  4. if(! fi) {
  5.   printf("Chyba!!\n");
  6.   return;
  7. }

A pak už dál volám funkce s otevřeným souborem fi, např. my_fgets(fi); Tohle funguje i ve VisualC, nejen na UNIXech. Jediné, na čem byste mohli trochu zatuhnout je znalost, co VisualC považuje za domovský adresář, pokud nezadám absolutní cestu. Tak je to přesně to, co jste při vytváření projektu zadali jako, tuším, Solution path.

Pokud máte program, který může zpracovávát vstupní soubor, nebo standardní vstup, je dobré si udělat „výkonnou“ funkci, které se předá parametr FILE. Tuhle funkci pak podle parametrů z příkazové řádky pak voláte buď s handlem otevřeným pomocí fopen, nebo jí prostě předáte stdin či stdout.

Zkuste si tyhle drobnosti nějak zažít, protože pak by vám zápočtová písemka měla jít podstatně snáz. Dnešní zápočtový test opravdu byl jen o tom udělat si spojový seznam vrcholů, kde každý vrchol obsahuje spojový seznam hran, a potom to projít a najít hrany do doplňku. Navíc fakt, že je to lexikograficky uspořádané, to dost zjednodušuje.

Staon | 9.6.2006 Pá 20:06 | <<< trvalý odkaz >>> | tisk | 1 komentář

Komentáře k textu

Rss komentářů tohoto textu

[1] reaguj
nAS mejl 10.6.2006 So 14:24

Diky moc, tohle se bude hodit…

Přidej komentář!

  Gravatar povolen.

Příspěvěk je formátován Texy! syntaxí. Není povoleno HTML, odkazy se převádějí automaticky.
Kolik je 3 x 5?
Odpověd: nevím, ale násobení na reálných číslech tvoří komutativní grupu. 237

Autor vzhledu: Staon. Stránky jsou postaveny na redakčním systému RS2 (verze RC2).