\r 与 \n 的区别

首先:换行的表示方式有四种,分别是 CRLF (\r\n),LFCR (\n\r),CR (\r) 和 LF (\n)

小历史:

在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。
于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。
这就是“换行”和“回车”的来历,从它们的英语名字上也可以看出一二
资料取自某知乎用户:his

CR-LF换行方式来自 ASCII,而 ASCII 沿袭了电传打字机的设计;电传打字机又沿袭了传统的机械打字机的设计。

Dos/Windows执行了这个标准换行;同时HTTP协议也采用了这一标准;


小问题: printf("\nab");printf("\bsi");printf("\rha"); 输出为:hai

stack overflow 上看到的解释:

\b (backspace) Moves the active position to the previous position on the current line. If the active position is at the initial position of a line, the behavior of the display device is unspecified.

\n (new line) Moves the active position to the initial position of the next line.

\r (carriage return) Moves the active position to the initial position of the current line.



区别总结:

1、 \r(回车 carriage return) \n(换行 line feed)

2、 \n的ASCII为10,\r为13 

3、 Unix系统中,每行结尾只有“换行”(\n);Windows中,每行结尾是“回车换行”(\r\n);Mac中“回车”(\r)

4、 Windows下C++中的奇怪代码  cout<<"wangss"<<"\r"<<"hao"<<endl;    \r  回到本行行首;


Tinyhttpd源码 int get_line(int sock, char *buf, int size); 函数 关于 换行与回车

int get_line(int sock, char *buf, int size)
{
    int i = 0;
    char c = '\0';
    int n;

    while ((i < size - 1) && (c != '\n'))
    {
        n = recv(sock, &c, 1, 0);
        /* DEBUG printf("%02X\n", c); */
        if (n > 0)
        {
            if (c == '\r')   \\Carriage Return
            {
                n = recv(sock, &c, 1, MSG_PEEK);
          
                if ((n > 0) && (c == '\n'))
                    recv(sock, &c, 1, 0);
                else
                    c = '\n';
            }

            buf[i] = c;
            i++;
        }
        else
            c = '\n';
    }
    buf[i] = '\0';
    return(i);

}

本函数作用:读取套接字中的一行数据,把回车换行等情况都统一为换行符结束(可以解决来自Unix\Windows\Mac的客户端请求消息)。

红字部分解析:若客户端为Unix系统,不需要读取到\r即可换行;若是Windows系统,读取到\r后在去读下一个字符,下一字符为\n即为换行;若是Mac系统,读取到\r后,无论下一字符是什么都认定为换行。

注:recv()函数,前三个参数与系统调用read()相同,上例中MSG_PEEK为窥看外来消息(可以读取得到消息但缓冲区的读取偏移量并没有被改变,故当窥看到下一字符为'\n'时,需要再次调用recv()函数以移动缓冲区偏移量)。


原创博文,有错误欢迎指正!!!

发布了15 篇原创文章 · 获赞 3 · 访问量 2242

猜你喜欢

转载自blog.csdn.net/sky_s_limit/article/details/80169681