Read stdout

Модератор: Модераторы разделов

BratSinot
Сообщения: 812
ОС: Slackware64

Read stdout

Сообщение BratSinot »

Доброго времени суток!

Вот написал я через printf строку. Как из потока stdout его вытащить? Программа типа этой, не работает:

Код: Выделить всё

 char tmp[1024];
 fprintf(stdout, "%X\n", 4815);
 rewind();
 fscanf(stdout, "%s", tmp);

Как вариант, можно запаралелить, и при выводе в stdout сразу считывать. Но это слишком громоздко и не надежно получится.
Спасибо сказали:
AlexBel
Сообщения: 27

Re: Read stdout

Сообщение AlexBel »

а зачем это понадобилось?
Спасибо сказали:
ssh
Сообщения: 78
ОС: Debian

Re: Read stdout

Сообщение ssh »

см. getc/putc и их аналоги.
Спасибо сказали:
Аватара пользователя
Crazy
Сообщения: 862
Статус: Адепт Дзен.
ОС: Mint, Win7.

Re: Read stdout

Сообщение Crazy »

Записать в буфер, и из буфера считать?!

Desipere in loco
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Read stdout

Сообщение BratSinot »

AlexBel писал(а):
21.09.2010 00:09
а зачем это понадобилось?

Быстрый перевод в 8-ричную и 16-ричную систему счисления.

Crazy писал(а):
21.09.2010 11:06
Записать в буфер, и из буфера считать?!

А что?

//см. getc/putc и их аналоги.
Они так-же как и fscanf не работают.
Спасибо сказали:
hippi90
Сообщения: 83
ОС: Debian testing

Re: Read stdout

Сообщение hippi90 »

Не совсем понимаю, зачем это понадобилось, но может здесь поможет sprintf()
Спасибо сказали:
Аватара пользователя
sgfault
Сообщения: 586
Статус: -

Re: Read stdout

Сообщение sgfault »

BratSinot писал(а):
21.09.2010 17:07
Быстрый перевод в 8-ричную и 16-ричную систему счисления.

А будет ли он таким уж быстрым? Скорее простым (для написания), но вряд ли быстрым.
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Read stdout

Сообщение BratSinot »

sgfault писал(а):
21.09.2010 18:11
BratSinot писал(а):
21.09.2010 17:07
Быстрый перевод в 8-ричную и 16-ричную систему счисления.

А будет ли он таким уж быстрым? Скорее простым (для написания), но вряд ли быстрым.

Что быстрее? Прочитать пару строчек, или делить число(другого способа перевода из 10-тичной в другие системы счисления я не знаю) с 2-мя переменными?
Спасибо сказали:
Аватара пользователя
Rootlexx
Бывший модератор
Сообщения: 4463
Статус: GNU generation
ОС: Debian GNU/Linux

Re: Read stdout

Сообщение Rootlexx »

BratSinot писал(а):
20.09.2010 23:16
rewind();

(man lseek) писал(а):...
Some devices are incapable of seeking and POSIX does not specify which devices must support lseek().
On Linux, using lseek() on a tty device returns ESPIPE.
...

tty это символьное устройство, а не блочное, поэтому ни о каком lseek() речи быть не может.

BratSinot писал(а):
21.09.2010 19:09
Что быстрее? Прочитать пару строчек, или делить число(другого способа перевода из 10-тичной в другие системы счисления я не знаю) с 2-мя переменными?

Для человека или машины? Машина переводит числа из одной системы в другую как раз делением, а учитывая накладные расходы на формирование строки и её чтение это будет медленнее, чем если бы вы сами реализовали этот алгоритм.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Read stdout

Сообщение NickLion »

1. Используйте sprintf:
sprintf(tmp,"%X",4815);
2.
Что быстрее? Прочитать пару строчек, или делить число(другого способа перевода из 10-тичной в другие системы счисления я не знаю) с 2-мя переменными?

