在C语言中,多字符是合法的吗?

6
我读到\n由CR和LF组成。它们各自有自己的ASCII码。
那么在C中,\n是由单个字符表示还是多个字符表示?
编辑:请明确您的答案,而不是简单地说“是”或“否”。

1
\n 在 ASCII 中表示 LF 或 0x0A \r 表示 CR 或 0x0D。 - Julien Roncaglia
“\n由CR和LF组成”?真的吗?你在哪里看到的?能提供一个链接或引用吗?这是一个奇怪的说法。 - S.Lott
@S.Lott,我认为这源于一些Windows应用程序同时使用\n\r来定义换行符。 - Paul Hadfield
在Windows中使用的"\n\r"与声称的"\n"是两个字符的说法相当不同。我想看到关于问题实际声称的引用或链接,因为这听起来很奇怪。 - S.Lott
维基百科对CRLF和LF背后的历史有着出色的讨论:http://en.wikipedia.org/wiki/Newline#History - hippietrail
显示剩余2条评论
9个回答

20

在C程序中,'\n'是代表行尾的一个字符。然而,一些操作系统(尤其是微软的Windows)在文本文件中使用两个字符来表示行尾,这很可能是引起混淆的原因。

C I/O函数的责任是在C表示的'\n'和操作系统使用的表示之间进行转换。

在C程序中,只需使用'\n'即可。这是保证正确的。当使用某种编辑器查看文本文件时,您可能会看到两个字符。当从Windows传输文本文件到某些基于Unix的系统时,每行末尾可能会出现"^M",这很烦人,但与C无关。


2
+1 正确答案。注意:每个操作系统都有自己特定的行尾序列。C I/O 运行时负责在 '\n' 和当前平台的行尾序列之间进行转换。注意:旧版 Mac 使用 '\r' 作为行尾序列。但在代码中始终使用 '\n'。 - Martin York
@Skumedel - 除了Windows,过去5年中发布的哪些操作系统使用除\n之外的其他东西?这并不是那么令人困惑 :) - Seth
2
@Skumedel - 实际上,如果你考虑一下,除了*nix和Mac OS经典之外,几乎所有东西都使用\r\n。以原始HTTP(或几乎任何基于文本的协议)头为例。 - Novikov
是的,我们真的需要结束这种混淆 ;) - MSalters
@Skurmedel:那只是个差笑话,你没看到笑脸吗? - MSalters
显示剩余4条评论

8
通常情况下,'\n'表示换行符,是一个单独的字符;'\r'表示回车符,也是一个单独的字符。它们是独立的 ASCII 字符。
问题在于,由于实际的文件表示方式不同,基于 UNIX 系统的系统会使用单独的'\n'表示换行符,而 Windows 则会使用'\r''\n'连续使用来表示一个换行符。
在文件中:
"This is my UNIX file\nwhich spans two lines"
"This is my Windows file\r\nwhich spans two lines"

当然,像所有的二进制数据一样,这些字符都是关于解释的,而这种解释取决于使用数据的应用程序。在处理C字符串时,请使用'\n',除非你需要一个字面上的回车,因为正如评论中指出的那样,操作系统表示对你不重要。IO库(包括C语言的)应该自己处理这个问题,并将其抽象化,远离你的视线。
为了满足你的好奇心,十进制下ASCII编码中的'\n'是10,'\r'是13,但请注意这是ASCII标准,而不是C语言标准。

@Andre:然后苹果公司采用了全新的基于Unix的系统(现在是真正的Unix)作为他们的操作系统。 - David Thornley
如果没有提供上下文,这个答案似乎有点令人困惑。\n 的使用位置和方式很重要;对于文本模式流,\n 会自动转换为必要的换行符序列(例如在 Windows 上的 \r\n)。 - jamesdlin
3
当'\n'被写入文件时(如果该文件处于文本模式),它将转换为特定于平台的EOL序列。当文件被读回到内存中时,EOL序列会被转换为字符'\n'。问题出现在一个文件保存在一个具有不同EOL序列的另一个平台上并被使用时。在内存中,EOL始终是'\n'。因此,在技术上讲,您的字符串示例并不完全准确,因为您应该提到这些是两个系统使用的文件格式。 - Martin York
1
"\n"并不一定是ASCII 10。 C标准并没有指定用于内部指定"\n"的字符是哪一个。 - JeremyP
@JeremyP:同意,但我的陈述仍然准确。 '\n' 在 ASCII 中始终为10。但是我已经更新了陈述,使其不那么模糊。谢谢。 - Chris Cooper

6

这要看情况而定:

  • '\n' 是一个单独的字符(ASCII LF)
  • "\n" 是一个 '\n' 字符后面跟着一个 0 终止符

某些 I/O 操作在某些系统上会将 '\n' 转换为 '\r\n' (CR-LF)。


