使用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
声明为具有三个条目,然后使用索引1
到3
对其进行索引。 但是C中的数组具有从0
到size-1
索引(例如,在您的情况下为2
)。
因此,您可以在数组的边界内写入/读取数据,从而导致未定义的行为。
将数组的索引更改为0
到2
,它应该可以正常工作。
在您的代码中,您有超出索引的问题,导致运行时出现未定义的行为:
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中构建并运行结果,都没有得到意外的打印结果。