基于strtok统计字符串末位单词出现次数的代码异常排查
代码问题排查与修改方向
现有代码的核心逻辑偏差
你之前实现首个单词统计的逻辑是:第一次拿到切分结果就立刻确定目标词,后续所有切分结果都和这个目标词比对计数——这个逻辑对首个单词的场景是成立的,但硬套到最后一个单词的需求上,就会出现几个实打实的硬伤:
- 错配了从旧代码遗留的判断逻辑:初始化
nr=51试图靠递减到1来抓取最后一个单词,但nr的初始值和实际切出的单词数量没有任何关联。哪怕字符串只有3个单词,循环走完3次后nr只会从51降到48,永远触不到nr==1的判断分支,存目标词的strcpy(s1,p)根本不会被执行,s1全程是空值,后续的字符串比对全是无效操作。 - 统计时机完全错位:就算你能侥幸触发最后一个单词的存储分支,这个单词也是在循环的最后一次迭代才被存入
s1,在这之前的所有切分结果,因为目标词还没确定,strcmp的比对没有任何意义,自然统计不到正确的出现次数。 - 初始计数逻辑不匹配:你把
k初始化为1,是沿用了首个单词统计的设定——第一个单词本身就是目标词,所以从1开始计数。但在最后一个单词的统计场景下,你没有办法在一开始就确定目标词,这个初始值的设定从根上就不成立。 - 边界场景直接失效:如果输入字符串只有1个单词,按现有逻辑根本触发不了目标词存储的分支,统计结果必然和实际情况不符。
正确的修改方向
这个需求和首个单词统计的实现逻辑有本质区别,不能直接小改循环里的判断条件,得拆成两步走:
- 先把整个输入字符串按分隔符全部切分遍历,每拿到一个非空的切分结果,就把它覆盖存入临时存储区
s1——等所有单词切完,最后一次覆盖存入的内容自然就是字符串里的最后一个单词,也就是我们要统计的目标词。 - 等目标词完全确定之后,再重新遍历所有切出来的单词,逐次比对和目标词是否一致,累计相等的次数就是最终要输出的结果。
调整后的核心代码参考(完全沿用你原来定义的变量):
char s[51], *p, sep[]=" ,.", s1[21]; int k = 0; cin.get(s, 51); // 第一次遍历:确定最后一个单词作为统计目标 p = strtok(s, sep); while(p != nullptr) { strcpy(s1, p); // 每次覆盖,循环结束后s1存的就是最后一个单词 p = strtok(nullptr, sep); } // 第二次遍历:统计目标词的出现次数 p = strtok(s, sep); // strtok会直接修改原字符串结构,需要从头重新切分 while(p != nullptr) { if(strcmp(s1, p) == 0) k++; p = strtok(nullptr, sep); } cout << k;
注意:strtok函数在切分过程中会把原字符串里的分隔符替换成字符串结束标记,第一次切分完成后原字符串的结构已经被改变,所以第二次计数的时候必须重新把字符串头指针传给strtok,才能正常遍历所有单词。
内容的提问来源于stack exchange,提问作者Bredor
相关产品推荐
相关产品推荐

