LINUX.ORG.RU

[C] есть ли поток аналогичный /dev/null ?

 


0

0

В коде заведомо прописан вывод в именованный поток, например:

fprintf (somestream, "Hi there");

но то, что есть somestream, определяется до его использования и это в зависимости от логики программы либо stdout, либо заведомо открытый файл, либо "НИЧТО" - то есть пустой поток, никуда нчего не выводить.

Есть ли стандартный аналог такого потока в C? Если нет, как таковой создать?


Ответ на: комментарий от Reset

Это выглядит громоздко - открывать файл на файловой системе, пусть даже файл фейковый. Неужели нельзя элегантнее пустышку сделать?

s0ldat
() автор топика
Ответ на: комментарий от s0ldat

>Это выглядит громоздко - открывать файл на файловой системе, пусть даже файл фейковый. Неужели нельзя элегантнее пустышку сделать?

Тогда заранее проверять необходимость вывода текста и не выводить его вообще.

anonymous
()
Ответ на: комментарий от anonymous

Да, это альтернативное решение, и я его использовал в виде макросов
оно требует громоздких макросов, то есть везде где вывод - должна быть проверка условия
А если вывод часто? Если не только выводить/не выводить, а еще в файл который в процессе работы программы определяется - с проверкой условий много лишнего кода, очень много.

Imho простое (пере)определение потока - очень красиво и удобно.
Или как минимум альтернативно.

С другой стороны: есть ли пустышка для fprintf() ? неужели нет?

s0ldat
() автор топика
Ответ на: комментарий от s0ldat

> Это выглядит громоздко - открывать файл на файловой системе, пусть даже файл фейковый

Может и выглядит громоздко, но на самом деле таковым не является. Громоздким в данном случае является лишний вызов printf со всеми его параметрами.
Кстати, а как подобное делается в оффтопике?

ShprotX
()
Ответ на: комментарий от ShprotX

> Может и выглядит громоздко, но на самом деле таковым не является. > Громоздким в данном случае является лишний вызов printf со всеми его параметрами.

наверное это и является лучшим решением

> Кстати, а как подобное делается в оффтопике?

Вот этого точно не знаю. Для меня оффтопик - это именно офф топик :-)

anonymous
()
Ответ на: комментарий от s0ldat

Если проблема в куче проверок, то можно создать две функции - одна с fprintf, другая ничего не делает. Завести указатель на функцию. После первой проверки условий присвоить указатель адресу одной из двух функций и потом везде использовать этот указатель.

Второй вариант - сделать что-то типа my_printf, который будет проверять надо выводить что-то или нет. Т.е. проверка будет только в одном месте. Тогда везде вместо printf/fprintf будет my_printf.

GArik ★★★
()
Ответ на: комментарий от GArik

Думаю для обоих случаев лучше писать макросы, причем конечно же на каждый новый вариант комбинации передаваемых параметров будет НОВЫЙ макрос (то есть когда предаем на вывод строку, строку с целочисленной переменной в середине, строку с целочисленной переменной в начале, ...) - я не представляю как это можно сделать одной функцией.

Так что наверное или куча макросов - или открываем /dev/null на запись и туда...

s0ldat
() автор топика
Ответ на: комментарий от s0ldat

#include <stdio.h>

#define WRAPFPF(a, x) \

if(x)\

fprintf a

int main()

{

FILE * out=fopen("out", "a+");

WRAPFPF((out, "blah %d %s\n", 25, "wqeqwe"), 1);

WRAPFPF((out, "blah %d %s\n", 25, "wqeqwe"), 0);

WRAPFPF((out, "%s %d bla bla %s\n", "222", 25, "wqeqwe"), 1);

WRAPFPF((out, "%s %d bla bla %s\n", "222", 25, "wqeqwe"), 0);

return 0;

}

anonymous
()
Ответ на: комментарий от s0ldat

>на каждый новый вариант комбинации передаваемых параметров будет НОВЫЙ макрос 
можно и одним макросом обойтись

#include <stdio.h>

#define WRAPFPF(a, x) \
	if(x)\
		fprintf a

int main()
{
	FILE * out=fopen("out", "a+");
	WRAPFPF((out, "blah %d %s\n", 25, "wqeqwe"), 1);
	WRAPFPF((out, "blah %d %s\n", 25, "wqeqwe"), 0);
	WRAPFPF((out, "%s %d bla bla %s\n", "222", 25, "wqeqwe"), 1);
	WRAPFPF((out, "%s %d bla bla %s\n", "222", 25, "wqeqwe"), 0); 
	return 0;
}

anonymous
()
Ответ на: комментарий от anonymous

спасибо!

больше узнал о макросах
(Си пока активно учусь...)

действительно можно красиво обернуть

s0ldat
() автор топика

ЧТобы что-то в дев нуль записать, надо сначала это что-то в память загрузить, а если это не надо, то поверх этих данных нужно записать новые данные, а старые данные пойдут в астрал

dimon555 ★★★★★
()
Ответ на: комментарий от anonymous

Макросы вообще дурной стиль, а гццизмы и вовсе

anonymous
()
Ответ на: комментарий от s0ldat

> больше узнал о макросах
Лучше делай, как говорит GArik, тогда ты больше узнаешь о языке. Оба его подхода верные, хотя я больше склоняюсь к первому - с указателем на функцию - быстро и никаких проверок.

> действительно можно красиво обернуть

Ты на пути к хаосу.

zzf
()
Ответ на: комментарий от zzf

#include <stdio.h>

typedef int (*fprintf_ptr_t)(FILE *, const char *, ...);

int fake_fprintf(FILE *fp, const char *str, ...) { return 0; }

FILE *fp = 0;
fprintf_ptr_t log = fake_fprintf;

void test()
{
    if( not_dev_null )
    {
        fp = fopen( "xx", "w+" );
        log = fprintf;
    }

    log( fp, "%d\n", 1 );
    log( fp, "%d, %d\n", 2, 3 );
}

zzf
()
Ответ на: комментарий от the_moon

#include <stdio.h>

int main()
{
FILE *nullstream = NULL;
fprintf(nullstream, "Hi there\n");
return 0;
}


на FreeBSD (сейчас под рукой фря, а вообще под Linux пишу) выполнение этого кода дает "Segmentation fault: 11 (core dumped)"

s0ldat
() автор топика
Ответ на: комментарий от s0ldat

>выполнение этого кода дает "Segmentation fault

Да, ляпнул не подумавши и не проверивши. Я думал в glibc есть проверка и на NULL. Там в начале реализации fprintf проверяется валидность стрима, но видимо нет проверки на NULL.

the_moon
()
Ответ на: комментарий от the_moon

> Я думал в glibc есть проверка и на NULL. Там в начале реализации fprintf проверяется валидность стрима, но видимо нет проверки на NULL.

Недавно где-то об этом вспоминалось... Проверки на NULL для FILE* в библиотечных функциях нигде нет. Не потому, что поленились сделать, а для того, чтобы её делало приложение один раз после fopen. Если уж не делает, так пусть лучше сразу свалится в segfault.

const86 ★★★★★
()

На си вероятно никак, кроме /dev/null/

Поэтому выброси си и возьми CL:
    (defvar *blackhole* (make-broadcast-stream))

Можно даже сделать блэкхол-сервер
и использовать вместо /dev/null:

(asdf:oos 'asdf:load-op :usocket)
(use-package :usocket)

(defvar *blackhole* (make-broadcast-stream))

(defun run-blackhole-server ()
  (let ((server (socket-listen "127.0.0.1" 666 
			       :element-type '(unsigned-byte 8))))
    (unwind-protect
      (loop
	(let ((stream-socket (socket-accept server)))
	  (with-open-stream (in (make-echo-stream
				  (socket-stream stream-socket) 
				  *blackhole*))
	    (handler-case
	      (loop (read-byte in))
	      (end-of-file ()
		   (socket-close stream-socket))))))
      (socket-close server))))

anonymous
()
Ответ на: комментарий от anonymous

думаю ты понимаешь, что независимо от красивости приемов другого языка, с "родным" языком прощаться никак.

как резюме по теме:

открывать '/dev/null' - громоздно и неправильно;
макрос - приемлемое решение;
переключение указателя на нужную функцию - имхо лучшее решение, по крайней мере я его использую

спасибо!

s0ldat
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.