Aufgabe zum Üben
-
Hallo,
zum Üben mache ich so Übungen.
Leider komme ich bei einer nicht weiter.Schreiben Sie ein Programm, das Strings in einen Vektor einliest.
Kopieren Sie diesen Vektor in ein Array mit Zeichenzeigern.
Weisen Sie für jedes Vektorelement ein neues Zeichenarray zu,
in das Sie die Daten des Elements kopieren.
Fügen sie in das Array mit Zeichenzeigern
einen Zeiger auf das Zeichenarray ein.
// mit Zeichenzeigern sind Arrays mit new und delete gemeint.
Wie soll ich da immer ein neues Zeichenarray zuweißen?
Mehrdimensionale Array darf ich nicht benutzen.
Soweit bin ich schon.
Aber wie soll ich für jedes Vektorelement ein neues Zeichenarray zuweißen?
ich weiß ja nicht wie viele Arrays ich brauche weil ich nicht weiß
wie viele eingelesen werden.#include <iostream> #include <string> #include <vector> using std::vector; using std::cout; using std::endl; using std::cin; using std::string; int main() { vector<string> svec; string buffer; while (getline(cin,buffer) ) svec.push_back(buffer); char *carr = new char[]; system("PAUSE"); return 0; }
-
Tip dazu: du kannst herausfinden wie viele Werte in deinem Vector drinstehn mit vector<T>::size() Dann sowas verwenden wie
char *carr = new char[svec.size()]; /* carr füllen */ size_t vecsize = svec.size(); for (size_t i = 0; i < vecsize; ++i) /* vector neu füllen */usw.
-
ist denke ich mal sowas gemeint:
int main() { std::vector<std::string> vec_data; // daten in vec_data einlesen ... char** arr_data(new char*[vec_data.size()](NULL)); for (std::size_t i(0); i < vec_data.size(); ++i) { arr_data[i] = new char[vec_data[i].length() + 1]; std::strcpy(arr_data[i], vec_data[i]); } // fertig ... for (std::size_t i(0); i < vec_data.size(); ++i) delete [] arr_data[i]; delete [] arr_data; }
-
ok danke.
ich habs jetzt mal so versucht:#include <iostream> #include <string> #include <vector> using std::vector; using std::cout; using std::endl; using std::cin; using std::string; int main() { vector<string> svec; string buffer; while (getline(cin,buffer) ) svec.push_back(buffer); char *carr = new char[svec.size()]; for (vector<string>::iterator iter = svec.begin(); iter != svec.end(); ++iter, ++carr) carr = *iter.c_str(); delete[]carr; system("PAUSE"); return 0; }Der Kompiler spuckt folgenden Fehler aus:
19 'class __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocatorstd::string > >' has no member named 'c_str'Also das c_str() um den String, auf den ich mit *iter zugreife in einen cstring zu verwandeln und in dann in carr einzulesen.
Warum funktioniert das nicht?
-
Das ist ein Problem mit der Operator-Rangfolge, das bereits in C existierte - und der Grund für die Einführung von -> war: Du mußt den Ausdruck klammern als "(*iter).c_str()" oder du verwendest "iter->c_str();".
PS: Aber tu dir selber einen Gefallen und arbeite mit std::string anstelle von dynamischen char-Arrays - mit dem jetzigen Code würdest du dir sowieso nur den Heap zerstören.
-
Scheint aber die (perverse) Aufgabenstellung zu sein.
-
ok danke so geht es :xmas1:
#include <iostream> #include <string> #include <vector> using std::vector; using std::cout; using std::endl; using std::cin; using std::string; int main() { vector<string> svec; string buffer; while (getline(cin,buffer) ) svec.push_back(buffer); const char *carr = new char[svec.size()]; for (vector<string>::iterator iter = svec.begin(); iter != svec.end(); ++iter, ++carr) { carr = (*iter).c_str(); cout << carr; } delete[]carr; system("PAUSE"); return 0; }Hierzu hätte ich noch 2 Fragen:
1. Verstehe ich nicht ganz WARUM man einen String in einen char einlesen kann.
carr = (*iter).c_str();
(*iter).c_str(); gibt doch einen cstring zurück (also mehrere chars) und carr erwartet doch nur einen char da es ein char Array ist !?!
2. Warum zerstört dieser Code den Heap?
Er funktioniert wunderbar - er gibt die gleichen Eingaben wieder aus.
-
zu 1.
carr ist ein const char* und (*iter).c_str() gibt einen const char* zurück. Klar kannst du den zuweisen. Es ist hier nur ziemlich sinnlos.
zu 2.
beiconst char *carr = new char[svec.size()];allozierst du Speicher und schreibst die dazugehörige Adresse nach carr.
Hiercarr = (*iter).c_str();überschreibst du diesen Zeiger wieder.
Hierdelete[]carr;versuchts du den Speicher wieder zu löschen. carr zeigt aber jetzt auf die letzte in der Schleife zugewiesene Adresse aus svec. Hier darfst du nichts freigeben.
-
zu 1.
carr ist ein const char* und (*iter).c_str() gibt einen const char* zurück. Klar kannst du den zuweisen. Es ist hier nur ziemlich sinnlos.jop schon aber wenn ich mir das so vorstelle...
(*iter).c_str(); gibt also z.b.wenn ich hallo welt eingebe
erstmal hallo zurück.
Und carr kann ja nur einen const char aufnehmen und nicht 6 const chars (hallo+0)Würde das mit einem char array auch/besser gehen?
also z.b. char[100] und dann dieser bekommt dann (*iter).c_str() zugewiesen.
-
carr ist kein const char sondern ein const char* und du übergibst an der Stelle keinen String sondern nur einen Zeiger darauf.
-
ok danke jetzt habe ich mir was anderes überlegt.
Ich gebe jetzt die einzelnen buchstaben der Strings in dem Vector
zurück und diese kommen in das array.
Aber das Programm funktioniert mal wieder nicht richtig zur Laufzeit.#include <iostream> #include <string> #include <vector> using std::vector; using std::cout; using std::endl; using std::cin; using std::string; int main() { vector<string> svec; string buffer; while (getline(cin,buffer) ) svec.push_back(buffer); char *carr = new char[svec.size()]; for (vector<string>::iterator iter = svec.begin(); iter != svec.end(); ++iter, ++carr) { // auf string zugreifen for (int i = 0; i != (*iter).size(); ++i, ++carr) // auf buchstabe zugreifen *carr = (*iter)[i]; // alle buchstaben in carr array übergeben cout << *carr; // und diese ausgeben } delete[]carr; system("PAUSE"); return 0; }
-
Versuchs mal so. (ungetestet weil zu müde)
int main() { vector<string> svec; string buffer; size_t maxlen(0); while (getline(cin,buffer) ) { svec.push_back(buffer); maxlen = max(maxlen,buffer.size()); } size_t count(svec.size()); char **carr = new char*[count]; for( size_t i=0; i<count; ++i) carr[i] = new char[maxlen]; for (vector<string>::iterator iter = svec.begin(); iter != svec.end(); ++iter, ++carr) { // auf string zugreifen strcpy(carr,iter->c_str()); cout << *carr; // und diese ausgeben } for( size_t i=0; i<count; ++i) delete[] carr[i]; delete[]carr; system("PAUSE"); return 0; }
-
ok vielen dank so gehts.
Weiß noch einer warum das obere Programm nicht Funktioniert hat?
Also das mit die Buchstaben einzeln übergeben
-
Weil wahrscheinlich dein carr zu klein ist. Du lengst es mit der Größe der Anzahl der eingelesenen Strings an willst aber die Zeichen aus den einzelnen Strings reinkopieren. Natürlich kann einer der Strings mehr Zeichen enthalten als in carr reinpassen. Außerdem dereferenzierst du carr beim Ausgabe. Da kommt dann nur das erste zeichen raus.
carr ist eben ein Array für einen String der angegeben Größe. Du brauchst hier aber ein Array von Strings.
Wenn du die Strings nicht speichern willst geht auch das hier.#include <iostream> #include <string> #include <vector> using std::vector; using std::cout; using std::endl; using std::cin; using std::string; int main() { vector<string> svec; string buffer; size_t maxlen(0); while (getline(cin,buffer) ) { svec.push_back(buffer); maxlen = max(maxlen,buffer.size()); } char *carr = new char[maxlen+1]; for (vector<string>::iterator iter = svec.begin(); iter != svec.end(); ++iter, ++carr) { // auf string zugreifen for (int i = 0; i < iter->size(); ++i, ++carr) // auf buchstabe zugreifen *carr = (*iter)[i]; // alle buchstaben in carr array übergeben carr[iter->size()] = '\0'; //Endnullbyte anfügen cout << carr; // und diese ausgeben } delete[] carr; system("PAUSE"); return 0; }
-
Schallalaa guckt mal auf die 1. seite @braunstein ... vllt fällt dir was auf ...
-
Danke Devil das funktioniert zwar,
aber das hier:char** arr_data(new char*[vec_data.size()](NULL));hab ich noch nicht gelernt in meinem Buch.
-
Hmm in dem Fall nicht wirklich nötig (also das "(NULL)"), bewirkt aber (sollte es zumindest), dass alle c-strings (char*) mit NULL initialisiert werden.
int main() { std::vector<std::string> vec_data; // daten in vec_data einlesen ... char** arr_data(new char*[vec_data.size()](NULL)); // array auf c-strings anlegen (c-string = char-array mit Nullterminierungszeichen) mit der Größe deines Vectors. for (std::size_t i(0); i < vec_data.size(); ++i) { arr_data[i] = new char[vec_data[i].length() + 1]; // c-string mit Größe des entsprechenden Elements des Vectors anlegen // + 1 für Nullterminierung! std::strcpy(arr_data[i], vec_data[i].c_str()); // c-string kopieren (da c-string groß genug, automatische Nullterminierung! } // fertig ... for (std::size_t i(0); i < vec_data.size(); ++i) // vec_data.size() darf sich nicht verändert haben! delete [] arr_data[i]; // c-string löschen delete [] arr_data; }...
-
(D)Evil schrieb:
Hmm in dem Fall nicht wirklich nötig (also das "(NULL)"), bewirkt aber (sollte es zumindest), dass alle c-strings (char*) mit NULL initialisiert werden.
ist unzulässig. Möglich ist bei Arrays nur Defaultinitialisierung.
char** arr_data = new char*[vec_data.size()]();Irgendein Grund, ständig alles zu klammern? Das ist so furchtbar unübersichtlich.
-
char** arr_data(new char*[vec_data.size()](NULL));
das mit NULL verstehe ich schon aber das char**
also Zeiger auf Zeiger oder wie kann ich das verstehen?
-
Flashgott schrieb:
char** arr_data(new char*[vec_data.size()](NULL));
das mit NULL verstehe ich schon aber das char**
also Zeiger auf Zeiger oder wie kann ich das verstehen?Richtig verstanden - arr_data ist ein Zeiger auf einen (char)Zeiger (und wird verwendet als Array von C-style Strings).
-
warum verwendet man nicht einfach einen Zeiger?
char* arr_data = new char[vec_data.size()]();