Почему расположение символа новой строки перед строкой, ведущей к нему, не печатается?

#c #sockets #newline

#c #сокеты #новая строка

Вопрос:

Я новичок в программировании сокетов. Я написал код для receiver:

 #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",amp;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 *)amp;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*)amp;receiver,amp;addrlen);
  printf("nreceived");
  str[rec]='';
  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("%sn",str) вместо printf("n%s",str) . Почему это происходит?

Комментарии:

1. Потому что stdout по умолчанию «строка с буферизацией», т.Е. … данные выводятся построчно (а строка определяется как последовательность символов, включающая и заканчивающаяся вводом). Ваш лучший вариант — прекратить печать с помощью "n" ; но вы можете попробовать изменить метод буферизации stdout с помощью maybe setvbuf() или принудительно выполнить вывод в любое время с помощью fflush()

2. Спасибо! Таким образом, это означает, что ОС не печатает str, потому что она обрабатывает ранее встреченный » n» как конец str. Я правильно понимаю?

Ответ №1:

Стандартный выходной поток, stdout , обычно буферизуется по строке, когда он направляется на терминал. Согласно C 2018 7.21.3 3:

… Когда поток буферизован по строкам, символы предназначены для передачи в среду хоста или из нее в виде блока при обнаружении символа новой строки. Кроме того, символы предназначены для передачи в виде блока в среду хоста при заполнении буфера, когда ввод запрашивается в небуферизованном потоке или когда ввод запрашивается в потоке с буферизацией строк, который требует передачи символов из среды хоста…

Таким образом, символы после символа новой строки остаются в буфере (внутри памяти компьютера, не отображаются на устройстве вывода) до тех пор, пока не будет записан символ новой строки, или вы не запросите ввод (как с scanf ) в связанном потоке ввода, или вы явно не запросите очистку буфера, или записано так много, что буфер заполнен.

По этой причине не рекомендуется писать printf инструкции с использованием символов новой строки в начале, таких как "nrecv succeeds" . C был разработан для вывода символов новой строки в концах строк для обычных приложений, таких как "recv succeedsn" .

Комментарии:

1. Понял. Большое спасибо!