Wie vergleiche ich Strings in C richtig?

Lesezeit: 8 Minuten

Benutzeravatar von nmagerko
magerko

Ich versuche, ein Programm zu bekommen, mit dem ein Benutzer ein Wort oder Zeichen eingeben, speichern und dann drucken kann, bis der Benutzer es erneut eingibt und das Programm verlässt. Mein Code sieht so aus:

#include <stdio.h>

int main()
{
    char input[40];
    char check[40];
    int i=0;
    printf("Hello!\nPlease enter a word or character:\n");
    gets(input);   /* obsolete function: do not use!! */
    printf("I will now repeat this until you type it back to me.\n");

    while (check != input)
    {
        printf("%s\n", input);
        gets(check);   /* obsolete function: do not use!! */
    }

    printf("Good bye!");
    

    return 0;
}

Das Problem ist, dass ich immer den Ausdruck der Eingabezeichenfolge bekomme, auch wenn die Eingabe des Benutzers (Check) mit dem Original (Eingabe) übereinstimmt. Vergleiche ich die beiden falsch?

  • gets( ) wurde aus der Norm entfernt. Verwenden fgets( ) stattdessen.

    – Eduard Karak

    29. Januar 2015 um 2:31 Uhr

  • Beachten Sie, dass diese Antwort auf Why does strcmp() Null zurückgeben, wenn seine Eingaben gleich sind, erklärt, wie Zeichenfolgen auf Gleichheit, Ungleichheit, kleiner als, größer als, kleiner oder gleich und größer als oder gleich verglichen werden. Nicht alle Zeichenfolgenvergleiche dienen der Gleichheit. Bei Vergleichen mit Berücksichtigung der Groß-/Kleinschreibung ist es wieder anders; Andere spezielle Vergleiche (z. B. Wörterbuchreihenfolge) erfordern spezialisiertere Komparatoren, und es gibt reguläre Ausdrücke für noch komplexere Vergleiche.

    – Jonathan Leffler

    22. November 2016 um 22:44 Uhr

  • Beachten Sie auch, dass es eine im Wesentlichen doppelte Frage gibt, wie ich überprüfe, ob ein Wert mit einer Zeichenfolge übereinstimmt, die Jahre zuvor gestellt wurde.

    – Jonathan Leffler

    10. Februar 2017 um 5:24 Uhr

  • Beantwortet das deine Frage? Wie überprüfe ich, ob ein Wert mit einer Zeichenfolge übereinstimmt?

    –Andreas

    16. Januar 2020 um 3:37 Uhr

  • Diese Frage ist gut, aber die Verwendung von gets() ist ein no go. Es wurde seit C11 auch aus dem Standard entfernt -> Bitte lesen Sie Warum ist die gets-Funktion so gefährlich, dass sie nicht verwendet werden sollte?

    – RobertS unterstützt Monica Cellio

    30. Mai 2020 um 9:50 Uhr

Benutzeravatar von Mystical
Mystisch

Sie können Zeichenfolgen nicht (sinnvoll) mit vergleichen != oder ==müssen Sie verwenden strcmp:

while (strcmp(check,input) != 0)

Der Grund dafür ist, weil != und == vergleicht nur die Basisadressen dieser Zeichenfolgen. Nicht der Inhalt der Strings selbst.

  • das gleiche in Java, was nur mit der Adresse verglichen werden kann.

    – Telerik

    6. September 2014 um 16:29 Uhr

  • Schreiben while (strcmp(check, input)) ist ausreichend und gilt als bewährte Praxis.

    – Schravan

    28. Juni 2015 um 15:53 ​​Uhr

  • mehr wissen…codificare.in/codes/c/…

    – Chanu-Panwar

    25. Juni 2016 um 9:55 Uhr

  • Es ist sicherer, strncmp zu verwenden! Ich will keinen Pufferüberlauf!

    – Floh

    10. November 2017 um 18:36 Uhr

  • @craigB Tut mir leid, dass deine Blase geplatzt ist, aber strcmp() sagt "abcde" ist größer als "abc"nicht gleich.

    – Deduplizierer

    11. September 2020 um 14:22 Uhr

Benutzeravatar von AusCBloke
AusCBloke

Ok ein paar Sachen: gets ist unsicher und sollte durch ersetzt werden fgets(input, sizeof(input), stdin) damit es keinen Pufferüberlauf gibt.

