Avatar billede morw Nybegynder
30. marts 2003 - 21:17 Der er 15 kommentarer og
1 løsning

Datastruktur i chat

Øv hvor er det træls at være newbie - der er så mange spørgsmål.

Jeg roder lidt med forberedelserne til en chatserver og skal finde ud af hvordan jeg kæder oplysninger om en bruger sammen med den filedescripter som retuneres af accept();

Jeg regner med en struct som indeholder filedescripter, nick til navn samt en mode der fortæller om nick er modtaget samt buffer.

// struct
struct Deltager_info
{
        int fd_socket;
        string nick;
        int mode;
        string buffer;
};

Men hvordan skal jeg gemme dem. Jeg vil tro i et array eller i en vector. Men det skal jo også gerne være muligt at hente nick ud fra fd_socket eller skrive til buffer når jeg kender fd_socket.

Nogen der kan hjælpe mig videre?
Avatar billede arne_v Ekspert
30. marts 2003 - 21:22 #1
Den nemmeste løsning er naturligvis et array (enten fix size eller
dynamisk allokeret med malloc/new).

Og når du så skal finde noget, så looper du gennem arrayet og
sammenligner med det du har.
Avatar billede arne_v Ekspert
30. marts 2003 - 21:23 #2
Alternativer er en double-linked list eller en STL data-struktur
(hvis du bruger C++).

I begge tilfælde skal der stadig søges normalt lineært igennem.
Avatar billede arne_v Ekspert
30. marts 2003 - 21:27 #3
Formentligt er det ikke noget problem at søge lineært
igennem et array/liste/whatever.

Hvis du skal have noget hurtigere så kan du lave en index-struktur.

strict Nick_Index {
    string *nick;
    Deltager_info *data;
}

så laver du et array af dem af samme størrelse som max antal
og så holder du det array sorteret og så kan du lave en binær
søgning på nick og hurtigt finde data.

Det sorterede array kan så forbedres ved at lave det som træ eller
som hash tabel.
Avatar billede morw Nybegynder
30. marts 2003 - 21:31 #4
I php ville jeg kunne lave et 2-dim array, da den er ligeglad med spring i element-id, så jeg kan tilgå alt direkte:

$liste[2]['fd_socket'] = 2;
$liste[2]['nick'] = "morw";
$liste[2]['mode'] = 2;
$liste[2]['buffer'] = "";

$liste[5]['fd_socket'] = 5;
$liste[5]['nick'] = "morw2";
$liste[5]['mode'] = 2;
$liste[5]['buffer'] = "";

Altså så jeg bruger fd_socket som element-id. På den måde kan jeg skrive direkte til socket 5's buffer ved:

$fd = 5;
$liste[$fd]['buffer'] = "hej\n";

Kan jeg ikke gøre noget lignende i c++
Avatar billede arne_v Ekspert
30. marts 2003 - 21:36 #5
Det gør du vel også i C++.

struct Deltager_info data[1000];

data[2].fd_socket = 2;
data[2].nick = "morw";
data[2].mode = 2;
data[2].buffer = "";

Det er bare med en array af struct i.s.f. med et 2-dim array.
Avatar billede morw Nybegynder
30. marts 2003 - 21:40 #6
Problemet er bare at jeg jo vil have folk der hopper ud af chatten og så kommer der jo huller i mit array.

Når jeg så skal loope alle igennem for at sende til alle giver det jo et problem.

Er lige gået i gang med at læse om <map> - måske det er en løsning.
Avatar billede arne_v Ekspert
30. marts 2003 - 21:43 #7
Der er mere avancered data-strukturer end array af struct.

Men du kan sagtens få array af struct til at virke, enten tilføjer
du bare et felt inuse eller så laver du en konvention fd_socker=-1
betyder at pladsen er ledig.
Avatar billede morw Nybegynder
30. marts 2003 - 21:47 #8
ok, ja jeg skal jo også arbejde lidt selv for sagen.
Avatar billede arne_v Ekspert
30. marts 2003 - 21:48 #9
Jeg kender ikke map specielt godt, men jeg troede
at man kun kunne have 1 key.
Avatar billede arne_v Ekspert
30. marts 2003 - 21:52 #10
Altså enten:

map<string, Deltager_info>

for nick->data eller:

map<int, Deltager_info>

for fs_socket->data
Avatar billede morw Nybegynder
30. marts 2003 - 21:54 #11
tak - jeg var lige igang med at skrive det samme... ;-D
Avatar billede morw Nybegynder
30. marts 2003 - 21:59 #12
Hmm, kan du uddybe?       

map<int, Deltager_info> alle;
alle[5]->nick = "hans";
alle[5]->mode = 2;
Avatar billede arne_v Ekspert
30. marts 2003 - 22:05 #13
map<int, Deltager_info> alle;
  alle[2].fd_socket = 2;
  alle[2].nick = "morw";
  alle[2].mode = 2;
  alle[2].buffer = "";
Avatar billede arne_v Ekspert
30. marts 2003 - 22:07 #14
Et komplet eksempel:

#include <map>
#include <string>
#include <iostream>

using namespace std;

struct Deltager_info
{
        int fd_socket;
        string nick;
        int mode;
        string buffer;
};

int main()
{
  map<int, Deltager_info> alle;
  alle[2].fd_socket = 2;
  alle[2].nick = "morw";
  alle[2].mode = 2;
  alle[2].buffer = "";
  alle[5].fd_socket = 5;
  alle[5].nick = "morw2";
  alle[5].mode = 2;
  alle[5].buffer = "";
  cout << alle[2].nick << endl;
  cout << alle[5].nick << endl;
}
Avatar billede morw Nybegynder
30. marts 2003 - 22:15 #15
Tak det var lige hvad jeg skulle bruge. havde smidt min struct i main.
Avatar billede morw Nybegynder
30. marts 2003 - 22:58 #16
Se det er jo smart i forhold til et array ik?

  for(map<int, Deltager_info>::const_iterator it = alle.begin(); it != alle.end(); ++it)
  {
    cout << it->first << "\t" << it->second.nick << "\n" << endl;
  }
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester