c将char *拆分为char **

时间:2010-11-27 11:45:16

标签: c

我正在从文件中读取一行(char by char,使用fgetc()),其中所有字段(firstname,lastname,...)由;分隔。我现在要做的是创建一个char**,将所有字符添加到该字符并将;替换为\0,以便我有效地获取所有字段的列表。

这实际上可能吗?当我创建一个char **时,例如char ** buf = malloc(80)我可以将它视为一维数组吗?如果malloc返回的内存是连续的?

修改

Sry,意味着将;替换为\0,机器人\n

编辑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?

4 个答案:

答案 0 :(得分:2)

是的,这是可能的。是的,您可以将其视为一维数组。是的,记忆是连续的。

但你可能想要:

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

然后你可以这样做:

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

答案 1 :(得分:1)

  

我现在要做的是创建一个char **,将所有字符添加到

您将分配一个char(char *)数组来存储字符,而不是char *(char **)数组。

  

当我创建一个char * 时,例如char * buf = malloc(80)我可以将它视为一维数组吗?如果malloc返回的内存是连续的?

是的,malloc总是返回连续的块。是的,您可以将其视为一维char*(带80/sizeof char*个元素)的数组。但是你需要为存储在这个数组中的每个字符串单独分配内存,或者创建另一个用于存储字符串数据的块,然后使用你的第一个数组来存储指向该块的指针。

(或其他东西;很多方法可以给这只猫上皮)

答案 2 :(得分:1)

你所描述的并不完全可能,但类似的东西是可能的。 更具体地说,示例char **list = (char **)buf;的最后一行不符合您的要求。 char **list表示* list指向的项目属于char*类型,但*buf的内容是字符。因此,不可能将一个变为另一个。

你应该明白char **只是一个指针,它本身不能保留任何东西。但char **可以是char *数组的起始地址,每个char *指向一个字段。

您必须使用第一个malloc为char *数组分配空间(或者您也可以使用char *而不是char**的静态数组。您还必须为每个字段找到空间,可能为每个字段执行malloc并从初始缓冲区复制它。如果初始缓冲区在读取后未触及,也可以使用它来保存字段名称,但是如果你只是替换它;的初始\n,你将缺少尾随的0字符串终止符,你不能用两个字符替换一个字符。

下面是一个简单的例子,说明了可以做什么(删除了malloc部分,因为它没有为示例添加太多内容,并使其无用复杂,这是另一个故事):

#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]);
}

答案 3 :(得分:1)

Helper Method可能希望将每个“字段”写入以空字符结尾的字符串。我不能说。你可以用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);
}