Wieder einmal das Thema mit den "Zeigern"



  • Hallo,
    ich habe ein Problem mit Zeigern und konnte auch darüber hinaus jetzt nichts brauchbares im Internet finden oder ich habe einfach nur falsch gesucht -.-'.
    Also hier mein Code mal:

    SPos = strchr(text,'€');
    		if(SPos == NULL)
    			return 0;
    
    	*PosLeft = *(SPos-1);
    

    Ich will auf das Element vor dem '€' Zeichen zugreifen.
    Leider stürtzt mein Programm immer ab.
    Kann mir vielleicht jemand erklären warum?



  • Zeigt PosLeft denn auf eine reale Speicherstelle?
    (Ich nehme mal an die Zeiger sind vom Type char*)



  • Die Tatsache, dass du auf das Eurokennzeichen auf völlig unportable Weise prüfst, lasse ich jetzt mal weg (es gibt keine sichere aber bessere).
    Falls das Kennzeichen an Position 0 in text vorliegt oder PosLeft undefiniert ist oder auf ein Stringliteral zeigt, ist dein Verhalten undefiniert.
    Schon erstaunlich, wieviel mal mehr Text man zu sowenig Code schreiben kann.



  • Die beiden Zeiger sind beide vom Typ "char".

    Die Tatsache, dass du auf das Eurokennzeichen auf völlig unportable Weise prüfst, lasse ich jetzt mal weg (es gibt keine sichere aber bessere).
    Falls das Kennzeichen an Position 0 in text vorliegt oder PosLeft undefiniert ist oder auf ein Stringliteral zeigt, ist dein Verhalten undefiniert.
    Schon erstaunlich, wieviel mal mehr Text man zu sowenig Code schreiben kann.

    Ok, wie könnte ich den nach dem Zeichen "besser" suchen?
    "text" ist ein char Array...

    Zeigt PosLeft denn auf eine reale Speicherstelle?

    ja ich denk schon oder?

    char *SPos=NULL,*PosLeft=NULL;
    char text[] = "Das ist wie immer nur ein kleiner Test\nDer Betrag beträgt 125,25€\n Leihst du mir was?";
    
           SPos = strchr(text,'€');
            if(SPos == NULL)
                return 0;
    
        *PosLeft = *(SPos-1);
    


  • Saal schrieb:

    Zeigt PosLeft denn auf eine reale Speicherstelle?

    ja ich denk schon oder?

    Denkst du falsch!

    Du versuchst das Zeichen von der Stelle SPos-1 an die Stelle NULL zu schreiben.
    Denn PosLeft zeigt auf NULL.

    Da die Variable PosLeft heißt solltest du mal die * weglassen:

    PosLeft = (SPos-1);
    

    oder PosLeft wird ein char (kein Zeiger):

    char *SPos=NULL,PosLeft;
    


  • Du versuchst das Zeichen von der Stelle SPos-1 an die Stelle NULL zu schreiben.
    Denn PosLeft zeigt auf NULL.

    Oh man da hast du Recht..
    Da habe ich wohl oder übel was verwechselt 😃
    Da ich momentan hier keinen Compiler auf dem Rechner installiert haben, kann ich es erst heute Mittag testen.
    Habe jetzt folgenden "Merk" Tipp gefunden:

    Wird der Indirektionsoperator (*) vorangestellt, erkennen Sie, dass nicht auf den Zeiger zurückgegriffen werden soll, sondern auf das Datenobjekt, dessen Anfangsadresse sich im Zeiger befindet.

    Das heißt doch das es eigentlich so funktionieren müsste oder irre ich mich da auch wieder?

    PosLeft = *(SPos-1);
    


  • Dereferenzieren von NULL Zeigern ist der Fehler.
    Für deinen Fall muss zum erfolgreichen Eurozeichentest die aktuelle Codepage, die du in deiner Entwicklungsumgebung eingestellt hast, exakt mit dem Encoding, mit dem dein text-String erzeugt wurde, übereinstimmen. Es gibt keinen eindeutigen Standard, an welcher Position das Eurozeichen im erweiterten ASCII-Satz (Position 128..255) abgelegt ist, z.B. haben dabei selbst IBM/MS/Oracle unterschiedliche Auffassungen. Wenn du dann festgestellt hast, an welcher Position das Eurozeichen in DEINEN Strings IMMER vorkommt, dann wäre z.B. für die Windows Codepage 1252 und die dortige Position 128 angebracht:

    char *pos = strchr(text,'\x80');
    


  • Saal schrieb:

    Das heißt doch das es eigentlich so funktionieren müsste oder irre ich mich da auch wieder?

    PosLeft = *(SPos-1);
    

    Wenn PosLeft ein char ist (KEIN Zeiger, also mein oder Beispiel): Ja.

    Du kannst die das auch so merken:
    Es heißt *char PosLeft; Dann kannst du *PosLeft (mit 😉 auch wie ein char benutzen. Ohne * ist es der Zeiger.



  • Wutz schrieb:

    Dereferenzieren von NULL Zeigern ist der Fehler.
    Für deinen Fall muss zum erfolgreichen Eurozeichentest die aktuelle Codepage, die du in deiner Entwikclungsumgebung eingestellt hast, exakt mit dem Encoding, mit dem dein text-String erzeugt wurde, übereinstimmen. Es gibt keinen eindeutigen Standard, an welcher Position das Eurozeichen im erweiterten ASCII-Satz (Position 128..255) abgelegt ist, z.B. haben dabei selbst IBM/MS/Oracle unterschiedliche Auffassungen. Wenn du dann festgestellt hast, an welcher Position das Eurozeichen in DEINEN Strings IMMER vorkommt, dann wäre z.B. für die Windows Codepage 1252 und die dortige Position 128 angebracht:

    char *pos = strchr(text,'\x80');
    

    Die Probleme hat man aber auch nur, wenn man sich auf so ein Windows Codepage und ISO 8859 Zeugs einlässt. Aus dem Grund gibt es ja Unicode. Dann muss man zwar schauen, welche Darstellung man haben will: Entweder UTF-8 oder UTF-32.

    Nach irgend einer magischen Konstante (0x80) im String zu suchen, ist sicher keine sinnvolle Lösung.



  • Codepages und ISO Normen sind "Zeugs" und Konstanten neuerdings "magisch". rüdiger, die Lernkurve entwickelt sich damit steil nach unten. Das war nicht hilfreich.
    Die Satz lautete

    dann wäre z.B. für die Windows Codepage 1252 und die dortige Position 128 angebracht

    und ist nur ein Beispiel, oder nicht?

    Eine UTF Konvertierung stand nie zur Debatte.



  • Rüdigers Kritik ist gerechtfertigt, und die Konstante ist in der Tat das, was man als magische Zahl bezeichnet. Es ist keineswegs portabler, statt auf '€' auf '\x80' zu prüfen, ganz im Gegenteil - Windows 1252 ist außerhalb von Windows eine sehr unübliche Kodierungsmethode.

    Seinerseits ist der Verweis auf ISO 10646 (≈ Unicode) keine wirkliche Lösung - unter Umständen (etwa, wenn man das Dateiformat vorschreiben kann) mag es möglich sein, sich auf Eingaben in einer bestimmten Kodierung zu verlassen, aber wenn ich etwa Eingaben von der Konsole einlese, ist das im Zweifel nicht der Fall. Es gibt Lösungsmöglichkeiten dafür - ich denke da beispielsweise an iconv - aber leider bewegen wir uns da außerhalb der für Anfänger geeigneten Materie.

    @Saal: Wenn es der Anwendungsfall erlaubt, rate ich dir, statt "€" einen in ASCII-7 darstellbaren Bezeichner zu benutzen - "Euro", "EUR" oder so. Ist das nicht möglich aber die Eingabekodierung konstant und nicht die gleiche wie die deiner Quellcodedateien, benutze statt einer magischen Konstante besser eine symbolische. Im Fall von Windows 1252 etwa

    #define EURO_CHAR '\x80'
    #define EURO_STR  "\x80"
    
    /* ... */
    
    double d;
    char *pos = strchr(src, EURO_CHAR);
    sscanf("%lf " EURO_STR, &d);
    

    Dann musst du im Fall einer Portierung den Code nicht an zwanzig sondern nur an einer Stelle ändern.

    Ist es nicht möglich und die Eingabekodierung zur Compilezeit unbekannt, dann melde dich nochmal - das könnte etwas komplizierter werden.


Anmelden zum Antworten