C 将动态字符数组转换为字符数组

C Turning a dynamic char array into an array of char arrays

我正在开发一个函数,它必须采用动态字符数组,在 space 处将其分开,然后将每个单词放入一个字符数组数组中。这是代码:

char** parse_cmdline(const char *cmdline)
{
    char** arguments = (char**)malloc(sizeof(char));
    char* buffer;
    int lineCount = 0, strCount = 0, argCount = 0;
    int spaceBegin = 0;
    while((cmdline[lineCount] != '\n'))
    {
        if(cmdline[lineCount] == ' ')
        {
            argCount++;
            arguments[argCount] = (char*)malloc(sizeof(char));
            strCount = 0;
        }
        else
        {
            buffer = realloc(arguments[argCount], strCount + 1);
            arguments[argCount] = buffer;
            arguments[argCount][strCount] = cmdline[lineCount];
            strCount++;
        }
        lineCount++;
    }
    arguments[argCount] = '[=10=]';
    free(buffer);
    return arguments;   
}

问题是我在途中的某个地方遇到了分段错误,但我不知道具体在哪里。 此外,该函数的当前版本假定字符串不以 space 开头,这是为了下一个版本,我可以处理,但我找不到 seg 的原因。故障

我要给的一些建议是,在调用 malloc 之前,您可能需要先计算您拥有的单词数。然后将 malloc 调用为 char ** charArray = malloc(arguments*sizeof(char*));。这将是 char ** charArray 的 space。然后 charArray 中的每个元素都应该根据您要存储在该元素中的单词的大小进行分配。然后您可以将该词存储在该索引中。 前任。 *charArray = malloc(sizeof(word)); 然后你可以将其存储为 **charArray = word;

但是要小心指针运算。

分段错误肯定是由于您试图访问未定义的数组中的元素而引起的 space。这是因为您没有为数组正确分配 space。

这段代码肯定不是你想要的:

char** arguments = (char**)malloc(sizeof(char));

它为一个 char 分配了足够大的内存块,并设置了一个 char ** (arguments) 类型的变量指向它。但是,即使您只想在 arguments 中为单个 char * 分配足够的 space,您分配的内容也是不够的(无论如何,在您可能遇到的任何 C 系统上都不够)。多指针肯定不够长

假设在您的 C 系统上指针确实比单个 char 更宽,您的程序一旦取消引用 arguments 就会调用未定义的行为。分段错误是更可能的结果之一。

最简单的方法可能是扫描输入字符串两次:一次计算单个参数的数量,以便您可以为指针分配足够的 space,然后再次创建单个参数参数字符串并在数组中记录指向它们的指针。

还要注意,return 值不包含任何有关分配了多少 space 或因此提取了多少参数字符串的可访问信息。解决这类问题的通常方法是为一个额外的指针分配 space,并将最后一个指向 NULL 的指针设置为哨兵。这与使用 null char 来标记 C 字符串的结尾非常相似,但并不相同。

编辑添加:

您想要的 arguments 分配更像这样:

arguments = malloc(sizeof(*arguments) * (argument_count + 1));

也就是说,分配 space 比参数多一个对象,每个对象的大小与 arguments 旨在指向的事物类型相同。 arguments 的值未被 sizeof 访问,因此此时不确定并不重要。

编辑添加:

最后的free()调用也有问题:

free(buffer);

此时,变量 buffer 指向与 arguments 的最后一个元素指向(或旨在指向)相同的分配块。如果释放它,那么 所有 指向该内存的指针都会失效,包括您即将 return 给调用者的指针。在那个时候你不需要释放 buffer 就像你在任何其他分配之后不需要释放它一样。

这可能是您出现分段错误的原因:

char** arguments = (char**)malloc(sizeof(char)); 中,您使用了 malloc (sizeof (char)),这分配 space 仅用于单个字节(足够 space 用于一个 char)。这不足以在 arguments.

中容纳单个 char*

但即使它在某些系统中,所以 arguments[argCount] 也只是读取为 argCount = 0 分配的内存。对于 argCount 的其他值,数组索引超出范围 - 导致分段错误。

例如,如果您的输入字符串是这样的 - "Hi. How are you doing?",那么在达到 \n 之前它有 4 ' ' 个字符,并且 argCount 的值会涨到 3.

你想要做的是这样的事情:

char** parse_cmdline( const char *cmdline )
{

为 1 个指针分配长度的参数指针数组,并用 0 初始化它。

char** arguments = malloc( sizeof(char*) );
arguments[0] = NULL;

在您的命令行中设置一个指向第一个 charchar* 指针并记住 第一个参数的开头

int argCount = 0, len = 0;
const char *argStart = cmdline;
const char *actPos = argStart;

继续,直到到达命令行末尾。 如果你找到一个空白,你就有了一个新的参数,它由 argStartactPos 之间的字符组成。从命令行分配和复制参数。

while( *actPos != '\n' && *actPos != '[=13=]' )
{
    if( cmdline[lineCount] == ' ' && actPos > argStart )
    {
        argCount++; // increment number of arguments
        arguments = realloc( arguments, (argCount+1) * sizeof(char*) ); // allocate argCount + 1 (NULL at end of list of arguments)
        arguments[argCount] = NULL; // list of arguments ends with NULL
        len = actPos - argStart;
        arguments[argCount-1] = malloc( len+1 ); // allocate number of characters + '[=13=]'
        memcpy( arguments[argCount-1], actPos, len ); // copy characters of argument
        arguments[argCount-1] = 0; // set '[=13=]' at end of argument string
        argStart = actPos + 1; // next argument starts after blank
    }
    actPos++;
}
return arguments;  

}