Frage zum String vergleichen



  • hey, ich wollte mal fragen warum diese fehlermeldung kommt
    ich vermute mal das man einen string nicht so einfach vergleichen kann oder?

    "comparison with string literal results in unspecified behavior"

    char *string = "hallo";
    
    if (string == "hallo")
    {
    ...
    .....
    }
    


  • Das ist korrekt. Das erste "hallo" kann an einer anderen Stelle im Speicher liegen als das zweite, daher kann dieser Vergleich fehlschlagen, und das ist dann nicht, was du willst.

    Zum Vergleichen von Strings gibt es in der Standardbibliothek die Funktion strcmp, die 0 zurückgibt, wenn zwei Strings lexikographisch gleich sind (kleiner Null bedeutet, dass der linke vor dem ersten kommt, größer Null, dass es umgekehrt ist). Das liest sich korrekt also wie folgt:

    /* Jedes Mal, wenn ein String-Literal einem char* zugewiesen wird, tötet
     * Algorithmos ein niedliches Kätzchen auf unnötig grausame Weise.
     *
     * Nimm char const*.
     */
    char const *string = "hallo";
    
    if(0 == strcmp(string, "hallo")) {
      ...
    }
    


  • Für den Vergleich von C-Strings gibt es
    http://www.cplusplus.com/reference/clibrary/cstring/strcmp/



  • HAHA xD
    Okay die Funktion hab ich auch schon in meinem Büchlein gefunden hätte ja sein können 😉 Ehm aber mit einem normalen char was ja nur ein Zeichen ist würde es klappen oder also

    char buchstabe = 'j';
    if (buchstabe == 'j')
    

    Falls jmd diesen Thread liest der das gleiche Problem hat, ist noch zu erwähnen das die string.h included werden muss.



  • Ja, das:
    char c = 'J';
    ist ein Zeichen und kann mit
    char d = 'J';

    if(c == d)
    ...
    verglichen werden.
    Hier:
    const char *str = "bla";
    ist str aber ein Zeiger auf eine Speicheradresse, an der "bla" gespeichert ist und
    ein Vergleich
    if (str == irgendwas)
    vergleicht die Zeiger, und nicht das, worauf sie zeigen, wird also in aller Regel nicht zu true ausgewertet werden.



  • Das kann man so nun auch wieder nicht sagen. Es gibt durchaus Umstände, unter denen Zeigervergleiche ausreichen (und dann dadurch glänzen, dass sie so schön billig sind): wenn sie als Iteratoren verwendet werden, oder in Bäumen bzw. Listen zum Beispiel. Auch bei Strings können sie mitunter ausreichen, wenn man beispielsweise sichergestellt hat, dass man sich ausschließlich aus einem statischen Stringpool bedient.

    So ist zum Beispiel

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    enum {
      LNG_GERMAN,
      LNG_ENGLISH
    };
    
    char const *hallo_string(int sprache) {
      return sprache == LNG_GERMAN ? "Hallo, Welt." : "Hello, world.";
    }
    
    int main(void) {
      char const *msg;
    
      srand(time(0));
    
      msg = hallo_string(rand() % 2);
    
      puts(msg);
    
      /* Zeigervergleich hier zulässig! */
      if(msg == hallo_string(LNG_ENGLISH)) {
        puts("That was English.");
      } else {
        puts("Das war die Sendung mit der Maus.");
      }
    
      return 0;
    }
    

    korrekt und wohldefiniert, weil die String-Literale in hallo_string (genauer: die aus den Stringliteralen in hallo_string generierten Zeichensequenzen) immer die selben sind.

    Wohlgemerkt: Sähe hallo_string etwa so aus:

    char const *hallo_string(int sprache) {
      return sprache == LNG_GERMAN ? "Hallo, Welt." : "Hallo, Welt.";
    }
    

    Dann dürfte ein Compiler die beiden identischen String-Literale an der selben Stelle im Speicher ablegen, müsste es aber nicht tun. Der Wert des Vergleiches msg == hallo_string(LNG_ENGLISH) wäre dann unspezifiziert.



  • Super Beispiel aus der täglichen Praxis der Stringvergleiche. Ich bin sicher, der TE versteht das und kann das gewinnbringend einsetzen.
    Was mich aber jetzt noch interessieren würde ist:
    Was an meinem Posting

    seldon schrieb:

    kann man so nun auch wieder nicht sagen.



  • Ich bezog mich auf das hier:

    Belli schrieb:

    if (str == irgendwas)
    vergleicht die Zeiger, und nicht das, worauf sie zeigen, wird also in aller Regel nicht zu true ausgewertet werden.

    Wichtiger als das Codebeispiel ist mir dann eigentlich der Hinweis auf Iteratoren, Bäume und Listen.

    Ansonsten mag die Stringpool-Kiste nichts sein, was Anfänger sofort und dauernd einsetzen können, aber ich halte nichts davon, die Regel darzustellen, ohne auf Ausnahmen zumindest hinzuweisen. Wenn dabei vorläufig nur hängen bleibt, dass es in dieser Richtung später noch mehr zu lernen gibt, ist das aus meiner Sicht schon ein Gewinn.



  • seldon schrieb:

    Ich bezog mich auf das hier:

    Belli schrieb:

    if (str == irgendwas)
    vergleicht die Zeiger, und nicht das, worauf sie zeigen, wird also in aller Regel nicht zu true ausgewertet werden.

    aber ich halte nichts davon, die Regel darzustellen, ohne auf Ausnahmen zumindest hinzuweisen.

    Okay, aber ich habe doch extra "in aller Regel" geschrieben. Das Thema heißt zudem "... String vergleichen" und nicht Zeiger vergleichen.

    Trotzdem hast Du selbstverständlich recht: Wenn zwei Zeiger auf denselben Speicher zeigen, ergibt eine Abfrage auf Gleichheit true. Soweit bin ich ganz bei Dir!



  • Was du geschrieben hast, ist ja auch nicht falsch. Ich wollte es nur ergänzen.


Anmelden zum Antworten