Passerer en matrise som et argument i C ++

stemmer
13

Jeg skriver et flettesorteringsfunksjon, og akkurat nå er jeg bare bruker en test array (det er ingen inngang - dette er statisk, for nå). Jeg vet ikke hvordan du skal passere en rekke som et argument. Her er min kode akkurat nå:

//merge sort first attempt

#include <iostream>
#include <algorithm>
#include <vector>

int mergeSort(int[]);
int main()
{
int originalarray[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
mergeSort(originalarray[]);
}

int mergeSort(int[] originalarray)
{
int num = (sizeof(originalarray)/sizeof(int));
std::vector<int> original(num);

if (num > 2) {
    return num;
}

// Fill the array using the elements of originalarray
// This is just for demonstration, normally original will be a parameter,
// so you won't be filling it up with anything.
std::copy(originalarray, originalarray + num, original.begin());

// Create farray and sarray of the appropriate size
std::vector<int> farray(num / 2);
std::vector<int> sarray(num - farray.size());

// Fill those using elements from original
std::copy(original.begin(), original.begin() + farray.size(), farray.begin());
std::copy(original.begin() + farray.size(), original.end(), sarray.begin());

mergeSort(farray);
mergeSort(sarray);    

}

Merk at denne mergeSort funksjonen ikke er funksjonelt, som jeg ikke har funnet ut hvordan å flette dem ennå (det er min oppgave). Jeg ønsker å få mine to vektorer sortert før jeg takle det, og jeg kan ikke kompilere dette på grunn av mitt behov for å passere en rekke som et argument. Jeg forstår ikke pekere, så hvis det er løsningen, er min unnskyldning uvitenhet. Jeg lærer programmering akkurat nå, med C ++ som førstespråk, og har bare en grunnleggende forståelse av språkets funksjoner. Takk for hjelpen.

Publisert på 18/04/2009 klokken 18:01
kilden bruker
På andre språk...                            


7 svar

stemmer
18

Du bør ikke bruke sizeof(originalarray)/sizeof(int)sånn. Det vil bare fungere for statisk erklært arrays (størrelsen er kjent ved kompilering). Du må passere størrelsen sammen med det. Hvorfor ikke bare lage en vectorut av tabellen og gi det i stedet?

Side Merk: Som en tommelfingerregel, alltid oppmerksom på at sizeofvil bli oversatt ved kompilering. Så det er ingen måte det kunne vite størrelsen på array sendes som et argument.

Svarte 18/04/2009 kl. 18:04
kilden bruker

stemmer
2
  • Når du passerer arrays til funksjoner, de visner til pekere til det første elementet i matrisen, notasjonen til tross. Så din sizeofdoesnot fungerer som forventet.

  • Når du passerer i en matrise, er det best å passere i matrisen størrelse, slik at du vet hvor du skal stoppe. Legg det som en ekstra parameter.

Svarte 18/04/2009 kl. 18:06
kilden bruker

stemmer
3

Jeg ser du har <vector>. Jeg foreslår at du gjør unna med all bruk av matriser og bare bruker den vectorklassen. Du kan se eksempler på hvordan du bruker STL beholdere slik som vector her .

Svarte 18/04/2009 kl. 18:07
kilden bruker

stemmer
30

Stikke fram til å utvide dette litt, husk at C ++ arrays er nøyaktig C arrays. Så alt du trenger er adressen til en del av minnet som hensikt (med ingen garantier) for å være en rekke somethings.

Oppdater

Ok, vi vil utvide litt mer.

C (og dermed C ++) har ikke egentlig "arrays" som sådan. Alt den har er adresser, pekere. Så når du gjør noe en "array", hva som egentlig skjer er at du forteller kompilatoren at noen variable representerer en adresse.

Det er nyttig å lage en forskjell i C mellom en erklæring og en definisjon . I en erklæring, er du rett og slett å gi noe et navn og en type; i en definisjon, du faktisk tildele plass.

Så, hvis vi starte med å definiing en matrise som

int ar[100];

det betyr at vi forteller kompilatoren vi vil ha plass til 100 int's, vi vil at det skal alle bli tildelt i en del, og vi kommer til å bruke navnet arfor det. Den sizeofOperatøren gir antallet byte brukt av en type eller et objekt, så vår rekke artar opp 100 x sizeof(int)bytes. På de fleste maskiner, vil det være 400 bytes, men det varierer fra maskin til maskin.

Hvis vi definerer en variabel

int * ar_p;   // using '_p' as a reminder this is a pointer

vi definerer plass til en variabel som vil inneholde en adresse. Størrelsen vil være sizeof(int*), som vanligvis vil være enten 4 eller 8, men på noen maskiner kan være alt fra 2 til 16 på noen maskiner du neppe å kjøre inn snart.

Den navn av tabellen er ar. Kompilatoren konverterer det navnet til en adresse, slik at vi kan lagre denne adressen med

ar_p = ar ;     // THIS WORKS

Nå, la oss si for enkelhets skyld at vår rekke arskjedde skal starter på plassering 1000 i minnet.

Det navnet arhar ikke har noen plass allokert til det; det er som en konstant, et tall. Så kan du ikke reversere det oppdraget

ar = ar_p ;     // THIS WON'T WORK

av samme grunn kan du ikke si

1000 = ar_p ;   // THIS WON'T WORK EITHER

dvs., kan du ikke endre verdien av 1000. (Tilbake i tidlige versjoner av FORTRAN, ville dette trikset fungerer, for kompliserte årsaker. Det var en feil. Du har aldri levd før du har prøvd å feilsøke et program der verdien "2" er 3.)

Arrays i C er alltid nullbasert, det vil si, er den første indeks alltid null. Eventuelle andre indekser er bare adresser beregnet ved hjelp av indeksen. Så, ar[0]er bare adresse 1000 pluss 0 byte offset eller 1000. ar[1]er 1000 pluss 1 ganger størrelsen på en int, så neste int over. Og faktisk, er dette alltid sant i C.

Dette kalles en matrise referanse .

Når vi bruker syntaksen *ar_pvi forteller kompilatoren for å få ting på adressen som finnes i ar_p. `.

Dette kalles dereferencing en peker .

Hvis vi sier

ar_p = ar;

deretter *ar_pog ar[0]refererer til det samme.

Når vi sier ar[0]vi forteller kompilatoren vi ønsker ting på adressen 0 byte fra ar. ar[1]er den adresse ett inteller 4 bytes, fra ar. Så, *(ar_p+3)refererer til det samme som ar[3]. (Vi trenger parentesene fordi vi ønsker å legge til tre til adressen først og deretter se på innholdet. *ar_p+3Ville få innholdet peker på ap_pførst, og deretter legge tre til dem.

Saken er, C ikke vet, eller mye omsorg, hvor stort utvalg egentlig er. Hvis jeg kommer sammen og gjøre ar[365], vil kompilatoren lykkelig generere kode for å se i cellen 1000 + (365 x sizeof(int)). Hvis det er i array, greit, men hvis det er bare tilfeldig minne, er det helt greit også. C bryr seg ikke.

(Husk at C kommer fra telefonselskapet "Vi bryr oss ikke, vi trenger ikke å Vi er Telefon-selskapet..".)

Så nå vet vi noen regler, som jeg har flyttet ned her. Les "≡" som "tilsvarer" eller "er det samme som".

Hva du kan stole på:

  • foo(TYPE t[])foo(TYPE * t)

Siden C ikke vet forskjell mellom pekere og matriser, kan du erklære ett. Når du definerer en funksjon, kan du skrive

void foo(int[] ar){

eller

void foo(int* ar){

og får akkurat samme effekt.

  • t[i]*(t+i)

Dette var over. Uansett hvor du kan skrive ar[i], kan du erstatte den med *(ar+i). (Det er faktisk en merkelig side sak som bryter dette, men du vil ikke kjøre inn i det som en nybegynner.)

  • hvor TYPE *t, (t+i)vil være lik den adressen tplussi*sizeof(TYPE)

Forklarte dette ovenfor også. Når du indeksen inn en matrise, som ar[42], det betyr at du vil ha den 42. uansett over fra startadressen. Så, hvis du bruker int, så må du flytte over 42 ganger men brede en inter, som er å si sizeof(int).

Nå, det er alt C, og siden C ++ er definert som en "type" C, det holder for C ++ også. UNNTATT

  • mindre TYPEer en brukerdefinert type som overbelaster operator[]og operator*.

i C ++, kan du bestemmer deg for å definere en ny type som fungerer akkurat som en hvilken som helst annen type, men du kan endre måten språket gjør konkrete ting. Så, en programmerer kan bestemme seg for å "overload" - det vil si, skifte - standard oppførsel av matrise referanse og peker dereferanseoperatorene med noe av sine egne devising. Som en nybegynner, bør du ikke bli konfrontert med det snart, men du bør være klar over det.

Svarte 18/04/2009 kl. 18:24
kilden bruker

stemmer
0

I tillegg til alle svarene ovenfor, kan du også være lurt å sjekke ut spørsmål og svar på arrays fra c-faq.com: http://c-faq.com/aryptr/index.html

Svarte 18/04/2009 kl. 19:42
kilden bruker

stemmer
0

Dessverre er det svært vanskelig å gjøre akkurat hva du vil gjøre i C eller C ++. Du kan sende rundt en fast størrelse utvalg som dette:

int mergeSort(int originalarray[20])
{
    // do something
}

Imidlertid er array størrelse ikke definert av et tall, er det definert av antall elementer i initialisering listen.

Tingen å gjøre i ditt tilfelle (selv om det er virkelig en feil ting å gjøre) er å gjøre det i to trinn:

int originalarray[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
const size_t arraySize = sizeof originalarray / sizeof originalarray[0];
int mergeSort(int array[arraySize])
{
    // do something
}

Synd det ikke vil gjøre det du må gjøres: bestått array til en funksjon som dette gjør en kopi av tabellen, og poenget med sortering ville være å endre den opprinnelige matrisen.

I sannhet, kan du ikke gå videre uten å forstå begrepet "pointer".

Funksjonen du trenger for å utvikle virkelig skal være som dette:

int originalarray[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
const size_t arraySize = sizeof originalarray / sizeof originalarray[0];

int mergeSort(int *array, const size_t size)
{
    // do something
}

mergeSort(&(originalArray[0]), arraySize);

Med andre ord, man passere en peker til første element, og det antall elementer.

Alternativt kan du avtale med vektorer. Vektor innkapsler de samme to ting (peker til første element og størrelse) i en enkelt enhet som kalles "objekt". Plus, den klarer minne for deg, slik at du kan utvide antall elementer som du trenger. Dette er C ++ måte. Synd du ikke kan initialisere en vektor med {...} som du kan en matrise.

Svarte 18/04/2009 kl. 20:35
kilden bruker

stemmer
0

Ser ut som du bruker både dynamisk tildelte matriser og vektorer, da tror jeg bare bruker std :: vector vil være nok.

Først, la dine innspill utvalg endres til en std :: vector, og fyll den med dine inndata.

int main()
{
   std::vector<int> originalarray;
   for (int data = 1; data <= 10; data++)
   {
      originalarray.push_back(data);
   }
   mergeSort(originaldata);
}

Nå er det viktig å erklære din mergeSort funksjon for å ta en referanse til en std :: vector.

int mergeSort(std::vector<int>& originalarray)
{
   // The rest of your code, note that now you are passing 
   // in your array for sorting, so you can continue with your code to split
   // the vector into farray and sarray

   // then call sort on your halves.
   mergeSort(farray);
   mergeSort(sarray);

   // I'm guessing at this point you'd write code to combine your farray sarray, and
   // put it back into originalarray...don't forget to clear original array first!
}

Bare et notat, ser ut som du ikke gjør en inplace slag, så forventer din slag for å ta en stund siden du kopierer ut en masse data.

Svarte 19/04/2009 kl. 03:36
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more