所有基于文本的I/O操作在一些系统上将 '\n' 转换为 '\r\n'。 - user411313

4
当你使用Windows C标准库将\n打印到文件时,该库会将其解释为逻辑换行符,而不是字面上的字符0x0A。输出到文件的结果将是Windows版本的换行符:0x0D0A\r\n)。 写入 示例代码:
#include <stdio.h>
int main() {
    FILE *f = fopen("foo.txt","w");
    fprintf(f,"foo\nbar");
    return 0;
}

快速执行cl /EHsc foo.c命令,即可得到以下结果

0x666F6F 0x0D0A 0x626172 (separated for convenience)

在十六进制编辑器中查看foo.txt文件。

需要注意的是,如果您在“二进制模式”下写入文件,则不会进行此翻译。

读取

如果您使用相同的工具在Windows上将文件读回来,如果您尝试与\n匹配,则“Windows EOL”将被正确解释。

读取文件时

#include <stdio.h>
int main() {
    FILE *f = fopen("foo.txt", "r");
    char c;
    while (EOF != fscanf(f, "%c", &c))
        printf("%x-", c);
}

您可以获得

 66-6f-6f-a-62-61-72-

因此,这只有在以下情况下才与您相关:
  • 在Mac / Unix和Windows之间来回移动文件。Unix在这里不需要真正的解释,因为\n直接转换为这些平台上的0x0A。(在OSX之前,\n0x0D在mac上)
  • 将文本放入二进制文件中,请小心操作。
  • 尝试弄清楚为什么在打开文件“w”而不是“wb”时会破坏二进制数据。
  • 根据文件大小估算重要信息,在Windows上,每个换行符会多一个字节。

3

\n 是换行符——它是文本文件中分隔一行与另一行的逻辑表示。

不同的平台会有一些物理上的换行符表示。在Unix和大多数类似系统上,换行符由换行(LF)字符表示(由于Unix与C密切相关,所以在Unix上,LF通常被称为新行)。在MacOS上,它通常由回车(CR)表示。在许多其他系统上,尤其是Windows中,它由回车/换行对表示——通常是按顺序排列,但偶尔也会看到使用LF后跟CR的情况(据我记得,Clarion曾这样做过)。

从理论上讲,换行符实际上不需要对应流中的任何字符。例如,系统可以将文本文件存储为长度,后跟适当数量的字符。在这种情况下,运行时库需要执行比现在常见的更广泛的文本文件内部和外部表示之间的转换,但生活就是如此。


我觉得它不是一个逻辑表示,你知道的。在ASCII系统上的C语言中,('\n' == 10)保证为真。在进行IO时可能会将换行符转换为本地行结束符,但\n本身的含义总是表示换行符。 - Tom Anderson
@Tom:你并不能保证这一点。你只能保证当表示为char时,'\n'将具有正值——仅此而已。大多数实现确实使用值10,但它们完全可以合法地使用另一个值。 - Jerry Coffin

3
根据C99标准(第5.2.2节),\n“将活动位置[即下一个fputc字符出现的位置]移动到下一行的初始位置”。此外,\n会产生一个可以存储在单个char对象中的独特的实现定义值。文本文件中的外部表示不需要与内部表示完全相同,且超出了C99标准的范围。由于历史原因,大多数C实现选择将\n定义为ASCII换行符(0x0A)。然而,在许多计算机操作系统上,将活动位置移动到下一行开头的序列需要两个字符通常为0x0D、0x0A。因此,在写入文本文件时,C实现必须将0x0A的内部序列转换为0x0D、0x0A的外部序列。如何完成这项工作超出了C标准的范围,但通常情况下,文件IO库会对任何以文本模式打开的文件执行此转换。

2

您的问题是关于文本文件的。

文本文件是一系列行的序列。
是以(包括)换行符结尾的字符序列。
换行符在不同的操作系统中有不同的表示方式。

在 Unix/Linux/Mac 中,它们通常由单个 LINEFEED 表示。
在 Windows 中,它们通常由 CARRIAGE RETURN 和 LINEFEED 一对表示。
在旧版 Mac 上,它们通常由单个 CARRIAGE RETURN 表示。
在其他系统(AS/400 ??)中,甚至可能没有特定的字符表示换行...

无论任何系统上的表示方式如何,C 的库代码负责将系统的换行符转换为 '\n' 读取文本文件时,并在写入文本文件时执行反向操作。

因此,当您在 C 中读取文本文件时,无论任何系统上的表示方式如何,行都将以 '\n' 结尾。

注意:在所有系统中,'\n' 不一定是 0x0a


0

是的,没错。

\n 表示换行。十六进制代码为 0x0A。

\r 表示回车。十六进制代码为 0x0D。


0

这是一个单一的字符。它代表换行符(但不是唯一的表示方法 - Wikipedia)。

编辑:当我正在输入答案时,问题已经被更改了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接