Als Nächstes müssen Sie zum Vergleichen von Zeichenfolgen verwenden strcmp, wobei ein Rückgabewert von 0 angibt, dass die beiden Zeichenfolgen übereinstimmen. Mit den Gleichheitsoperatoren (z. !=) vergleicht die Adresse der beiden Zeichenfolgen im Gegensatz zu der einzelnen chars in ihnen.

Beachten Sie auch, dass dies in diesem Beispiel zwar kein Problem verursacht, fgets speichert das Newline-Zeichen, '\n' auch in den Puffern; gets() nicht. Vergleicht man die Benutzereingaben aus fgets() zu einem String-Literal wie z "abc" es würde niemals übereinstimmen (es sei denn, der Puffer wäre zu klein, so dass die '\n' würde da nicht reinpassen).

  • Können Sie bitte die Beziehung/das Problem von “\n” und String-Literal klären? Ich erhalte ein ungleiches Ergebnis beim Vergleichen von Zeichenfolgen (Zeile) einer Datei mit einer anderen ganzen Datei.

    – inkompetent

    17. Juli 2019 um 16:32 Uhr

  • @incompetent — wenn Sie eine Zeile aus einer Datei mit lesen fgets()dann könnte die Zeichenfolge sein "abc\n" Weil fgets() behält den Zeilenumbruch. Wenn man das vergleicht "abc"erhalten Sie ‘ungleich’ wegen des Unterschieds zwischen einem Nullbyte am Ende "abc" und der Zeilenumbruch in den gelesenen Daten. Sie müssen also den Zeilenumbruch zappen. Der zuverlässige einzeilige Weg, dies zu tun, ist buffer[strcspn(buffer, "\n")] = '\0'; was den Vorteil hat, dass es korrekt funktioniert, unabhängig davon, ob sich Daten im Puffer befinden oder ob diese Daten mit einem Zeilenumbruch enden oder nicht. Andere Möglichkeiten, den Zeilenumbruch zu zappen, stürzen leicht ab.

    – Jonathan Leffler

    16. Januar 2020 um 3:39 Uhr

  • Diese Antwort behandelt die Probleme des Kodex genau, während die am meisten positiv bewertete und akzeptierte Antwort nur die Beantwortung des Titels der Frage abdeckt. Besonders zu erwähnen ist der letzte Absatz super. +1

    – RobertS unterstützt Monica Cellio

    30. Mai 2020 um 9:49 Uhr

Box Box Box Benutzeravatar von Box
Kiste Kiste Kiste Kiste

Verwenden strcmp.

Das ist in string.h Bibliothek und erfreut sich großer Beliebtheit. strcmp gibt 0 zurück, wenn die Zeichenketten gleich sind. Siehe dies für eine bessere Erklärung dessen, was strcmp kehrt zurück.

Grundsätzlich müssen Sie Folgendes tun:

while (strcmp(check,input) != 0)

oder

while (!strcmp(check,input))

oder

while (strcmp(check,input))

Du kannst nachschauen Diesein Tutorial zu strcmp.

mugetsus Benutzeravatar
mugetsu

Sie können Arrays nicht direkt so vergleichen

array1==array2

Sie sollten sie Zeichen für Zeichen vergleichen; Dazu können Sie eine Funktion verwenden und einen booleschen Wert (True:1, False:0) zurückgeben. Dann können Sie es in der Testbedingung der While-Schleife verwenden.

Versuche dies:

#include <stdio.h>
int checker(char input[],char check[]);
int main()
{
    char input[40];
    char check[40];
    int i=0;
    printf("Hello!\nPlease enter a word or character:\n");
    scanf("%s",input);
    printf("I will now repeat this until you type it back to me.\n");
    scanf("%s",check);

    while (!checker(input,check))
    {
        printf("%s\n", input);
        scanf("%s",check);
    }

    printf("Good bye!");

    return 0;
}

int checker(char input[],char check[])
{
    int i,result=1;
    for(i=0; input[i]!='\0' || check[i]!='\0'; i++) {
        if(input[i] != check[i]) {
            result=0;
            break;
        }
    }
    return result;
}

Benutzeravatar von thb
thb

Willkommen beim Konzept der Zeiger. Generationen von Programmieranfängern fanden das Konzept schwer fassbar, aber wenn Sie sich zu einem kompetenten Programmierer entwickeln möchten, müssen Sie dieses Konzept schließlich beherrschen – und außerdem stellen Sie bereits die richtige Frage. Das ist gut.

Ist Ihnen klar, was eine Adresse ist? Siehe dieses Diagramm:

----------     ----------
| 0x4000 |     | 0x4004 |
|    1   |     |    7   |
----------     ----------

