Passerer en matrise som en funksjon parameter i C ++

stemmer
17

I C ++ kan arrays ikke bli gitt bare som parametere. Betydning hvis jeg oppretter en funksjon slik:

void doSomething(char charArray[])
{
    // if I want the array size
    int size = sizeof(charArray);
    // NO GOOD, will always get 4 (as in 4 bytes in the pointer)
}

Jeg har ingen måte å vite hvor stor matrise er, siden jeg bare har en peker til tabellen.

Hvilken vei har jeg, uten å endre metoden signaturen, for å få størrelsen på array og iterere over det er data?


EDIT: bare et tillegg om løsningen. Hvis char array, spesielt ble initialisert slik:

char charArray[] = i am a string;

da den \0allerede er lagt til på slutten av tabellen. I dette tilfellet svaret (markert som akseptert) fungerer ut av boksen, så å si.

Publisert på 14/01/2009 klokken 21:24
kilden bruker
På andre språk...                            


12 svar

stemmer
23

Uten å endre signatur? Føye til et fast punkt element. For char matriser spesielt, kan det være den null-terminer '\0'som benyttes for standard C strenger.

void doSomething(char charArray[])
{
    char* p = charArray;
    for (; *p != '\0'; ++p)
    {
         // if '\0' happens to be valid data for your app, 
         // then you can (maybe) use some other value as
         // sentinel
    }
    int arraySize = p - charArray;

    // now we know the array size, so we can do some thing
}

Selvfølgelig, så din matrise seg selv kan ikke inneholde sentinel element som innhold. For andre typer (dvs. ikke-røye) matriser, kan det være noen verdi som ikke er juridiske data. Hvis det ikke finnes en slik verdi, så denne metoden ikke fungerer.

Dessuten krever denne samarbeid på den som ringer side. Du må virkelig være sikker på at den som ringer forbeholder en rekke arraySize + 1elementer, og alltid setter sentinel element.

Men hvis du virkelig ikke kan endre signaturen, alternativene er ganske begrenset.

Svarte 14/01/2009 kl. 21:25
kilden bruker

stemmer
4

hvis det er nullterminated, strlen () ville fungere.

Svarte 14/01/2009 kl. 21:26
kilden bruker

stemmer
2

Du kan ikke bestemme størrelsen fra charArrayalene. Denne informasjonen blir ikke automatisk sendes til funksjonen.

Selvfølgelig hvis det er en null-terminert streng du kan bruke strlen(), men du har sikkert vurdert at allerede!

Betrakt passerer en std::vector<char>& parameter, eller et par av pekere, eller en peker pluss en størrelse parameter.

Svarte 14/01/2009 kl. 21:26
kilden bruker

stemmer
2

Dette er faktisk mer C enn C ++, C ++ du vil nok heller bruke en std :: vector. Men i C er det ingen måte å vite størrelsen på en matrise. Kompilere vil tillate deg å gjøre en sizeof dersom matrisen ble erklært i dagens omfang, og bare hvis det ble eksplisitt erklært med en størrelse ( EDIT: og "med en størrelse", mener jeg at det enten ble erklært med et heltall størrelse eller initialisert ved erklæring, i motsetning til å føres som en parameter, takket for downvote).

Den vanlige løsningen i C er for å passere en andre parameter som beskriver antallet elementer i tabellen.

EDIT:
Sorry, savnet en del om ikke ønsker å endre metoden signaturen. Så er det ingen løsning unntatt som beskrevet av andre også, hvis det er noen data som ikke er tillatt i matrisen, kan den brukes som en terminator (0 i C-strenger, -1 er også ganske vanlig, men det kommer an på selve datatype, forutsatt at røye array er hypotetisk)

Svarte 14/01/2009 kl. 21:28
kilden bruker

stemmer
1

For at en funksjon for å vite hvor mange elementer i en matrise som har gått til det, må du gjøre ett av to ting:

  1. Bestå i en størrelsesparameter
  2. Sett størrelsen informasjon i matrisen eller annen måte.

Du kan gjøre det siste på flere måter:

  • Avslutte den med en NULL eller et annet fast punkt som ikke vil forekomme i normal informasjon.
  • lagre elementet teller i første oppføring hvis matrisen har tall
  • lagre en peker til den siste oppføringen hvis tabellen inneholder pekere
Svarte 14/01/2009 kl. 21:34
kilden bruker

stemmer
37

Bruke maler. Dette teknisk ikke passer dine kriterier, fordi det endrer signatur, men kaller kode trenger ikke å endres.