Угу, а Вы думаете они хранятся в 10-ной системе? Святая наивность :) В двоичной они хранятся, а для перевода из 2-ой в 8-ми и 16-ти ричную делить не надо - достаточно побитовых операций.
Спасибо сказали:
Аватара пользователя
Portnov
Модератор
Сообщения: 1786
Статус: Матёрый линуксоид
ОС: Debian testing/unstable

Re: Read stdout

Сообщение Portnov »

BratSinot писал(а):
20.09.2010 23:16
Вот написал я через printf строку. Как из потока stdout его вытащить?

AlexBel писал(а):
21.09.2010 00:09
а зачем это понадобилось?

BratSinot писал(а):
21.09.2010 17:07
Быстрый перевод в 8-ричную и 16-ричную систему счисления.

BratSinot писал(а):
21.09.2010 19:09
Что быстрее? Прочитать пару строчек, или делить число(другого способа перевода из 10-тичной в другие системы счисления я не знаю) с 2-мя переменными?


Гм... эта... http://lurkmore.ru/Индусский_код
:/
Работа: Ubuntu 9.10
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Read stdout

Сообщение BratSinot »

/*1. Используйте sprintf:
sprintf(tmp,"%X",4815);*/
С чего оно работать будет? tmp это не поток.

//tty это символьное устройство, а не блочное, поэтому ни о каком lseek() речи быть не может.
А кто про него что-то сказал?

/*Для человека или машины? Машина переводит числа из одной системы в другую как раз делением, а учитывая накладные расходы на формирование строки и её чтение это будет медленнее, чем если бы вы сами реализовали этот алгоритм.*/
Давайте я сам потом сравню?
Спасибо сказали:
Аватара пользователя
sgfault
Сообщения: 586
Статус: -

Re: Read stdout

Сообщение sgfault »

Я вижу тут и так уже все написали. Ну ладно, я тоже добавлю -)

Во-первых, пока ваши printf и scanf это все напишут и считают, они не только разделят, они еще кучу всего лишнего и не нужного наделают. Хоть бы тот же разбор аргументов. А во-вторых, я вас уверяю, что такой (далекий от совершенства) код будет работать _намного_ быстрее вашего способа.


Код: Выделить всё

#include <stdio.h>

int main() {
    int d = 0;
    char xstr[8];
    const int n_xstr=8;

    const int x_0=0x0;
    const int x_1=0x1;
    const int x_2=0x2;
    const int x_3=0x3;
    const int x_4=0x4;
    const int x_5=0x5;
    const int x_6=0x6;
    const int x_7=0x7;
    const int x_8=0x8;
    const int x_9=0x9;
    const int x_a=0xa;
    const int x_b=0xb;
    const int x_c=0xc;
    const int x_d=0xd;
    const int x_e=0xe;
    const int x_f=0xf;
    const int x_mask=0xf;
    int i = 0;
    int x_val = 0;
    if (sizeof(int) != (n_xstr / 2))
        return(-1);
    scanf("%d", &d);
    printf ("%x\n", d);
    i = n_xstr - 1;
    while (1) {
        x_val = d & x_mask;
        if      ((x_val & x_0) == x_val) { xstr[i] = '0'; }
        else if ((x_val & x_1) == x_val) { xstr[i] = '1'; }
        else if ((x_val & x_2) == x_val) { xstr[i] = '2'; }
        else if ((x_val & x_3) == x_val) { xstr[i] = '3'; }
        else if ((x_val & x_4) == x_val) { xstr[i] = '4'; }
        else if ((x_val & x_5) == x_val) { xstr[i] = '5'; }
        else if ((x_val & x_6) == x_val) { xstr[i] = '6'; }
        else if ((x_val & x_7) == x_val) { xstr[i] = '7'; }
        else if ((x_val & x_8) == x_val) { xstr[i] = '8'; }
        else if ((x_val & x_9) == x_val) { xstr[i] = '9'; }
        else if ((x_val & x_a) == x_val) { xstr[i] = 'a'; }
        else if ((x_val & x_b) == x_val) { xstr[i] = 'b'; }
        else if ((x_val & x_c) == x_val) { xstr[i] = 'c'; }
        else if ((x_val & x_d) == x_val) { xstr[i] = 'd'; }
        else if ((x_val & x_e) == x_val) { xstr[i] = 'e'; }
        else if ((x_val & x_f) == x_val) { xstr[i] = 'f'; }
        //printf ("-- xstr[%d] = %d\n", i, xstr[i]);
        if (i == 0)
            break;
        d = d>>4;
        i--;
    }
    printf ("xstr='");
    for (i = 0; i < n_xstr; i++)
        printf ("%c", xstr[i]);
    printf ("'\n");
    return(0);
}

Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Read stdout

