首先:换行的表示方式有四种,分别是 CRLF (\r\n),LFCR (\n\r),CR (\r) 和 LF (\n)
小历史:
于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。
这就是“换行”和“回车”的来历,从它们的英语名字上也可以看出一二
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()函数以移动缓冲区偏移量)。
原创博文,有错误欢迎指正!!!