#include <stdio.h>
#include <stdlib.h> // malloc
#include <string.h> // strlen
char** _malloc_2D_array (char** arg_2D_array,
int rows,
int cols,
int type)
{
int i = 0;
int j = 0;
if (type == 0)
{
arg_2D_array = malloc(sizeof(char**) * rows);
for (; i < rows; i++)
{
arg_2D_array[i] = malloc(sizeof(char*) * cols);
}
}
return arg_2D_array;
}
char** _strtok (char* arg_string, const char* arg_delimeter)
{
char** after_tokenization = _malloc_2D_array (after_tokenization, 10, 20, 0);
char* hold_chars_of_one_group = malloc(sizeof(char*) * strlen(arg_string));
int j = 0;
int i = 0;
int k = 0;
while (arg_string[i])
{
if (arg_string[i] != *arg_delimeter)
{
hold_chars_of_one_group[k] = arg_string[i];
k++;
}
else
{
after_tokenization[j] = hold_chars_of_one_group;
j++;
k = 0;
}
i++;
}
return after_tokenization;
}
int main()
{
char** p = _strtok ("anisha,kaul,shizuka,sharma", ",");
printf ("-%s- p is being printed:", *p);
return 0;
}
输出:
-sharmaa- p is being printed
我期待所有的话而不是最后一个。此外,还有一个额外的a
附加了打印的单词。为什么呢?
这一行:
after_tokenization[j] = hold_chars_of_one_group;
似乎也会覆盖2D数组中的地址。为什么?
答案 0 :(得分:2)
char** after_tokenization = _malloc_2D_array (after_tokenization, 10, 20, 0);
调用_malloc_2D_array
时,after_tokenization
仍然未初始化。 _malloc_2D_array
无法使用其值。这个论点完全是多余的。你是否将指针传递给malloc
?不,malloc返回指向你的指针。 _malloc_2D_array
也不例外。实际上,_malloc_2D_array
未使用arg_2D_array
的值,但会立即为其分配新值。 IOW,它只不过是一个局部变量。固定:
char** after_tokenization = _malloc_2D_array (10, 20, 0);
修复_malloc_2D_array(BTW为什么要在函数名称中添加下划线?它没有任何意义......)
char** _malloc_2D_array (int rows,
int cols,
int type)
{
int i = 0;
int j = 0;
char** result;
if (type == 0)
{
result = malloc(sizeof(char**) * rows); // BAD
糟糕!这里的星计数错误。我们回过头来回顾一些例子。
/* Example */ char* str = malloc (length+1);
/* Example */ int* array = malloc (sizeof(int) * array_length);
在上面的示例中,结果类型有一个星号,sizeof
的参数没有星号。您为类型X 分配内存并返回指向X 的指针。指向X的指针的类型比X本身多一个星。固定:
result = malloc(sizeof(char*) * rows); // GOOD
for (; i < rows; i++)
{
arg_2D_array[i] = malloc(sizeof(char*) * cols); // BAD
同样的错误。当你对它进行空终结时,请留空。定影: arg_2D_array [i] = malloc(sizeof(char)*(cols + 1)); // BETTER,sizeof(char)== 1根据定义,您可以跳过它: arg_2D_array [i] = malloc(cols + 1); //好的 } } 返回结果; }
好的,回到_strtok(顺便说一句,这是一个非常糟糕的功能名称)。
char* hold_chars_of_one_group = malloc(sizeof(char*) * strlen(arg_string)); // BAD
与上面相同的错误再加上一个:你还需要一个字符来保存空终止符。固定:
char* hold_chars_of_one_group = malloc(sizeof(char) * strlen(arg_string) + 1);
int j = 0;
int i = 0;
int k = 0;
while (arg_string[i])
{
if (arg_string[i] != *arg_delimeter) // BAD, that's not how strtok works
arg_delimeter
中有零个或多个字符,而您只使用第一个字符(不检查它是否存在)。您需要在arg_delimeter
修复:
const char* delim;
int found = 0;
for (delim = arg_delimiter; *delim && !found; ++delim) // delimiter is spelled this way
if (*delim == arg_string[i]) found = 1;
if (!found) // GOOD
继续:
{
hold_chars_of_one_group[k] = arg_string[i];
k++;
}
else
{
after_tokenization[j] = hold_chars_of_one_group; // PROBLEM
首先,hold_chars_of_one_group
不是以空值终止的。其次,这不是你复制字符串的方式。
hold_chars_of_one_group[k] = '\0';
strcpy(after_tokenization[j], hold_chars_of_one_group)
j++;
k = 0;
}
i++;
}
需要处理最后一个令牌,而不是由分隔符分隔。
hold_chars_of_one_group[k] = '\0';
strcpy(after_tokenization[j], hold_chars_of_one_group);
并以某种方式表明我们有多少令牌。通常这是通过NULL终止指针数组来实现的。
j++;
after_tokenization[j] = NULL;
return after_tokenization;
}
唉!现在测试:
int main()
{
char** p = _strtok ("anisha,kaul shizuka;sharma", ",; "); // use different delimiters
while (*p) // print all tokens
printf ("-%s-\n", *p++);
return 0;
}
为了完整性,这里是固定程序,不间断:
#include <stdio.h>
#include <stdlib.h> // malloc
#include <string.h> // strlen
char** _malloc_2D_array (int rows,
int cols,
int type)
{
int i = 0;
int j = 0;
char** result;
if (type == 0)
{
result = malloc(sizeof(char*) * rows);
for (; i < rows; i++)
{
result[i] = malloc(cols + 1);
}
}
return result;
}
char** _strtok (char* arg_string, const char* arg_delimeter)
{
char** after_tokenization = _malloc_2D_array (10, 20, 0);
char* hold_chars_of_one_group = malloc(sizeof(char) * strlen(arg_string) + 1);
int j = 0;
int i = 0;
int k = 0;
while (arg_string[i])
{
const char* delim;
int found = 0;
for (delim = arg_delimeter; *delim && !found; ++delim)
if (*delim == arg_string[i]) found = 1;
if (!found)
{
hold_chars_of_one_group[k] = arg_string[i];
k++;
}
else
{
hold_chars_of_one_group[k] = '\0';
strcpy(after_tokenization[j], hold_chars_of_one_group);
j++;
k = 0;
}
i++;
}
hold_chars_of_one_group[k] = '\0';
strcpy(after_tokenization[j], hold_chars_of_one_group);
j++;
after_tokenization[j] = NULL;
return after_tokenization;
}
int main()
{
char** p = _strtok ("anisha,kaul shizuka;sharma", ",; ");
while (*p)
printf ("-%s-\n", *p++);
return 0;
}
答案 1 :(得分:1)
使用您的代码,malloc()
不仅char **after_tokenization
空间,还需after_tokenization[j]
。after_tokenization[j]
。这是因为malloc()
没有指向内存中的任何位置,您需要使用after_tokenization[j] = hold_chars_of_one_group;
进行分配。
而不是:
after_tokenization[j]
哪个会覆盖after_tokenization[j] = malloc(strlen(hold_chars_of_one_group)+1);
的地址,您可以使用:
after_tokenization[j]
返回指向hold_chars_of_one_group
的有效指针,现在指针可以占用空间,因为它指向内存中有效的某个位置。您的代码仍然无法工作的原因是您需要将strcpy()
的内容复制到此指针中以等待占用空间。
可以使用<string.h>
strcpy(after_tokenization[j], hold_chars_of_one_group);
来完成此操作
after_tokenization[j]
现在您已将内容复制到after_tokenization[j]
。
注意:您可能需要添加空字节和char** after_tokenization = _malloc_2D_array(after_tokenization, 10, 20, 0);
的结尾,否则最终会导致未定义的行为。
另一点需要注意的是这一行:
after_tokenization
这会导致问题,因为{{1}}未在此处初始化,并且变量也是函数调用的参数也很尴尬。
此外,我认为我之前回答了一个非常相似的答案,并且我展示了一些可以完成很多这些事情的代码。