我正在尝试对字符串进行标记。
存在于输入数组(char **)
中的行不同使用以下函数存储生成到不同数组中的不同标记。
int tokenize_string(int max_lines,char *input_lines[max_lines],char **tokens)
{
char *token;
int index,token_index=0;
for(index = 0; index < max_lines;++index)
{
token = strtok(input_lines[index]," ");
while(token != NULL)
{
tokens[token_index] = malloc(sizeof(char*));
tokens[token_index] = token;
token = strtok(NULL," ");
token_index++;
}
}
return token_index;
}
使用valgrind时会显示以下内容
==25710== Invalid write of size 8
==25710== at 0x400AA6: tokenize_string (functions.c:28)
==25710== by 0x400953: main (main.c:29)
==25710== Address 0x51c3048 is 0 bytes after a block of size 8 alloc'd
==25710== at 0x4C27A2E: malloc (vg_replace_malloc.c:270)
==25710== by 0x40091B: main (main.c:25)
==25710==
==25710== Invalid write of size 8
==25710== at 0x400ABA: tokenize_string (functions.c:29)
==25710== by 0x400953: main (main.c:29)
==25710== Address 0x51c3048 is 0 bytes after a block of size 8 alloc'd
==25710== at 0x4C27A2E: malloc (vg_replace_malloc.c:270)
==25710== by 0x40091B: main (main.c:25)
我知道问题出在malloc
和for
循环上。
//编辑
int main(int argc,char *argv[])
{
int max_lines = atoi(argv[1]);
char *input_lines[max_lines];
char **tokens;
char *output_string;
int token_index;
tokens=malloc(sizeof(char*));
get_input(max_lines,input_lines);
token_index = tokenize_string(max_lines,input_lines,tokens);
output_string= concat_string(tokens,output_string,token_index);
print_string(output_string);
}
void get_input(int max_lines,char *input_lines[max_lines])
{
int index;
printf("Enter %d lines",max_lines);
for(index = 0; index < max_lines;++index)
{
input_lines[index] = malloc(sizeof(char*));
fgets(input_lines[index],50,stdin);
}
}
有什么建议吗?
谢谢
答案 0 :(得分:2)
让我们仔细看看这两行:
tokens[token_index] = malloc(sizeof(char*));
tokens[token_index] = token;
在第一个中为指针分配空间并将其分配给tokens[token_index]
。下一行 重新分配 tokens[token_index]
指向不同的地方,丢失malloc
返回的指针。与拥有int
变量(让我们将其命名为i
)没有区别,正在做
i = 5;
i = 10;
然后想知道为什么i
不是5
。
如果调用函数中tokens
的生命周期小于(或等于)input_lines
的生命周期,那么您不需要在此处分配内存,来自{{{ 1}}(第二行)就足够了。
还有其他问题,例如你没有在任何地方增加token
。
至于&#34;无效写&#34;如果没有合适的Minimal, Complete, and Verifiable Example来说明如何调用此函数,很难说出来。
答案 1 :(得分:1)
在malloc()
中,您为指针本身分配空间,然后将值指定为指向该指针。下一行,你覆盖它。
假设您需要在此函数的生命周期后使用标记作为标记数组,您需要的是以下内容。您为tokens
数组中的标记包含的字符串创建空间,然后将其复制。
int tokenize_string(int max_lines,char *input_lines[max_lines],char **tokens)
{
char *token;
int index,token_index=0;
for(index = 0; index < max_lines;++index)
{
token = strtok(input_lines[index]," ");
while(token != NULL)
{
size_t len = strlen(token) + 1;
tokens[token_index] = malloc(len);
strcpy(tokens[token_index], token);
token = strtok(NULL," ");
}
}
return token_index;
}
另请注意,除非您在循环中的某处更改它,否则此函数将覆盖相同的token_index
。您还必须确保tokens[]
能够适合您需要创建的字符串的所有指针。
修改强>
好的,我会从一开始就开始工作,但是
tokens=malloc(sizeof(char*));
没有创建一个指向字符串的指针数组,因为我相信你期待的。这只是说tokens
指向一个内存区域,有足够的空间用于指向char
的单个指针。您需要预先指定的最大字符串数,或者找到提前知道的方法。
在get_input()
中,您正在做类似的事情 - 您使用
input_lines[index] = malloc(sizeof(char*));
尝试为新字符串创建空间,但这只是指向指向char
的指针。根据您的fgets()
电话和50个字符的限制,您只需执行
input_lines[index] = malloc(50);
这样你就可以拥有50个字符的空间。之后,您需要确保它是一个以空字符结尾的字符串。
最重要的一点是malloc(sizeof(char *))
NOT 为字符串分配空间,只为指针分配空间。这些不一样,我建议再多阅读一下here。
基本上,你似乎是在你正在分配的记忆范围之外写作。