访问在指向 strtok 的字符数组的指针中传递的变量时获取不正确的值
Getting incorrect values when accessing variables passed along in a pointer to a character array for strtok
这是我的代码
//Split up the config by lines
int x;
int numberOfConfigLines = 0;
for (x = 0; x < strlen(buffer); x++)
{
if (buffer[x] == '\n') {
numberOfConfigLines++;
}
}
char *configLines[numberOfConfigLines];
tokenize(configLines, buffer, "\n", numberOfConfigLines);
这个函数的想法是计算缓冲区中换行符的数量,然后使用以下方法将缓冲区拆分为一个 strtok 数组:
#include <string.h>
#include <stdlib.h>
void tokenize(char **arrToStoreTokens, char *delimitedString, char *delimiter, int expectedTokenArraySize) {
//Create a clone of the original string to prevent making permanent changes to it
char *tempString = (char *)malloc(strlen(delimitedString) + 1);
strcpy(tempString, delimitedString);
if (expectedTokenArraySize >= 1) {
arrToStoreTokens[0] = strtok(tempString, delimiter);
int x;
for (x = 1; x < expectedTokenArraySize; x++ ) {
arrToStoreTokens[x] = strtok(NULL, delimiter);
}
}
//Dispose of temporary clone
free(tempString);
}
如果我直接访问 arrToStoreTokens[0]
,我会得到正确的结果,但是当我尝试在 tokenize
函数结束后访问 configLines[0]
时,我会得到不同的结果(可以是未知字符或空)
此外,我相信这只是在我以 root 身份开始 运行 程序(针对不同的要求)后才开始发生 - 不过我可能错了。 -编辑:确认不是问题。
有什么想法吗?
strtok 不重新分配任何东西。它只对你给它的东西进行切割和指针。
您的数组存储 strtok 给您的指针,但不要复制内容。
因此,如果您释放 tempString
变量,则释放由 strtok 的 return 值指向的数据。你必须保留它并只在最后释放它。
或者您可以为 strtok 的每个 return 创建一个 strdup 以将其存储在您的数组中以制作每个令牌的真实副本,但在这种情况下,您必须释放每个标记在最后。
第二个解决方案如下所示:
void tokenize(char **arrToStoreTokens, char *delimitedString, char *delimiter, int expectedTokenArraySize) {
//Create a clone of the original string to prevent making permanent changes to it
char *tempString = (char *)malloc(strlen(delimitedString) + 1);
strcpy(tempString, delimitedString);
if (expectedTokenArraySize >= 1) {
arrToStoreTokens[0] = strdup(strtok(tempString, delimiter)); // Here is the new part : strdup
int x;
for (x = 1; x < expectedTokenArraySize; x++ ) {
arrToStoreTokens[x] = strdup(strtok(NULL, delimiter)); // Here is the new part : strdup
}
}
//Dispose of temporary clone
free(tempString);
}
并且在使用这个数组之后,你必须删除它,函数如下:
void deleteTokens(char **arrToStoreTokens, int arraySize)
{
int x;
for (x = 0; x < arraySize; ++x)
{
free(arrToStoreTokens[x]);
}
}
这是我的代码
//Split up the config by lines
int x;
int numberOfConfigLines = 0;
for (x = 0; x < strlen(buffer); x++)
{
if (buffer[x] == '\n') {
numberOfConfigLines++;
}
}
char *configLines[numberOfConfigLines];
tokenize(configLines, buffer, "\n", numberOfConfigLines);
这个函数的想法是计算缓冲区中换行符的数量,然后使用以下方法将缓冲区拆分为一个 strtok 数组:
#include <string.h>
#include <stdlib.h>
void tokenize(char **arrToStoreTokens, char *delimitedString, char *delimiter, int expectedTokenArraySize) {
//Create a clone of the original string to prevent making permanent changes to it
char *tempString = (char *)malloc(strlen(delimitedString) + 1);
strcpy(tempString, delimitedString);
if (expectedTokenArraySize >= 1) {
arrToStoreTokens[0] = strtok(tempString, delimiter);
int x;
for (x = 1; x < expectedTokenArraySize; x++ ) {
arrToStoreTokens[x] = strtok(NULL, delimiter);
}
}
//Dispose of temporary clone
free(tempString);
}
如果我直接访问 arrToStoreTokens[0]
,我会得到正确的结果,但是当我尝试在 tokenize
函数结束后访问 configLines[0]
时,我会得到不同的结果(可以是未知字符或空)
此外,我相信这只是在我以 root 身份开始 运行 程序(针对不同的要求)后才开始发生 - 不过我可能错了。 -编辑:确认不是问题。
有什么想法吗?
strtok 不重新分配任何东西。它只对你给它的东西进行切割和指针。
您的数组存储 strtok 给您的指针,但不要复制内容。
因此,如果您释放 tempString
变量,则释放由 strtok 的 return 值指向的数据。你必须保留它并只在最后释放它。
或者您可以为 strtok 的每个 return 创建一个 strdup 以将其存储在您的数组中以制作每个令牌的真实副本,但在这种情况下,您必须释放每个标记在最后。
第二个解决方案如下所示:
void tokenize(char **arrToStoreTokens, char *delimitedString, char *delimiter, int expectedTokenArraySize) {
//Create a clone of the original string to prevent making permanent changes to it
char *tempString = (char *)malloc(strlen(delimitedString) + 1);
strcpy(tempString, delimitedString);
if (expectedTokenArraySize >= 1) {
arrToStoreTokens[0] = strdup(strtok(tempString, delimiter)); // Here is the new part : strdup
int x;
for (x = 1; x < expectedTokenArraySize; x++ ) {
arrToStoreTokens[x] = strdup(strtok(NULL, delimiter)); // Here is the new part : strdup
}
}
//Dispose of temporary clone
free(tempString);
}
并且在使用这个数组之后,你必须删除它,函数如下:
void deleteTokens(char **arrToStoreTokens, int arraySize)
{
int x;
for (x = 0; x < arraySize; ++x)
{
free(arrToStoreTokens[x]);
}
}