#define - Problem

Cusco

Erfahrenes Mitglied
Ich habe ein Problem mit define:

Code:
#define nprintf(arg) {TCHAR szNPPuffer[1024];sprintf(szNPPuffer,arg);puts(szNPPuffer);}

nprintf(TEXT("Das ist meine eigenen Funktion 1:\n")); //Funktioniert

int zahl = 2;
nprintf(TEXT("Das ist meine eigenen Funktionen Nr.: %i\n"),zahl); //Funktioniert nicht mehr :(

Nummer zwei funktioniert nicht mehr, da kommt die Meldung das ich dem Macro, falsche parameter Übergeben habe, weil er denkt es sind 2 statt 1 Parameter. Wie kann man das ändern?
 
Hallo,

da hat der Compiler schon recht. Du hast für das Makro nur einen Parameter definiert, übergibst aber zwei.
Um das zu Ändern, musst du dein Makro erweitern:
Code:
#define nprintf2(format, arg) { TCHAR szNPPuffer[1024]; sprintf(szNPPuffer,format,arg); puts(szNPPuffer); }
int zahl = 2;
nprintf2(TEXT("Das ist meine eigenen Funktionen Nr.: %i\n"), zahl);

Gruß
MCoder
 
Cusco hat gesagt.:
Code:
#define nprintf(arg) {TCHAR szNPPuffer[1024];sprintf(szNPPuffer,arg);puts(szNPPuffer);}
Ich hoffe mal das ist nur ein Test - denn erst in einen Puffer zu schreiben (und nicht snprintf zu verwenden) um dann das Resultat auf die Standardausgabe zu schreiben ist etwas *hust* *hust* "ungünstig".

Gruß
 
Ich mag mit meiner Meinung ja allein stehen, aber ich rate dringend davon ab Macros in dieser Form zu verwenden. Das mag ja "cool" sein, aber es rächt sich wenn man später versucht einen Fehler zu finden, weil die meisten debugger die ich bisher kennengelernt habe, nciht durch das macro steppen können. Der Code im Macro bleibt also fürs debuggen unsichtbar.

Sicher _kann_ man Macros so verwenden, aber nicht alles was man machen kann ist auch gleich eine gute Idee. Pack den Code besser gleich in eine Funktion.
 
deepthroat hat gesagt.:
Ich hoffe mal das ist nur ein Test - denn erst in einen Puffer zu schreiben (und nicht snprintf zu verwenden) um dann das Resultat auf die Standardausgabe zu schreiben ist etwas *hust* *hust* "ungünstig".

Gruß

Das Teil sieht jetzt so aus:

Code:
#define snaprintf(arg1) {TCHAR szSNAPuffer[MAX_SNAPRINTF_PUFFER];wsprintf(szSNAPuffer,arg1);snaausgabe(szSNAPuffer);}

snaausgabe(TCHAR *) gibt dabei den Text entweder in der MessageBox oder im DOS-Fenster per printf bei ANSI oder wprintf bei UNICODE aus. Also die Routiene kommt mit beiden Zeichen-Codes zurecht. Ich habe mich für das Macro entschieden, damit ich nicht 10Funktionen je nach Argumentenanzahl schreiben muss. Und bei ner Funktion wo ich beliebig mehere Parameter angeben kann, da weiss ich nicht wie ich das schreiben soll. Die Routiene soll ja Text und Zahlen gleichzeitig verstehen können, je nach Text-Format.

Ausserdem kann der Code per define komplett aus den Relase-Source geschmissen werden, er soll nur zum Debuggen dienen das sieht dann so aus:

Code:
snadebug(snaprinf2(TEXT("Das ist ein Beispiel mit Zahl: %i\n"),zahl));

Ich sehe gerade das das snaprintf eigentlich blödsinn ist, der Text könnte ja gleich direkt in die ausgabefunktion geschrieben werden... bei den anderen mit mehr Parametern macht schon aber schon sinn, denke ich.
 
Ein beliebige Anzahl an Parametern würde so aussehen:

Code:
const char* MeinPrintf( const char* lpszFormat, ... )
{

  static char         szMiscBuffer[3000];

  vsprintf( szMiscBuffer, lpszFormat, (char *)( &lpszFormat + 1 ) );

  return szMiscBuffer;

}

Achtung, der Code prüft nichts und kann Fehler produzieren, wenn man nicht aufpasst. Zum einen max. 3000 Zeichen in einer Zeile. Zum anderen kannst du bei falschen Parametern (std::string direkt) richtig schön auf die Schnauze fallen. Und verschachteln geht auch nicht.