In dem Diagramm wird die ganze Zahl 1 im Speicher bei gespeichert die Anschrift 0x4000. Warum an einer Adresse? Weil der Speicher groß ist und viele ganze Zahlen speichern kann, genauso wie eine Stadt groß ist und viele Familien beherbergen kann. Jede ganze Zahl wird an einem Speicherort gespeichert, da jede Familie in einem Haus wohnt. Jeder Speicherplatz wird durch ein gekennzeichnet die Anschriftda jedes Haus durch eine Adresse identifiziert wird.

Die beiden Kästchen im Diagramm repräsentieren zwei unterschiedliche Speicherorte. Sie können sie sich vorstellen, als wären sie Häuser. Die Ganzzahl 1 befindet sich an der Speicherstelle bei Adresse 0x4000 (denken Sie an “4000 Elm St.”). Die Ganzzahl 7 befindet sich an der Speicherstelle bei Adresse 0x4004 (denken Sie an “4004 Elm St.”).

Sie dachten, dass Ihr Programm die 1 mit der 7 vergleicht, aber das war nicht der Fall. Es wurde 0x4000 mit 0x4004 verglichen. Was passiert also, wenn Sie diese Situation haben?

----------     ----------
| 0x4000 |     | 0x4004 |
|    1   |     |    1   |
----------     ----------

Die beiden Ganzzahlen sind gleich, aber die Adressen unterscheiden sich. Ihr Programm vergleicht die Adressen.

Benutzeravatar von StephenTG
Stephen TG

Wann immer Sie versuchen, die Zeichenfolgen zu vergleichen, vergleichen Sie sie in Bezug auf jedes Zeichen. Dafür können Sie die eingebaute String-Funktion namens strcmp(input1,input2) verwenden; und Sie sollten die Header-Datei namens verwenden #include<string.h>

Versuchen Sie diesen Code:

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h>  

int main() 
{ 
    char s[]="STACKOVERFLOW";
    char s1[200];
    printf("Enter the string to be checked\n");//enter the input string
    scanf("%s",s1);
    if(strcmp(s,s1)==0)//compare both the strings  
    {
        printf("Both the Strings match\n"); 
    } 
    else
    {
        printf("Entered String does not match\n");  
    } 
    system("pause");  
} 

Wie vergleiche ich Strings richtig?

char input[40];
char check[40];
strcpy(input, "Hello"); // input assigned somehow
strcpy(check, "Hello"); // check assigned somehow

// insufficient
while (check != input)

// good
while (strcmp(check, input) != 0)
// or 
while (strcmp(check, input))

Lassen Sie uns tiefer graben, um zu sehen warum check != input ist nicht ausreichend.

In C, Schnur ist eine Standardbibliotheksspezifikation.

EIN Schnur ist eine fortlaufende Folge von Zeichen, die durch das erste Nullzeichen abgeschlossen wird und dieses enthält.
C11 §7.1.1 1

input oben ist nicht a Schnur. input ist Array 40 von Zeichen.

Die Inhalte von input kann ein werden Schnur.

Wenn ein Array in einem Ausdruck verwendet wird, wird es in den meisten Fällen in die Adresse seines ersten Elements konvertiert.

Das Folgende konvertiert check und input mit ihren jeweiligen Adressen des ersten Elements, dann werden diese Adressen verglichen.

check != input   // Compare addresses, not the contents of what addresses reference

Vergleichen Saitenmüssen wir diese Adressen verwenden und uns dann die Daten ansehen, auf die sie verweisen.
strcmp() macht den Job. §7.23.4.2

int strcmp(const char *s1, const char *s2);

Das strcmp Die Funktion vergleicht die Zeichenfolge, auf die von gezeigt wird s1 zu der Zeichenfolge, auf die von gezeigt wird s2.

Das strcmp Die Funktion gibt eine ganze Zahl zurück, die größer, gleich oder kleiner als Null ist, entsprechend der Zeichenfolge, auf die von zeigt s1 größer, gleich oder kleiner als die Zeichenfolge ist, auf die gezeigt wird s2.

Der Code kann nicht nur feststellen, ob die Zeichenfolgen dieselben Daten enthalten, sondern auch, welche größer/kleiner ist, wenn sie sich unterscheiden.

Das Folgende gilt, wenn sich die Zeichenfolge unterscheidet.

strcmp(check, input) != 0

Weitere Informationen finden Sie unter Eigene erstellen strcmp() Funktion

1426140cookie-checkWie vergleiche ich Strings in C richtig?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy