Frage zu #define

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Antworten
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Frage zu #define

Beitrag von Jan »

Normaler Weise arbeite ich bei Sprachwahlen ja so:

Code: Alles auswählen

#define wasauchimmer = 123456

// Deutsch
123456 = "Was auch immer"
// Englisch
123456 = "What ever"

? LoadResource(wasauchimmer, , RES_STRING, sprache)
Wie aber mache ich das, wenn wasauchimmer nicht als Variable vorhanden ist, sondern als String? Also so:

Code: Alles auswählen

? LoadResource("wasauchimmer", , RES_STRING, sprache)
Dann gibt der mir immer zurück: "Unknown variable"

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9357
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von Tom »

wasauchimmer ist keine Variable, sondern eine Konstante. Der Präprozessor führt eine Textersetzung durch, aber nur, wenn er wasauchimmer erstens direkt im Quelltext findet und zweitens nicht als Bestandteil eines Textes.

Die einfache Lösung bestünde also darin:

Code: Alles auswählen

cLoadVar := wasauchimmer
? LoadResource(cLoadVar , , RES_STRING, sprache)
Das entspricht allerdings der direkten Verwendung von wasauchimmer (ohne Anführungszeichen) in "LoadResource". Die Frage lautet also, was Du erreichen willst.
Herzlich,
Tom
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von Jan »

Hallo Tom,

natürlich hast Du Recht, wir reden über eine Konstante, nicht über eine Variable.

Aber leider funktioniert Dein Beispiel auch nicht. Immer noch die gleiche Rückmeldung "Unknown variable".

Vielleicht sollte ich meine Vorgehensweise etwas präsizieren: Ich habe die ganzen #defines und Übersetzungen in verschiedene Dateien geschrieben, weil das wesentlich übersichtlicher ist (und mir eine Menge scrollen erspart). Das sieht dann so aus:
programm.arc hat geschrieben:LANGUAGE = "de"
#include "Deutsch.ch"
LANGUAGE = "en-us"
#include "English.ch"
defines.ch hat geschrieben:#define LANG_wasauchimmer = 123456
Alle Konstanten, die die Sprache betreffen, haben ein "LANG_" davor.
deutsch.ch hat geschrieben:123456 = "Was auch immer"
englisch.ch hat geschrieben:123456 = "What ever"
Zusätzlich habe ich eine Funktion, die mir den gewünschten String zurück gibt:

Code: Alles auswählen

FUNCTION langText(cResource, cSprache)

IF cSprache == "Deutsch"
   cSprache := "de"

 ELSEIF cSprache == "English"
   cSprache := "en-us"
ENDIF

RETURN Loadresource(cResource, , RES_STRING, IIf(cSprache == NIL, MEMVAR->gcSprache, cSprache))
Sinn dieser Sache ist es, das ich wahlweise die global eingestellte Sprache abfrage, oder eine für genau diese Ausgabe gewünschte. Und das ganze ist ausgelagert, damit ich nicht an hunderten Stellen das ganze wieder und wieder coden muß.

Normalerweise arbeite ich mit der Angabe der Konstanten, die dann korrekt in LoadResource als der numerische Wert verarbeitet werden und mir den sprachlich passenden String zurück. Jetzt habe ich aber gerade die Situation, das ich aus einer API Rückgaben erhalte, die ich gerne in einer Schleife abarbeiten möchte. Ohne für jede Konstante eine eigene IF-Abfrage zu schreiben. Statt dessen nehme ich die Strings in der Rückgabe, und übergebe die an meine Funktion als langText("LANG_" + cString). Und genau das funktioniert halt leider nicht.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16508
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von Martin Altmann »

Kann auch nicht funktionieren, da es keine Zeichenkette, sondern ein numerischer Wert ist!
Du musst das nach dem Zusammensetzen noch Makroexpandieren - dann sollte das klappen!

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von Jan »

Martin,

Makroexpandieren? Du meinst &? Nein, dann kommt sofort beim & die Meldung, das die Variable unbekannt sei.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von brandelh »

Wenn ich dich richtig verstehe gibt dir z.B. die API den String "Offen" zurück und du willst in deiner Resource nach dem Inhalt "Offen" suchen, der Compiler sucht aber nach der Variablen "Offen" ... ist das so ?

Resourcen werden normalerweise als numerische Werte gespeichert, man kann aber auch einen String als Resource ID nutzen,
die Frage ist aber ob du das überhaupt machst ? Ich vermute du speicherst nur numerische SprachIDs !
Hierzu müsste man aber den Quellcode der Funktion kennen ...
<nResId|cResId>

