非常奇怪的行为 - printf&strcmp只在一行中忽略我的输入字符串

avi*_*i.c 4 c unix

这是代码:

printf("   DEBUG:%s\n" ,array[7] );
printf("address of %s is %p  (again %d)\n",
    array[7],
    array[7],
    strcmp("N\\A", array[7]) );

printf("5DEBUG collection:%s\n" ,array[7] );
Run Code Online (Sandbox Code Playgroud)

这是输出:

DEBUG:N\A

是0x7c0600(再次-13)

5DEBUG集合:N\A.

正如你所看到的,在第二个printf - 数组[7](需要指向"N\A")消失了.

我不知道这里发生了什么......

Ray*_*hen 15

您正在unix上读取Windows格式的文件.Windows和unix使用不同的行终止符.Unix使用0x0A,而Windows使用0x0D后跟0x0A.

如果文件中的行以0x0D 0x0A结尾,则unix会将0x00A视为行终止符,但将0x0D作为字符串的一部分.

你可以在你的strcmp回归中看到这个-13.请注意,它不会返回零,这意味着字符串不相等.实际上,差值是13,即0x0D的十进制值,它确认最后array[7]有一个0x0D.

另一个证据就是您所看到的奇怪的印刷行为.在unix上,打印0x0D会导致光标返回到同一行的第0列.因此,第二个打印指令从打印开始

address of N\A
Run Code Online (Sandbox Code Playgroud)

然后遇到0x0D,它将光标移回第0列.因此,字符串的其余部分会叠印输出,从而产生

 is 0x7c0600 (again -13)
Run Code Online (Sandbox Code Playgroud)

如果您尝试与在代码中设置断点调试器来调试程序,你会注意到,array[7]有一个0x0D底.

添加

这不是通灵调试.实际上非常简单.这是一步一步的:

  1. 当您注意到奇怪的行为时,您应该使用调试器来查看字符串array[7].如果你已经这样做了,你会看到尾随的0x0D,问题将在5秒内解决.
  2. 下一个巨大的线索是结果strcmp不是零.这意味着字符串in array[7]不等于"N\\A",这是你应该使用调试器查看字符串array[7]以查看其实际内容的下一个巨大线索.
  3. 没有调试的好处,我观察到array[7]和之间的区别"N\\A"必须是不容易看到的东西,因为第一行打印好了.这里的选项是控制字符或空格.
  4. strcmp报告差异的事实13表明字符串in array[7]在末尾有一个0x0D:"N\\A"\0(数值零)结束,差值为13表示array[7]以0x0D结束,因为0x0d十六进制= 13十进制.
  5. 如果你没有使用第4步中的逻辑,你可能已经停下来想:"哪些字符会弄乱打印?" 你跑下心理清单.空格,制表符(导致打印多个空格),回车(将光标返回到第0列),换行符(前进到下一行),换页(清除屏幕)和转义(引入控制台控制序列).匹配证据的是回车,其ASCII码为(惊讶)13.
  6. 如果您没有使用步骤4或5中的逻辑,那么您可能已经研究过Windows上不存在该问题的声明.Windows使用0x0D 0x0A作为其行终止符,而unix使用0x0A.额外的0x0D是一个回车符,它将光标返回到第0列,它再次匹配证据.

因此,有四种独立的方法可以进行相同的诊断.(如果算上五则"查看调试器中的字符串.")既然他们都同意了,这就得到了一个相当自信的结论.我的实际分析从第5步开始,然后使用其他步骤确认诊断.

  • 雷蒙德,你的半心理调试技能**比你的通灵调试技能更棒! (2认同)