Hallo,
ich hab schon wieder ein Problem mit Listen oder auch mit den C++ Klassen:
int window::foren_fenster(string a) { ifstream foren(a.c_str()); int anzahl; foren >> anzahl; char *temp[anzahl]; for (int i=0; i<=anzahl; i++){ foren.getline(temp[i],80);///<-Hier müsste das Problem liegen } //Alles Curses Funktionen... noecho(); WINDOW *border = newwin(25,20,1,1); wattrset(border,COLOR_PAIR(4)); wborder(border,0,0,0,0,0,0,0,0); mvwaddstr(border,0,1,"Foren"); wrefresh(border); WINDOW *neu = newwin(23,18,2,2); waddstr(neu,temp[1]); wrefresh(neu); }
Ich habe hier also eine Datei, an deren Anfang die Anzahl der Einträge (Zeilen) steht (daher foren >> anzahl). Jetzt will ich jede Zeile in ein *char[n] reinschreiben. Alles was rauskommt ist ein wundervoller Speicherzugriffsfehler. Habt ihr einen Tipp was ich anders machen muss damit es funktioniert?
<endlos diskussion> Und um mal auf eure Diskussion um die für Einsteiger geeignetste Programmiersprache zu kommen: Am wichtigsten ist für einen Einsteiger (wie mich) eine gute Dokumentation. In TurboPascal war die integriert und einigermassen übersichtlich. Aber gerade jetzt, wo ich endlich mal c++ lernen will, fehlt mir einfach die Dokumentation! Ihr meint gar nicht wie lange man suchen/probieren muss bis eine ganz simple Funktion funktioniert. Und alles nur, weil nirgendwo steht was die Funktion genau macht. Ihr (als gestandene Programmierer) werdet jetzt freilich sagen, dass man das in den Headern der Funktion/Klasse nachlesen kann. Das ist aber für einen Einsteiger mehr als schwer, weil meist unverständlich. Für die meisten C Funktionen gibt es ja Informationen über Manpages. Für C++ hab ich sowas allerdings noch nicht gefunden.
Zu Kylix: Mir gefällt es auch nicht, aber eher dadurch dass der Einstieg durch die völlig unübersichtliche Oberfläche erschwert wird (wer sagt mir denn was das schön zusammengeklickte im Hintergrund wirklich macht). Da verliert man doch völlig die Kontrolle über seine selbstgeschriebenen Programme. Aber ich denke auch, dass Kylix für Delphi Entwickler sehr gut ist. Damit fangen vielleicht auch welche von denen an Programme für Linux zu schreiben. Und solange wir da neue gute Programme bekommen kann es uns doch egal sein wie die entstanden sind...
Letztlich soll sich doch jeder selber für die für ihn geeignetste Programmiersprache entscheiden. </endlos diskussion>
Hallo,
On Wednesday, 30. January 2002 23:30, Steffen Liebergeld wrote: [...]
char *temp[anzahl]; for (int i=0; i<=anzahl; i++){ foren.getline(temp[i],80);///<-Hier müsste das Problem liegen
[...]
Ich habe hier also eine Datei, an deren Anfang die Anzahl der Einträge (Zeilen) steht (daher foren >> anzahl). Jetzt will ich jede Zeile in ein *char[n] reinschreiben. Alles was rauskommt ist ein wundervoller Speicherzugriffsfehler. Habt ihr einen Tipp was ich anders machen muss damit es funktioniert?
Du schreibst in einen nicht allokierten Speicherbereich. Das Feld temp mußt du dir so vorstellen: (temp[0])(temp[1])(temp[2])(...) Jede der Runden Klammern (...) ist 4 Byte lang auf einem normalen x86-Rechner, weil es nur Pointer sind, die irgendwo hinzeigen, und keiner weiß wohin. Du müßtest also erst den Platz reservieren (in C wird das über malloc() gemacht), aber in C++ geht das viel besser: Du nimmst dir eine Liste von Strings, und verwendest weiterhin den operator>>, d.h. so wie du die erste Zeile einliest. Noch besser (und eleganter) ist es, die erste Zeile wegzulassen, und die Liste dynamisch zu erweitern bis die Datei zuende ist, z.B. über: list<string> a: a.push_back(s);
...
Letztlich soll sich doch jeder selber für die für ihn geeignetste Programmiersprache entscheiden.
Gut so... ich hab mir gerade ein paar COBOL-Quelltexte durchgelesen, eine Sprache die laut Statistik noch recht häufig in Firmen eingesetzt wird. Man sollte also zumindest eine Schmerzgrenze definieren :)
Josef Spillner
Am Mittwoch, 30. Januar 2002 21:50 schrieben Sie:
Hallo,
On Wednesday, 30. January 2002 23:30, Steffen Liebergeld wrote: [...]
char *temp[anzahl]; for (int i=0; i<=anzahl; i++){ foren.getline(temp[i],80);///<-Hier müsste das Problem liegen
[...]
Ich habe hier also eine Datei, an deren Anfang die Anzahl der Einträge (Zeilen) steht (daher foren >> anzahl). Jetzt will ich jede Zeile in ein *char[n] reinschreiben. Alles was rauskommt ist ein wundervoller Speicherzugriffsfehler. Habt ihr einen Tipp was ich anders machen muss damit es funktioniert?
Du schreibst in einen nicht allokierten Speicherbereich. Das Feld temp mußt du dir so vorstellen: (temp[0])(temp[1])(temp[2])(...) Jede der Runden Klammern (...) ist 4 Byte lang auf einem normalen x86-Rechner, weil es nur Pointer sind, die irgendwo hinzeigen, und keiner weiß wohin. Du müßtest also erst den Platz reservieren (in C wird das über malloc() gemacht), aber in C++ geht das viel besser:
ok, malloc also. Aber wie bekome ich den zeiger in mein programm wenn malloc void ist?
Du nimmst dir eine Liste von Strings, und verwendest weiterhin den operator>>, d.h. so wie du die erste Zeile einliest. Noch besser (und eleganter) ist es, die erste Zeile wegzulassen, und die Liste dynamisch zu erweitern bis die Datei zuende ist, z.B. über: list<string> a: a.push_back(s);
Strings würden mir nur dann was nützen wenn ich sie in *char[i] zurückverwandelt könnte. (n)curses geben nämlich in den waddstr() funktionen nur solche sachen aus. Aber strings sind doch im grunde auch nur char arrays oder?
On Fri, Feb 01, 2002 at 04:07:41PM +0000, Steffen Liebergeld wrote:
Am Mittwoch, 30. Januar 2002 21:50 schrieben Sie:
On Wednesday, 30. January 2002 23:30, Steffen Liebergeld wrote:
Hi Steffen,
<schnipp>
Du schreibst in einen nicht allokierten Speicherbereich. Das Feld temp mußt du dir so vorstellen: (temp[0])(temp[1])(temp[2])(...) Jede der Runden Klammern (...) ist 4 Byte lang auf einem normalen x86-Rechner, weil es nur Pointer sind, die irgendwo hinzeigen, und keiner weiß wohin. Du müßtest also erst den Platz reservieren (in C wird das über malloc() gemacht), aber in C++ geht das viel besser:
ok, malloc also.
Du solltest dich langsam mal entscheiden, ob du nun C _oder_ C++ programmieren möchtest ;) Unter C++ verwendet man zur Speicherallokierung das Schlüsselwort 'new'.
for (int i = 0; i < x; i++) tmp[i] = new char[80];
Um den Speicher wieder frei zu geben verwendet man nicht free() sondern 'delete'. Da du hier einen Array allokiert hast, musst du '[]' zwischen Schlüsselwort und Pointer setzen.
for (int i = 0; i < x; i++) if (tmp[i]) delete [] tmp[i];
Aber wie bekome ich den zeiger in mein programm wenn malloc void ist?
Genau so, wie du es unter C machen würdest: casten Nur das man unter C++ nicht () sondern dynamic_cast<> verwendet (wie ich seit kurzem weis :))
Unter C: time_t *ptr = (time_t*)malloc(sizeof(time_t));
Unter C++: AObject *ptrA = dynamic_cast<AObject*>ptrB;
Du nimmst dir eine Liste von Strings, und verwendest weiterhin den operator>>, d.h. so wie du die erste Zeile einliest. Noch besser (und eleganter) ist es, die erste Zeile wegzulassen, und die Liste dynamisch zu erweitern bis die Datei zuende ist, z.B. über: list<string> a: a.push_back(s);
Strings würden mir nur dann was nützen wenn ich sie in *char[i] zurückverwandelt könnte.
string mString = "Hallo Welt!"; printf("Text: %s\n", mString.c_str());
Ciao, Tobias
On Fri, Feb 01, 2002 at 04:07:41PM +0000, Steffen Liebergeld wrote:
Am Mittwoch, 30. Januar 2002 21:50 schrieben Sie:
On Wednesday, 30. January 2002 23:30, Steffen Liebergeld wrote: [...]
char *temp[anzahl]; for (int i=0; i<=anzahl; i++){ foren.getline(temp[i],80);///<-Hier müsste das Problem liegen
[...]
Hm. erstmal wieder OFF BY ONE. Wenn Du "anzahl" Elemente in Deinem Feld hast, dann kannst Du bestensfalls bis Index i = (anzahl - 1) zugreifen.
1 Element: Index 0 2 Elemente: Index 0 .. 1 3 Elemente: Index 0 .. 2 ...
Also:
for (int i = 0; i < anzahl; ++i) { ...
Und ++i ist m.E. schneller als i++, was aber hier wahrscheinlich unerheblich ist.
Dann mußt Du, wie andere auch schon schrieben, den Speicher besorgen für Deine Zeilen. Du hast nur ein Array (eine Liste) von Zeigern auf Zeichen. Aber die zeigen eben noch ins nichts.
Die klassische Variante wäre:
tmp[i] = (char*) malloc(80); // natürlich auch noch prüfen! Dazu passend dann irgendwann das free(tmp[i]) nicht vergessen!
Oder C++: tmp[i] = new char[80]; Dazu passend dann irgendwann delete tmp[i];
Oder die harte Tour: char tmp[80][anzahl]; Braucht dann kein delete oder free...
Strings würden mir nur dann was nützen wenn ich sie in *char[i] zurückverwandelt könnte. (n)curses geben nämlich in den waddstr() funktionen nur solche sachen aus. Aber strings sind doch im grunde auch nur char arrays oder?
Na ja, dynamischer sind sie. Und wenn Du sie als char* brauchst, dann
string.c_str()
oder Wenn Du ein einzelnes Zeichen brauchst:
string[i],
Was curses will, weiß ich nicht.
Heiko
Hallo Steffen,
On Wed, Jan 30, 2002 at 10:30:20PM +0000, Steffen Liebergeld wrote:
char *temp[anzahl];
Ein Feld mit Zeigern auch Zeichen.
for (int i=0; i<=anzahl; i++){ foren.getline(temp[i],80);///<-Hier müsste das Problem liegen
Du uebergibst an getline() einen Zeiger, den Du nie initialisiert hast. Dann muss getline fast zwangslaeufig einen Segfault liefern, wenn es versucht, dorthin zu schreiben, wo der Zeiger rein zufaellig hinzeigt. Mit etwas Pech machst Du damit den Stack kaputt...
Du musst schon die Zeiger so initialisieren, dass Du dort auch fuer 80 Zeichen Platz hast.
Gruss
Holger
On Wed, Jan 30, 2002 at 10:30:20PM +0000, Steffen Liebergeld wrote:
Und um mal auf eure Diskussion um die für Einsteiger geeignetste Programmiersprache zu kommen: Am wichtigsten ist für einen Einsteiger (wie mich) eine gute Dokumentation. In TurboPascal war die integriert und einigermassen übersichtlich. Aber gerade jetzt, wo ich endlich mal c++ lernen will, fehlt mir einfach die Dokumentation! Ihr meint gar nicht wie lange man suchen/probieren muss bis eine ganz simple Funktion funktioniert. Und alles nur, weil nirgendwo steht was die Funktion genau macht. Ihr (als gestandene Programmierer) werdet jetzt freilich sagen, dass man das in den Headern der Funktion/Klasse nachlesen kann. Das ist aber für einen Einsteiger mehr als schwer, weil meist unverständlich. Für die meisten C Funktionen gibt es ja Informationen über Manpages. Für C++ hab ich sowas allerdings noch nicht gefunden.
Speziell bei den C++-Klassen muss man allerdings dazu sagen, dass die wesentlich mehr als nur ein paar Funktionen sind. Die Ideen sind dann zm Beispiel, dass man Listen hat (maps), denen man unabhaengig vom Typ eine Sortierfunktion uebergeben kann, plus Sortierfunktions-templates, die Vergleiche a la "a < b" machen, und dann lediglich voraussetzen, dass die Klasse von a und b den kleiner-als-Operator unterstuetzt. Ziemlich schweres Konzept fuer den Anfang, das man erst dann toll findet, wenn man es einigermassen kapiert hat. Als Tip koennte ich dir da nur ein Buch empfehlen.
Ave' Stepardo
cu, Ulf
lug-dd@mailman.schlittermann.de