Lesen eines Strings mit Leerzeichen mit sscanf

Lesezeit: 6 Minuten

Benutzeravatar von SDLFunTimes
SDLFunTimes

Für ein Projekt versuche ich, ein Int und einen String aus einem String zu lesen. Das einzige Problem ist sscanf() scheint beim Lesen an zu brechen %s wenn es ein Leerzeichen sieht. Gibt es eine Möglichkeit, diese Einschränkung zu umgehen? Hier ist ein Beispiel dafür, was ich versuche:

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

int main(int argc, char** argv) {
    int age;
    char* buffer;
    buffer = malloc(200 * sizeof(char));
    sscanf("19 cool kid", "%d %s", &age, buffer);

    printf("%s is %d years old\n", buffer, age);
    return 0;
}

Was es druckt ist: cool is 19 years old wo ich brauche cool kid is 19 years old. Weiß jemand, wie man das beheben kann?

  • Überprüfung des Ergebnisses von sscanf() ist ein guter erster Schritt zur Versicherung ageusw. erfolgreich gescannt.

    – chux – Wiedereinsetzung von Monica

    9. November 2015 um 15:00 Uhr

Benutzeravatar von BrunoLM
BrunoLM

Die folgende Zeile beginnt mit dem Lesen einer Zahl (%d) gefolgt von etwas anderem als Tabulatoren oder Zeilenumbrüchen (%[^\t\n]).

sscanf("19 cool kid", "%d %[^\t\n]", &age, buffer);

  • Vielen Dank. Außerdem funktioniert %d aus irgendeinem Grund nicht mehr, also habe ich % verwendet[0-9]. Danke noch einmal.

    – SDLFunTimes

    18. Mai 2010 um 5:34 Uhr

  • Aber … aber das ist katastrophal falsch! %[0-9] Bezeichner (und ähnliche) können nur zum Lesen von Zeichenfolgen verwendet werden. Und Sie lesen ein int (age) damit. Das kann und wird nicht funktionieren.

    – AnT steht zu Russland

    24. September 2010 um 2:11 Uhr


  • Wenn Sie eine lesen möchten intdu brauchst %d (oder vielleicht %i oder irgendetwas int-kompatibel). Aber nicht %[].

    – AnT steht zu Russland

    24. September 2010 um 2:15 Uhr

  • Du meinst, du liest ein int variabel mit an %[0-9] formatieren und dann wie im OP-Code drucken und es “funktioniert”? Tut mir leid, ich kann das kaum glauben 🙂 Nein, es funktioniert nicht. Ich kann mir vorstellen, dass Sie eine Zeichenfolge mit 3 Zeichen (oder weniger) in eine 4-Byte-Zeichenfolge quetschen können intaber sobald Sie das drucken int Sie werden Müll bekommen. Zu sagen, dass dieser zufällige Hack “funktioniert”, ist natürlich eine Beleidigung für das Wort “Arbeit” 🙂

    – AnT steht zu Russland

    24. September 2010 um 2:46 Uhr


  • @RyanS: Nein, ich bin es nicht, es ist die natürliche Dissonanz zwischen Saiten und Zahlen, die dich traurig macht. Sie sind nicht gleich. Manchmal macht es mich auch traurig, aber irgendwie habe ich gelernt, damit umzugehen. Warum oh warum, grausame Welt?!!!

    – AnT steht zu Russland

    19. Juni 2012 um 21:44 Uhr


Du willst die %c Konvertierungsbezeichner, der nur eine Folge von Zeichen ohne besondere Behandlung von Leerzeichen liest.

Beachten Sie, dass Sie den Puffer zuerst mit Nullen füllen müssen, da die %c Bezeichner schreibt kein Null-Terminator. Sie müssen auch die Anzahl der zu lesenden Zeichen angeben (ansonsten ist es standardmäßig nur 1):

memset(buffer, 0, 200);
sscanf("19 cool kid", "%d %199c", &age, buffer);

  • Nun, das wird nicht für meinen Cousin funktionieren, der verdächtigerweise “George Fortescue Aloicious Broomhilda Doreen Beelzebub … Johanssen MacGregor” heißt 🙂

    – paxdiablo

    18. Mai 2010 um 4:17 Uhr

  • In der Tat – Ihr Cousin sollte sich beim OP beschweren, weil er nur einen Puffer von 200 Bytes zugewiesen hat;)

    – Café

    18. Mai 2010 um 4:23 Uhr

  • Guter Punkt und da Sie das Pufferüberlaufproblem mit meinen und Brunos Antworten erfasst haben, +1. Mach bei uns mit 🙂

    – paxdiablo

    18. Mai 2010 um 5:13 Uhr


  • @paxdiablo Nun, ich habe das gefunden %199c nützlich für mich, weil in meinem Fall die Zeichenfolge tatsächlich eine feste Länge hat.

    – Wesley

    27. Mai 2015 um 9:26 Uhr

