Czy można stworzyć vector z różnymi typami danych?

0

Chciałem stworzyć vector który by zawierał

vector <int, string> abc;

a potem moc do niego wrzucac dane np:

push_back(2,"test");

Da się tak zrobić ?

4
vector<pair<int,string>>
1

eee, możesz użyć std::pair

1

Ewentualnie wektor zawierający struktury :P

1

Może też być kontener z krotką :) np vector<tuple<int, char, bool>>

#include <iostream>
#include <tuple>
#include <vector>
using namespace std;

int main() {
	vector<tuple<int, int, int>> vec = {
		{1, 2, 3},
		{4, 5, 6}
	};
	
	for(const auto tup : vec){
		int a, b, c;
		tie(a, b, c) = tup;
		cout << a << ", " << b << ", " << c << endl;
	}
	return 0;
}
0

Dziekuje za pomoc

6

A ja odradzam takie operacje. Te dane chcesz zgrupować razem bo mają razem jakiś sens z punktu widzenia dziedziny pisanej aplikacji. Zrób więc z tego klasę/strukturę i sensownej nazwie. Dużo wygodniej czyta sie kod w którym używasz klas o znaczeniu dziedzinowym! Bo na przykład vector<Person> wygląda dużo lepiej i czytelniej od vector<tuple<string, string, int, int>>. A jak już zaczynasz zagnieżdżać takie rzeczy to robi się z tego meksyk bo zamiast czytelnego map<Department, Workers> masz nagle map<tuple<string, string>, vector<tuple<string, string, int, int>>>. Pomyśl o tym ;)

2

@Shalom ma rację. Poza tym warto dodać, że std::tuple trzyma poszczególne typy bardzo nieefektywnie w pamięci. Tzn. w odwrotnej kolejności, niż ta z deklaracji (zamiast np. grupować elementy tego samego typu). Tutaj warto wspomnieć. że w trakcie rekurencyjnego dziedziczenia podczas definiowania std::tuple zachodzi tzw. empty base optimization, więc nie jest znowu aż tak traficznie z tym, ze to trochę inna para kaloszy ; p.
std::tuple są przeważnie używane (i tam mają sens) w MTP, poza nim raczej wielkiego z nich pożytku nie ma.

0
satirev napisał(a):

@Shalom ma rację. Poza tym warto dodać, że std::tuple trzyma poszczególne typy bardzo nieefektywnie w pamięci. Tzn. w odwrotnej kolejności, niż ta z deklaracji (zamiast np. grupować elementy tego samego typu). Tutaj warto wspomnieć. że w trakcie rekurencyjnego dziedziczenia podczas definiowania std::tuple zachodzi tzw. empty base optimization, więc nie jest znowu aż tak traficznie z tym, ze to trochę inna para kaloszy ; p.
std::tuple są przeważnie używane (i tam mają sens) w MTP, poza nim raczej wielkiego z nich pożytku nie ma.

Normalnie idzie, ale bez tych trupich stl.

Robisz tak:

struct TVList
{
  TVList(int intsiz, int int...); 

// dalej walisz te prymitywy, np.:
  int add(void *data, int len);
  int insert, ect.

  int limit, sizmem, *plist, *pdata, ... ect.
};

tak z 16 sekund roboty... i zapierdalasz z 1000 razy szybciej od stl, no i ze 100 razy miej ramu marnujesz...

1

Prawdopodobnie szukasz czegoś w rodzaju std::map, przykład:

#include <iostream>
#include <map>
using namespace std;
 
int main() {
	map<int, string> mymap = {
		{1, "ala"},
		{4, "ma"},
		{8, "kota"}
	};
 
  auto it = mymap.find(1);
  if (it != mymap.end())
	cout << "Znaleziona wartość: " << it->second << endl;
  else
	cout << "Wartosc nie znaleziona" << endl;
 
  return 0;
}

http://ideone.com/XpTfJ0

Czym się różni od std::vector? Szybkością znajdowania elementów wg int (std::map jest teoretycznie szybsze).

0

A jak zrobie zwykla strukture i wrzuce ja do vectora i bede sobie grupowal wpisy w tej strukturze to bedzie ok ?

1

Sam sobie odpowiedz - nikt nie wie co chcesz zrobic.

0

Mam structurę

struct sockaddr_in server;

Kiedy klient coś wysyła to ta struktura zawiera między innymi IP i PORT.
Jeśli po wysłaniu do servera ządania logowania i logowanie powiedzie się
funkcja generuje unikalny klucz session_key. Chcałbym teraz przypisać ten klucz sesji
, user ID, oraz czas zalogowania i strukture sockaddr_in do powiedzmy nowej struktury.

struct conectedUsers {
    int id; //usera
    string session_key;
    struct socket;
    //added
};

