therap Geschrieben 11. Mai 2009 Geschrieben 11. Mai 2009 Hallo liebe Community, ich habe bevor ich diesen Fred eröffnet habe die SuFu benutzt - welche wenig aufschlusreich war. Folgende Angelegenheit, ich bin noch C - Anfänger und habe die Aufgabe mit Hilfe der strtok Funktion einen String zu teilen, welchen ich mir aus einer Datei hole. So weit kein Problem. Die Ausgabe des Strings bzw. der Teilstrings in der Standardausgabe stellen kein Problem dar. Da ich allerdings die Var. zu späteren Weiterverarbeitung zwischenspeichern muss bin ich z.Z. aufgeschmissen. google.de konnte mir auch nicht helfen. Ich möchte bzw. ich muss den Eingabestring in 3 Token teilen und 3 Variablen besitzen - kann mir bitte jmd. helfen? Danke im Voraus für Tipps, Lösungen etc. Zitieren
flashpixx Geschrieben 11. Mai 2009 Geschrieben 11. Mai 2009 Ich möchte bzw. ich muss den Eingabestring in 3 Token teilen und 3 Variablen besitzen - kann mir bitte jmd. helfen? Ich verstehe Dein Problem nicht, ggf postest Du bitte einmal den Quellcode und beschreibst das Problem deutlicher. Evtl hilft folgendes Bsp strtok - C++ Reference Phil Zitieren
therap Geschrieben 11. Mai 2009 Autor Geschrieben 11. Mai 2009 Hallo Phil, vll. habe ich mich falsch ausgedrückt. Ich versuche es nochmals. Ich habe einen String, welchen ich aus einer .csv Datei einlese. Um genauer zu sein einen Pfad, einen Dateinamen und einen "Operator", Bsp. String aus .csv Datei \\c:\qs\aktennotizen\;va-209.pdf;1 Ich öffne den Datenstrom, lese die erste Zeile ein. Speichere diese in einer Variablen. Nun möchte ich anhand der ';' den vorhandenen String teilen mit Hilfe von strtok. würde in der Standardausgabe so aussehen: \\c:\qs\aktennotizen\ va-209.pdf 1 Ich möchte den String bzw. die Teilstrings allerdings nicht auf dem Bildschirm ausgeben, sondern in Variablen speichern. Heißt: char pfad[50]; //\\c:\qs\aktennotizen\ char dateiname[50]; //va-209.pdf int operat; // 1 Ich habe allerdings keine Ahnung wie ich das anstelle. Zitieren
flashpixx Geschrieben 11. Mai 2009 Geschrieben 11. Mai 2009 Ich möchte den String bzw. die Teilstrings allerdings nicht auf dem Bildschirm ausgeben, sondern in Variablen speichern. Heißt: char pfad[50]; //\\c:\qs\aktennotizen\ char dateiname[50]; //va-209.pdf int operat; // 1 Ich habe allerdings keine Ahnung wie ich das anstelle. Eine Referenz zu strtok hatte ich gepostet. Vielleicht schaust Du Dir aber mal die Methoden "substr" und "find" aus der Stringklasse an, die könnten auch etwas für Dich sein. Vielleicht einmal zu Deiner Überlegung: Du hast einen String, in dem Du durch einen Separator getrennte Blöcke hast, Du suchst das erste Vorkommen des Separators und extrahierst den Teilsing von Beginn bis zum Zeichen vor dem Separator. Danach beginnst Du die Suche erneut vom Separator bis zum nächsten usw Phil Zitieren
unbenannt Geschrieben 12. Mai 2009 Geschrieben 12. Mai 2009 Vielleicht schaust Du Dir aber mal die Methoden "substr" und "find" aus der Stringklasse an, die könnten auch etwas für Dich sein. Ich nehme folgendes einmal wörtlich ich bin noch C - Anfänge "substr" und "find" gibt es doch nur in C++, oder? Ich möchte den String bzw. die Teilstrings allerdings nicht auf dem Bildschirm ausgeben, sondern in Variablen speichern. Bei eLook ist strtok ebenfalls schön beschrieben und mit einem Beispiel versehen. In Deinem Falle würde ich aber eher zu Phils Vorschlag tendieren. Die Separatoren selbst zu suchen und die Teilstrings manuell zu extrahieren bietet, insofern ich das richtig sehe (leider ja nicht immer der Fall), die schöne Möglichkeit, direkt den passenden Speicher für die Variablen anzufordern. Damit würdest Du dann nur belegen, was Du auch wirklich brauchst. Zitieren
Klotzkopp Geschrieben 12. Mai 2009 Geschrieben 12. Mai 2009 Ich habe allerdings keine Ahnung wie ich das anstelle.Strings kannst du mit strcpy kopieren. Für den int musst du den String, den dir strtok liefert, zunächst mit atoi in int umwandeln. Zitieren
therap Geschrieben 12. Mai 2009 Autor Geschrieben 12. Mai 2009 Hallo, danke für die fixe Hilfestellung, ich hab mal versucht die Aufgabe zu lösen - Hauptsache erstmal gelöst, auch wenn es vermutlich in euren Augen eine Schmuddellösung ist ;-) Ich bitte hierbei allerdings auch kurz um Hilfestellung da ich vorab folgende Fehlermeldungen bekomme: 41 [Warning] comparison between pointer and integer 44 [Warning] passing arg2 of 'strtok' makes pointer from integer without a cast 53 [Warning] passing arg1 of 'strcpy' makes pointer from integer without a cast 56 [Warning] passing arg2 of 'strtok' makes pointer from integer without a cast 64 [Warning] assignment makes pointer from integer without a cast #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define TOKEN_LENGTH 100 #define INPUTCSV "Steuerdatei.csv" #define MAX 200 int main(int argc, char *argv[]) { char pfad[TOKEN_LENGTH] = "", dateiname[TOKEN_LENGTH] = ""; char gesamte_zeile[MAX], pfad_file_out[MAX], *ptr_strtok; int operat, i=0; const char sep_char = ';'; struct tm *local; time_t t; FILE *file_in, *file_out, *log_file; t = time(NULL); local = localtime(&t); // .csv Datei öffnen file_in = fopen(INPUTCSV, "r"); // Fehlerbehandlung ( Öffnen von INPUTCSV ) if ((file_in = fopen(INPUTCSV, "r")) == NULL) { fprintf(log_file, "Kann '%s' nicht oeffnen\n", INPUTCSV); } // Log-File öffnen log_file = fopen("Log-File.txt", "w+"); // Fehlebehandlung Log-File if (NULL == log_file){ printf("Kann Log-Datei nicht erstellen\n"); fclose(log_file); } // Log-File INPUT erstellen fprintf(log_file, "'%s' : Log-File erstellt", asctime(local)); // Zeilenweise lesen aus .csv Datei while(fgets(gesamte_zeile, MAX, file_in) != EOF) { fputs(gesamte_zeile, file_in); // gesamte Zeile von .csv Datei zerlegen und in Variablen speichern mit strtok ptr_strtok = strtok(gesamte_zeile, sep_char); while (ptr_strtok != NULL) { i++; switch (i) { case 1: strcpy(pfad, ptr_strtok); break; case 2: strcpy(dateiname, ptr_strtok); break; case 3: strcpy(operat, ptr_strtok); break; } ptr_strtok = strtok (NULL, sep_char); // Dateiname an Dateipfad hängen // Addressierbar strcat(pfad_file_out, pfad); strcat(pfad_file_out, dateiname); switch (operat) { // File löschen case 1 : file_out = remove(pfad_file_out); fprintf(log_file, "'%s' : wurde geloescht", dateiname); break; // File kopieren case 2 : file_out = fopen(pfad_file_out, "w"); fprintf(log_file, "'%s' : wurde kopiert", dateiname); break; // File ersetzen case 3 : file_out = fopen(pfad_file_out, "w+"); fprintf(log_file, "'%s' : wurde ersetzt", dateiname); break; default : fprintf(log_file, "Konnte '%s' nicht oeffnen\n", pfad_file_out); }// switch (operat) }// while (ptr:strtok != NULL) }// Zeilenweise lesen // Streams freigeben fclose(file_in); fclose(file_out); fclose(log_file); system("PAUSE"); return 0; } Zitieren
Klotzkopp Geschrieben 12. Mai 2009 Geschrieben 12. Mai 2009 41 [Warning] comparison between pointer and integerfgets kann nicht EOF zurückgegeben. 44 [Warning] passing arg2 of 'strtok' makes pointer from integer without a castDer zweite Parameter von strtok muss ein nullterminierter String sein, kein Einzelzeichen. 53 [Warning] passing arg1 of 'strcpy' makes pointer from integer without a castSiehe mein Hinweis zum Umwandeln von String nach int. 56 [Warning] passing arg2 of 'strtok' makes pointer from integer without a castSiehe Zeile 44. 64 [Warning] assignment makes pointer from integer without a castremove gibt kein FILE* zurück, sondern int. Zitieren
therap Geschrieben 12. Mai 2009 Autor Geschrieben 12. Mai 2009 (bearbeitet) Hallo zusammen, ich konnte soweit sämtliche Fehler ausschließen bis auf die Sache mit dem atoi - habe mir zwar die Referenz davon durchgelesen. Wende diese aber offensichtlich falsch an, da der Compiler immer noch meckert. Ich habe folgende Zeilen zu meinem Quelltext hinzugefügt: int j; j = atoi ( operat ); da ich gerade privat unterwegs bin, habe ich den editierten Quelltext nicht. Habe beim Case 3 vor der eigentlichen Aktion dieses "j = atoi ( operat ) hinzugefügt. Vll. könnte mir jemand nochmals helfen? Vielen Dank im Voraus! Edit sagt: Werde den aktualisierten Quelltext morgen früh mal posten Bearbeitet 12. Mai 2009 von therap Zitieren
Klotzkopp Geschrieben 12. Mai 2009 Geschrieben 12. Mai 2009 Der Parameter von atoi muss der String sein, den du umwandeln willst. Das ist nicht operat. Das Ergebnis musst du der int-Variablen zuweisen, in der die umgewandelte Zahl stehen soll. Der Compiler beklagt sich vermutlich darüber, dass du einerseits atoi mit einem int-Parameter aufrufst, und andererseits in einem case-Block eine Variable definierst. Das geht nur, wenn du den ganzen Block in geschweifte Klammern steckst. Nicht dass das hier nötig wäre. Zitieren
therap Geschrieben 13. Mai 2009 Autor Geschrieben 13. Mai 2009 Wie folgt habe ich das nun verstanden: // Ausschnitt aus Quelltext. int main { int j; switch (i) { case 1: strcpy(pfad, ptr_strtok); break; case 2: strcpy(dateiname, ptr_strtok); break; case 3: j = atoi(ptr_strtok); strcpy(operat, j); break; } } Der Fehler besteht weiterhin. Zitieren
Klotzkopp Geschrieben 13. Mai 2009 Geschrieben 13. Mai 2009 Der Fehler besteht weiterhin.Geht's ein wenig genauer als "der Fehler"? Was willst mit j? Du brauchst keine weitere Variable, du hast doch bereits eine int-Variable, die den Wert aufnehmen soll. Und strcpy brauchst du dafür auch nicht. Zitieren
therap Geschrieben 13. Mai 2009 Autor Geschrieben 13. Mai 2009 Der Fehler lautete: "passing arg 1 of strcpy makes pointer from integer without a cast." Habe nachdem ich den Tritt vorm Kopf von dir bekommen habe, es nochmals versucht. switch (i) { case 1: strcpy(pfad, ptr_strtok); break; case 2: strcpy(dateiname, ptr_strtok); break; case 3: operat = atoi(ptr_strtok); break; } Compiler meckert nicht - nun kommt ein Segmentation fault. Eine Zugriffsverletzung hab ich noch nie gesehen. Ich nehme an diese Treten da durch auf, das ich versuche auf Speicher zu zugreifen der nicht für "mein" Programm reserviert ist, oder bereits einem anderem Programm "gehört"? Kann es auch sein, das ein s.g. Segmentation Fault durch Dateiströme entsteht? Zitieren
Klotzkopp Geschrieben 13. Mai 2009 Geschrieben 13. Mai 2009 Ich nehme an diese Treten da durch auf, das ich versuche auf Speicher zu zugreifen der nicht für "mein" Programm reserviert ist, oder bereits einem anderem Programm "gehört"?Richtig. In deinem Fall liegt es vermutlich daran, dass die weitere Verarbeitung (Zusammensetzen des Pfades, Dateioperationen) innerhalb deiner Einleseschleife geschieht, und damit schon beim ersten Schleifendurchlauf, also bevor überhaupt alle dafür notwendigen Daten eingelesen wurden. Das gehört also hinter die Einleseschleife. Zitieren
therap Geschrieben 13. Mai 2009 Autor Geschrieben 13. Mai 2009 (bearbeitet) Hallo, ich glaube es lag daran, dass ich in die Log-File etwas schreiben wollte - bevor ich einen Stream geöffnet habe? Sie Post 3. Ich bastel mal rum und zeige dann wieder den Quelltext. Edit sagt: Nach manipulieren/analysieren des Quelltextes fällt mir auf das, dass Segmentation fault auftritt - nachdem das Programm feststellt, dass keine .csv Datei vorhanden ist. Ich habe das Programm wie folgt geändert, allerdings tritt das Problem weiterhin in Zeile 37 & 38 auf. Selbst wenn keine .csv Datei gefunden werden kann. Möchte ich, dass der Benutzer keine Meldung sieht - dafür dient das Log-File. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define TOKEN_LENGTH 100 #define INPUTCSV "Steuerdatei.csv" #define MAX 200 int main(int argc, char *argv[]) { char pfad[TOKEN_LENGTH] = "", dateiname[TOKEN_LENGTH] = ""; char gesamte_zeile[MAX], pfad_file_out[MAX], *ptr_strtok; int operat, i=0, j; struct tm *local; time_t t; FILE *file_in, *file_out, *log_file; t = time(NULL); local = localtime(&t); // Log-File öffnen log_file = fopen("Log-File.txt", "w+"); // Fehlebehandlung Log-File if (NULL == log_file){ printf("Kann Log-Datei nicht erstellen\n"); fclose(log_file); } // Log-File INPUT erstellen fprintf(log_file, "'%s' : Log-File erstellt", asctime(local)); // .csv Datei öffnen file_in = fopen(INPUTCSV, "r"); fprintf(log_file, "'%s' wurde erfolgreich geoeffnet\n", INPUTCSV); // Fehlerbehandlung ( Öffnen von INPUTCSV ) if ((file_in = fopen(INPUTCSV, "r")) == NULL) { fprintf(log_file, "Kann '%s' nicht oeffnen\n", INPUTCSV); fclose(log_file); fclose(file_in); } // Zeilenweise lesen aus .csv Datei while(fgets(gesamte_zeile, MAX, file_in)) { fputs(gesamte_zeile, file_in); // gesamte Zeile von .csv Datei zerlegen und in Variablen speichern mit strtok ptr_strtok = strtok(gesamte_zeile, ";"); while (ptr_strtok != NULL) { i++; switch (i) { case 1: strcpy(pfad, ptr_strtok); break; case 2: strcpy(dateiname, ptr_strtok); break; case 3: operat = atoi(ptr_strtok); break; } ptr_strtok = strtok (NULL, ";"); }// while }// Zeilenweise lesen // Dateiname an Dateipfad hängen // Addressierbar strcat(pfad_file_out, pfad); strcat(pfad_file_out, dateiname); switch (operat) { // File löschen case 1 : remove(pfad_file_out); fprintf(log_file, "'%s' : wurde geloescht", dateiname); break; // File kopieren case 2 : file_out = fopen(pfad_file_out, "w"); fprintf(log_file, "'%s' : wurde kopiert", dateiname); break; // File ersetzen case 3 : file_out = fopen(pfad_file_out, "w+"); fprintf(log_file, "'%s' : wurde ersetzt", dateiname); break; default : fprintf(log_file, "Konnte '%s' nicht oeffnen\n", pfad_file_out); }// switch (operat) // Streams freigeben fclose(file_in); fclose(file_out); fclose(log_file); system("PAUSE"); return 0; } Bearbeitet 13. Mai 2009 von therap Quelltext & Debug Zitieren
Klotzkopp Geschrieben 14. Mai 2009 Geschrieben 14. Mai 2009 Erstens öffnest du die Eingabedatei zweimal (zähl mal die fopen-Aufrufe). Die Erfolgsmeldung gibst du allerdings aus, ohne das Ergebnis des ersten Versuchs zu prüfen. Zweitens ist es Unsinn, fclose aufzurufen, wenn das Öffnen fehlschlägt, weil es nichts zu Schließen gibt. Statt dessen solltest du die weitere Verarbeitung abbrechen oder den Fehler sonst irgendwie behandeln. Bisher gibst du nur eine Meldung aus und machst dann weiter, als wäre nichts passiert. Zitieren
therap Geschrieben 14. Mai 2009 Autor Geschrieben 14. Mai 2009 Nachdem ich mal richtig drauf geschaut habe und den Segmentation fault gesucht habe. Bin ich auch darauf gestoßen. Habe den Quelltext so weit angepasst, er läuft. Nur noch auf Funktionalität testen. Danke an alle Bei Bedarf poste ich den Quelltext nochmal. Zitieren
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.