Сообщение NickLion »

1. А sprintf работает со строкой, а не потоком. man sprintf
2. sgfault, у меня сегодня плохое настроение, уберите этот код пока его ещё кто не увидел :-D.

Вот перевод в шестнадцатеричную систему:

Код: Выделить всё

#include<stdio.h>
int main()
{
    long x = 4815;
    char tmp[256], *p;
    bool q = false;
    int i, c;
    for( i = sizeof(x) * 8 - 4, p = tmp; i >= 0; i -= 4 ) {
        c = ( x >> i ) & 0xF;
        if( q || c || !i ) {
            if( c < 10 ) {
                *p++ = '0' + c;
            } else {
                *p++ = 'A' + c - 10;
            }
            c = 0;
        }
    }
    *p = 0;
    printf( "%s\n", tmp );
    return 0;
}


Можно ещё прооптимизировать на скорость разбив цикл на 2 и упростив условия.
Спасибо сказали:
Аватара пользователя
sgfault
Сообщения: 586
Статус: -

Re: Read stdout

Сообщение sgfault »

NickLion писал(а):
21.09.2010 21:13
2. sgfault, у меня сегодня плохое настроение, уберите этот код пока его ещё кто не увидел :-D.

Зачем? Он работает и не так уж плохо. Ну, а то, что ваш лучше, - ну так ничего удивительного, я не писал программы уже несколько лет, да и раньше-то не сильно хорошо это делал.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Read stdout

Сообщение NickLion »

sgfault, там смайлик в конце был ;) Решение не такое уж плохое, но вот заменить константы на массив, ну аж просится.
Спасибо сказали:
Аватара пользователя
Rootlexx
Бывший модератор
Сообщения: 4463
Статус: GNU generation
ОС: Debian GNU/Linux

Re: Read stdout

Сообщение Rootlexx »

BratSinot писал(а):
21.09.2010 20:15
А кто про него что-то сказал?

(man stdout) писал(а):...
Under normal circumstances every Unix program has three streams opened for it when it starts up, one for input, one for output, and one for printing diagnostic or error messages. These are typically attached to the user's terminal (see tty(4))...
Спасибо сказали:
Аватара пользователя
RasenHerz
Сообщения: 1341
ОС: Arch Linux amd64

Re: Read stdout

Сообщение RasenHerz »

sgfault писал(а):
21.09.2010 20:19

Код: Выделить всё

#include <stdio.h>

