Zum Inhalt springen

strtok - Tokens in Var. speichern


Empfohlene Beiträge

Geschrieben

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.

Geschrieben

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.

Geschrieben

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

Geschrieben
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.

Geschrieben

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;

}

Geschrieben
41 [Warning] comparison between pointer and integer
fgets kann nicht EOF zurückgegeben.

44 [Warning] passing arg2 of 'strtok' makes pointer from integer without a cast
Der zweite Parameter von strtok muss ein nullterminierter String sein, kein Einzelzeichen.

53 [Warning] passing arg1 of 'strcpy' makes pointer from integer without a cast
Siehe mein Hinweis zum Umwandeln von String nach int.

56 [Warning] passing arg2 of 'strtok' makes pointer from integer without a cast
Siehe Zeile 44.

64 [Warning] assignment makes pointer from integer without a cast
remove gibt kein FILE* zurück, sondern int.
Geschrieben (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 von therap
Geschrieben

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.

Geschrieben

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.

Geschrieben
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.

Geschrieben

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?

Geschrieben
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.

Geschrieben (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 von therap
Quelltext & Debug
Geschrieben

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.

Geschrieben

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.

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.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...