2013-04-23 3 views
6

Как отделить линии, идущие от трубы. В трубе есть этот текст:Прочтите из трубопровода по строке в C

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

Я хочу, чтобы отделить строки из трубы, потому что я хочу, чтобы сохранить значения в переменных.

Вот мой код с:

#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

'for the best '- субъективный вопрос. Вы действительно сталкиваетесь с какой-либо проблемой? – abasu

+0

Замените 'fread' на [' fgets'] (http://pubs.opengroup.org/onlinepubs/009695399/functions/fgets.html). –

ответ

13

Обычно это просто называется чтение с stdin. Программа не должна заботиться о том, является ли вход каналом, перенаправленным файлом или клавиатурой.

fread будет читать только до тех пор, пока буфер не будет заполнен. Используйте fgets для чтения строки.

Также размер буфера должен быть достаточно большим, чтобы удерживать линию. Для маленьких одноразовых программ вы можете просто выбрать номер. Или есть стандартное имя BUFSIZ, которое дает вам довольно-большой буфер. Насколько велик? Достаточно большой. В самом деле? Вероятно.

fgets скопирует символ новой строки в строку, если только строка не заполнится первой. Таким образом, вы можете проверить последний символ, чтобы узнать, была ли линия усечена или нет. При разумных затратах это не произойдет. Но более надежный подход будет выделять больший буфер, скопировать частичную линию и снова вызвать fgets. Tp продолжать пытаться получить полную строку.

#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

ok у вас есть хороший пример использования fgets? – bladepit

+1

Я бы это сделал. Но вы должны научиться делать «man fgets» для себя. (Это первое, что я сделал бы, чтобы написать пример. Я всегда получаю аргументы назад, когда пишу, не проверяя.) –

+1

Я не пытаюсь звучать сопливый. Я действительно думаю, что мне лучше не писать такой пример. –

1

Вот еще один вариант (я не совсем уверен, что это «правильный» способ) - используйте количество байтов, считанных функцией read. В этом примере я читал от stdin, хотя было сделано перенаправление, так что fd в 0 - файл/труба/все, что вам нужно.

while ((nbytes=read(STDIN_FILENO, buffer, MAX_PIPE_SIZE)) > 0) { 
    write(STDOUT_FILENO, buffer, nbytes); 
    } 
Смежные вопросы