int main() {
    int d = 0;
    char xstr[8];
    const int n_xstr=8;

    const int x_0=0x0;
    const int x_1=0x1;
    const int x_2=0x2;
    const int x_3=0x3;
    const int x_4=0x4;
    const int x_5=0x5;
    const int x_6=0x6;
    const int x_7=0x7;
    const int x_8=0x8;
    const int x_9=0x9;
    const int x_a=0xa;
    const int x_b=0xb;
    const int x_c=0xc;
    const int x_d=0xd;
    const int x_e=0xe;
    const int x_f=0xf;
    const int x_mask=0xf;
    int i = 0;
    int x_val = 0;
    if (sizeof(int) != (n_xstr / 2))
        return(-1);
    scanf("%d", &d);
    printf ("%x\n", d);
    i = n_xstr - 1;
    while (1) {
        x_val = d & x_mask;
        if      ((x_val & x_0) == x_val) { xstr[i] = '0'; }
        else if ((x_val & x_1) == x_val) { xstr[i] = '1'; }
        else if ((x_val & x_2) == x_val) { xstr[i] = '2'; }
        else if ((x_val & x_3) == x_val) { xstr[i] = '3'; }
        else if ((x_val & x_4) == x_val) { xstr[i] = '4'; }
        else if ((x_val & x_5) == x_val) { xstr[i] = '5'; }
        else if ((x_val & x_6) == x_val) { xstr[i] = '6'; }
        else if ((x_val & x_7) == x_val) { xstr[i] = '7'; }
        else if ((x_val & x_8) == x_val) { xstr[i] = '8'; }
        else if ((x_val & x_9) == x_val) { xstr[i] = '9'; }
        else if ((x_val & x_a) == x_val) { xstr[i] = 'a'; }
        else if ((x_val & x_b) == x_val) { xstr[i] = 'b'; }
        else if ((x_val & x_c) == x_val) { xstr[i] = 'c'; }
        else if ((x_val & x_d) == x_val) { xstr[i] = 'd'; }
        else if ((x_val & x_e) == x_val) { xstr[i] = 'e'; }
        else if ((x_val & x_f) == x_val) { xstr[i] = 'f'; }
        //printf ("-- xstr[%d] = %d\n", i, xstr[i]);
        if (i == 0)
            break;
        d = d>>4;
        i--;
    }
    printf ("xstr='");
    for (i = 0; i < n_xstr; i++)
        printf ("%c", xstr[i]);
    printf ("'\n");
    return(0);
}

Код: Выделить всё

std::string hex(const void *ptr, unsigned size){
    if (!(ptr && size))
        return "";

    char syms[] = "0123456789abcdef";
    const unsigned char *str_ptr = reinterpret_cast<const unsigned char* >(ptr);
    std::string ret = "";

    for (int i = 0; i < size; i++)
        ret += syms[(str_ptr[i] & 0xF0) >> 4], ret += syms[(str_ptr[i] & 0x0F)];

    return ret;
}

Переводит строки вида "AABBCCDD" в "4141424243434444", перепишите его на С и приспособьте под свои нужды и уверяю вас, получится очень быстрый код, а ту портянку что вы накатали больше никому не показывайте.

P.S. за работоспособность кода не ручаюсь - писал на коленке.
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Read stdout

Сообщение BratSinot »

И вообще, даже если будет медленнее, имеет место чисто спортивный интерес.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Read stdout

Сообщение NickLion »

Ну, спортивный интерес - это когда быстрее, меньше (выше, дальше, сильнее). А тут немного как-то нездоровый интерес ;)
Можно:
* использовать sprintf
* орагнизовать пайп - man pipe; man fdopen - но там нужно 2 потока (один - fprintf, второй - fscanf), чтобы гарантировать отсутствие дедлока (пул, вроде 4кб, или с чём-то путаю)

Ну, или ещё можно с обычным файлом:
fopen
unlink
fprintf
fscanf
fclose
но зачем?

PS ах, да, ещё можно fmemopen использовать, совсем забыл
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Read stdout

Сообщение BratSinot »

NickLion писал(а):
21.09.2010 23:37
Ну, спортивный интерес - это когда быстрее, меньше (выше, дальше, сильнее). А тут немного как-то нездоровый интерес ;)
Можно:
* использовать sprintf
* орагнизовать пайп - man pipe; man fdopen - но там нужно 2 потока (один - fprintf, второй - fscanf), чтобы гарантировать отсутствие дедлока (пул, вроде 4кб, или с чём-то путаю)

