2010-11-27 19 views
2

Ich lese in einer Zeile aus einer Datei (char von char, mit fgetc()), wo alle Felder (Vorname, Nachname, ...) durch ein getrennt sind ;. Was ich jetzt tun möchte, ist ein char** erstellen, fügen Sie alle Zeichen hinzu und ersetzen Sie die ; von \0, so dass ich effektiv eine Liste aller Felder erhalten.c Aufteilen eines char * in ein char **

Ist das möglicherweise möglich? Und wenn ich ein Char **, z. char ** buf = malloc(80) kann ich es wie ein eindimensionales Array behandeln? Wenn der Speicher von malloc zusammenhängend zurückgegeben wird?

EDIT

Sry, bedeutete ; von \0, bot \n zu ersetzen.

EDIT 2

sollten Dieser Code zeigen, was ich beabsichtige zu tun (ein wenig kann klären Dinge):

int length = 80; // initial length char *buf = malloc(length); int num_chars = 0; 

// handle malloc returning NULL 

// suppose we already have a FILE pointer fp for (int ch = fgetc(fp); ch != EOF && ferror(fp) == 0; ch = fgetc(fp)) { 
    if (length == size) { // expand array if necessary 
     length += 80; 
     buf = realloc(buf, length); 
     // handle realloc failure 
    } 

    if (ch == ';') { 
     buf[num_chars] = '\0'; // replace delimiter by null-terminator 
    } else { 
     buf[num_chars] = ch; // else put char in buf 
    } } 

// resize the buffer to chars read buf 
= realloc(buf, num_chars); 

// now comes the part where I'm quite unsure if it works/is possible 

char **list = (char **)buf; // and now I should be able to handle it like a list of strings? 

Antwort

1

Es ist nicht genau möglich, wie Sie es beschreiben, aber etwas Ähnliches möglich. Genauer gesagt, die letzte Zeile Ihres Beispiels char **list = (char **)buf; wird nicht tun, was Sie glauben. char **list bedeutet, dass Elemente, auf die mit * list gezeigt wird, vom Typ char* sind, aber der Inhalt von *buf sind Zeichen. Daher wird es nicht möglich sein, eines in ein anderes zu ändern.

Sie sollten verstehen, dass ein char ** nur ein Zeiger ist, kann es nichts von sich halten. Aber die char ** kann die Startadresse eines Arrays von char * sein, jedes char * zeigt auf ein Feld.

Sie müssen Speicherplatz zuweisen für die char * Array einen ersten malloc (oder Sie können auch eine statische Anordnung von char * anstelle eines char** verwenden. Sie werden auch Raum für jeden einzelnen Bereich finden müssen, wahrscheinlich eine malloc Durchführung Wenn der Anfangspuffer nach dem Lesen unverändert bleibt, ist es auch möglich, ihn zu verwenden, um die Feldnamen beizubehalten, aber wenn Sie einfach die ursprüngliche ; durch eine \n ersetzen, werden Sie fehlt der abschließende 0-String-Terminator, können Sie nicht ersetzen ein Char durch zwei Char.

Unten ist ein vereinfachtes Beispiel, was getan werden kann (entfernt malloc Teil, wie es nicht viel hinzufügen zum Beispiel, und es unnütz komplex macht, das ist eine andere Geschichte):

#include <stdio.h> 
#include <string.h> 

main(){ 
    // let's define a buffer with space enough for 100 chars 
    // no need to perform dynamic allocation for a small example like this 
    char buf[100]; 
    const char * data = "one;two;three;four;"; 

    // now we want an array of pointer to fields, 
    // here again we use a static buffer for simplicity, 
    // instead of a char** with a malloc 
    char * fields[10]; 
    int nbfields = 0; 
    int i = 0; 
    char * start_of_field; 

    // let's initialize buf with some data, 
    // a semi-colon terminated list of strings 
    strcpy(buf, data); 

    start_of_field = buf; 
    // seek end of each field and 
    // copy addresses of field to fields (array of char*) 
    for (i = 0; buf[i] != 0; i++){ 
     if (buf[i] == ';'){ 
      buf[i] = 0; 
      fields[nbfields] = start_of_field; 
      nbfields++; 
      start_of_field = buf+i+1; 
     } 
    } 

    // Now I can address fields individually 
    printf("total number of fields = %d\n" 
      "third field is = \"%s\"\n", 
      nbfields, fields[2]); 
} 
2

Ja, es möglich ist. Ja, Sie können es als eindimensionales Array behandeln. Ja, der Speicher ist zusammenhängend.

Aber Sie wollen wahrscheinlich:

char ** fields = malloc(sizeof(char *) * numFields); 

Dann können Sie tun:

// assuming `field` is a `char *` 
fields[i++] = field; 
1

ich jetzt tun möchte, ist ein Char erstellen **, fügen Sie alle Zeichen in diesem

Sie würden ein Array von char (char *) zuweisen, um die Zeichen zu speichern, nicht ein Array von char * (char **).

Und wenn ich ein char * , z. char * buf = malloc (80) kann ich es wie ein eindimensionales Array behandeln? Wenn der Speicher von malloc zusammenhängend zurückgegeben wird?

Ja, malloc gibt immer zusammenhängende Blöcke zurück. Ja, Sie können es als eindimensionales Array von char* (mit 80/sizeof char* Elementen) behandeln. Sie müssen jedoch für jede in diesem Array gespeicherte Zeichenfolge separat Speicher reservieren oder einen anderen Block zum Speichern der Zeichenfolgedaten erstellen und dann das erste Array zum Speichern von Zeigern in diesem Block verwenden.

(oder etwas anderes, viele Möglichkeiten, um diese Katze zu Haut)

1

Es kann sein, dass Helper-Methode jeder der „Felder“ will einen nul terminierten String geschrieben. Ich kann es nicht sagen. Das können Sie mit strtok() tun. Allerdings hat strtok() Probleme - es zerstört die ursprüngliche Zeichenkette "fed".

#define SPLIT_ARRSZ 20 /* max possible number of fields */ 
char ** 
split(char *result[], char *w, const char *delim) 
{ 
    int i=0; 
    char *p=NULL; 
    for(i=0, result[0]=NULL, p=strtok(w, delim); p!=NULL; p=strtok(NULL, delim), i++) 
    { 
      result[i]=p; 
      result[i+1]=NULL; 
    } 
    return result; 
} 

void 
usage_for_split(void) 
{ 
    char *result[SPLIT_ARRSZ]={NULL}; 
    char str[]="1;2;3;4;5;6;7;8;9;This is the last field\n"; 
    char *w=strdup(str); 
    int i=0; 
    split(result, w, ";\n"); 
    for(i=0; result[i]!=NULL; i++) 
     printf("Field #%d = '%s'\n", i, result[i]); 
    free(w); 
}