Benutzeravatar von paxdiablo
paxdiablo

Wenn Sie bis zum Ende der Zeichenfolge scannen möchten (wobei ein Zeilenumbruch entfernt wird), verwenden Sie einfach:

char *x = "19 cool kid";
sscanf (x, "%d %[^\n]", &age, buffer);

Das ist, weil %s stimmt nur mit Zeichen überein, die keine Leerzeichen sind, und stoppt beim ersten gefundenen Leerzeichen. Das %[^\n] Formatbezeichner stimmt mit jedem Zeichen überein, das nicht (wegen ^) in der angegebenen Auswahl (was ein Zeilenumbruch ist). Mit anderen Worten, es passt zu jedem anderen Zeichen.


Denken Sie daran, dass Sie genügend Platz in Ihrem Puffer haben sollten, um die Zeichenfolge aufzunehmen, da Sie nicht sicher sein können, wie viel gelesen wird (ein guter Grund, sich von scanf/fscanf es sei denn, Sie verwenden bestimmte Feldbreiten).

Das könntest du machen mit:

char *x = "19 cool kid";
char *buffer = malloc (strlen (x) + 1);
sscanf (x, "%d %[^\n]", &age, buffer);

(braucht man nicht * sizeof(char) denn das ist stets 1 per definitionem).

  • Also verursacht Ihr Cousin hier drüben einen Unfall, anstatt die Empörung zu erleiden, dass sein Name abgeschnitten wird? Auch mein Cousin, dessen Name noch verdächtiger ist (wobei das dritte Zeichen seines zweiten Namens ein Zeilenumbruch ist), ist unglücklich.

    – Café

    18. Mai 2010 um 4:23 Uhr


  • Der Kommentar muss im Zusammenhang mit den Kommentaren zu meiner Antwort gelesen werden.

    – Café

    18. Mai 2010 um 4:39 Uhr

Benutzeravatar von ɲeuroburɳ
ɲeuroburɳ

Da Sie die abschließende Zeichenfolge aus der Eingabe benötigen, können Sie verwenden %n (Anzahl der bisher verbrauchten Zeichen), um die Position zu erhalten, an der die abschließende Zeichenfolge beginnt. Dies vermeidet Speicherkopien und Probleme mit der Puffergröße, hat jedoch den Preis, dass Sie diese möglicherweise explizit ausführen müssen, wenn Sie eine Kopie wünschen.

const char *input = "19  cool kid";
int age;
int nameStart = 0;
sscanf(input, "%d %n", &age, &nameStart);
printf("%s is %d years old\n", input + nameStart, age);

Ausgänge:

cool kid is 19 years old

Ich denke, das ist, was Sie wollen, es macht genau das, was Sie angegeben haben.

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

int main(int argc, char** argv) {
    int age;
    char* buffer;
    buffer = malloc(200 * sizeof(char));
    sscanf("19 cool kid", "%d cool %s", &age, buffer);
    printf("cool %s is %d years old\n", buffer, age);
    return 0;
}

Das Format erwartet: zuerst eine Zahl (und setzt sie an die Stelle, auf die &age zeigt), dann Leerzeichen (null oder mehr), dann die literale Zeichenfolge „cool“, dann wieder Leerzeichen (null oder mehr) und schließlich eine Zeichenfolge (and setzen Sie das an welchen Pufferpunkten auch immer). Sie haben den “coolen” Teil in Ihrem Format-String vergessen, also nimmt das Format einfach an, dass dies der String ist, den Sie Buffer zuweisen wollten. Aber Sie möchten diese Zeichenfolge nicht zuweisen, sondern nur überspringen.

Alternativ könnten Sie auch einen Format-String wie: “%d %s %s” haben, aber dann müssen Sie ihm einen anderen Puffer zuweisen (mit einem anderen Namen) und ihn ausgeben als: “%s %s ist %d Jahre alt\n”.

  • Gefährlich: Der Puffer ist nicht zugewiesen, um auf irgendetwas zu zeigen. Sie möchten “char* buffer = malloc(100)” sagen, um Speicher dafür zu bekommen, wenn 100 Bytes ausreichen. Sie müssten dann eine Größe für %s angeben, die dazu passt (in diesem Fall 99, was Platz für ein 0-Terminator lässt, das sscanf() anhängt).

    – Schweizer Franken

    27. Mai 2018 um 16:57 Uhr

  • Gefährlich: Der Puffer ist nicht zugewiesen, um auf irgendetwas zu zeigen. Sie möchten “char* buffer = malloc(100)” sagen, um Speicher dafür zu bekommen, wenn 100 Bytes ausreichen. Sie müssten dann eine Größe für %s angeben, die dazu passt (in diesem Fall 99, was Platz für ein 0-Terminator lässt, das sscanf() anhängt).

    – Schweizer Franken

    27. Mai 2018 um 16:57 Uhr

1402230cookie-checkLesen eines Strings mit Leerzeichen mit sscanf

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

Privacy policy