Ну, или ещё можно с обычным файлом:
fopen
unlink
fprintf
fscanf
fclose
но зачем?

PS ах, да, ещё можно fmemopen использовать, совсем забыл

С обычным файлом это будет как два байта переслать.
Спасибо сказали:
Аватара пользователя
netelis
Сообщения: 95
ОС: Debian Wheezy i686

Re: Read stdout

Сообщение netelis »

Как прочитать stdout. Я думаю можно перехватить stdout перехватив sys_write и забирать всё что проходит через дескриптор 1 и записывать в буффер, а потом написать функцию или системный вызов который будет возвращать в пространство пользователя из пространства ядра этот буффер, так получится вроде обратного клавиатурного шпиона только на вывод, а не ввод. Только надо отключить буфферизацию или делать fflush перед выводом новой функции. Только для конкретного процесса.
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Read stdout

Сообщение BratSinot »

netelis писал(а):
29.09.2010 13:53
Как прочитать stdout. Я думаю можно перехватить stdout перехватив sys_write и забирать всё что проходит через дескриптор 1 и записывать в буффер, а потом написать функцию или системный вызов который будет возвращать в пространство пользователя из пространства ядра этот буффер, так получится вроде обратного клавиатурного шпиона только на вывод, а не ввод. Только надо отключить буфферизацию или делать fflush перед выводом новой функции. Только для конкретного процесса.

Это платформо-зависимо будет.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Read stdout

Сообщение NickLion »

С обычным файлом - да, легко, но stdout - не обычный файл. А если программа запущена:
prog1 | prog2
Ваш вывод уже улетел к программе prog2. Что будете читать?
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Read stdout

Сообщение BratSinot »

NickLion писал(а):
30.09.2010 11:23
С обычным файлом - да, легко, но stdout - не обычный файл. А если программа запущена:
prog1 | prog2
Ваш вывод уже улетел к программе prog2. Что будете читать?

Две проги на одном терминале/консоли? Честно, я не видел такого.
Спасибо сказали:
Аватара пользователя
netelis
Сообщения: 95
ОС: Debian Wheezy i686

Re: Read stdout

Сообщение netelis »

Что то вроде этого?

Код: Выделить всё

#include <stdio.h>

int main(int argc,char **argv){
int buf[]={125};
int tmp[10];
if(argc>=2){
scanf("%d\n",&tmp[0]);
printf("%X\n",tmp[0]);
};

if(argc<2)printf("%d\n", buf[0]);
return 0;
};

Получается ./p1 | ./p1 edf sdfs
Выводит 7D. А аргументы нужны для того чтоб узнать вводить или выводить.
Оно перенаправляет stdout через канал другому процессу вывод buf то что идёт при первом запуске.
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Read stdout

Сообщение BratSinot »

netelis писал(а):
30.09.2010 17:05
Что то вроде этого?

Код: Выделить всё

#include <stdio.h>

int main(int argc,char **argv){
int buf[]={125};
int tmp[10];
if(argc>=2){
scanf("%d\n",&tmp[0]);
printf("%X\n",tmp[0]);
};

if(argc<2)printf("%d\n", buf[0]);
return 0;
};

Получается ./p1 | ./p1 edf sdfs
Выводит 7D. А аргументы нужны для того чтоб узнать вводить или выводить.

Мне нужно stdout прочесть. Если нужно в строку Hex число записать, то можно так:

Код: Выделить всё

tmp[1024];
fprintf(tmp, "%x", 100);
Спасибо сказали:
Аватара пользователя
Rootlexx
Бывший модератор
Сообщения: 4463
Статус: GNU generation
ОС: Debian GNU/Linux

Re: Read stdout

Сообщение Rootlexx »

BratSinot писал(а):
30.09.2010 17:30
Если нужно в строку Hex число записать, то можно так:

Код: Выделить всё

tmp[1024];
fprintf(tmp, "%x", 100);

Наверное, вы имели в виду sprintf()?
Спасибо сказали: