• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

[C++] Kontenery

Object Storage Arubacloud
+1 głos
592 wizyt
pytanie zadane 8 stycznia 2016 w C i C++ przez Qhoros Mądrala (7,110 p.)

Hej, ciekawi mnie czy jest jakiś "zgrabny" sposób na zmianę typu, na którym operujemy. Wrzucam przykład prymitywnego kodu:

 

#include <cstdio>
#include <vector>
int main()
{
	std::vector < int > dane;
	dane.push_back(5);
	dane.push_back(2);
	dane.push_back(3);
	dane.push_back(1);

	for (size_t i = 0; i < dane.size(); i++)
		printf("%d, ", dane[i]);

	std::vector < double > vect;
	vect.push_back(5);
	vect.push_back(2);
	vect.push_back(3);
	vect.push_back(1);

	for (size_t i = 0; i < vect.size(); i++)
		printf("%d, ", dane[i]);

	system("pause");
	return 0;
}

Rzecz w tym, by nie dublować wywołań dla kontenerów dane i vect, a po prostu móc się pomiędzy nimi swobodnie przełączać i na konkretnym kontenerze operować.

6 odpowiedzi

+1 głos
odpowiedź 9 stycznia 2016 przez Patrycjerz Mędrzec (192,320 p.)
A nie możesz użyć szablonów funkcji?
komentarz 9 stycznia 2016 przez Qhoros Mądrala (7,110 p.)
Mogę, ale właśnie tego póki co chcę uniknąć. :) Jeżeli nie znajdę innej możliwości to zrobię szablon.
0 głosów
odpowiedź 8 stycznia 2016 przez kantekand Obywatel (1,180 p.)
edycja 8 stycznia 2016 przez kantekand
możesz użyć funkcji, która jako parametr przyjmie wektor (a dokładniej referencję lub wskaźnik)
komentarz 8 stycznia 2016 przez Qhoros Mądrala (7,110 p.)
Taka możliwość niestety mnie nie satysfakcjonuje.
0 głosów
odpowiedź 8 stycznia 2016 przez po ile ptysie Początkujący (470 p.)

Nie wiem czy do końca o to ci chodzi, ale można zrobić tak:

typedef int twoja_nazwa;

i teraz 

std::vector <twoja_nazwa> vect;

jeżeli chcesz double, to zamienisz tylko w typedefie inta na double'a, a nazwa pozostaje ta sama.

komentarz 9 stycznia 2016 przez Qhoros Mądrala (7,110 p.)
To zmieni mi tylko nazwę, chodzi o to by kontener zmieniał swój typ w locie. ;)
0 głosów
odpowiedź 8 stycznia 2016 przez Szykem2 Nałogowiec (29,510 p.)

Prawdopodobnie chodzi o coś takiego

#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::cin;


int main() {
	std::vector<int> intVec;
	for (int i = 0; i < 5; i++)
	{
		intVec.push_back(i);
	}
	std::vector<double> doubleVec(intVec.begin(), intVec.end());
	for (unsigned i = 0; i < doubleVec.size(); i++)
	{
		cout << doubleVec[i] << " ";
	}
}

 

komentarz 9 stycznia 2016 przez Qhoros Mądrala (7,110 p.)
Nie, nie o to. Chodzi o to by móc swobodnie przełączać się w trakcie pracy programu pomiędzy kontenerami różnego typu. Późniejszą obsługę biorę już na siebie.
0 głosów
odpowiedź 8 stycznia 2016 przez adrian17 Ekspert (344,860 p.)
A z ciekawości... do czego konkretnie to potrzebujesz?
komentarz 9 stycznia 2016 przez Qhoros Mądrala (7,110 p.)
Ten przykład ma tylko obrazować sytuację. Nic więcej. ;)
komentarz 9 stycznia 2016 przez adrian17 Ekspert (344,860 p.)
edycja 9 stycznia 2016 przez adrian17

Wiem po co mi zmiana typu w locie,

Ale my nie wiemy.

To wygląda jak problem XY (http://xyproblem.info/). Masz jakiś problem, stwierdziłeś że najlepszym rozwiązaniem jest "zmiana typu w locie" (który nie jest możliwy w C++ie bez uciekania się do polimorfizmu lub, ugh, unii) i teraz pytasz jak to zrobić, podczas gdy może istnieć zupełnie inne i znacznie sensowniejsze rozwiązanie. Będziemy w stanie znacznie lepiej pomóc jeśli powiesz po co konkretnie jest Ci to potrzebne.

komentarz 9 stycznia 2016 przez Qhoros Mądrala (7,110 p.)
Niestety, ale zmiana typu w trakcie wykonywania się programu jest konieczna. Można tego nie robić dokładając 300 linii ekstra w moim przypadku. Póki co pobawię się dalej. :)
komentarz 9 stycznia 2016 przez adrian17 Ekspert (344,860 p.)
Uparty. Jak chcesz.
0 głosów
odpowiedź 9 stycznia 2016 przez Sebastian Fojcik Nałogowiec (43,020 p.)
edycja 9 stycznia 2016 przez Sebastian Fojcik

Liczby całkowite są zapisywane trochę inaczej niż rzeczywiste. W takim razie mając wektor liczb całkowitych zapisanych w pamięci binarnie w jakiś tam sposób, nie możesz tak po prostu zamienić je na typy double. Jest mechanizm rzutowania w C++ i to jest jedyna metoda, aby traktować int jak double i na odwrót.

Nie wiem jak wyobrażasz sobie posiadać wektor typu double z liczbami: 1.5, 2.25, 3.11 i potem zamienić to na wektor liczb typu int. Jedyne co możesz zrobić, to rzutować każdą wartość na int po kolei przy wyciąganiu jej z wektora. Wtedy liczby po przecinku zostaną ucięte.

Z kolei posiadanie wektora liczb int i późniejsze rzutowanie na double jest już raczej nieprzydatne, bo wektor zawsze będzie przechowywał liczby całkowite. Co Ci po wektorze double, w którym liczby zawsze będą całkowite?

Typ double nie powinien służyć jako zamiennik int, bo zapisuje liczby trochę inaczej. Niech za przykład posłuży mi taki kod:

int n = 0;
double d = 0;

cout << -n << endl;
cout << -d << endl;

Program wypisze dla -int wartość 0, a dla -double -0. Taki stan rzeczy wynika ze sposobu zapisu tych liczb w komputerze. SPOJ odrzuciłby wartość -0, ale na szczęście dla komputera -0 == 0. No chociaż tyle dobrego :-)

To był tylko taki przykład różnicy między int a double. A teraz wracam do Twojego pytania.

Jeśli znasz obiektowość, to jest coś takiego jak funkcje konwertujące. Działa to tak, że jeden obiekt Twojej klasy (np. taki wektor), może być traktowany w różnych sytuacjach jak inny typ. Może to jest właśnie tym, czego szukasz. Wystarczy poznać obiektowość :-)

Czytając jednak Twoje wypowiedzi domniemam, że jeszcze obiektowości nie znasz na tyle dobrze, aby to zrozumieć. W takim wypadku pozostaje Ci rzutowanie:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
	std::vector < double > dane;
	dane.push_back( 5 );
	dane.push_back( 2 );
	dane.push_back( 3 );
	dane.push_back( 1 );

	for( int i = 0; i < dane.size(); i++ )
		cout << (int)dane[ i ] << endl;

	return 0;
}

Powyższy program wypisuje wektor, ale z taką różnicą, że każdy element jest traktowany jak int. Nie wiem na co to komu, ale o to chyba pytałeś, prawda?

Pozdrawiam :-)

komentarz 9 stycznia 2016 przez Qhoros Mądrala (7,110 p.)
Obiektowość znam i nie chodzi mi o taki banał. Tak jak pisałem wielokrotnie powyższy przykład ma tylko służyć zobrazowaniu sytuacji. Nie będę wstawiał kodu, zawierający aktualnie 17 plików i tysiące linii kodu. Wiem po co mi zmiana typu w locie, więc nie musisz traktować mnie protekcjonalnie. Obsługę błędów przy różnych typach mam już napisaną, więc nie robi mi różnicy jaki typ odbierze kontener. Rzecz tylko w tym, by w locie się zmieniał. Ot co ;)

Konwersja na inny typ nie wchodzi tutaj w grę.
komentarz 9 stycznia 2016 przez Sebastian Fojcik Nałogowiec (43,020 p.)

Wektor zawierający 5 elementów typu int zajmuje mniej miejsca w pamięci niż taki sam wektor z typami double.

Jeśli chciałbyś taki wektor zamienić na inny typ, to nie ma wyjścia, trzeba stworzyć nowy wektor i wartość po wartości przenosić.

Poza tym u Ciebie w kodzie nazwa "dane" odnosi się do wektora typu < int >, a więc niemożliwym jest, aby później gdzieś w kodzie ta sama nazwa odnosiła się do wektora, ale już innego typu. Co jeśli ustawisz na taki wektor iterator? Iteratory też mają swój typ, więc jeśli zmieniłbyś dynamicznie typ wektora wraz ze wszystkimi elementami w środku, to wszystko by się posypało. Iterator przeskakiwałby o błędną ilość bitów, bo double jest "dłuższy" od int.

To co próbujesz osiągnąć jest niemożliwe do osiągnięcia w C++. Gdyby można było w trakcie działania programu takie rzeczy robić, to kod byłby bardzo niestabilny. Głównie z uwagi na wskaźniki, które po prostu już same by nie wiedziały na co pokazują :-D

komentarz 9 stycznia 2016 przez Qhoros Mądrala (7,110 p.)
Zrobić się da, tylko trzeba to wymyślić. :) Błędami się nie martwię, bo obsługa różnych typów jest napisana i teoretycznie (bo jeszcze nie była testowana w locie) będzie śmigać. No cóż. To ja lecę myśleć dalej. :)

Podobne pytania

0 głosów
1 odpowiedź 1,056 wizyt
pytanie zadane 3 września 2016 w C i C++ przez niezalogowany
0 głosów
1 odpowiedź 808 wizyt
pytanie zadane 10 grudnia 2016 w C i C++ przez Kasztan Dyskutant (8,080 p.)
0 głosów
1 odpowiedź 1,218 wizyt
pytanie zadane 16 czerwca 2017 w C i C++ przez excavelty Bywalec (2,480 p.)

92,567 zapytań

141,420 odpowiedzi

319,616 komentarzy

61,953 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...