使用strtok在C中解析字符串

我有这个小源代码,用于测试解析类似于我需要在其他项目中使用的变量string

 #include  #include  #include  int main (void) { char string[] = "C-AC-2C-3C-BOB"; char* s; char* hand[3]; char* usr; s = (char*) calloc(1, sizeof(char)); hand[1] = (char*) calloc(3, sizeof(char)); hand[2] = (char*) calloc(3, sizeof(char)); hand[3] = (char*) calloc(3, sizeof(char)); usr = (char*) calloc(21, sizeof(char)); s = strtok (string,"-"); hand[1] = strtok (NULL, "-"); hand[2] = strtok (NULL, "-"); hand[3] = strtok (NULL, "-"); usr = strtok (NULL, "\0"); printf("%s:%s:%s:%s:%s\n", s, hand[1], hand[2], hand[3], usr); return 0; } 

问题是我得到了这些3C:AC:2C:3C:BOB是printf而不是C:AC:2C:3C:BOB

– – – -编辑 – – –

没有内存泄漏的代码。 问题仍然存在

 #include  #include  #include  int main (void) { char string[] = "C-AC-2C-3C-BOB"; char* s; char* hand[3]; char* usr; s = strtok (string,"-"); hand[1] = strtok (NULL, "-"); hand[2] = strtok (NULL, "-"); hand[3] = strtok (NULL, "-"); usr = strtok (NULL, "\0"); printf("%s:%s:%s:%s:%s\n", s, hand[1], hand[2], hand[3], usr); return 0; } 

您将数组hand声明为具有三个条目,然后使用索引13对其进行索引。 但是C中的数组具有从0size-1索引(例如,在您的情况下为2 )。

因此,您可以在数组的边界内写入/读取数据,从而导致未定义的行为。

将数组的索引更改为02 ,它应该可以正常工作。

在您的代码中,您有超出索引的问题,导致运行时出现未定义的行为:

 hand[3] = strtok (NULL, "-"); ^ printf("%s:%s:%s:%s:%s\n", s, hand[1], hand[2], hand[3], usr); ^ wrong index value 

记住,根据声明char* hand[3]; ,数组中的索引值以0开头char* hand[3]; 索引值可以是0到2

 #include  #include  #include  int main (void) { char string[] = "C-AC-2C-3C-BOB"; char* s; char* hand[3]; char* usr; s = strtok (string,"-"); hand[0] = strtok (NULL, "-"); hand[1] = strtok (NULL, "-"); hand[2] = strtok (NULL, "-"); usr = strtok (NULL, "\0"); printf("%s:%s:%s:%s:%s\n", s, hand[0], hand[1], hand[2], usr); return 0; } 

你不需要calloc你的指针,因为strtok()将返回一个有效的内存地址(实际上strtok()修改字符串并用空字符替换分隔符)。 另一个问题是数组的索引:在C中,索引从0开始。 hand的第一个元素是hand[0] ,最后一个是hand[2]

这是你的程序堆栈:

 +-----------------------+ | ... | |0x***00 hand[0] | | | |0x***04 hand[1] | | | |0x***08 hand[2] | | | |0x***0C hand[3] | <---hander[1] pointer this address | |______ hand[3] end here 

所以手[3]使用地址覆盖*手[1],这是3C来的

首先,您应该注释这些行以避免内存泄漏:

 s = (char*) calloc(1, sizeof(char)); hand[1] = (char*) calloc(3, sizeof(char)); hand[2] = (char*) calloc(3, sizeof(char)); hand[3] = (char*) calloc(3, sizeof(char)); usr = (char*) calloc(21, sizeof(char)); 

然后,在更改代码后,我在Windows和Linux中构建并运行结果,都没有得到意外的打印结果。