Staonův svět - Nahrazení podřetězce jiným řetězcem

Pro inspiraci uvádím své řešení domácího úkolu na C/C++.

Zadání bylo jednoduché. Napsat funkci, která nalezne v řetězci jiný podřetězec a tento nahradí třetím řetzěcem. Podle zadání se nesměl používat žádný buffer navíc, žádná knihovní funkce a úprava se měla udělat rovnou ve vstupním řetězci s předpokladem, že obsahuje dostatečně paměti (bez kontroly přetečení).

  1. /* -- nalezne v retezci dany podretezec.
  2.    Parametry:
  3.       str ............... prohledavany retezec
  4.       substring ... hledany vzorek
  5.       first ....... zde vraci ukazatel na prvni znak nalezeneho
  6.                     podretezce
  7.       last ........ zde vraci ukazatel za posledni znak nalezeneho
  8.                     podretezce
  9.    Vraci:
  10.       0 ........... podretezec nenalezen
  11.       1 ........... podretezec nalezen
  12. */
  13. int str_find(char * str, char * substring, char ** first, char ** last) {
  14.   char *s1, *s2;
  15.  
  16.   /* -- projedu si cely retezec a pro kazdou pozici si zkusim,
  17.         zda jsem retezec nasel */
  18.   while(* str) {
  19.     /* -- nastavim si pomocne ukazatele */
  20.     s1 = str; s2 = substring;
  21.     /* -- srovnavam se vzorkem, tak dlouho, dokud odpovida */
  22.     while(* s1 && * s2 && * s1 == * s2) {
  23.       ++ s1; ++ s2;
  24.     }
  25.     /* -- pokud jsem dosel na konec vzorku, nalezl jsem */
  26.     if(! * s2) {
  27.       * first = str;
  28.       * last = s1;
  29.       return 1;
  30.     }
  31.  
  32.     /* -- vzorek neodpovida teto pozici, posunu se dal */
  33.     ++ str;
  34.   }
  35.   return 0;
  36. }
  37.  
  38. /* -- spocita delku zadane retezce.
  39.    Parametry:
  40.       str ......... retezec
  41.    Vraci: pocet znaku retezce
  42. */
  43. int str_len(const char * str) {
  44.   int delka = 0;
  45.  
  46.   while(* str ++) ++ delka;
  47.   return delka;
  48. }
  49.  
  50. /* -- nalezne v retezci str podretezec substr. Pokud ho nalezne,
  51.       nahradi ho retezcem replacement */
  52. char * str_replace(char * str, char * substr, char * replacement) {
  53.   char * first, * last;    /* -- ukazatele na zacatek a konec
  54.                                  nalezeneho podretezce */
  55.   char * s1, *s2;          /* -- sesypani */
  56.   int repl_len;            /* -- delka nahrazeni */
  57.   int delta;
  58.  
  59.   /* -- naleznu prvni vyskyt podretezce s2. Pokud nenaleznu, koncim */
  60.   if(! str_find(str, substr, & first, & last)) return str;
  61.  
  62.   /* -- zjistim si delku nahrady */
  63.   repl_len = str_len(replacement);
  64.  
  65.   if(repl_len < last - first) {
  66.     /* -- pokud je nahrada kratsi nez substr, sesypu dolu */
  67.     s1 = first + repl_len;
  68.     s2 = last;
  69.     while(* s1 ++ = * s2 ++);
  70.   }
  71.   else if(repl_len > last - first) {
  72.     /* -- pokud je nahrada delsi nez substr, sesypu nahoru */
  73.  
  74.     /* -- najdu konec */
  75.     s1 = last; while(* s1) ++ s1;
  76.  
  77.     /* -- budu od konce presypat */
  78.     delta = repl_len - (last - first);
  79.     while(s1 >= last) {
  80.       * (s1 + delta) = * s1;
  81.       -- s1;
  82.     }
  83.   }
  84.  
  85.   /* -- prekopiruji nahradu na misto substr */
  86.   while(* replacement) * first ++ = * replacement ++;
  87.  
  88.   return str;
  89. }

Tak, to by bylo vše. Myslím, že komentáře jsou dost výstižné, takže další řeči už k tomu dodávat nebudu.

Staon | 5.4.2006 St 18:22 | <<< trvalý odkaz >>> | tisk | 2 komentáře

Komentáře k textu

Rss komentářů tohoto textu

[1] reaguj
Jimi mejl web 5.4.2006 St 19:05

Prisiel som, videl som, nechapem, odchadzam :D Len ma zaujala taka vec… pri smernikoch sa neda pouzivat klasicke ++ ale musi to byt naopak (++ s1 a podobne) alebo to ma nejaky hlbsi zmysel?

[2] reaguj
Staon mejl web 6.4.2006 Čt 00:44

[1] Jimi : operátor ++ existuje v C/C++ ve dvou variantách:

  • prefixové – v tomto případě se vezme aktuální hodnota, zvětší se o jedna (ukazatel se posune na další prvek) a tato nová hodnota se vezme jako hodnota výrazu,
  • postfixové – zde se vezme aktuální hodnota, ta se vrátí jako hodnota výrazu a následně se jako vedlejší efekt hodnota o 1 zvýší.

Když se koukneš, tak v kódu mám použité obě možnosti, podle toho, jak se mi to hodí. A na místech, kde je jedno, jestli se zvětší o jedna předem nebo potom, já osobně radši používám prefixovou verzi. Ale spousta lidí zase dává přednost postfixové :)

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.
Matfyz je sbírka čeho?
Odpověd: naprostých cvoků malých červených kulatých kostiček

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