2010-11-27 12 views
2

私はファイル(char、char、fgetc()を使用して)から行を読み込んでいますが、すべてのフィールド(firstname、lastname、...)は;。私が今したいことは、char**を作成し、すべての文字を追加して;\0に置き換えて、すべてのフィールドのリストを効果的に取得するようにします。c char *をcharに分割する**

実際には可能でしょうか? char **を作成すると、 char ** buf = malloc(80)私は1次元配列のように扱うことができますか? mallocによって返されたメモリが連続していれば?

EDIT

SRYは、\0、ボット\nによって;に代わるもの。

EDIT 2

このコードは、私が(ささいなことを明確にすること)するつもり何を証明する必要があります

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? 

答えて

1

それはあなたがそれを説明するように、正確に可能ではないですが、似た何かが可能です。 具体的には、例char **list = (char **)buf;の最後の行は、あなたが信じていることをしません。 char **list *が指す項目がchar*であることを意味しますが、内容は*bufです。したがって、あるものを別のものに変更することはできません。

char **は単なるポインタであり、単独では何も保持できないことを理解する必要があります。しかし、char **は、char *の配列の先頭アドレスになります。各フィールドは、char *です。

あなたは最初のmallocを使用してchar *アレイの領域を割り当てる必要があります(または、あなたもchar**の代わりにchar *の静的配列を使用することができます。あなたはまた、おそらくmalloc関数を実行し、すべての個々のフィールドのためのスペースを見つける必要があります最初のバッファを読み込んだ後に変更しないとフィールド名を保持することもできますが、最初に;\nに置き換えるだけで、末尾の0文字列ターミネータがない場合、1つのcharを2つのcharで置き換えることはできません。

以下は、何ができるかの簡単な例です例に、それは無駄に複雑になり、それは)別の話だ:

#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

はい、それは可能です。はい、1次元配列として扱うことができます。はい、メモリは連続しています。

しかし、あなたはおそらくしたい:

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

次に、あなたが行うことができます:

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

私が今やりたいが、**文字を作成すること

に、すべての文字を追加することです

char *(char **)の配列ではなく、文字を格納するchar(char *)の配列を割り当てます。

また、char * を作成すると、 char * buf = malloc(80)1次元配列のように扱えますか? mallocによって返されたメモリが連続していれば?

はい、mallocは常にcontingousブロックを返します。はい、char*80/sizeof char*要素)の配列を1次元として扱うことができます。しかし、この配列に格納されている各文字列に別々にメモリを割り当てるか、文字列データを格納する別のブロックを作成し、最初の配列を使ってそのブロックにポインタを格納する必要があります。

(または何か他のもの;この猫を肌にする方法はたくさん)

1

それはヘルパーメソッドは、ヌル文字で終わる文字列に書かれた「フィールド」のそれぞれを望んでいる可能性があります。分かりません。あなたはstrtok()でそれを行うことができます。しかし、strtok()は問題を抱えています。元の文字列を "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); 
}