Permalänk
Medlem

Fylla en strängvektor i c++

Hej.

Jag har problem med att fylla en strängvektor i C++ och hoppas någon kan hjälpa mig.

#include <cstring> #include <cstdlib> #include <iostream> using namespace std; void fyllvektor(char &strang) { /* Här har jag problem */ } int main(void) { char strang[20][5]; fyllvektor(strang); for (i=0;i<5;i++) { cout << strang[i] << endl; } }

Om jag förstått rätt så skapar char strang[20][5] en vektor med 5 positioner och 20 tecken i varje position.

Har provat med alla sätt att tilldela strängar som jag kan komma på, däribland strcpy(strang[0], "text") osv.

I och för sig blir det även fel i funktionsanropet, man kanske inte kan använda callbyreference med vektorer?

Felmeddelandet blir
error: invalid initialization of non-const reference of type 'char&' from a temporary type 'char (*)[5]'
error: in passing argument 1 of 'void fyllvektor(char&)'

Visa signatur

Light travels faster than sound. Is that why some people appear to be smart before they speak?
It's a big rock. I can't wait to tell my friends. They don't have a rock this big.

Permalänk
Medlem

Jag blir förvirrad då du skriver char "strang[5][20];" en gång och char "strang[20][5];" en annan. Troligtvis menar du den sista, 5 strängar på 20 tecken var.

void fyllvektor(char **strang) { strcpy(strang[0], "foobar"); }

Du bör använda någon strängklass (bra träning att skriva själv), annars blir stränghanteringen jobbig. Lätt att få minnesläckor, överskridningar osv.

Rättning: char ** kompilerar visserligen, men det bör vara "char strang[20][5]"

Visa signatur

Perl - Made by Idiots, Java - Made for Idiots, C++ - Envied by Idiots

Permalänk
Medlem

Jag menade den andra, det stämmer.

Ska man alltså använda ** och inte &? Varför?

Visa signatur

Light travels faster than sound. Is that why some people appear to be smart before they speak?
It's a big rock. I can't wait to tell my friends. They don't have a rock this big.

Permalänk
Medlem

Det du försöker göra är inte möjligt med C-strängar (char-vektorer), i vart fall inte på det sätt du gör det. För det första är strang[] i sig en pekare så det är liksom ingen idé att att göra ett referensanrop. För det andra kan funktionen fyllvektor inte "veta" hur mycket minne som allokerats till strang[], eftersom C++ inte "lagrar" den informationen då pekaren används.

Använd hellre std::string, bättre och säkrare på alla sätt och vis.

Visa signatur

perga

Permalänk
Medlem

std::string försökte jag mig på, med strang[0].insert("text") men jag blev inte riktigt klok på det. Dessutom behandlar kursen inte den objektorienterade delen av c++ så jag vet inte om jag ska använda det.

med **strang istället för &strang återstår bara ett felmeddelande.

In function int main()':
error: cannot convert 'char (*)[5]' to 'char**' for argument '1' to 'void fyllvektor(char**)'

Då slog det mig att jag någon gång för länge sedan gjort något liknande, och satte

fyllvektor(&strang) som funktionsanrop, detta resulterade i felmeddelandet
error: cannot convert 'char (*)[20][5]' to 'char**' for argument '1' to 'void fyllvektor(char**)'.

Dvs, det gav inget.

Visa signatur

Light travels faster than sound. Is that why some people appear to be smart before they speak?
It's a big rock. I can't wait to tell my friends. They don't have a rock this big.

Permalänk
Medlem

Felet ligger i att din fyllvektor()-funktion aldrig kan "veta" vilka dimensioner den strang-vektor som deklareras i main() har. Det som skickas till funktionen är en minnesadress, varken mer eller mindre. Det innebär att om funktionsargumentet i fyllvektor() är char ** s, så saknar uttrycket s[1][2] mening i fyllvektor(), eftersom s inte har några dimensioner i den funktionen.

Följande kod fungerar dock:

#include <iostream> #include <cstring> #include <cstdlib> using namespace std; struct str { char s1[20]; }; void fyllvektor(str *, int); int main() { struct str strang[5]; fyllvektor(strang, 5); for (int i = 0; i < 5; i++) cout << strang[i].s1 << '\n'; return 0; } void fyllvektor(str * s, int b) { for (int i = 0; i < b; i++) { strcpy(s[i].s1, "foo bar"); s[i].s1[19] = '\0'; } }

Visa signatur

perga

Permalänk
Medlem

Använd std::string och std::vector.

#include <string> #include <vector> void fyll_vector( std::vector< std::string >& v ) { // lägger till 10 element i slutet av vectorn. for( int i = 0; i < 10; ++i ) v.push_back( "hejsan" ); } void fyll_vector2( std::vector< std::string >& v ) { // sätter varje element i vectorn till "hejsan" for( int i = 0; i < v.size(); ++i ) v[i] = "hejsan"; } int main() { std::vector< std::string > vector_of_strings; // skapar en tom vector fyll_vector( vector_of_strings ); std::vector< std::string > vec_of_str( 10 ); // skapar en vector med 10 element fyll_vector2( vec_of_str ); }

Blir mycket smidigare när du inte behöver hålla koll på storleken, kan lägga till element längst bak så sköter klassen om minneshantering själv.

Permalänk
Medlem

Tackar, använda sig av vector och push_back verkar väldigt smidigt.

Visa signatur

Light travels faster than sound. Is that why some people appear to be smart before they speak?
It's a big rock. I can't wait to tell my friends. They don't have a rock this big.

Permalänk
Medlem

Det är det verkligen Det är bra att man lätt kan byta ut vector mot tex list, eller deque som behållare utan att ändra mycket kod. För mer info om standardbiblioteket kan du alltid kolla:
http://www.cppreference.com/
http://www.josuttis.com/libbook/ (finns en del länkar där, boken är mycket bra om du vill ha en bok)