Konwersja pomiędzy typami w C++
Konwersja pomiędzy typami w C++ to coś, co początkującym programistom spędza sen z powiek. Nawet programistom, którzy posiadają już pewien staż zdarza się czasem zapomnieć, jak to się robiło np. przejście z inta na stringa. Stąd inspiracja do napisania tego artykułu - żeby zebrać wszystko w jednym miejscu. Na wstępie konieczne są drobne wyjaśnienia użytych oznaczeń:
C string - string w stylu C
std::string - string w stylu C++
całkowite - int, short, long (w przykładach zawsze int)
zmiennoprzecinkowe - float, double (w przykładach zawsze float)
liczby - zarówno stało- jak i zmiennoprzecinkowe (w przykładach zawsze int) Ok, zaczynamy!
char -> (jednocyfrowe) całkowite
#include <iostream>
int main() {
char ch='3';
int i=ch-'0';
std::cout << i;
return 0;
}
Jest to tzw. metoda odejmowania wartości zera (chodzi o wartość ASCII liczby zero). Taki sam wynik można uzyskać odejmując 48 zamiast '0'.
(jednocyfrowe) całkowite -> char
#include <iostream>
int main() {
int i=3;
char ch=i+'0';
std::cout << ch;
return 0;
}
Metoda odwrotna - dodawania wartości zera. Taki sam wynik można uzyskać dodając 48 zamiast '0'.
(jednoznakowy) C string -> char
#include <iostream>
int main () {
char Cstr[2]="s";
char ch = Cstr[0];
std::cout << ch;
return 0;
}
char -> (jednoznakowy) C string
#include <iostream>
int main () {
char Cstr[2]="";
char ch = 's';
Cstr[0] = ch;
std::cout << Cstr;
return 0;
}
Wyzerowanie Cstr jest ważne - w przeciwnym wypadku otrzymasz losowe znaki przechowywane akurat w tym miejscu pamięci.
(jednoznakowy) std::string -> char
#include <iostream>
int main () {
std::string str("s");
char ch = str[0];
std::cout << ch;
return 0;
}
char -> (jednoznakowy) std::string
#include <iostream>
int main () {
char ch = 's';
std::string str(1, ch);
std::cout << str;
return 0;
}
Użyty tu został jeden z konstruktorów klasy string, w którym pierwszy parametr oznacza liczbę powtórzeń danego znaku.
C string -> std::string
#include <iostream>
#include <string>
using namespace std;
int main() {
char Cstr[10]="witaj";
string str(Cstr);
cout << str;
return 0;
}
Przy jednorazowym użyciu można też pominąć deklarację i od razu napisać:
cout << string(Cstr);
std::string -> C string
#include <iostream>
#include <string>
using namespace std;
int main() {
string str("witaj");
cout << str.c_str();
return 0;
}
C string -> całkowite
#include <iostream>
int main() {
char Cstr[10]="15";
int liczba;
liczba = strtol(Cstr, NULL, 10);
std::cout << liczba;
return 0;
}
Jak widać kluczową rolę ma funkcja strtol (string to long). Jako pierwszy parametr funkcji podajemy C string, a jako trzeci system liczbowy (od 2 do 32) w jakim zapisana jest liczba w stringu. Drugi parametr jest niepotrzebny - funkcja działa zupełnie normalnie, kiedy podamy tam NULL. Podobne funkcje: strtoul (string to unsigned long), oraz atoi:
liczba = atoi(Cstr);
Ta funkcja przyjmuje tylko jeden parametr - C string. Uwaga, atoi zwraca int, a nie jak strtol long, więc użycie jej do zbyt dużej liczby zaowocuje jej "przekręceniem". Identyczną funkcją, ale zwracającą long jest atol. Warto wiedzieć, że ze względu na lepszą obsługę błędów zawsze poleca się stosowanie strtol zamiast atoi.
całkowite -> C string
#include <iostream>
int main () {
char Cstr[20];
int liczba = 467;
sprintf(Cstr, "%i", liczba);
std::cout << Cstr;
return 0;
}
Parametr "%i" oznacza, że mamy do czynienia z liczbą całkowitą (jeżeli jest to liczba bez znaku,
powinniśmy użyć "%u"). Istnieje również prostsza funkcja - itoa, jednak nie należy ona do ANSI C (nie jest dostępna w każdym kompilatorze), dlatego nie zalecam jej stosowania.
C string -> zmiennoprzecinkowe
#include <iostream>
int main() {
char Cstr[10]="15.2";
float liczba;
liczba = strtod(Cstr, NULL);
std::cout << liczba;
return 0;
}
Teraz używamy funkcji strtod (string to double), która działa zupełnie jak strtol, za wyjątkiem tego, że nie przyjmuje trzeciego parametru - systemu liczbowego. Możemy też skorzystać z:
liczba = atof(Cstr);
Tym razem nazwa jest podstępna, ponieważ ta funkcja również konwertuje do double, a nie tak jak możnaby pomyśleć - do float. Warto wiedzieć, że i w tym wypadku poleca się stosowanie strtod. Uwaga, język C++
wywodzi się z Ameryki i jako taki do reprezentacji liczb zmiennoprzecinkowych używa kropki (a nie tak jak zwyczajowo robimy w Polsce - za pomocą przecinka), dlatego nie bądźcie zaskoczeni jak konwersja "15,2"
da wam 15.
zmiennoprzecinkowe -> C string
#include <iostream>
int main () {
char Cstr[20];
float liczba = 2942.249;
gcvt(liczba, 7, Cstr);
std::cout << Cstr;
return 0;
}
Parametr o wartości 7 oznacza ile cyfr ma przedstawiać liczba w formie C stringa. Dla przykładu, gdy podamy 3 uzyskamy 1.37e+03, a jak 6 to 2942.25. W podanym w źródle przykładzie otrzymamy dokładnie taką liczbę, jaka jest wpisana do float'a. Można też użyć sposobu analogicznego do konwersji liczby
całkowitej:
sprintf(Cstr, "%f", liczba);
Gdzie "%f", to parametr określający, że mamy do czynienia z liczbą zmiennoprzecinkową.
liczba -> std::string
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main() {
int i=123;
stringstream ss;
string str;
ss << i;
ss >> str;
cout << str;
return 0;
}
Użyliśmy tutaj typu stringstream. Wygodnie jest sobie zrobić następującą funkcję:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
string int2str(int i) {
stringstream ss;
string temp;
ss << i;
ss >> temp;
return temp;
}
int main() {
int i=123;
cout << int2str(i);
return 0;
}
std::string -> liczby
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int str2int(string str) {
stringstream ss;
int temp;
ss << str;
ss >> temp;
return temp;
}
int main() {
string str("123");
std::cout << str2int(str);
return 0;
}
Inna metoda może wyglądać tak:
#include <iostream>
#include <string>
int main() {
std::string str("123");
int liczba;
liczba = strtol(str.c_str(), NULL, 10);
std::cout << liczba;
return 0;
}
Jak widać jest to kombinacja zmiany std::string na C string, ze zmianą C string na liczbę całkowitą (po użyciu strtod zadziała dla zmiennoprzecinkowych). Kod jest prostszy, jednak zamiast jednej konwersji mamy dwie.
Niniejszy artykuł jest dostępny na licencji Creative Commons Uznanie autorstwa - Użycie niekomercyjne 3.0 Polska. Zrzekam się wszelkich praw do źródeł programów.