Aber einfacher zu formatieren als die std::streams isses :)


Nachtrag: Defines haben ihren Platz, aber was du da machst, ist keiner davon.
 
Endurion hat gesagt.:
Achtung, der Code prüft nichts und kann Fehler produzieren, wenn man nicht aufpasst. Zum einen max. 3000 Zeichen in einer Zeile. Zum anderen kannst du bei falschen Parametern (std::string direkt) richtig schön auf die Schnauze fallen. Und verschachteln geht auch nicht.

Aber einfacher zu formatieren als die std::streams isses :)

Nachtrag: Defines haben ihren Platz, aber was du da machst, ist keiner davon.

Anhand deines Beispieles habe ich eine eigene geschrieben, die auch zum Teil funktioniert, aber eben nur zum Teil :( Wenn mehrere Parameter angeben werden z.B: Zahlen wie int dann wird irgendeine wahlose zahl reingeschrieben aber nicht die die übergeben wurde, es sollte 5 zeigen aber raus kam 124xxx :(

Wo liegt der Fehler? Und nach möglichkeiot sollte die Routiene sicher sein.

Code:
// Text Ausgeben nach einstellung
void snaprintf(const TCHAR *lpszFormat, ...)
{
  TCHAR szpuffer[MAX_SNAPRINTF_PUFFER];
  wsprintf(szpuffer, lpszFormat,(TCHAR *)(&lpszFormat + sizeof(TCHAR)));  
  
   #ifdef SNAPRINTF_REQUSTER
      #ifdef UNICODE
        InfoReq(TEXT("SNA-Ausgabe (UNICODE)"),szpuffer);
      #else
        InfoReq(TEXT("SNA-Ausgabe (ANSI)"),szpuffer);
      #endif
   #else
      #ifndef UNICODE
        printf(szpuffer);
      #else
        wprintf(szpuffer);
      #endif
   #endif   
}
 
Ach verflixt, ich habe vergessen zu sagen, dass die Routine so als ersten Parameter einen Formatstring wie sprintf oder fprintf erwartet.

Ohne so etwas müsste der Compiler zur Laufzeit herausfinden, welcher Typ der Parameter ist und wie er ihn formatieren soll.

Also könnte ein Aufruf so aussehen:

Code:
//Nur ein Text: 
MeinPrintf( "Hallo Welt!" );

// Zahlen
MeinPrintf( "Du hast %d von %d Punkten erreicht.", 17, 32 );

// Strings
MeinPrintf( "Dein Name ist %s und du hast %d Goldstücke.", "Wullewatz", 17 );

Wenn du diesen Format-String nicht haben willst, musst du auf eine andere Schreibweise ausweichen (wie ihn die std::streams bieten, mit dem <<-operator).

Ich persönlich habe mir eine Mischform gebastelt, eine Klasse, die die Parameter per <<-operator bekommt, aber einen Formatstring benötigt. Ich komme mit dem Format-String wesentlich besser klar als mit kuriosen std::setw usw.
 
Endurion hat gesagt.:
Wenn du diesen Format-String nicht haben willst, musst du auf eine andere Schreibweise ausweichen (wie ihn die std::streams bieten, mit dem <<-operator).

Ich persönlich habe mir eine Mischform gebastelt, eine Klasse, die die Parameter per <<-operator bekommt, aber einen Formatstring benötigt. Ich komme mit dem Format-String wesentlich besser klar als mit kuriosen std::setw usw.
Er programmiert übrigens in C, also kannste die Tips über die iostreams und Klassen stecken lassen ;)

@Cusco: Bitte möglichst immer gleich im Titel angeben welche Sprache du verwendest. Die Konvention ist "[<Sprache>]" vor den eigentlichen Titel zu schreiben, also z.B. "[ C ] #define - Problem".

Gruß
 
deepthroat hat gesagt.:
Er programmiert übrigens in C, also kannste die Tips über die iostreams und Klassen stecken lassen ;)

@Cusco: Bitte möglichst immer gleich im Titel angeben welche Sprache du verwendest. Die Konvention ist "[<Sprache>]" vor den eigentlichen Titel zu schreiben, also z.B. "[ C ] #define - Problem".

Gruß

Ok werde dran denken, :) habe ich noch nicht gewust. mit C++ kenne ich mich noch überhaupt nicht aus :( Mein Buch zur WinAPI ist auch C online gehalten also denke ich das das reicht, zumindest noch
 
Zurück