46

背景:

在最高版本 9 的 Mac OS 版本中,文本文件的标准表示使用 ASCII CR(回车)字符(十进制值 13)来标记行尾。

Mac OS 10 与早期版本不同,它类似于 UNIX,并使用 ASCII LF(换行)字符(十进制值 10)来标记行尾。

问题是,在 OS X 之前的 Mac OS 版本中,字符常量'\n'和C 和 C++ 编译器的值是什么?'\r'

有(至少)两种可能的方法可以采取:

  1. 将其视为'\n'ASCII LF 字符,并在输出到文本流和从文本流输入时将其与 CR 转换(类似于 Windows 系统上的 LF 和 CR-LF 之间的转换);或者
  2. 视为'\n'ASCII CR 字符,不需要对输入或输出进行转换。

第二种方法会有一些潜在的问题。一是假设'\n'是 LF 的代码可能会失败。(无论如何,这样的代码本质上是不可移植的。)另一个是仍然需要有一个不同的值'\r',并且在基于 ASCII 的系统上 CR 是唯一合理的值。并且 C 标准不允许'\n' == '\r'(感谢 mafso 找到引用,5.2.2 第 3 段),所以有些必须'\r'.

当N小于 10在 Mac OS N下编译和执行时,这个 C 程序的输出是什么?

#include <stdio.h>
int main(void) {
    printf("'\\n' = %d\n", '\n');
    printf("'\\r' = %d\n", '\r');
    if ('\n' == '\r') {
        printf("Hmm, this could be a problem\n");
    }
}

这个问题适用于 C 和 C++。我想两者的答案都是一样的。

答案也可能因一个 C 编译器而异——但我希望编译器实现者能够保持彼此的一致性。

需要明确的是,我不是在问 Mac OS 的旧版本使用什么表示来表示文本文件中的行尾。我的问题是专门关于常量的值'\n'以及'\r'C 或 C++ 源代码中的值。我知道打印'\n'(无论它的值是什么)到文本流会导致它被转换为系统的行尾表示(在本例中为 ASCII CR);该行为是 C 标准所要求的。

4

5 回答 5

45

字符常量的值在经典 Mac OS 环境中\r\n在其他任何地方完全相同:\rCR 是否为 ASCII 13 ( 0x0d);\nLF 是 ASCII 10 ( 0x0a)。在 Classic Mac OS 上唯一不同的是它\r被用作文本编辑器中的“标准”行结尾,就像\n在 UNIX 系统或\r\nDOS 和 Windows 系统上使用的一样。

下面是一个在 Mac OS 9 上的 Metrowerks CodeWarrior 中运行的简单测试程序的屏幕截图,例如:

在 CodeWarrior 中运行的示例程序

请记住,经典 Mac OS 系统没有系统范围的标准 C 库!类似的函数printf()仅作为特定于编译器的库的一部分存在,例如 CodeWarrior 的 SIOUX,它通过将输出写入带有文本字段的窗口来实现 C 标准 I/O。因此,标准文件 I/O 的某些实现可能已经在\r和之间执行了一些自动转换\n,这可能是您所想的。\r\n(例如,如果您不将"b"标志传递给,许多 Windows 系统会执行类似的操作fopen()。)不过,Mac OS 工具箱中肯定没有类似的东西。

于 2014-07-31T19:07:36.703 回答
5

我进行了搜索,发现这个页面有一个旧的讨论,特别是可以找到以下内容:

Metrowerks MacOS 实现更进了一步,它颠倒了 CR 和 LF 在涉及文件的 i/o 中的 '\r' 和 '\n' 转义的重要性,但在任何其他上下文中都没有。这意味着如果您在文本模式下打开 FILE 或 fstream,每个 '\r' 都将作为 LF 输出,每个 '\n' 都将作为 CR 输出,输入也是如此 - 转义 - to-ASCII-binary 的对应关系是相反的。但是它们在内存中不会被反转,例如使用 sprintf() 到缓冲区或使用 std::stringstream。我发现这令人困惑,如果不是非标准的,至少比其他实现更糟糕。

事实证明,MSL 有一种解决方法 - 如果您以二进制模式打开文件,则 '\n' 总是 == LF 和 '\r' 总是 == CR。这就是我想要的,但在获得这些信息时,我也从那里的人们那里得到了很多理由,即这是获得我想要的东西的“标准”方式,当我觉得这更像是他们的错误的解决方法时执行。毕竟,CR 和 LF 是 7 位 ASCII 值,我希望能够以标准方式在文本模式下打开文件时使用它们。

(答案清楚地表明这确实违反标准。)

所以很明显,至少有一种实现使用\n\r通常的 ASCII 值,但将它们转换为(非二进制)文件输出(仅通过交换它们)。

于 2014-07-31T21:19:41.453 回答
2

在较旧的 Mac 编译器上,\r 和 \n 的角色颠倒了:我们有 '\n' == 13 和 '\r' == 10,而今天 '\n' == 10 和 '\r' == 13.过渡阶段非常有趣。使用旧编译器将 '\n' 写入文件,使用新编译器读取文件,并获得 '\r' (当然,这两次你实际上都有一个数字 13)。

于 2014-07-31T18:27:33.087 回答
1

我没有旧的 Mac 编译器来检查它们是否遵循这个,但是 的数值'\n'应该与 ASCII 换行符相同(假设那些编译器使用 ASCII 兼容编码作为执行编码,我相信他们做到了)。'\r'应该与 ASCII 回车具有相同的数值。

处理写入文本模式文件的库或操作系统函数负责将 的数值转换为'\n'操作系统用来终止行的任何值。这些字符在运行时的数值完全由执行字符集决定。

因此,由于我们仍然是 ASCII 兼容的执行编码,因此数值应该与经典 Mac 编译器相同。

于 2014-07-31T18:40:42.693 回答
1

C语言规范:

5.2.2
...
2 表示执行字符集中非图形字符的字母转义序列旨在在显示设备上产生如下操作:
...
\n(新行)将活动位置移动到下一行的初始位置.
\r(回车)将活动位置移动到当前行的初始位置。

所以\n代表该字符编码中的适当字符......在ASCII中是LF字符

于 2014-07-31T18:20:51.197 回答