Avatar billede Slettet bruger
08. juni 2000 - 18:33 Der er 14 kommentarer og
1 løsning

Så er den gal igen!!

Jeg er igang med et program der skal registrere øboere
(se http://www.eksperten.dk/spm.asp?id=18586 )

Jeg har oprette en dynamisk tabel indeholdende indbygger-objekter:
   
       
        Indbygger *tabel;
    tabel = new Indbygger[arraySize];    //Tabel med 50 indbyggere


Hver objekt består af to Strings "Navn og Cpr nr" samt pointere til ægtefæller, børn og forældre.

Når tabellen er fyldt op med indbyggere har jeg lavet en funktion der udvider tabellen og kopiere de gamle ojekter over:

Indbygger *udvid_tabel(Indbygger *arr, int &arraySize)
{
    int newSize = arraySize*2;
  Indbygger *tempArr;
  tempArr = new Indbygger[newSize];
  for(int i=0; i<arraySize; i++)
      tempArr[i] = arr[i];
  delete [] arr;
  return tempArr;
}

PROBLEMET:
Pointerne bliver IKKE kopieret med over. Dvs. de peger stadig på den gamle adresse i tabellen som jo nu er sletttet.
Hvordan får jeg pointerne i objekterne til at pege på den ny adresse???


Avatar billede dmk Nybegynder
08. juni 2000 - 19:17 #1
Hej igen.

Er du nu også sikker på, at du gerne vil lave det med pointere??? Når du vil sådan noget her, så er pointere muligvis ikke det smarteste... Men okay, det kan da lade sig gøre!

Indbygger *udvid_tabel(Indbygger *arr, int &arraySize)
{
  int newSize = arraySize*2;
  Indbygger *tempArr;
  tempArr = new Indbygger[newSize];
  for(int i=0; i<arraySize; i++)
  {
      tempArr[i] = arr[i];
      if (arr[i].aegtefaelle!=NULL)
      tempArr[i].aegtefaelle=&tempArr[((int)arr[i].aegtefaelle-(int)arr))/sizeof(Indbygger)];
  }   
  delete [] arr;
  return tempArr;
}

Jeg tror det skulle virke, men umiddelbart ikke det nemmeste kode at læse...

DMK
Avatar billede dmk Nybegynder
08. juni 2000 - 19:21 #2
Okay, jeg må nok hellere lige forklare :-)

Vi skal finde indekset (i den nye tabel, tempArr) på den ægtefælle, som aegtefaelle-pointeren peger på. Når vi har fundet indekset, sætter vi aegtefaelle-pointeren i tempArray til at pege på adressen på elementet på dette indeks.

arr[i].aegtefaelle giver adressen på det element den peger på lige nu. Hvis vi trækker adressen på starten af arrayet fra, har vi antallet af bytes som pointeren peger ind i arrayet. Hvis vi dividerer med størrelsen af de enkelte objekter (sizeof(X) giver byte-størrelsen af X), har vi hvor mange elementer den peger forbi, altså indekset på aegtefaellen! Sådan.

DMK
Avatar billede denniss Nybegynder
08. juni 2000 - 19:42 #3
Pyyyha.. hvad er det nu sådan en fyr hedder?


binær træ, mener jeg.. kan man mestre et binært træ.. er man godt inde i pointere... vist også en meget hurtig måde at søge igennem..... nå det var bare en kommentar.
Avatar billede dmk Nybegynder
08. juni 2000 - 19:44 #4
Ja, det er rigtigt der findes mange smartere strukturer til at holde sådan noget data i, hvis det skal være bare en smule fleksibelt. En kædet liste ville fx. være langt smartere, og meget nemmere at indsætte og slette i, men hvis det skal være et array, so be it!

Hvis du gerne vil have hjælp til at lave det som en kædet liste, så kan vi også finde ud af det...


DMK
Avatar billede nostra_d92 Nybegynder
08. juni 2000 - 20:56 #5
hvilket program bruger du?

det kunne skyldes at du bruger microsoft
Avatar billede nolle_k Nybegynder
08. juni 2000 - 22:20 #6
Hvis ikke du har defineret en Assignment operator vil det gå galt! Du prøver at sætte indholdet af de to pointere lig med hinanden men da klassen ikke ved hvordan det gøres går det galt! Kompileren burde faktisk informere om at der ikke findes en operator!! Operatoren defineres på følgende måde i klassen

void operator = (CIndbygger& a)
    {
                Navn = a.Navn;
        CPRNr = a.CPRNr;
        Samlever = a.Samlever;
            //Alle de variable der skal kopieres kopieres her!
        }


Det burde løse dit problem! Så slipper du også for at bekymre dig om pointere og den slags!

Det burde kunne klare dit problem!

