String stueckeln ohne strtok
-
Hallo,
ich werfe scheinbar andauernd die Zeiger durcheinander.
Das Programm soll Serverdaten einlesen und sie gestückelt in eine verkettete Liste packen.
Die Datei ist wie folgt aufgebaut:
servername;ip;login;pw;
Sprich alles durch ";" getrennt.
Ich habe mir eine printfausgabe mit strtok testweise ausgeben lassen. Nur funktioniert diese Funktion scheinbar nicht bei mir.
strtok(puffer,DELIMITER),strtok(NULL,DELIMITER)
Bei dem zweiten strtok gibt es Speicherprobleme.
Also möchte ich den string so splitten. Nur bei meinem jetzigem Stand meckert er bei allen vergleichen in der stueckeln funktion, dass ich char nicht mit const char vergleichen kann.
Hat wer eine Idee?
Danke im voraus.
int serverdaten_einlesen(struct element **liste) { FILE *serverliste; char puffer[ZEICHENLAENGE]; char puffer2[ZEICHENLAENGE]; serverliste = fopen("server.txt","r"); if (serverliste==NULL) { printf("Keine Serverliste vorhanden"); return EXIT_FAILURE; } while(fgets(puffer, ZEICHENLAENGE, serverliste)){ stueckeln(puffer,puffer2); getchar(); } }
void stueckeln(char puffer[ZEICHENLAENGE], char ausgabe[ZEICHENLAENGE]) { int j, k, i=0; while(puffer[i]!=DELIMITER){ if (puffer[i]=="\0") return; i++; } for (j=0;j<i+1;j++) { if(puffer[j]==DELIMITER||puffer[j]=="\0") break; ausgabe[j]=puffer[j]; } while (ausgabe[k+j+1]!="\0"){ ausgabe[k]=ausgabe[k+j+1]; k++; } ausgabe[k]="\0"; printf("Ausgabe: %s\n",ausgabe); }
-
kedas schrieb:
Ich habe mir eine printfausgabe mit strtok testweise ausgeben lassen. Nur funktioniert diese Funktion scheinbar nicht bei mir.
strtok(puffer,DELIMITER),strtok(NULL,DELIMITER)
Bei dem zweiten strtok gibt es Speicherprobleme.
Sah deine Zeile so aus?
printf("Erster: %s, Zweiter: %s\n, strtok(puffer,DELIMITER),strtok(NULL,DELIMITER));
Das funktioniert nicht, weil du nicht wissen kannst, in welcher Reiehnfolge die Parameter von printf ausgwertet werden.
Es kann zuerststrtok(NULL,DELIMITER)
"berechnet" werden. Nur worauf bezieht sich dann die NULL?
Andere Reihenfolge der Paramter ist auch keine Loesung, da es dafuer keine Vorschrift im Standard gibt.kedas schrieb:
.. dass ich char nicht mit const char vergleichen kann.
Da steht sicher noch ein Zeichen hinter
const char
. Ein *
Dann hast du kein Zeichen sondern einen Zeiger. Ein Stringliteral (Text in Anfuehrungszeichen) ist so ein Zeiger.Bei
if (puffer[i]=="\0")
vergleichst du ein char (puffer[i] mit einem const char* ("\0").Denke daran 0 ist etwas anderes als '0' ist etwas anderes als "0"
Wobei 0 und '\0' den gleichen Wert haben.Bei solchen Fehlermeldungen liefert der Compiler auch die Zeilennummer und oft auch die Spalte in der der Fehler auftritt. Diese Angaben sind auch fuer uns sehr hilfreich.
-
#include <string.h> // strchr, strlen, memcpy #include <stdlib.h> // malloc, free #include <stdio.h> // printf // List node typedef struct node_t{ char* s; // Node value struct node_t* next; // Next node } node; // Create list out of string tokens node* split_string(const char* s, const char delim){ // Empty list node* list = NULL; // Fill list const char* end; int token_len; node** plist = &list; do{ // Get token length token_len = (end = strchr(s, delim)) ? end-s : strlen(s); // Create list node *plist = malloc(sizeof(node)); memcpy(((*plist)->s = malloc(token_len+1)), s, token_len); (*plist)->s[token_len] = '\0'; (*plist)->next = NULL; // Set list pointer to next node plist = &(*plist)->next; // Set next token begin s = end+1; }while(end); // Return list return list; } // Program entry point main(){ // Input string const char s[] = "Hello;world;from;C;!"; // Create list node* list = split_string(s, ';'); // Output list node* cur_node = list; while(cur_node){ printf("%s\n", cur_node->s); cur_node = cur_node->next; } // Clean list cur_node = list; node* tmp; while(cur_node){ tmp = cur_node; cur_node = cur_node->next; free(tmp->s); free(tmp); } // End program with success code return 0; }
Rest solltest du selber schaffen.
-
Youka schrieb:
...
Rest solltest du selber schaffen.
Braucht er doch gar nicht.
Er muss nur seine strtok Aufrufe nacheinander ausführen.
-
DirkB schrieb:
kedas schrieb:
Ich habe mir eine printfausgabe mit strtok testweise ausgeben lassen. Nur funktioniert diese Funktion scheinbar nicht bei mir.
strtok(puffer,DELIMITER),strtok(NULL,DELIMITER)
Bei dem zweiten strtok gibt es Speicherprobleme.
Sah deine Zeile so aus?
printf("Erster: %s, Zweiter: %s\n, strtok(puffer,DELIMITER),strtok(NULL,DELIMITER));
Das funktioniert nicht, weil du nicht wissen kannst, in welcher Reiehnfolge die Parameter von printf ausgwertet werden.
Es kann zuerststrtok(NULL,DELIMITER)
"berechnet" werden. Nur worauf bezieht sich dann die NULL?Ich hatte es ja auch versucht nacheinander einzeln einem String zuzuweisen. Bei einer schrittweisen Ausführung funktionierte auch nur die erste Funktion.
-
kedas schrieb:
DirkB schrieb:
kedas schrieb:
Ich habe mir eine printfausgabe mit strtok testweise ausgeben lassen. Nur funktioniert diese Funktion scheinbar nicht bei mir.
strtok(puffer,DELIMITER),strtok(NULL,DELIMITER)
Bei dem zweiten strtok gibt es Speicherprobleme.
Sah deine Zeile so aus?
printf("Erster: %s, Zweiter: %s\n, strtok(puffer,DELIMITER),strtok(NULL,DELIMITER));
Das funktioniert nicht, weil du nicht wissen kannst, in welcher Reiehnfolge die Parameter von printf ausgwertet werden.
Es kann zuerststrtok(NULL,DELIMITER)
"berechnet" werden. Nur worauf bezieht sich dann die NULL?Ich hatte es ja auch versucht nacheinander einzeln einem String zuzuweisen. Bei einer schrittweisen Ausführung funktionierte auch nur die erste Funktion.
Ich nehme alles zurück. Verstehe nun meinen Fehler... das vereinfacht ziemlich viel. Danke nochmal.
-
Bedenke bitte, dass
strtok
den Originalstring zerstört. Es schreibt an die Stellen der Trennzeichen ein '\0'In stueckeln hättest du auch
strcpy
benutzen dürfen.
Und, das sehe ich erst jetzt, DELIMITER ist sicher auch ein Stringliteral.
Dann gehtpuffer[i]!=DELIMITER
natürlich auch in die Hose.
-
Hab es nun so gelöst. Zwar ist die verkettete Liste nun global, aber das hat andere Gründe.
Und ja ich hatte
#define DELIMITER ";"
definiert
int serverdaten_einlesen() { FILE *serverliste; char puffer[ZEICHENLAENGE]; struct element *puffer2; puffer2=(struct element*) malloc(sizeof(*puffer2)); serverliste = fopen("server.txt","r"); if (serverliste==NULL) { printf("Keine Serverliste vorhanden"); return EXIT_FAILURE; } while(fgets(puffer, ZEICHENLAENGE, serverliste)){ strcpy(puffer2->name, strtok(puffer,DELIMITER)); strcpy(puffer2->ip, strtok(NULL,DELIMITER)); strcpy(puffer2->db, strtok(NULL,DELIMITER)); strcpy(puffer2->logon,strtok(NULL,DELIMITER)); strcpy(puffer2->pw, strtok(NULL,DELIMITER)); append(puffer2); } fclose(serverliste); }
-
Was mir aufgefallen ist:
serverdaten_einlesen()
hat kein return, wenn die Datei geoeffnet werden konnte.Legt
append()
eine Kopie von puffer2 an?puffer2 wird nicht frei gegeben.
\n und das Leerzeichen wuerde ich auch noch mit in DELIMITER aufnehmen.