2013-04-23 96 views
6

如何分开管道中的管道。在管道中有这样的文字:从管道中逐行读取C

HALLO:500\n 
TEST:300\N 
ADAD 
ADAWFFA 
AFAGAGAEG 

我想从管道中分隔线条,因为我想将值保存在变量中。

这里是我的C代码:

#include <stdio.h> 
#include <stdlib.h> 

#define BUFFERSIZE 1 

int main(int argc, char **argv){ 
    unsigned char  buffer[BUFFERSIZE]; 
    FILE       *instream; 
    int       bytes_read=0; 
    int       buffer_size=0; 


    buffer_size=sizeof(unsigned char)*BUFFERSIZE; 
    /* open stdin for reading */ 
    instream=fopen("/dev/stdin","r"); 

    /* did it open? */ 
    if(instream!=NULL){ 
     /* read from stdin until it's end */ 
     while((bytes_read=fread(&buffer, buffer_size, 1, instream))==buffer_size){ 
      fprintf(stdout, "%c", buffer[0]); 
     } 
    } 
    /* if any error occured, exit with an error message */ 
    else{ 
     fprintf(stderr, "ERROR opening stdin. aborting.\n"); 
     exit(1); 
    } 

    return(0); 
} 

这是从管道读通过线的最佳路线的正确方法?

+0

“为了最好”是一个主观问题。你真的有什么问题吗? – abasu 2013-04-23 07:24:08

+0

将'fread'替换为['fgets'](http://pubs.opengroup.org/onlinepubs/009695399/functions/fgets.html)。 – 2013-04-23 07:25:29

回答

13

这通常被称为从stdin读取。程序不应该在乎输入是管道,重定向文件还是键盘。

fread只会读取,直到缓冲区已满。使用fgets来读取一行。

此外,缓冲区大小应足够大,以保持线路。对于一次性小程序,您可以选择一个数字。或者有一个标准名称BUFSIZ它给你一个相当大的缓冲区。多大?足够大。真?大概。

fgets将复制字符串中的换行符,除非字符串先填满。所以你可以测试最后一个字符来判断该行是否被截断。通过合理的投入,这不会发生。但更强大的方法将分配一个更大的缓冲区,复制部分行,并再次呼吁fgets继续尝试获得完整的行。

#include <stdio.h> 

int main() { 
    char buf[BUFSIZ]; 
    fgets(buf, sizeof buf, stdin); 
    if (buf[strlen(buf)-1] == '\n') { 
     // read full line 
    } else { 
     // line was truncated 
    } 
    return 0; 
} 

这让你中途的保护,可怕的缓冲区溢出问题。 fgets不会写入超过传递给它的大小。如上所述,另一半正在做一些合理的事情,可能由于意想不到的长输入线引起的部分线路。

+0

好的,你有使用fgets的好例子吗? – bladepit 2013-04-23 07:24:29

+1

我会的。但是你应该学会为自己做一个'fgets'。 (这是我写第一个例子的例子,当我没有检查的时候,我总是会反驳我的观点)。 – 2013-04-23 07:26:28

+1

我并不是想听起来很暴躁。我真的认为最好不要写这样一个例子。 – 2013-04-23 07:29:03

1

下面是另一个选项(我不完全确定它是一个'正确'的方式) - 使用read函数读取的字节数。 在这个例子中,我从stdin中读取,虽然重定向是这样做的,所以0中的fd是一个文件/管道/无论你需要它。

while ((nbytes=read(STDIN_FILENO, buffer, MAX_PIPE_SIZE)) > 0) { 
    write(STDOUT_FILENO, buffer, nbytes); 
    }