std::string VS rekurencja

Hey o/

Dziś będzie o tym, jak to pewien człowiek zmagał się z funkcją rekurencyjną która zwraca stringa…
Ale do rzeczy. Ostatnio przypominając sobie rekurencję, na przykładzie funkcji która zamienia liczbę (przy założeniu że jest ona podana w systemie decymalnym) na jej binarny odpowiednik, wpadłem na pomysł… “A dlaczego by tak nie zwrócić stringa ?”.

No tak, tylko po co ? Po co taka funkcja miałaby zwracać obiekt klasy string, skoro można prościej, np intem.
Niby można, ale przecież warto się pobawić ;) Dodam, że oczywiście sam nie wpadłem na ten genialny pomysł, bo wpadł na niego Unavowed ;)

Ok, załóżmy że funkcja zwracająca int’a w tym przypadku mogłaby wyglądać mniej więcej tak:


int bin(int n)
{

int rest = n%2;
if(rest >= 1)
bin(n/2);
else
printf("%i",0);

return rest;
}


Ofc powyższy kod nie ma jakichkolwiek zabezpieczeń przed integer overflow’ami itp, oraz zakłada że przekażemy funkcji liczbę w mniemaniu decymalnej.

Super, a teraz warto się zastanowić jak ta funkcja mogłaby wyglądać gdybyśmy chcieli zwrócić std::string.

Pierwsze co rzuca się na myśl początkującym programistom to pewnie:


string bin(int n)
{
string rest;
if(n>=1)
bin(n/2);

return rest;
}

Nawet jeśli z logicznego pkt widzenia ten kod może się wydawać prawidłowy, to kompilator i tak zaprotestuje pod pretekstem:


bin.cpp: In function ‘std::string bin(int)’:
bin.cpp:15:19: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
/usr/include/c++/4.6/bits/basic_string.tcc:214:5: error: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits, _Alloc = std::allocator]’ [-fpermissive]

Kłania się semantyka C++, bo nie można sobie od tak do stringa wpisać int’a .
Pod systemami z rodziny Windows zapewne jest funkcja (nienatywna) typu itoa, ale nie opłaca się z niej korzystać (bo to chociażby nieładne :P), a jeśli nawet, to nie mam jej pod *unixami ;)
Nie ma lekko, trzeba coś wymyślić samemu.

Całe szczęście , w C++ są strumienie, a zwłaszcza strumienie stringów ;>
Całego tego nieszczęścia można uniknąć poprzez posłużenie się strumieniem stringów chociażby w taki sposób :


...
#include
...
string bin(int n)
{
osstream ss;

if(n>=1)
{
ss << bin(n/2);
ss << n%2;
}

return ss.str();
}

I po sprawie. Dzięki temu że do string streamu możemy zapisać zmienne niemal każdego typu, to potem możemy zawartość strumienia
przekonwertować do stringa, jednym prostym wywołaniem metody z klasy sstream


ss.str();

Mała rzecz, a może się przydać w wielu sytuacjach ;)

Leave a Reply


six − 5 =