web-dev-qa-db-fra.com

lire une chaîne avec des espaces avec sscanf

Pour un projet, j'essaie de lire un entier et une chaîne à partir d'une chaîne. Le seul problème est que sscanf semble interrompre la lecture d'un% s lorsqu'il voit un espace. Est-il possible de contourner cette limitation? Voici un exemple de ce que j'essaie de faire:

#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;
}

Ce qu'il imprime est: "cool a 19 ans" où j'ai besoin de "cool kid a 19 ans". Est-ce que quelqu'un sait comment réparer ceci?

37
SDLFunTimes

La ligne suivante commencera à lire un nombre (%d) suivi de tout élément différent des onglets ou des retours à la ligne (%[^\t\n]).

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

Vous voulez le %c spécificateur de conversion, qui lit simplement une séquence de caractères sans traitement spécial pour les espaces.

Notez que vous devez d'abord remplir le tampon avec des zéros, car le %c le spécificateur n'écrit pas de terminateur nul. Vous devez également spécifier le nombre de caractères à lire (sinon il ne vaut par défaut que 1):

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

Si vous souhaitez numériser jusqu'à la fin de la chaîne (en supprimant une nouvelle ligne s'il y en a), utilisez simplement:

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

C'est parce que %s Ne correspond qu'aux caractères non blancs et s'arrêtera sur le premier espace blanc qu'il trouve. Le spécificateur de format %[^\n] Correspondra à chaque caractère qui n'est pas (à cause de ^) Dans la sélection donnée (qui est une nouvelle ligne). En d'autres termes, il correspondra à tout autre caractère.


Gardez à l'esprit que vous devriez avoir alloué suffisamment d'espace dans votre tampon pour prendre la chaîne, car vous ne pouvez pas être sûr de la quantité lue (une bonne raison de rester à l'écart de scanf/fscanf Sauf si vous utilisez des largeurs de champ spécifiques).

Vous pouvez le faire avec:

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

(vous n'avez pas besoin de * sizeof(char) puisque c'est toujours 1 par définition).

8
paxdiablo

Puisque vous voulez la chaîne de fin de l'entrée, vous pouvez utiliser %n (nombre de caractères consommés jusqu'à présent) pour obtenir la position à laquelle la chaîne de fin commence. Cela évite les copies de mémoire et les problèmes de dimensionnement de la mémoire tampon, mais se fait au prix que vous devrez peut-être les faire explicitement si vous vouliez une copie.

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);

les sorties:

cool kid is 19 years old
2
ɲeuroburɳ