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++
- stałoprzecinkowe - 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 -> (jednoznakowe) stałoprzecinkowe
#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'.
(jednoznakowe) stałoprzecinkowe -> 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 -> stałoprzecinkowe
#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.
stałoprzecinkowe -> 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ą stałoprzecinkową (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 stałoprzecinkowej:
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ę stałoprzecinkową (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 - Na tych samych warunkach 2.5 Polska. Zrzekam się przy tym wszelkich praw do zamieszczonych tutaj źródeł programów.
<< PowrótKomentarze:
k_b | 13:56 | 18.12.2006
Super! Wszędzie szukałem konwersji int do string... a tu jest wszystko! Pewnie jeszcze nie raz tutaj zajrzę...
KrystianD | 20:22 | 27.07.2007
Stronka bardzo fajna :) w końcu wszystko zebrane w jednym miejscu :)
icywire | 21:50 | 26.03.2008
Super! Bardzo pomocne nawet dla studentów informatyki ;)
sadi | 21:19 | 03.04.2008
Dzięki za komentarze :) Dodam, że sam też tu wpadam, jak coś piszę ;)
Olek | 16:32 | 24.04.2008
Mam taki kod:
#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
#include <conio.h>
int main ()
{
char a;
char b;
char c;
int liczba1;
int liczba2;
char pobrane[2];
pobrane[0]=\"5\";
pobrane[1]=\"7\"
a=pobrane[0];
b=pobrane[1];
liczba1=strtol(a, NULL, 10);
liczba2=strtol(b, NULL, 10);
cout<<a<<\" \"<<b<<\" \"<<c<<endl;
getch();
}
I Dev-C++ zwraca mi błąd \"invalid conversion from char to const char*\"...
Co z tym zrobić? Oryginalny probram pobiera te dwie liczby z pliku i zapisuje je w tablicy pobrane. Pobrane musi być char, bo pobieram też z pliku znak jakiegoś działania.
L.U | 23:10 | 14.05.2008
zeczywiscie bardzo przydatna stronka i bardzo poszukiwana.
sadi | 14:16 | 05.06.2008
Olek, ten sposób nie zadziałał, bo użyłeś sposobu na string w stylu C, podczas, gdy z tego co widzę interesują cię pojedyncze znaki, czyli chary. Użyj metody konwersji char -> (jednoznakowe) stałoprzecinkowe (odejmowanie wartości zera) i będzie działać.
falladil | 12:34 | 28.08.2008
Mam małe zastrzerzenie co do konwersli liczba->std::string. Jeśli wpiszemy liczbę o dużej ilości zer to zamiast ładnej konwersji otrzymamy jakieś dziwne \"e\" wklejone między cyferki.
Rafalx | 00:30 | 26.09.2008
swietna i pomocna strona
falladil - poczytaj troche zanim zaczniesz o czyms mowic zle
lukas | 15:11 | 12.10.2008
super strona :D nie raz tu zajrze
ush | 19:08 | 16.10.2008
super, autor stronki to równy gość XD
sadi | 00:04 | 05.11.2008
ush, założę się, że teraz co druga osoba pomyśli, że sam piszę połowę komentarzy ;)
dawido | 21:59 | 18.03.2009
a jak zrobić konwersję unsigned int -> AnsiString??
sadi | 12:06 | 02.04.2009
dawido: Nie bardzo wiem co masz na myśli pisząc \"AnsiString\". Brzmi, jak jakaś niestandardowa klasa z Borlanda, czy Visuala. W takim wypadku pozostaje ci grzebanie w dokumentacji.
Marek | 17:22 | 14.04.2009
Super, jeszcze tylko zamiana QString z QT4
QString jakis_str;
int jakas_liczba;
jakis_str.setNum(jakas_liczba);
A jak w druga stronę, żeby QString zamienić na liczbę?
Gell | 21:28 | 03.11.2009
Wyrąbane nawet dokumentacja mi nie pomogła jak to!
omer | 19:09 | 23.11.2009
mega dobra strona !
jak najwiecej takich opracowań
Wszystkie przedstawione tutaj opinie należą do ich autorów i twórca strony nie ponosi żadnej odpowiedzialności za ich treść.
W polu "Strona WWW" wpisywanie członu "http://" nie jest konieczne. Tagi (X)HTML wpisane w treści nie będą działać jako element strony, zamiast tego pojawią się w samym komentarzu. Komentarze obraźliwe, nie na temat lub niezgodne z prawem będą w miarę możliwości usuwane.