4

这是代码:

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] );

这是输出:

调试:不适用

是 0x7c0600(又是 -13)

5DEBUG 集合:N\A

如您所见,在第二个 printf - array[7] (需要指向 "N\A" )中消失了。

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

4

1 回答 1

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

然后遇到 0x0D,这会将光标移回第 0 列。因此,字符串的其余部分会叠印输出,从而导致

 is 0x7c0600 (again -13)

如果您尝试在调试器中使用代码上的断点调试程序,您会注意到末尾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表明字符串 inarray[7]末尾有一个 0x0D:"N\\A"以 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 开始,然后使用其他步骤来确认诊断。

于 2013-05-17T01:45:44.147 回答