2013-05-11 16 views
12

Ist es möglich, Stille eine Funktion? Zum Beispiel:Wie verhindert man das Drucken von Funktionen?

#include <stdio.h> 
int function(){ 
    printf("BLAH!"); 
    return 10; 

} 
int main(){ 
    printf("%d", silence(function())); 
return 0; 
} 

Und statt:

BLAH! 
10 

würde ich:

10 

Ist es möglich? Wenn positiv wie es geht?

+3

Sie die Funktion nicht nennen ... Was ist Ihre Absicht? –

+1

Es ist Software, fast alles ist möglich. Willst du eine Funktion? Oder ist eine Präprozessor-Methode akzeptabel? Wie wäre es, Code zur Laufzeit zu modifizieren? –

+0

http://chat.stackoverflow.com/rooms/29552/c (Lassen Sie uns darüber diskutieren, aye?) :) – cipher

Antwort

10

Eine ziemlich komplizierte Möglichkeit, fast das zu tun, was Sie wollen, ist die Verwendung des Systemaufrufs dup2(). Dies erfordert die Ausführung von fflush(stdout); dup2(silentfd, stdout);, bevor function() aufgerufen wird, und das anschließende Kopieren: fflush(stdout); dup2(savedstdoutfd, stdout);. Es ist also nicht möglich, nur silence(function()) zu machen, da dieses Konstrukt nur Code ausführen kann, nachdem function() bereits ausgeführt wurde.

Die Filedeskriptoren silentfd und savedstdoutfd haben im Voraus (ungetestet Code) vorbereitet werden:

int silentfd = open("/dev/null",O_WRONLY); 
int savedstdoutfd = dup(stdout); 

Das ist nicht mit ziemlicher Sicherheit ist das, was Sie wirklich wollen, aber da Ihre Frage „ist es möglich, formuliert wird ? ", Die Antwort ist" fast ".

+1

Technisch könnten Sie einen C-Interpreter in C programmieren, den Interpreter die Funktion ausführen lassen und alle 'printf's innerhalb der Funktion ignorieren. Natürlich ist die Antwort "ja", Turing-Vollständigkeit schreibt es vor. –

+0

@PascalCuoq Warum kann es so ausgewertet werden, dass es ausgeführt wird, bevor es an die "Stille" übergeben wird? – BLUEPIXY

+0

@BLUEPIXY Ah, ja, du machst einen guten Punkt, selbst 'dup2()' erlaubt nicht ganz, was das OP machen möchte, nämlich 'Stille (f())' zu schreiben, um 'f' zum Schweigen zu bringen. Ich werde diese Nuance in meine Antwort aufnehmen. –

0

Leider wenn Sie die Funktion explizit drucken und es so aufrufen, wird es immer gedruckt. Wenn Sie die Funktion vollständig stummschalten möchten, können Sie diese Zeile einfach auskommentieren. Sie können sogar eine Steueranweisung verwenden, so dass IF nur gedruckt wird und eine Bedingung erfüllt ist. Andernfalls bleibt sie leer und gibt nur die Zahl zurück.

5

Nein, das ist nicht möglich. Sie könnten jedoch versuchen, das stdout vorübergehend auf etwas anderes umzuleiten. Das könnte nahe kommen, was Sie wollen.

5

können Sie dieses Makro verwenden, anstatt printf der Lage sein, den Druckvorgang zu verhindern:

int flag=0; 
#define PRINT(...) if(flag){printf(...)} 

dann mit PRINT Makro durch die Variable flag berücksichtigen. Wenn flag==1, wird die Funktion gedruckt und wenn flag==0, die Funktion wird nicht gedruckt.

8

Verwenden Sie Makrofunktion und Null-Gerät.

z. für Fenster

#include <stdio.h> 

#define silence(x) (_stream = freopen("NUL:", "w", stdout), _ret_value = x,_stream = freopen("CON:", "w", stdout),_ret_value) 
int _ret_value; 
FILE *_stream; 

int function(){ 
    printf("BLAH!"); 
    return 10; 

} 
int main(void){ 
    printf("%d", silence(function())); 
    return 0; 
} 
+0

Makro-Funktion ist keine Funktion. Es ist nur das Aussehen. – BLUEPIXY

+0

Zuerst eine bis viele schließende Klammern neben der Funktion. Zweitens, was könnte die richtige Makro-Version für UNIX, SunOS um genau zu sein. Und drittens für ein vollständiges Codebeispiel. – PovilasID

+0

Ich denke, der Test der Umgebung für * nix, weil die Windows-Umgebung kann nicht sein (andere Leute auch zu schreiben) und kann das gleiche tun. – BLUEPIXY

3

Wenn Sie die Funktion gehen Sie wie folgt sind der Gestaltung:

int function(void (*printer)(char *)){ 
    if (!printer) 
     printer = printf; 

    printer("BLAH!"); 
    return 10; 
} 

void silence(char *s){ 
    return; 
} 

int main(int argc, char **argv){ 
    printf("%d\n", function(silence)); 
    return 0; 
} 

das tun sollten, was Sie suchen. Leider habe ich es nicht getestet und mein C ist wahrscheinlich ein wenig eingerostet.

