'\r'转义序列有什么用途?

91

我有这样的C代码:

#include<stdio.h>
int main()
{
    printf("Hey this is my first hello world \r");
    return 0;
}

我尝试使用转义序列\r,作为一次实验。在运行代码时,输出结果如下:

o world
为什么会这样,\r 的作用是什么?如果我在在线编译器上运行相同的代码,输出结果将是:
Hey this is my first hello world

为什么在线编译器会忽略\r并产生不同的输出结果?


5
这应该完美回答了你的问题... https://dev59.com/G2445IYBdhLWcg3w6eVo - arijeet
8个回答

144

\r是一个回车符,它告诉你的终端仿真器将光标移动到行首。

光标是下一组字符将呈现的位置。

因此,打印\r可以覆盖终端仿真器中的当前行。

Tom Zych 指出了为什么在行末有\r而您没有在其后打印任何内容时,程序输出为o world

当您的程序退出时,shell会打印命令提示符。 终端会在您离开光标的地方呈现它。 由于您的程序将光标留在行首,因此命令提示符部分地覆盖了您打印的行。 这就解释了为什么您看到命令提示符后面跟着o world

您提到的在线编译器只会将原始输出打印到浏览器中。 浏览器会忽略控制字符,因此\r没有任何效果。

请参阅https://en.wikipedia.org/wiki/Carriage_return

以下是\r的用法示例:

#include <stdio.h>
#include <unistd.h>

int main()
{
        char chars[] = {'-', '\\', '|', '/'};
        unsigned int i;

        for (i = 0; ; ++i) {
                printf("%c\r", chars[i % sizeof(chars)]);
                fflush(stdout);
                usleep(200000);
        }

        return 0;
}

该代码会在同一位置反复打印字符-\|/,以营造一个旋转的|在终端上的假象。


你能详细解释一下“移动光标”是什么意思吗?然后我该如何得到“o world”? - Ant's
9
太好了:D 你给的示例程序非常完美!+1 - Ant's
你能解释一下 usleep 是做什么的吗? - Ant's
2
usleep函数可以让程序暂停指定的微秒数。 - Arnaud Le Blanc
你需要在其中某个位置使用 fflush... 如果变量 i 溢出程序最终将导致未定义行为,应将其声明为 unsigned - R.. GitHub STOP HELPING ICE
显示剩余2条评论

27
该程序正在打印 "Hey this is my first hello world ",然后将光标移回到行的开头。在屏幕上它的显示效果取决于您使用的环境。似乎字符串的开头被某些内容覆盖了,可能是您的命令行提示符。

赞一个,因为发帖人省略了命令提示符已经打印在输出之上的部分。 - R.. GitHub STOP HELPING ICE
嗯,我不知道那是否正确。这只是一个合理的猜测。 - Tom Zych

14
'\r'代表"回车符"——它是打字机和非常老的打印机时代的遗物。最好的例子是在Windows和其他DOSsy操作系统中,换行符被表示为"\r\n"。这些是发送给旧打印机开始新行的指令:首先将打印头移回开头,然后向下移动一行。
不同的操作系统将使用其他换行序列。Linux和OSX只使用'\n'。旧版Mac OS只使用'\r'。维基百科有一个更完整的列表,但这些是重要的。
希望这可以帮助你!
附:至于为什么会得到奇怪的输出...也许控制台正在将“光标”移到行的开头,然后用空格或summat覆盖第一位。

7

\r 将光标移动到行首。

不同系统使用不同的方式管理换行符。一些系统只使用\n(换行符,例如Unix),一些系统使用\r(例如早期的MacOS) ,还有一些系统使用 \r\n(例如Windows)。


1
Mac OS <= 9 使用\r,但是OS X基于Unix,所以使用\n - ughoavgfhw
2
不要混淆文件的行终止序列和交互式 shell 如何解释 '\r' 或 '\n' 字符。这是两个完全不同的主题。 - Martin York
1
如果这是真的,那么今天我确实学到了新东西。在我看来,这两个主题至少是密切相关的,因为在Unix I/O端口中,STDIN和STDOUT只是文件,而C++流可以用于文件以及控制台输出。而且据我所知,std::endl被定义为\n\r\r\n,具体取决于系统。但感谢您的建议,我会去了解一下。如果您能指引我一些指定差异的来源,我将不胜感激。 - Nornagest

2

回答你问题的一部分:

\r 的用途是什么?

许多互联网协议,例如FTP、HTTP和SMTP,都是以回车和换行符为界限来指定行的。因此,例如在发送电子邮件时,您可能会有以下代码:

fprintf(socket, "RCPT TO: %s\r\n", recipients);

或者,当FTP服务器回复权限被拒绝的错误时:

fprintf(client, "550 Permission denied\r\n");

2

正如amaud576875所说,\r转义序列表示回车符,类似于按Enter键。然而,我不确定你是怎么得到"o world"的;你应该(我也是)得到"my first hello world",然后是一个新行。根据你使用的操作系统(我使用的是Mac),你可能想使用\n代替\r


使用Ubuntu软件包中提供的编译器。 - Ant's
只需使用\n。在任何系统上都不需要\r。那些认为仍然需要它的愚蠢系统将在看到\n时插入一个。 - David Hammen

2

这段内容来自于过时的技术:老式打字机风格的打印机。它有一个滚筒(纸车)来推进纸张,同时有一个打印头用力敲击金属键盘来印刷字迹。

\r 将打印头返回到左侧。

\n 推进纸车一行。

如果不发出 \n 命令,你就会在已有文本上继续输入(主要用于下划线文本)。


2
你怎么能在不知道斜杠和反斜杠的区别的情况下获得3k声望值呢?O_o - R.. GitHub STOP HELPING ICE
3
抱歉,我刚才是在镜子里看我的电脑屏幕。 :| 我已经纠正了错别字。 - Steve Wellens

1

当你在Unix平台上运行且需要创建一个在DOS平台上打开的文本文件时,这非常有用。

Unix使用'\n'作为行终止符,而DOS使用'\r\n'作为行终止符,因此您可以使用它来创建一个DOS文本文件。


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