Czyli za każdym udanym zalogowaniem miałbym jakby w tej nowej strukturze
wszystkie dane potrzebne do obslugi usera.
Wyszukując po ID usera dane w stukturze mailbym adres polaczenia.
Tylko nie wiem czy dobrze myśle i jak dodawac dynamicznie kolejne
polaczenia albo jak usuwac te nieaktywne ?

Chyba że dałoby się to samo uzyskac za pomocą vectora ? ale nie wiem jak

0

Jak chcesz szukać userów po id to zrób mapę map<int, conectedUser> bo będzie wygodniej :) Do mapy możesz dynamicznie dodawać elementy, ale nieaktywne to musisz sobie sam wyszukiwać i usuwać.

0

A date dodania i klucz sesji moge dodac do structury ? a da sie jakos strukture zrobic i dodawac do niej dynamicznie kolejne pozycje ? bo co szukam przykladow to w nich zawsze deklaruja ile ma byc w strukturze elementow.

0

Nie no ale jaki to by miał sens? o_O Jak byś potem chciał z takiej struktury korzystać skoro nie wiesz jakie zawiera pola? Możesz pokazać jakis przykład tego co chcesz zrobić?

0

To jest moja struktura:

struct conectedUsers {
    string session_key;
    sockaddr_in socket;
    //added
};

int main() {

conectedUsers Tablica;

    //init
    struct sockaddr_in from;

    recvfrom( main_socket, rcv_message, sizeof( rcv_message ), 0,( struct sockaddr * ) & from, & len )

    Tablica.session_key = "983290849";
    Tablica.socket = from;

    //i teraz kod powinien byc taki:
    map(id_user, Tablica) 

I to co chciałbym zrobić to to że jak użytkownik dowolny wyśle coś do servera jego dane jak IP, PORT znajda sie w strukturze
struct sockaddr_in from;
Pod zmienna FROM. Teraz chce dodac do mojej struktury conectedUsers pole z kluczme sesji i data dodania tego klucza oraz
structure from o danych usera ktory wyslal cos na serwer. Czyli w mojej strukturze mam dane o uzytkowniku, logujac sie
uzytkownik wysyla swoj numer ID (login) i haslo. Wiec majac ten numer ID zapisalbym go do MAP<id_users,struktura).
Co za tym idzie byloby teraz MAP(1, Tablica)

Opcje jakie musze miec to mozliwosc wyszukac w MAP strukture po user ID.
Gazelle user istnieje to zaktualizowac klucz sesji a jak nie istnieje to dodac usera do MAP

Nie wiem jak dodać kolejnych uzytkownikow do TABLICA
A jak ich dodam jakos to jak usunac wybranego uzytkownika.

Jak patrzylemna przyklady to deklarowali w nich strukture np:
conectedUsers Tablica[4];
i potem

Tablica[1].id = 2
Tablica[2].id = 3 

it'd, ale ja nie chce okreslac maksimum. Da sie to jakos rozwiazac ?

1

Da się. A tym ID usera to jest jego nick? Ja bym w ogóle zrobił tak:

struct ConectedUser{
    string session_key;
    sockaddr_in socket;
};
//
map<string, ConectedUser> users;
//
string nick = ....
std::map<string,ConectedUser>::iterator it = users.find(nick);
if(it != map::end){
    ConectedUser userData  = it->second; //użytkownik istnieje, mamy jego strukturę
}else{
    //dodajemy użytkownika
    users[nick] = ConectedUser(cośtam, cośtam);
}

I tak przy okazji: sturktura opisuje JEDNEGO usera więć nie nazywaj jej "...users".

Zamiast tej mapy mozesz też mieć po prostu vector ale w mapie szybciej się szuka.

0

Nie do końca zrozumiałem ten opis, ale:

  1. Obiekt struktury trzyma dane dla jednego użytkownika, czyli ConnectedUser (bez s)
  2. Mapa mapuje ID jednego użytkownika na obiekt, który trzyma dane jednego użytkownika.
    Stąd pytanie:

Nie wiem jak dodać kolejnych uzytkownikow do TABLICA
wydaje się bez sensu. Czy nie chcesz przypadkiem dodać kolejnych użytkowników do mapy?

Jeśli to co napisałem jest prawdą, to wszystko jest już dostarczone przez interfejs std::map lub std::unordered_map.

std::map<int, ConnectedUser> users;
users[1] = jakis_tam_user;      // wbrew pozorom to jest DODANIE do mapy

Zapoznaj się z http://www.cplusplus.com/reference/map/map/?kw=map

0