Natürlich, wenn function ist nicht etwas, was Sie Kontrolle haben, die Antworten bereits geschrieben sind alle richtigen Lösungen.


Eigentlich, wenn Sie die Funktion selbst sind die Gestaltung, tun gerade:

int function(int print){ 
    if (print) 
     printf("BLAH!"); 

    return 10; 
} 


function(0); /* Won't print anything */ 
function(!0); /* Will print "BLAH!" */ 

weil 0 falsch ist und jeder Nicht-Null (oder !0) Wert gilt. Mein vorstehender Vorschlag ist fehleranfällig, da Sie die printf Signatur für silence oder für jede andere Funktion, die Sie verwenden möchten, imitieren können.

+0

Ich arbeite am Collaboration-Projekt, also gibt es Funktionen, die ich nicht bearbeiten kann, aber für einige werde ich diese Arbeit wahrscheinlich anwenden. – PovilasID

+0

Wenn Sie die Funktion als Teil einer Bibliothek verwenden, sollte diese Bibliothek * niemals * nichts drucken. Alles, was gedruckt werden muss, sollte vom Benutzer ausgeführt werden. Fühlen Sie sich frei, den Bibliotheksautor anzuschreien. Außerdem sollte eine bestimmte Funktionalität im Allgemeinen entkoppelt sein, um Wiederverwendbarkeit bereitzustellen. Viel Glück mit dem Projekt. –

3

Mit GCC extensions, können Sie Makros betrachten, die wie

bool silent; 
#define silence(X) ({int _x; quiet(); _x = (X); verbose(); _x; }) 
#define printf(Fmt,...) \ 
    do{if (!silent) printf(Fmt,##__VA_ARGS__);}while(0) 

dass silence Makro funktionieren würde nur dann, wenn ihr Argument X ein int Ausdruck (oder verwenden Sie typeof) Ich gehe davon aus, dass das Ergebnis der printf ist nie benutzt. Erinnern Sie sich, dass "rekursive" Makros speziell vorverarbeitet werden, das interne Auftreten von printf (in diesem printf Makro) wird wortwörtlich ohne Makroexpansion verlassen.

Beachten Sie, dass silence keine Funktion sein kann (andernfalls wäre das Argument vor dem Aufruf ausgewertet worden). Und Sie müssen GCC statement expressions Erweiterung zu "erinnern" das Ergebnis des Arguments in einer Variablen _x (Sie könnten diesen Namen mit __COUNTER__ und Präprozessor-Verkettung generieren), um es als Wert von silence Makroaufruf geben.

Dann müssen Sie Ihre Funktionen quiet() und verbose() definieren, vielleicht so etwas wie

void quiet() 
{ 
    silent = true; 
} 

void verbose() 
{ 
    silent = false, 
} 

wenn Sie nicht printf als Makro definieren möchten, können Sie freopen(3) auf stdout (vielleicht mit "/dev/null" usw. verwenden könnte ..) oder tun dup2(2) Tricks (wie suggested by Pascal Cuoq).

Wenn Ihre Codebasis riesig ist und Sie etwas Ernsteres wollen und Tage oder Wochen mit der Arbeit verbringen möchten, ziehen Sie in Betracht, Ihren GCC-Compiler mit einem Plugin oder einer MELT Erweiterung anzupassen (oder bitten Sie jemanden, dies zu tun). Beachten Sie, dass printf GCC bekannt ist.

In Wirklichkeit sollten Sie Ihr eigenes Makro wie

#define myprintf(Fmt, ...) do{if (!silent) \ 
    printf(Fmt,__VA_ARGS__);}while(0) 

definieren und nur myprintf statt printf überall verwenden, ist dies ein tragbarer Trick. Natürlich nehme ich an, dass Sie printf nicht als Funktionszeiger übergeben.

Zum Debuggen, empfehle ich eigentlich

#define dbgprintf(Fmt,...) do{if (wantdebug) \ 
    printf("%s:%d:" Fmt "\n", __FILE__, __LINE__, \ 
      ##__VA_ARGS__);}while(0) 

und ich verwende dann dbgprintf("i=%d",i) oder einfach dbgprintf("foo here") in meinem Code.

Ich verwende ##__VA_ARGS__, die eine GCC-Erweiterung ist, um no variable arguments zu einem variadic Makro zu akzeptieren. Wenn Sie strikte C99 wollen, werden Sie einfach __VA_ARGS__ sagen und jeder dbgprintf würde ein Argument nach dem Format benötigen.

Sie könnten auch Ihre eigene printf Funktion implementieren, aber ich rate davon ab.

(Beachten Sie, dass die Dinge könnte komplexer sein, können Sie fputs nicht printf mit drucken ....)

+1

'printf (" BLAH! ");' Wird erweitert als 'printf (" BLAH! ",);'. Ich kann nicht mit einem Fehler kompilieren. – BLUEPIXY

+0

Entschuldigung, Sie brauchen '## __ VA_ARGS__' .. korrigiert ... –

+0

Es ist perfekt funktioniert. Vielen Dank. – BLUEPIXY

Verwandte Themen