如何从C中的只读FIFO读取一行?

如何从C中的只读FIFO读取一行?,c,fifo,C,Fifo,我在读取只读FIFO中的几行代码时遇到问题。特别是,我必须读两行-一个数字n,后面是一个\n和一个字符串str-我的C程序应该在一个只写FIFO中写入str次。这是我的尝试 #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <ctype.h> #include <sys/types.h> #in

我在读取只读FIFO中的几行代码时遇到问题。特别是,我必须读两行-一个数字
n
,后面是一个
\n
和一个字符串
str
-我的C程序应该在一个只写FIFO中写入
str
次。这是我的尝试

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

char *readline(int fd);

int main(int  argc, char** argv) {
    int in = open(argv[1], O_RDONLY);
    mkfifo(argv[2], 0666);
    int out = open(argv[2] ,O_WRONLY);
    char *line = (char *) malloc(50);
    int n;

    while (1) {
        sscanf(readline(in), "%d", &n);
        strcpy(line, readline(in));

        int i;
        for (i = 0; i < n; i++) {
            write(out, line, strlen(line));
            write(out, "\n", 1);
        }
    }

    close(in);
    close(out);
    return 0;
}

char *readline(int fd) {
    char *c = (char *) malloc(1);
    char line[50];

    while (read(fd, c, 1) != 0) {
        if (strcmp(c, "\n") == 0) { 
            break;
        }
        strcat(line, c);
    }
    return line;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
字符*读线(int-fd);
int main(int argc,字符**argv){
int in=打开(argv[1],仅限Ordu);
mkfifo(argv[2],0666);
int out=打开(argv[2],仅限O_wr);
字符*行=(字符*)malloc(50);
int n;
而(1){
sscanf(读线(in),%d,&n);
strcpy(行、读行(in));
int i;
对于(i=0;i
代码工作正常,但它在最后一个字符串重复之后放置了随机数目的换行符。此外,该数字在每次执行时都会发生变化


有人能给我一些帮助吗?

我没有试着运行你的代码,但是在你的
readline
函数中,你没有用null(
'\0'
)字符终止
行。一旦你点击了
“\n”
字符,你只需在
循环时中断
,并返回字符串
。在从函数
读取行返回之前,请尝试添加
'\0'
字符


点击查看更多信息。

除了按字符读取和使用“字符串”比较法比较两个字符的效率都很低之外,
readline()
还返回一个指向内存的指针,该内存声明为
readline()
,即
line[50]
只要
readline()
返回,内存就会被释放,因此随后访问它会调用取消定义行为

解决此问题的一种可能性是声明缓冲区,以便将该行读入外部
readline()
,并向下传递对该行的引用,如下所示:

char * readline(int fd, char * line, size_t size) 
{
  if ((NULL != line) && (0 < size))
  {
    char c = 0;
    size_t i = 0;
    while (read(fd, &c, 1) >0) 
    {
      if ('\n' == c) or (size < i) { 
        break;
      }
      line[i] = c;
      ++i;
    }
    line [i] = 0;
  }

  return line;
}

你的代码在我的机器上不起作用,我想说你很幸运能得到任何有意义的结果

以下是一些需要考虑的问题:

  • readline
    返回一个本地定义的静态字符缓冲区(
    line
    ),当函数结束时,该缓冲区将被销毁,它所占用的内存将被其他操作自由覆盖
  • 如果分配时未将
    line
    设置为空字节,
    strcat
    将其垃圾值视为字符,并可能尝试在其结束后写入
  • 我猜想,您分配了一个1字节的缓冲区(
    c
    ),只是因为您在
    read
    中需要一个char*。这是不必要的(参见下面的代码)。更糟糕的是,在
    readline
    退出之前,您没有释放它,因此它会泄漏内存
  • while(1)
    循环将重新读取文件并将其重新打印到输出fifo,直到时间结束
  • 您正在使用一些“重炮”——即strcat
和内存分配——其中有更简单的方法
  • 最后,一些C标准版本可能要求在使用变量之前声明所有变量。看
  • 下面是我如何修改你的代码。请注意,如果第二行长度超过50个字符,则此代码也可能无法正常运行。关于缓冲区限制有一些技巧,但在本例中我不使用任何技巧:

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <ctype.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <string.h>
    
    char *readline(int fd, char * buffer);
    
    int main(int  argc, char** argv) {
        int in = open(argv[1], O_RDONLY);
        int out;
        int n;
        int i;
        char line[50];
    
        memset(line, 0, 50);
        mkfifo(argv[2], 0666);
        out = open(argv[2] ,O_WRONLY);
    
        sscanf(readline(in, line), "%d", &n);
        strcpy(line, readline(in, line));
    
        for (i = 0; i < n; i++) {
            write(out, line, strlen(line));
            write(out, "\n", 1);
        }
    
        close(in);
        close(out);
        return 0;
    }
    
    char *readline(int fd, char * buffer) {
        char c;
        int counter = 0;
        while (read(fd, &c, 1) != 0) {
            if (c == '\n') {
                break;
            }
            buffer[counter++] = c;
        }
        return buffer;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    字符*读线(int-fd,字符*缓冲区);
    int main(int argc,字符**argv){
    int in=打开(argv[1],仅限Ordu);
    指出;
    int n;
    int i;
    字符行[50];
    memset(第0、50行);
    mkfifo(argv[2],0666);
    out=打开(argv[2],仅限O_wr);
    sscanf(读线(in,line),%d,&n);
    strcpy(行,readline(in,line));
    对于(i=0;i

    正如你所描述的,这在我的盒子上起作用。使用GCC 4.8.2编译。

    char*c=(char*)malloc(1)一个1字符缓冲区将没有足够的位置容纳一个字符和一个空终止符;
    strcat(行,c)
    希望它的参数都以nul结尾。并且不要强制转换malloc。谢谢,这对我来说也很好。我只想问最后一个问题:在使用
    mkfifo
    创建之前,如何打开只写FIFO?你说的“之前”是什么意思?你想做什么?好吧,我假设
    out
    FIFO在使用
    mkfifo(argv[2],0666)
    创建后不存在,所以我想知道如何更早地打开它(即
    open
    调用首先出现)。抱歉,这对你来说可能是一个愚蠢的问题,但我对FIFO还很陌生,我必须花很大的努力去理解它们。哦,我在创建命名管道之前尝试访问它时出错了。它工作的唯一原因是上一次运行编辑后留下的命名管道。这就是你要问的,对吗?
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <ctype.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <string.h>
    
    char *readline(int fd, char * buffer);
    
    int main(int  argc, char** argv) {
        int in = open(argv[1], O_RDONLY);
        int out;
        int n;
        int i;
        char line[50];
    
        memset(line, 0, 50);
        mkfifo(argv[2], 0666);
        out = open(argv[2] ,O_WRONLY);
    
        sscanf(readline(in, line), "%d", &n);
        strcpy(line, readline(in, line));
    
        for (i = 0; i < n; i++) {
            write(out, line, strlen(line));
            write(out, "\n", 1);
        }
    
        close(in);
        close(out);
        return 0;
    }
    
    char *readline(int fd, char * buffer) {
        char c;
        int counter = 0;
        while (read(fd, &c, 1) != 0) {
            if (c == '\n') {
                break;
            }
            buffer[counter++] = c;
        }
        return buffer;
    }