Tak trzyma dla jednego a chce by trzymalo dla kazdego nowego użytkownika czyli musialbym zrobic
conectedUsers Tablica[100]; //dla stu uzytkownikow Kazdy kolejny uzytkownik ma byc
dodany do tej struktury i przypisany do map. Algrotym

  1. Laczy sie uzytkownik
  2. dodaje go do structury
    Tablica[1].session_key = "ejfiejfiwef";
    Tablica[1]. sockaddr_in = from;
  3. dodaj id_user = 1 i strukture do mapera
    map(1, Tablica[1]);
  4. laczy sie kolejny user
  5. dodaje go do structury
    Tablica[2].session_key = "8748383u483";
    Tablica[2]. sockaddr_in = from;
  6. dodaj id_user = 6 i strukture do mapera
    map(6, Tablica[2]);

W ten sposob w maperze jak wybiore user id = 54 to mam jego polaczenie
na ktore odesle wiadomosc. Pytanie wlasnie jak stworzyc taka dynamiczna strukture
zeby zamiast:
conectedUsers Tablica[100]; zrobic
conectedUsers Tablica[];
i potem dodawac ich kolejno jako:

Tablica[].session_key = "ejfiejfiwef";
Tablica[]. sockaddr_in = from;

Pobrac jakos ostatnio wstawiony numer do tablicy
i wpisac do mapera
map(54,Tablica[Oststnio_dodany_numer])

0

Czy my piszemy niewyraźnie? o_O
map<int, ConectedUser> mapa może trzymać ilu userów chcesz. Napiszesz mapa[1000] to ci usera wpisze pod takim indeksem. Napiszesz mapa[100000] to pod takim. Ta mapa jest, tak przy okazji, sparse wiec te dwie komendy dodaja tylko dwóch userów a nie 100000

0
vpiotr napisał(a):

Czym się różni od std::vector? Szybkością znajdowania elementów wg int (std::map jest teoretycznie szybsze).

@vpiotr: Nie tylko teoretycznie szybsze. std::map jest zaimplementowane jako zrownoważone BST, zatem wyszukiwanie w nim to O(logn). std::vector to natomiast ciągły obszar pamięci (zresztą sam doskonale wiesz co) o złożoności wyszukiwania O(n).
std::unordered_map to z kolei hash table, w którym możemy wyszukiwać w zamortyzowanym czasie O(1).

1

@masterO jejku, jej!

struct ConectedUser{
    string session_key;
    sockaddr_in socket;
};
int main(){
    map<string, ConectedUser> users;
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        ConectedUser user;
        cin>>user.session_key;
        cin>>user.socket; //wiem że niepoprawne, ale to tylko przykład!
        users.insert(i, user);
    }
}

I voila. Możesz mieć ilu userów sobie chcesz. Rozumiesz?

0

Zrobiłem jak z przykładu:

         

struct ConnectedUsers {
    int id;
    string session_key;
    sockaddr_in socket;
    //added
};

    map<int, ConnectedUsers> users;

        ConnectedUsers user;
        user.session_key = UUID;
        user.socket = from;
        users.insert(pair<int,ConnectedUsers>(1,from));

ale mam taki błąd :(

error: no matching function for call to ‘std::pair<int, ConnectedUsers>::pair(int, sockaddr_in&)’

Mam naglowek

#include<map>
1

Spójrz na treść błędu, a najlepiej przeczytaj na głos ze zwróceniem uwagi na typy argumentów oraz parametrów.

0

Mam jeszcze takie pytanie, bo kod mam taki jak wyżej:

users.insert(pair<int,ConnectedUsers>(ID_USER,user));

I teraz jesli loguje sie na 2 różnych użytkownikach i po każdym logowaniu
w pętli wyświetlam to co zawiera MAP to pokazuje mi 2 userów. Nawet jak
loguje się kilka razy to i tak mam tylko dwóch a nie robiłem nic żeby sprawdzał
co znajduje się w MAP i jeśli user taki istnieje to ma nie dodawać nowego?

To on sam to sprawdza jakoś ?

0

Bo to geniusz ;] Mapa może mieć tylko jeden rekord dla danego klucza. Jak robisz nowy insert pod ten sam klucz to "nadpisujesz go" po prostu.

0

Teraz sprawdziłem wyszukiwanie i działa ok bo wyszukuje mi po ID usera. Ale u mnie działą to tak:
Przed INSERT generate session_key. ten klucz jest za kazdym razem inny, wiadomo.
Potem wstawiam INSERT do MAP z tym samym kluczem co wczesniej (KLUCZ to USER ID)
i nie wstawia mi nowego wpisu tylko pozostaje ten stary wpis. To znaczy ze MAP sprawdza czy taki
klucz istnieje i nie robi nic ? czy nadpisuje bo z klucza sesji wynika ze nie nadpisuje nic tylko zosatwia
bez zmian, a mi zalezy na nadpisywaniu. I najpierw przed INSERTEM chciałem wyszukiwać ID usera
i nadpisywac wartosc klucza jesli user istnieje albo dodac jesli nie ustnieje

0

No to nie insert, tylko

mapa[ID] = nowa_wartosc;

1 użytkowników online, w tym zalogowanych: 0, gości: 1