我是C语言的新手,希望能够很好地理解来自Java背景的char数组赋值。我使用stringTok()
将本地sentence[]
数组拆分为单个数组字,并希望将该字分配给传入的char ** tokens
。我收到以下输出:
value of i:4
len:1 ,
len:1 ,
len:6 ,8?k
len:0 ,
有些人有价值(指定的值是胡言乱语)而有些人没有。我最初认为我必须为字符数组中的每个字符分配内存。但是,这似乎也没有用。所以,我想我一定做错了。我也尝试使用tokens[4][10]
代替char ** tokens
,但也没有任何区别。所以,我被困在这里已有一段时间了。
#include <string.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void stringTok(char** tokens)
{
int i = 0;
char sentence[] = "jake is really cool.";
char *word = strtok(sentence, " .");
while (word != NULL)
{
//printf("%s\n", word);
tokens[i++] = word;
word = strtok(NULL, " .");
}
printf("value of i:%d\n", i);
tokens[i] = NULL;
}
int main()
{
char **cmdArr = calloc(5, sizeof(char*));
for (int i = 0; i < 5; i++)
cmdArr[i] = (char*)calloc(10, sizeof(char));
stringTok(cmdArr);
for(int i = 0; i < 4; i++)
{
printf("len:%ld ,", strlen(cmdArr[i]));
printf("%s\n", cmdArr[i]);
}
return 0;
}
答案 0 :(得分:1)
您已为这些值分配了存储空间。主要的错误是你使用赋值思维它会复制你的字符串。相反,它覆盖了指向strtok
返回的临时指针。
快速解决方法是:
while (word != NULL) {
strcpy(tokens[i++], word);
word = strtok(NULL, " .");
}
你应该小心点。您的字符串仅支持10个字符(包括空终止符)。通常,您会使用strncpy
,如果源字符串对于您可用的存储量太长,它将停止。这有助于避免诸如缓冲区溢出之类的不良内容,这些内容会产生未定义的行为并产生通常在网络攻击中利用的漏洞。
更安全的方法可能是让您的标记生成器执行分配。
int tokenize( const char *sentence, char** tokens, int max_tokens )
{
const char * delim = " .";
int count = 0;
// Make copy of sentence for strtok
int len = strlen(sentence);
char *copy = malloc(len+1);
if( !copy ) return 0;
strncpy( copy, len, sentence );
copy[len] = '\0';
// Allocate and copy tokens
for( char *word = strtok(copy, delim);
word && count < max_tokens;
word = strtok(NULL, delim) )
{
int len = strlen(word);
tokens[count] = malloc(len+1);
if( !tokens[count] ) break;
strncpy( tokens[count], len, word );
tokens[count][len] = '\0';
count++;
}
return count;
}
现在,这有点傻。由于您已经复制了原始文件并且strtok
将要插入终结符,因此无需分配和复制所有内容。您可以将copy
存储在tokens[0]
中,然后将word
存储在每个后续指针中。调用者只需要知道清理内存它只需要free(tokens[0])
和永远其他任何一个(只是指向该块的指针)。