void doSomething(char charArray[], size_t size)
{
   // do stuff here
}

template<size_t N>
inline void doSomething(char (&charArray)[N])
{
    doSomething(charArray, N);
}

Denne teknikken brukes av Microsofts Secure CRT funksjoner og ved STLSoft er array_proxy klasse mal.

Svarte 14/01/2009 kl. 21:47
kilden bruker

stemmer
6

Det faktisk brukes til å være en ganske vanlig løsning for å passere lengden i det første element i matrisen. Denne typen struktur er ofte kalt BSTR(for “BASIC streng”), selv om dette også betegnes forskjellige (men lignende) typer.

Den fordel fremfor de aksepterte løsningen er at bestemme lengden ved hjelp av en fast punkt er langsom for store strenger. Ulempen er åpenbart at dette er en ganske lav-nivå hakke som føyer seg verken typer heller struktur.

I skjemaet nedenfor det også fungerer bare for strenger av lengde <= 255. Men dette kan lett utvides ved å lagre lengden i mer enn én byte.

void doSomething(char* charArray)
{
    // Cast unnecessary but I prefer explicit type conversions.
    std::size_t length = static_cast<std::size_t>(static_cast<unsigned char>(charArray[0]));
    // … do something.
}
Svarte 14/01/2009 kl. 22:03
kilden bruker

stemmer
5

Vanligvis når du arbeider med C eller lavt nivå C ++, kan du vurdere omskolering hjernen din til å aldri vurdere å skrive array-parametere til en funksjon, fordi C-kompilator vil alltid behandle dem som pekere uansett. I hovedsak ved å skrive disse klammeparenteser er du lure deg selv i å tenke at en reell matrise blir vedtatt, komplett med størrelsen informasjon. I virkeligheten, i C kan du bare sende pekere. Funksjonen

void foo(char a[])
{
    // Do something...
}

er, fra det synspunkt av den C-kompilator, nøyaktig tilsvarende:

void foo(char * a)
{
    // Do something
}

og åpenbart at nekkid char pekeren inneholder ingen lengdeinformasjon.

Hvis du sitter fast i et hjørne og ikke kan endre funksjonen signatur, vurdere å bruke en lengde prefiks som foreslått ovenfor. En ikke-bærbar, men kompatibel hack er å spesifisere rekke lengden i en size_t feltet ligger før rekken, noe som dette:

void foo(char * a)
{
    int cplusplus_len = reinterpret_cast<std::size_t *>(a)[-1];
    int c_len = ((size_t *)a)[-1];
}

Tydeligvis den som ringer må lage arrays i den aktuelle veien før du passerer dem til foo.

Unødvendig å si at dette er en fryktelig hack, men dette trikset kan få ut av problemer i en klemme.

Svarte 14/01/2009 kl. 22:44
kilden bruker

stemmer
-1

Du guarranteed å motta fire i en 32-bits PC, og det er det riktige svaret. på grunn av grunnen forklart her og her . Det korte svaret er, er du faktisk teste sizeof en peker snarere enn en matrise, fordi "array implisitt konvertert, eller henfaller, inn en peker Pekeren, dessverre, ikke lagre matrisen dimensjon;. Det gjør ikke også fortelle deg at variabelen i spørsmålet er en matrise."

Nå som du bruker C ++, øke :: matrise er et bedre valg enn rå arrays. Fordi det er et objekt, vil du ikke miste dimensjon info nå.

Svarte 18/03/2009 kl. 08:52
kilden bruker

stemmer
-2

Jeg tror du kan gjøre dette:

size_t size = sizeof(array)/sizeof(array[0]);

PS: Jeg tror at tittelen på dette emnet ikke er riktig, også.

Svarte 19/11/2012 kl. 17:49
kilden bruker

stemmer
-3

Dude du kan ha en global variabel til å lagre størrelsen på matrisen som vil være tilgjengelig gjennom hele programmet. Minst kan du passere størrelsen på array fra main () -funksjonen til den globale variabelen, og du vil ikke engang å endre metoden signaturen som størrelsen vil være tilgjengelig globalt.

Vennligst se eksempel:

#include<...>
using namespace std;

int size; //global variable

//your code

void doSomething(char charArray[])
{
    //size available

}
Svarte 16/01/2013 kl. 08:36
kilden bruker

stemmer
0

prøve å bruke strlen (charArray); ved hjelp av cstring topptekstfilen. Dette vil produsere antall tegn inkludert mellomrom til den når den avsluttende".

Svarte 07/06/2014 kl. 06:03
kilden bruker

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