//Nolle_K
Avatar billede dmk Nybegynder
09. juni 2000 - 09:44 #7
Hej Nolle_k

Nej, det er ikke rigtigt. Den kan fint finde ud af at kopiere en pointer, når man sætter en struct lig med en anden. Det den gør helt konkret, er noget tilsvarende:
memcpy(&DestStruct, &SourceStruct, sizeof(struct));

Når man bare kopierer dataindholdet fra en struct til en anden, vil pointere blive kopieret rigtigt. Det der derimod ikke vil blive kopieret er dynamisk oprettet hukommelse for en pointer inde i structen. Hvis vi har følgende:

struct A_struct {
  int a;
  char* b;
};

void main()
{
  A_struct a, b;
  a.b=new char[200];
  b=a;
}
Nu vil selve arrayet fra a IKKE blive kopieret til b! Det er kun pointeren der bliver kopieret, så hvis man ændrer på arrayet i a, vil det også være ændret i b.

Problemet for zap er, at pointerene peger på objekter i et array, som han sletter lige efter. Pointerne skal selvfølgelig pege på objekter i det nye array.


DMK
Avatar billede nolle_k Nybegynder
09. juni 2000 - 10:26 #8
Det kan godt være! Men det er da ikke selve pointerne han vil kopiere men indholdet af det pointerne peger på!


Men ikke desto mindre burde det løse hans problem!!
Avatar billede dmk Nybegynder
09. juni 2000 - 10:29 #9
Nej, det er det ikke. Han vil ikke kopiere indholdet af pointeren, han vil opdatere pointeren til at pege ind i det nye array, i stedet for at pege ind i det gamle, som han jo sletter. Hans problem vil bestemt ikke være løst ved det du gør, faktisk giver det NØJAGTIG samme resultat som han selv havde fundet frem til. Om man sætter pointeren explicit lig med pointeren fra den anden struct, eller om man memcopyer pointeren ved blot at sætte structen lig med den anden, giver nu engang stadig den samme pointer, som nu engang stadig er den forkerte.

DMK
Avatar billede channex Nybegynder
09. juni 2000 - 10:55 #10
Jeg ved godt det er en lidt anden løsning, men hvis kravet bare er et dynamisk array, hvorfor så ikke bruge STLs vector (svarer til et dynamisk array)? Det ville se nogenlunde såddan ud:
vector<Indbygger*> tabel;

Sæt en ny indbygger ind:
Indbygger *pJohnDoe=new Indbygger;
tabel.push_back(pJohnDoe);

Indexering foregår som normalt (kant operatoren er defineret):
Indbygger *pCur=tabel[42];
tilsvarende (dog med sanity check):
Indbygger *pCur=tabel.at(42);

Det eneste man skal huske er så, at huske at delete entries, før (eller samtidigt med :) man fjerner dem fra listen. Ellers kan man jo selvfølgelig også bare erklære listen som:
vector<Indbygger> tabel;
..Men så er vi tilbage ved samme ballade med assignment/kopiering af strukturen/klassen.
Avatar billede channex Nybegynder
09. juni 2000 - 11:01 #11
.. Men mens vi er ved STL kunne du også bare bruge string klassen til at opbevare navnene med. Den sørger selv for at kopiere ved assignment.
string sTemp="Hello world.";
string sTemp2=sTemp;

Hvis sTemp bliver destructed før sTemp2 (hvilket ikke vil være tilfældet i dette eksempel ;), vil sTemp2 automatisk overtage ejerskabet af hukommelsen (hvor strengen rent faktisk ligger).
Avatar billede nolle_k Nybegynder
09. juni 2000 - 11:21 #12
Jamen så skal det vel være et array af pointere pointere der skal bruges! Så kan der mingeleres rundt så meget som man lyster!

Indbygger** tmp;

Avatar billede dmk Nybegynder
09. juni 2000 - 11:26 #13
Et array af pointere (ikke pointere pointere) vil være langt smartere, for så behøver en indbygger aldrig at skifte adresse i hukommelsen, og så behøver man ikke opdatere nogle pointere.

Desuden vil det være mere effektivt (eg. hurtigere), da man ikke skal slette, oprette og kopiere en masse hukommelse.

DMK
Avatar billede nolle_k Nybegynder
09. juni 2000 - 11:36 #14
OK! Jeg er nok ikke nok inde i problemstillingen til at give et helt konkret svar! Men det var da enormt hyggeligt og lærerigt! *GGG*
Avatar billede Slettet bruger
09. juni 2000 - 16:02 #15
Så er opgaven afleveret og jeg svaret fra DMK virkede fint.
I har ret i at et array af pointere vil være smartere, så ved jeg det til næste gang: )
Tak for hjælpen!

ZAP

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