<nResId> ist ein numerischer Resourcen-Identifikator. Diese ID muß beim Linken einer Resource-Datei an eine EXE- oder DLL-Datei mit ARC.EXE verwendet werden. <cResId> ist ein Resourcen-Identifikator des Types Character. In der ARC-Datei muß ebenfalls ein Identifikator dieses Types verwendet worden sein. Hinweis: Das Aufsuchen eines Resourcen-Identifikators des Typs Character (<cResId> ) ist abhängig vom Betriebssystem. Daher wird empfohlen, <cResId> immer mit Grossbuchstaben zu schreiben, ebenso in der ARC-Datei.
Wichtig ist aber die Erkenntnis, dass eine cResId nicht gleich mit dem Inhalt ist !
Man könnte eventuell eine cResID mit dem benötigten Suchbegriff anlegen, und eventuell auf die numerische umleiten, aber das habe ich nie gemacht.

Eventuell auch den Inhalt aller nResIDs einlesen und den String darin suchen ?
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von Jan »

Hubert,

die API gibt mir ein "Offen" zurück, und ich suche dann nach der Konstanten "LANG_Offen". Und genau das erkennt der zur Laufzeit als Variable, nicht als Konstante. Und LANG_Offen ist nun einmal keine Variable, so das es zwei Möglichkeiten gibt:
- Suche ich nach &cResource, dann bekomme ich einen Laufzeitfehler von wegen unbekannter Variablen
- Suche ich nach cResource, dann gibt LoadResource() mir ein NIL zurück. Weil der halt eine nResID sucht und nicht eine cResID, da meine ResIDs grundsätzlich numerisch sind.

Es stellt sich also die Frage, wie ich den String in eine in den Konstanten suchbaren Begriff wandle (& geht halt nicht, weil der nur auf Variablen geht). Oder wie ich nicht nach der nResID suche, sondern nach der Entsprechung. Letzteres hat natürlich das Problem, daß das nur ein Umweg wäre. Denn in den beiden Sprachdateien suche ich ja nach der nResID. Aber wenn es denn klappen würde, wäre ich auch damit zufrieden.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von brandelh »

Hallo JAN,

wenn du mit KONSTANTE "DE_OFFEN" meinst:

Code: Alles auswählen

#define DE_OFFEN 123423
dann hast du die Wirkung von #define nicht verstanden ;-)

ES GIBT IN DER EXE KEIN DE_OFFEN sondern nur 123423 also die nResourceID in diesem Falle.

Xbase++ selbst hat keine richtigen Konstanten !
Es tauscht nur den Begriff DE_OFFEN gegen 123423 aus ... schau dir doch mal die Stellen in der PPO Datei an :!:
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von Jan »

Hubert,

doch. Zumindest soweit habe ich das vollkommen verstanden. Und genau das ist das Problem. Wie bekomme ich aus aus dem String "LANG_Offen" die 123423 raus? Keine Ahnung.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von brandelh »

In der EXE gar nicht mehr, denn XPP tauscht diesen gegen den Teil rechts aus, einfaches suchen & ersetzten !

Außer du machst einen Trick ;-) ...
man müsste beides angeben, aber wie ...
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von brandelh »

Du könntest in einer Funktion alle Namen hinterlegen, wobei die Schreibweise im Quellcode anders sein müsste (sonst wird es ersetzt), zur Laufzeit aber keine Rolle spielen darf:

Code: Alles auswählen

...
#define DE_OFFEN 123423
MyIDTable("De_Offen", DE_OFFEN )
...
function MyIDTable(cKey,nKey)
   static aKeyInfo := {}
   cKey := upper(alltrim(cKey)) // Fehler abfangen ?
   if nKey=NIL // Abfrage
      x := aScan(aKeyInfo,cKey) // syntax prüfen, eventuell muss man auf ArrayElement[1] abprüfen
      if x > 0 
         nKey := aKeyInfo[x,2]
      else
         ??? NIL ???
      endif 
   else   // setzen
      ... eventuell abfragen ob es den schon gibt
      aadd(aKeyInfo, {cKey,nKey})
   endif
return nKey
so könnte es gehen, ist aber Aufwand beim Schreiben ... dafür ist es sicherer, dass beide identisch sind.
Bei aScan bin ich mir nicht ganz sicher ob ein einfacher Suchstring gefunden wird, vermutlich besser den codeblock angeben, auch damit auf == geprüft werden kann (wenn gewünscht).

PS: ich nutze die DBF methode, da ist das viel einfacher ;-)
Zuletzt geändert von brandelh am Do, 19. Feb 2015 15:30, insgesamt 1-mal geändert.
Grund: offensichtliche Tippfehler verbessert ;-)
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von Jan »

Hallo Hubert,

ich muß gestehen - ich verstehe Deinen Code nicht. Kann es sein, das Deine Finger teilweise was anderes gemacht haben als das Hirn dachte?

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von brandelh »

Ich weiß was ich dachte und die Finger haben sich nicht vertippt.

Ich erkläre es in Worten ...

nach dem DEFINE (der ja in der EXE nicht verfügbar ist), rufe ich eine eigene Funktion auf, die sowohl den Text als auch die numerische ID speichert !
da beides im gleichen Quellcode definiert wird, ist es noch wartbar ...

Die Funktion die ich oben so aus der Hüfte skiziert habe (sie dürfte arbeiten, aber ich habe sie nicht compiliert), macht nichts anderes als das Speichern bzw. Abfragen von cIDs mit der Rückgabe von nID, also das was du wolltest. Ich nutzte häufig solche Funktionen, die beim ersten einlesen z.B. alle Postleitzahlen aus einer Datei nachladen und in der Static speichern ...

Allerdings gebe ich dir in einem Punkt Recht, vermutlich stehen deine Defines in einem Bereich der gar nicht zur Laufzeit aufgerufen wird und somit würde die Funktion nicht geladen.

PS: ich muss aber zugeben, dass die Schrift im Eingabemodus mittlerweise zu klein geworden ist ... vergessener Funktionsname ... :(
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von brandelh »

du könntest auch eine eigene ARC Datei machen in denen du die nötigen Werte als Resource Namen definierst, welche die nötige Resource-ID zurückgeben.
Beides wäre aber natürlich sehr fehleranfällig ... und #DEFINE dürfte auf diese Datei nicht angewendet werden.
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von Jan »

Hubert,

meine Bemerkung bezog sich darauf, das schon die Anrede in Deinem Beitrag verstümmelt und in der falschen Zeile steht. Du dann in dem Code eine Funktion aufrufst, die sonst nirgends erwähnt wird. Und untern einen Aufruf "function(cKey, nKey)". Eine Funktion namens function scheint mir etwas ... merkwürdig.

Aber inzwischen verstehe ich, auf was Du hinaus willst. Aber wenn das der einzige Weg sein sollte, dann dürfte es einfacher sein, den betreffenden Part doch nicht als Schleife zu schreiben, sondern ausführlich. Das kostet mich vielleicht 50 Codezeilen, Dein Vorschlag dagegen mehrere tausend.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von brandelh »

Jan hat geschrieben:meine Bemerkung bezog sich darauf, das schon die Anrede in Deinem Beitrag verstümmelt und in der falschen Zeile steht.
Du dann in dem Code eine Funktion aufrufst, die sonst nirgends erwähnt wird. Und untern einen Aufruf "function(cKey, nKey)".
Stimmt, bei "Hallo JAN," habe ich das H nicht richtig erwischt und bei function habe ich den Namen vergessen ;-)

Code: Alles auswählen

#define DE_OFFEN 123423
MyIDTable("De_Offen", DE_OFFEN )
...
function MyIDTable (cKey,nKey)
Aber inzwischen verstehe ich, auf was Du hinaus willst. Aber wenn das der einzige Weg sein sollte,
dann dürfte es einfacher sein, den betreffenden Part doch nicht als Schleife zu schreiben, sondern ausführlich.
Das kostet mich vielleicht 50 Codezeilen, Dein Vorschlag dagegen mehrere tausend.
nochmal, das was du als Konstante bezeichnest (also DE_Open) gibt es in der EXE nicht mehr, somit ist dies direkt nicht suchbar.
Ich wollte aufzeigen wie man es so hinbiegen könnte, dass es geht; ob es sinnvoll ist muss jeder selbst entscheiden ;-)

Hast du mal versucht eine Resource "DE_OPEN" mit 12345 zusätzlich zur "normalen" anzulegen ?
Ich habe nie ResourcenNamen verwendet, aber es könnte das sein was du brauchst.
Gruß
Hubert
Benutzeravatar
Wolfgang Ciriack
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2934
Registriert: Sa, 24. Sep 2005 9:37
Wohnort: Berlin
Hat sich bedankt: 13 Mal
Danksagung erhalten: 34 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von Wolfgang Ciriack »

Warum machst du nicht einen numerischen Offset für die einzelnen Sprachen:
#define LANG_OFFEN "deutsch_blabla"
#define LANG_OFFEN+1000 "engl_blabla"
#define LANG_OFFEN+2000 "franz_blabla"

im Programm definierst du den offset je nach Sprache (deutsch=0, engl=1000, franz=2000 und setzt überall
LANG_OFFEN+offset.
Viele Grüße
Wolfgang
Benutzeravatar
andreas
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1902
Registriert: Mi, 28. Sep 2005 10:53
Wohnort: Osnabrück
Hat sich bedankt: 4 Mal
Kontaktdaten:

Re: Frage zu #define

Beitrag von andreas »

Jan,

sieh dir den Beispiel von Alaska unter XPPW32\SOURCE\samples\basics\Language an.
Ich denke, dass es genau das ist, was du suchst!
Gruß,

Andreas
VIP der XUG Osnabrück
Antworten