为什么换行符在导致它的字符串之前的位置没有被打印出来?
Why is the positioning of the newline character before the string leading to it not getting printed?
我是套接字编程的新手。我为接收器写了一个代码:
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<string.h>
#include<unistd.h>
int main()
{int ret= socket(AF_INET,SOCK_DGRAM,0);
if (ret==-1)
{printf("\nsocket creation fails");
exit (0);}
else
printf("\nsocket creation succeeds");
struct sockaddr_in sender;
int port;
printf("\nEnter port:");
scanf("%d",&port);
sender.sin_family= AF_INET;
sender.sin_port=htons(port);
sender.sin_addr.s_addr=INADDR_ANY;
int ret1;
ret1= bind(ret,(struct sockaddr *)&sender,sizeof(sender));
if(ret1==-1)
{printf("\nsocket binding fails");
exit (0);}
else
printf("\nsocket binding succeeds");
struct sockaddr_in receiver;
char str[15];
int addrlen=sizeof(receiver);
while(1)
{int rec=recvfrom(ret,str,sizeof(str),0,(struct sockaddr*)&receiver,&addrlen);
printf("\nreceived");
str[rec]='[=10=]';
if(strcmp(str,"exit")==0)
break;
if (rec==-1)
{printf("\nrecvfrom fails");
exit (0);}
else
{printf("\nrecv succeeds");
printf("\n%s",str);}
}
close(ret);
return 0;
}
此代码的输出在下一行打印 received
然后 recv succeeds
,之后光标转到下一行但不打印 str。然而,在 while 的下一次迭代中,旧的 str 值在 received
和 recv succeeds
之前打印。这个问题在我使用的时候解决了
printf("%s\n",str)
而不是 printf("\n%s",str)
。为什么会这样?
标准输出流 stdout
在定向到终端时通常是行缓冲的。根据 C 2018 7.21.3 3:
… When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. Furthermore, characters are intended to be transmitted as a block to the host environment when a buffer is filled, when input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment…
因此,new-line 字符之后的字符保留在缓冲区中(在计算机内存中,不显示在输出设备上)直到写入 new-line 字符,或者您请求输入(如在关联的输入流上使用 scanf
),或者您明确请求刷新缓冲区,或者写入的内容太多以至于缓冲区已满。
因此,在开头使用 new-line 个字符编写 printf
语句是不好的做法,例如 "\nrecv succeeds"
。 C 设计用于在常见应用程序的行尾具有 new-line 个字符的输出,例如 "recv succeeds\n"
.
我是套接字编程的新手。我为接收器写了一个代码:
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<string.h>
#include<unistd.h>
int main()
{int ret= socket(AF_INET,SOCK_DGRAM,0);
if (ret==-1)
{printf("\nsocket creation fails");
exit (0);}
else
printf("\nsocket creation succeeds");
struct sockaddr_in sender;
int port;
printf("\nEnter port:");
scanf("%d",&port);
sender.sin_family= AF_INET;
sender.sin_port=htons(port);
sender.sin_addr.s_addr=INADDR_ANY;
int ret1;
ret1= bind(ret,(struct sockaddr *)&sender,sizeof(sender));
if(ret1==-1)
{printf("\nsocket binding fails");
exit (0);}
else
printf("\nsocket binding succeeds");
struct sockaddr_in receiver;
char str[15];
int addrlen=sizeof(receiver);
while(1)
{int rec=recvfrom(ret,str,sizeof(str),0,(struct sockaddr*)&receiver,&addrlen);
printf("\nreceived");
str[rec]='[=10=]';
if(strcmp(str,"exit")==0)
break;
if (rec==-1)
{printf("\nrecvfrom fails");
exit (0);}
else
{printf("\nrecv succeeds");
printf("\n%s",str);}
}
close(ret);
return 0;
}
此代码的输出在下一行打印 received
然后 recv succeeds
,之后光标转到下一行但不打印 str。然而,在 while 的下一次迭代中,旧的 str 值在 received
和 recv succeeds
之前打印。这个问题在我使用的时候解决了
printf("%s\n",str)
而不是 printf("\n%s",str)
。为什么会这样?
标准输出流 stdout
在定向到终端时通常是行缓冲的。根据 C 2018 7.21.3 3:
… When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. Furthermore, characters are intended to be transmitted as a block to the host environment when a buffer is filled, when input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment…
因此,new-line 字符之后的字符保留在缓冲区中(在计算机内存中,不显示在输出设备上)直到写入 new-line 字符,或者您请求输入(如在关联的输入流上使用 scanf
),或者您明确请求刷新缓冲区,或者写入的内容太多以至于缓冲区已满。
因此,在开头使用 new-line 个字符编写 printf
语句是不好的做法,例如 "\nrecv succeeds"
。 C 设计用于在常见应用程序的行尾具有 new-line 个字符的输出,例如 "recv succeeds\n"
.