C从命名管道读取和写入

puk*_*puk 0 c named-pipes

我最终想要一个解决这个问题的方法,但是在真正的一步前进 - 后退两步方式编程中,我已经减少了解决为什么我甚至不能将一个字符写入命名管道然后得到它非常相同的角色.这是一个简单的MWE脚本,我很遗憾地得到了以下输出:

MWE:

#include <stdio.h>
#include <fcntl.h>
#define PIPE_PATH "testpipe"

int main( int argc, char *argv[] ) {
   int fd;
   FILE *fp;
   char c;
   int result;
   int contingency;

   //Initialize it for debugging purposes
   c = 0;
   contingency = 0;

   if ( atoi ( argv [ 1 ] ) == 1 )
   {
      printf ("Writer [%s]\n", argv[1]);

      mkfifo ( PIPE_PATH, 0666 );

      fd = open ( PIPE_PATH, O_WRONLY );
      c = getchar();
      printf ( "[%d] [%s]\n", c, &c );

      if ( ( result = write ( fd, &c, 1 ) ) == -1)
      {
         fprintf ( stderr, "error writing to pipe\n" );
         return -1;
      }

      close(fd);
   }
   else if ( atoi ( argv [ 1 ] ) == 2 )
   {
      printf ( "Reader [%s]\n", argv[1] );

      fp = fopen( PIPE_PATH, "r" );
      while ( contingency < 3 && ( c = getc ( fp ) ) != EOF )
      { //contingency set to 3 to avoid infinite loop
         c = getc ( fp );
         putchar ( c );
         printf ( "[%d]\n", c ); //don't print c as a string or the shell will go nuts

         printf ( "\n" );
         contingency++;
      }
      fclose ( fp );

      unlink( PIPE_PATH );
   }

   return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

Writer [1]
q
[113] [q]
....
Reader [2]
?[255]
?[255]
?[255]
Run Code Online (Sandbox Code Playgroud)

由于某些原因,我得到一个问题符号卡在六边形,但在vim看起来像ay(伽玛?)与umlat在它上面.由于与此字符关联的ASCII代码为255,因此我假设管道未按预期工作并返回可能的最高值.有人可以告诉我发生了什么事,因为我在生命的最后6个小时里没有完成任何事情吗?

Die*_*Epp 7

第一个错误

这里有个大问题......

char c = getc(fp);
Run Code Online (Sandbox Code Playgroud)

看到了吗?这是一个大问题.为什么?让我们来看看getc()... 的定义

int getc(FILE *stream);
Run Code Online (Sandbox Code Playgroud)

是的,它int不会返回char,这对于大写字母I和粗体字体来说很重要.的函数(或宏)信号与EOF ,通常是-1,并且因此成为存储在时.getc()EOF0xffchar

始终使用intgetc().

int c = getc(fp);
if (c == EOF) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

第二个错误

那么,我们为什么要获得EOF?因为getc()被叫两次而不是一次......

while ((c = getc(fp)) != EOF) {
    c = getc(fp); // <-- should not be there
    ...
}
Run Code Online (Sandbox Code Playgroud)

第三个错误

这段代码也错了:

char c = ...;
printf("[%d] [%s]\n", c, &c);
Run Code Online (Sandbox Code Playgroud)

是的,&c有类型,char *但这并不意味着你可以打印出来%s.该%s说明符是严格NUL结尾的字符串.使用%c或继续使用%sNUL终止传递它的字符串.

char c = ...;
printf("[%d] [%c]\n", c, c);
Run Code Online (Sandbox Code Playgroud)

要么...

char c = ...;
printf("[%d] [%s]\n", c, (char[]){c, '\0'});
Run Code Online (Sandbox Code Playgroud)