C语言字符串分割函数解析:*token = '\0'语句作用疑问
1. *token = '\0';的作用
C语言中的字符串必须以**空终止符'\0'**作为结束标记,否则printf、strcpy这类字符串处理函数会从内存中持续读取数据,直到碰到随机的'\0',最终导致乱码甚至程序崩溃。
看splitter函数里的核心循环:
while (*str && (delimiter != *str)) { *token++ = *str; str++; }
这个循环会把分隔符(此处为:)之前的字符逐个复制到token指向的内存区域,每复制一个字符,token指针就向后移动一位。循环结束时,token已经指向了最后一个有效字符的下一个位置,此时执行*token = '\0';,就是在这个位置写入终止符,让刚才复制的字符序列变成合法的C字符串。
比如处理/bin时,循环会把/、b、i、n依次复制到数组中,token指针移到第5个位置(数组下标4),这里写入'\0'后,数组内容就变成{'/','b','i','n','\0',...},printf就能正确识别这是/bin字符串。
2. 为什么设置空终止符后main中的token仍能正确输出
你混淆了指针副本和原数组的区别:
splitter函数里的token是形参,它只是main函数中token数组的一个指针副本。- 循环里的
*token++ = *str;操作,是把字符写入到原数组的内存地址中,指针token自己只是向后移动,原数组里的有效字符已经被保存下来了。 - 最后
*token = '\0';只是在原数组的正确位置(有效字符的下一位)写入终止符,并没有覆盖之前复制到数组里的有效字符。
举个具体例子:
当处理/bin时,main里的token数组初始是随机值,调用splitter后,循环把/、b、i、n写入数组的0、1、2、3下标位置,token指针此时指向下标4的位置,*token = '\0';把下标4设为'\0'。此时main里的数组前5位是'/','b','i','n','\0',printf输出时读到'\0'就停止,自然能正确输出/bin。
再看连续冒号的情况:比如::,此时循环一次都没执行,token指针还是指向数组的起始位置(下标0),*token = '\0';把下标0设为'\0',也就是空字符串,这时候main里的判断token[0] == '\0'触发,把token改成./,所以输出里会有两行./。
内容的提问来源于stack exchange,提问作者Yoshiro

