为了准备天体赛选拔赛, 上星期所有课都用来做题了. 比赛结束以后开始补这周课堂所学的知识, 因此昨晚碰到了kmp这个可怕的东西. tm的看了好久还是搞不懂. 关于kmp算法晚点理清楚再发一篇.

回到正题, 昨晚看这辣鸡玩意的时候, 参考了无数博客后所写下来的代码运行的结果一直不对. 最后又拷了另外一个博客所写的代码, 一测试发现能出结果. 然后仔细对比对比两段代码的差别. 发现是如下的:

最初写的版本是带注释的 而后来能正常运行的是新添加的上下两行
简单的说下两者的区别
注释版本: 在while循环条件中才通过strlen函数获取字符串长度
非注释版本: 在循环外预先定义两个变量存放两个数组的长度 循环中使用这两个变量作为条件

有什么区别呢? 当初真是看了很久都没发现. 当时试过debug, 一步一步看. 发现当j为-1的时候 会跳出循环 但是没道理啊! -1 怎么可能大于 strlen(p) (为5) .   事实上 按照注释的写法是大于的(

最后在校内的acm群问了一下, 某师兄大佬发现了问题所在. 因为strlen函数返回的是一个size_t类型的值 也可以叫做unsigned int,这个东西在64位的系统中会为long unsigned int.

unsigned 无符号的意思, 而如果按照注释那样写, 当开始判断条件的时候, 因为strlen返回的是无符号类型, 会把比较的数转换为无符号类型. 而-1转化为无符号类型, 就是unsigned int的最大值 4294xxxxxx   那么自然就会比字符串长度大了 于是循环跳出.

下面放几张实验图:

该图可以清晰的表达出本文所想表达的意思

尝试把strlen(a)的结果输出为整型 编译器弹出警告 建议使用%lu格式 也就是 long unsigned
而后面的if语句结果。。 因为没有截图没有截上, 该图是在macOs环境截的 而这种警告在我win上的编译器不会显示(-x  于是, 再新添加一张图表明截图
 (来自于Luogu IDE

ok, 那么总的来说就是, 这次让我知道了原来使用strlen还有这样的秘密. 虽然我一般是不会在循环条件上写strlen 因为会很花时间, O(n)的时间复杂度会强行变成O(n^2). 这次虽然被这玩意坑了我4、5个小时… 搞的我心情都不好, 不过能发现这个坑 还是值得的

Categories: 学习日记

1 Comment

关于做题的一些注意事项 – Chino Home >.< · 2018年3月17日 at 19:17

[…] 4. 要使用strlen获取字符串长度并作为循环条件时,应定义变量储存长度并将该变量作为循环条件. 除非逼不得已, 否则不要在while的判断条件使用strlen函数 会费时不说, 当条件所判断的变量为负值的时候, 循环会出问题. 详细 […]

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Related Posts

学习日记

最小生成树学习总结

前言 今天学习的是最小生成树. 它包括两个算法. 分别是Prim和Kr Read more…

OIer

归并排序学习总结 & P1309

背景 之所以突然说到归并排序,是因为P1309这道题要用到&#8230 Read more…

OIer

队列和广度优先搜索

队列(queue) 队列是什么 队列是一种特殊的线性表. 是一种先进先 Read more…