morytox Geschrieben 22. März 2010 Teilen Geschrieben 22. März 2010 Hi Leute. Bin beim programmieren auf nen fehler gestoßen , eigentlich wollte ich nur nen Chararray in nen String umwandeln aber da bekomm ich bei egal welcher methode nen Laufzeitfehler. Also er compiliert aber gleich dannach bekomm ich ein fehler von ******* ausgespuckt ... Bissel oll ... z.b. beim verwenden der funktion strlen hat wer ne ahnung von euch ? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 22. März 2010 Teilen Geschrieben 22. März 2010 Das kann passieren, wenn du strlen einen Nullzeiger oder einen Zeiger auf ein nicht nullterminiertes Array übergibst. Zeig doch mal ein wenig Code, dann kann man auch spezifischer helfen. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
El Ninjo Geschrieben 22. März 2010 Teilen Geschrieben 22. März 2010 Was für eine Fehlermeldung? Kannste sie mal posten? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
morytox Geschrieben 22. März 2010 Autor Teilen Geschrieben 22. März 2010 ifstream file("dictlst.csv"); string line if(file.is_open()) { while(!file.eof()) { getline(file, line); char* wort=stringtoarray(line); cuts = tokenizer(wort, ';'); cout << strlen(cuts) << endl; Cuts ist nen zeiger (char*) mit der letzten zeile hat er dann seine Probleme. habe die beiden folgenden funktionen verwendet: String to array: #include <string> using namespace std; char* stringtoarray(string line) { char* charline=new char[line.length()]; for(int i=0; i<line.length();i++) charline[i]=line[i]; return(charline); } und den geschriebenen Tokenizer (hatte ich als ne art vorlage im netz gefunden , glaube hier is das Prob mit der Terminierung--> #include <stdio.h> #include <string.h> char* tokenizer(char* lines, char seperator) { char* curr = NULL; char* ret = NULL; static char* buffer = NULL; if(lines) { buffer = lines; } curr = buffer; if(curr) { while(*curr != seperator && (*(curr++)) != '\0'); if(*curr == '\0') { return NULL; } *curr = '\0'; ret = buffer; buffer = curr +1; } return ret; } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
unbenannt Geschrieben 22. März 2010 Teilen Geschrieben 22. März 2010 Was mir spontan auffällt: char* charline=new char[line.length()]; length() gibt meines Wissens die Anzahl der Zeichen des Strings zurück. Bei einem String mit n Elementen würde ein n-elementiges Array erzeugt. Für das Nullbyte, welches Du bei diesem Vorgehen selbst setzen müsstest, wird jedoch ein n+1-elementiges Array benötigt. while(*curr != seperator && (*(curr++)) != '\0'); if(*curr == '\0') { return NULL; } Abgesehen davon, dass hier auch strtok verwendet werden könnte: wird das Nullbyte erreicht, wird ein Nullzeiger zurückgegeben (siehe Post von Klotzkopp). Insgesamt erscheint mir diese Funktion etwas merkwürdig: Die Zeile wird einmal durchlaufen, bis entweder der Seperator oder ein Nullbyte gefunden wird. Bei Nullbyte erfolgt Rückgabe des Nullzeigers und dies wird nicht abgefangen. Wird der Seperator gefunden, wird dieser durch das Nullbyte ausgetauscht und das daraus entstehende Array zurückgegeben. Ob das wirklich das gewünschte Resultat erzeugt, wage ich zu bezweifeln. Baue doch ein paar Debug-Ausgaben ein und schaue Dir einmal an, was dort überhaupt geschieht. Oder schmeiß die Funktion gleich weg und schau Dir das Beispiel bei strtok an Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
morytox Geschrieben 23. März 2010 Autor Teilen Geschrieben 23. März 2010 danke für die schnelle antwort! Ich probier das mal ! Das war nach einer nich allzulanger recherche wohl ne akzeptable lösung ... wie gesagt das war auch nur nen abtippen. Ich versuch halt beides mal =) Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 23. März 2010 Teilen Geschrieben 23. März 2010 Du kannst dir eigentlich beide Funktionen sparen. Der Tokenizer ist offensichtlich in C geschrieben. In C++ versucht man, sich möglichst nicht mit rohen Zeigern und char-Arrays herumzuärgern. Damit hättest du auch nicht mehr das Problem, das jemand den in stringtoarray angeforderten Speicher wieder freigeben muss, weil es sonst ein Speicherleck gibt. Das Ganze könnte auch so aussehen: ifstream file("dictlst.csv"); string line; while(getline(file, line) ) { istringstream iss(line); string cuts; getline(iss, cuts, ';'); }[/code] Keine Zeiger, keine char-Arrays, keine aufwändigen zusätzlichen Funktionen, kein Speicherleck. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
morytox Geschrieben 23. März 2010 Autor Teilen Geschrieben 23. März 2010 Danke für deine antwort! Ist wahrscheinlich noch einfacher, aber kannst du mir den Teil in der while schleife erklären ? wo kommen die 3 oder mehr teile aus dem line string dann genau hin ? bzw. wann legt er was auf cuts? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 23. März 2010 Teilen Geschrieben 23. März 2010 wo kommen die 3 oder mehr teile aus dem line string dann genau hin ?Keine "3 oder mehr" Teile. Der Code liest aus jeder Zeile nur bis zum ersten Semikolon, genau wie dein ursprünglicher Code. Wenn du alle Teile auslesen willst, kannst du getline wieder in eine Schleife stecken. Getline funktioniert mit Stringstreams genauso wie mit Filestreams. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
morytox Geschrieben 23. März 2010 Autor Teilen Geschrieben 23. März 2010 ok da merk ich dasses mit meinen kenntnissen wohl doch noch nicht so gut gestellt ist ... kp ^^ Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
morytox Geschrieben 23. März 2010 Autor Teilen Geschrieben 23. März 2010 (bearbeitet) Sorry 4 Doppelpost aber ich hab nen neues Prob , hab es mich der Alten methode zum funzen gebracht (strtok).... jetzt hab ich das prob dass bei einigen wörtern manchmal "der" "er" oder sowas angehängt ist ... o.O in der datei Dictlst stehts aber richtig drin ... ich poste mal den text der aktuellen umsetzung: int l,i; int index=0; string line; ifstream myfile("dictlst.csv"); if(myfile.is_open()) { while(!myfile.eof()) { getline(myfile, line); index += 1; } index -=1; myfile.close(); cout << index << endl; } else cout << "Unable to open File" << endl; string vergl; char* verglwort=NULL; char* ger=NULL; char* engl=NULL; char* engl2=NULL; char* engl3=NULL; string gerstr,englstr,engl2str,engl3str; //index = listenlaenge l=randomlang(); i=randompos(index); char* cuts; string wortliste[5]; int indexnummer; cout << i << endl; ifstream file("dictlst.csv"); if(file.is_open()) { while(!file.eof()) { getline(file, line); char* wort=stringtoarray(line); int x = 1; int n = 0; bool y = true; char *str1; //cout << "String: " << wort << endl; str1 = strtok(wort, ";"); /* extract first string from string sequence */ indexnummer = atoi(str1); if (indexnummer == i) { //cout <<indexnummer<<endl << l <<endl; //cout << "i: " << x << str1 << endl; while (y == true) /* loop until finishied */ { str1 = strtok(NULL, ";"); printf("%i: %s\n", x, str1); /* extract string from string sequence */ switch(n) { case 0: ger=str1; break; case 1: engl=str1; break; case 2: engl2=str1; break; case 3: engl3=str1; break; default: cout << n << endl; break; } if (str1 == NULL) /* check if there is nothing else to extract */ { cout << "Tokenizing complete" << endl; y = false; } //cout << str1 << endl; x++; n++; } cout << "Indexnummer: " << indexnummer << " Deutsches Wort: " << ger << " 1. Englisches Wort: " << engl << endl; } } file.close(); } else cout << "Unable to open File" << endl; gerstr=arraytostring(ger); englstr=arraytostring(engl); Habe ne ausgabe gleich bei der tokenbestimmung eingesetzt und da kommt es schon vor ... csv datei ist wie gesagt sauber ... irgendwo kommen reste oder weiß ich was her die er anhängt ... und noch ein problem: wenn ich wörter mit leerzeichen eingebe erkennt er diese als 2 wörter o.O Bearbeitet 23. März 2010 von morytox Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 23. März 2010 Teilen Geschrieben 23. März 2010 Hast du deine stringtoarray-Funktion denn soweit repariert, dass sie eine Nullterminierung anhängt? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
morytox Geschrieben 23. März 2010 Autor Teilen Geschrieben 23. März 2010 Habe die Funktion jetzt wie folgt bearbeitet: #include <string> using namespace std; char* stringtoarray(string line) { char* charline=new char[line.length()+1]; for(int i=0; i<line.length();i++) charline[i]=line[i]; charline[line.length()]='\0'; return(charline); } Hab auch erstmal den Fehler mit falschem auslesen nicht enddecken können ... jedoch nur weil ich nicht ausfühlich testen kann da er keine strings mit leerzeichen annimt ... sobald eins drin is (eingabe) sieht er diese als 2 wörter ... kann man das umgehen ? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 23. März 2010 Teilen Geschrieben 23. März 2010 Fehlerquellen eliminieren: char* stringtoarray(string line) { char* charline=new char[line.length()+1]; strcpy(charline, line.c_str()); return charline; }[/code] Ein Speicherleck haben wir dann zwar immer noch, aber sonst sollte das so funktionieren. und noch ein problem: wenn ich wörter mit leerzeichen eingebe erkennt er diese als 2 wörter o.OIch sehe im Code keine Eingabeverarbeitung. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
morytox Geschrieben 23. März 2010 Autor Teilen Geschrieben 23. März 2010 das war weiter unten ... habe ich aber lösen können da cin >> xyz ja bekanntermaßen kein leerzeichen nimmt habe ich es dann über cin.getline gelöst Und die Probleme bei der fehlerkennun konnte ich auch allein irgendwie fixen... wenn ich mein programm ma optimieren will werd ich die ganzen zeilen hier einbaun . aber noch bin ich so in der lernphase dass ich möglichst viel selber schreiben möchte und wenig vorgefertigte funktionen nutzen möchte ... wenn ich weiß wies alles funzt nehm ich dann auch gern den sicheren kürzeren weg! Trotzdem danke für die hilfe ! Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
morytox Geschrieben 24. März 2010 Autor Teilen Geschrieben 24. März 2010 Neues Problem! Ich möchte nun eine Auswahl erstellen bei der Verschiedene Datein eingelesen werden können (versch. Vokabellisten) Wenn ich diese nun anwähle Legt er nen String auf ne Variable... ich zeigs einfach mal: so isses Ursprünglich gewesen: ifstream myfile("dictlst.csv"); if(myfile.is_open()) { while(!myfile.eof()) { getline(myfile, line); index += 1; } index -=1; myfile.close(); if(debug==true){ cout << "Indexgroesse betraegt: " << index << endl << endl; } } else cout << "Unable to open File" << endl; Jetzt wollte ich nen string unitifile machen auf dem dieser wert: "dictlst.csv" liegt und diesen anstelle des Strings verwenden. Das hat er nicht gemacht da er dafür keine Funktion kannte also so : ifstream myfile(unitifile); Der Folgende Code ist dann ne variante unter der es zu Kompilieren ging , aber das File kann er dann trotzdem nicht öffnen ... Wie kann ich an das Problem rangehn ? ifstream unitifile; if(unitifile.is_open()) { while(!unitifile.eof()) { getline(unitifile, line); index += 1; } index -=1; unitifile.close(); if(debug==true){ cout << "Indexgroesse betraegt: " << index << endl << endl; } } else cout << "Unable to open File" << endl; Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 24. März 2010 Teilen Geschrieben 24. März 2010 ifstream myfile(unitifile[B].c_str()[/B]); Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
morytox Geschrieben 24. März 2010 Autor Teilen Geschrieben 24. März 2010 (bearbeitet) Hat sich schon erledigt! index von pw war zu klein! und wieder nen Prob wo ich kp hab wo das herkommen soll -.-: char pw1,pw2,pw3,pw4,pw5,pw6,pw7,pw8; char pw[8]; system("cls"); cout << " Passworteingabe fuer den Debugmodus: "; pw1 = getch(); cout << "*"; pw2 = getch(); cout << "*"; pw3 = getch(); cout << "*"; pw4 = getch(); cout << "*"; pw5 = getch(); cout << "*"; pw6 = getch(); cout << "*"; pw7 = getch(); cout << "*"; pw8 = getch(); cout << "*"; cout << endl; system("cls"); for (int i=0; i<8 ; i++) { switch(i) { case 0: pw[i]=pw1; break; case 1: pw[i]=pw2; break; case 2: pw[i]=pw3; break; case 3: pw[i]=pw4; break; case 4: pw[i]=pw5; break; case 5: pw[i]=pw6; break; case 6: pw[i]=pw7; break; case 7: pw[i]=pw8; break; default: break; } } cout << pw[0] << pw[1] << pw[2] << pw[3] << pw[4] << pw[5] << pw[6] << pw[7] << endl; pass=arraytostring(pw); cout << pass << endl; Als laenge gibt mir strlen(pw) 24 aus obwohl sich doch nur 8 von 8 definierten darin befinden ... Die Ausgabe sieht auch komisch aus : erst das wort , dann nen paar sonderzeichen und dann das ganze wort nur umgekehrt o.O Funktion Arraytostring : #include <string> #include <iostream> using namespace std; string arraytostring(char* tempdat) { int lenge=strlen(tempdat); std::string tempstring(tempdat); return(tempstring); } Bearbeitet 24. März 2010 von morytox Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 24. März 2010 Teilen Geschrieben 24. März 2010 Als laenge gibt mir strlen(pw) 24 aus obwohl sich doch nur 8 von 8 definierten darin befinden ...Weil (schon wieder) die Nullterminierung fehlt. In C gibt es keine Strings. Darum benutzt man Arrays von char dafür. Arrays haben aber ein paar Eigenheiten. So geht beispielsweise die Größeninformation verloren, wenn man ein Array als Funktionsparameter übergibt. Darum hat man die Vereinbarung getroffen, dass das Ende eines Strings durch ein spezielles Zeichen markiert wird. Ansonsten weiß keine C-Funktion, wo dein String aufhört, weder strlen noch printf noch sonst irgendeine. Da du offenbar unbedingt mit rohen char-Arrays hantieren willst, musst du dich an diese Konvention halten. Funktion Arraytostring :Die ist komplett überflüssig. Die Variable "lenge" benutzt du nirgends. Und ansonsten rufst du nur den std::string-Konstruktor für char* auf. Das geht aber auch, ohne da noch eine Funktion drumherum zu stricken: // statt std::string s = arraytostring(einchararrayoderzeiger); // besser std::string s(einchararrayoderzeiger); [/code] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
morytox Geschrieben 26. März 2010 Autor Teilen Geschrieben 26. März 2010 Okay ... Prob again ... Jetzt bemerk ich dass ich nen Speicherleck habe wie ihr es mir gesagt habt ... Das is die Auslastung von meinem letzten Programmdurchlauf: Oben das ist noch ein unausgereifter algorithmus zur indexbestimmung um keine doppelten zu haben ... Kann mir das jemand mit dem Speicherleck erklären ? Es bringt mir nich viel wenn es mir wer sagt und ne andere Zeile code hinknallt ... lieber hab ich eine kleine Erklärung warum und dann kann ich es guten gewissens abändern. Schnmal Danke im voraus. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 26. März 2010 Teilen Geschrieben 26. März 2010 Du hast mindestens eine Stelle im Code, an der wiederholt ein malloc/new stattfindet, ohne dass der reservierte Speicher mit free/delete wieder freigegeben wird. So wird nach und nach immer mehr Speicher verbraucht. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
morytox Geschrieben 26. März 2010 Autor Teilen Geschrieben 26. März 2010 wahrscheinlich isses dieses stringtoarray von der letzten seite , hast du nen beispiel wie ich das dann wieder freigebe ? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 26. März 2010 Teilen Geschrieben 26. März 2010 wahrscheinlich isses dieses stringtoarray von der letzten seite ,Keine Ahnung, ich kenne den Rest deines Codes nicht. Vielleicht ist da irgendwo noch ein delete[]. Es ist auch nicht sicher, dass das das einzige Leck ist. Dein Programmiersteil zeigt eine gewisse Sorglosigkeit im Umgang mit dynamischem Speicher. Ich könnte mir vorstellen, dass es noch andere Stellen gibt. hast du nen beispiel wie ich das dann wieder freigebe ? Zum Beispiel so: delete[] wort; Das kommt dann dahin, wo du den dynamisch reservierten Speicher nicht mehr brauchst. Ich rede vermutlich gegen die Wand, aber wenn du das gleich mit den Klassen der Standardbibliothek statt mit rohen Zeigern gemacht hättest, hättest du dieses Problem jetzt nicht Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
morytox Geschrieben 26. März 2010 Autor Teilen Geschrieben 26. März 2010 ja ich bin ja auch erst im lernstadium ... will mich an das verhalten von code erstmal rantasten ... mit letzten seite meinte ich die seite 1 hier im thread im forum .. da hast du meine stringtoarray funktion schonmal unter die lupe genommen , is die einzige stelle wo ich ein new verwende.. kanns da liegen ? und wenn ja , muss ich das dann in der Funktion verwenden (das delete) oder kann ich dass auch im mein programmcode dann würde ich es nämlich nach dem parsen wieder freigeben... Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 26. März 2010 Teilen Geschrieben 26. März 2010 da hast du meine stringtoarray funktion schonmal unter die lupe genommen , is die einzige stelle wo ich ein new verwende.. kanns da liegen ?Dann wird's das sein. und wenn ja , muss ich das dann in der Funktion verwenden (das delete) oder kann ich dass auch im mein programmcode dann würde ich es nämlich nach dem parsen wieder freigeben...Du kannst es nicht in der Funktion machen, weil du den Zeiger auf den reservierten Speicher für die weitere Verarbeitung rausgibst. Wenn du ihn vorher wieder freigibst, gibt die Funktion einen ungültigen Zeiger zurück, und das Programm fliegt dir um die Ohren - wenn du Glück hast. Du speicherst den zurückgegebenen Zeiger ja in der Variablen wort. Es reicht also, wenn du nach der Verarbeitung das hier einbaust: delete[] wort; Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.