Que signifie le n dans `sscanf (s,“% d% n ”, & i, & n)`?

La page de manuel indique que la signature de sscanf est

 sscanf(const char *ressortingct s, const char *ressortingct format, ...); 

J’ai vu une réponse sur SO où une fonction dans laquelle sscanf est utilisée comme ceci pour vérifier si une entrée était un entier.

 bool is_int(char const* s) { int n; int i; return sscanf(s, "%d %n", &i, &n) == 1 && !s[n]; } 

En regardant !s[n] cela semble suggérer de vérifier si sscanf balayé la séquence de caractères jusqu’au caractère de fin \0 . Donc, je suppose que n représente l’index où sscanf sera dans la chaîne s à la fin de la fonction.

Mais qu’en est-il de la variable i ? Qu’est-ce que ça veut dire?

Modifier:

Pour être plus explicite: je vois la signature de sscanf veut un pointeur de type char * comme premier paramètre. Un spécificateur de format en tant que paramètre seconf afin qu’il sache parsingr la séquence de caractères et autant de variables que les spécificateurs de conversion que les parameters suivants. Je comprends maintenant que i pour la tenue du nombre entier analysé.

Puisqu’il n’y a qu’un seul spécificateur de format, j’ai essayé de déduire la fonction de n .

Est-ce que mon hypothèse ci-dessus pour n correcte?

On dirait que l’op a déjà sa réponse, mais depuis que je me suis donné la peine de chercher cela par moi-même et de lancer le code …

De la section scanf () de “C The Pocket Reference” (2e édition de Herbert Shildt):

% n Reçoit un entier de valeur égal au nombre de caractères lus jusqu’à présent

et pour la valeur de retour:

La fonction scanf () renvoie un nombre égal au nombre de champs auxquels des valeurs ont été affectées.

La fonction sscanf () fonctionne de la même manière, elle prend simplement son entrée à partir de l’argument tampon fourni (s dans ce cas). Le test “== 1” s’assure qu’un seul entier a été analysé et le! S [n] s’assure que le tampon d’entrée est correctement terminé après cet entier et / ou qu’il n’y a en réalité qu’un seul entier dans la chaîne.

En exécutant ce code, une valeur s telle que “32” donne une valeur “vraie” (nous n’avons pas défini de type bool sur notre système) mais s en tant que “3 2” donne une valeur “fausse” car s [n] dans ce cas est “2” et n a la valeur 2 (“3” est analysé pour créer l’int dans ce cas). Si s est “3”, cette fonction retournera toujours la valeur true car tout cet espace blanc est incorporé et n a la valeur 3.

Un autre exemple d’entrée, “3m”, donne une valeur “false” comme vous le souhaitiez.

Verbatim de la sscanf() de sscanf() de sscanf() :

Conversions

[…]

n

Rien n’est attendu. au lieu de cela, le nombre de caractères consommés jusqu’ici depuis l’entrée est stocké via le pointeur suivant, qui doit être un pointeur sur int. Ce n’est pas une conversion, bien qu’elle puisse être supprimée avec le caractère * assign-suppression. La norme C dit: “L’exécution d’une directive% n n’incrémente pas le nombre d’assignations renvoyé à la fin de l’exécution”, mais le corrigendum semble le contredire. Il est probablement sage de ne pas formuler d’hypothèses sur l’effet des conversions% n sur la valeur de retour.

variable i signifie que, jusqu’à ce qu’il ait lu une valeur entière.

qu’essayez-vous de demander cependant? Ce n’est pas trop clair! le code va (essayer de) lire un entier de la chaîne en ‘i’

Je tiens à souligner que le code d’origine est un buggy:

 bool is_int(char const* s) { int n; int i; return sscanf(s, "%d %n", &i, &n) == 1 && !s[n]; } 

Je vais expliquer pourquoi. Et je vais interpréter la chaîne de format sscanf.

Tout d’abord, buggy:

Avec l’entrée “1”, qui correspond à l’entier un, sscanf enregistre 1 dans i. Ensuite, puisqu’il n’y a pas d’espace blanc après, sscanf ne touchera pas n. Et n n’est pas initialisé. Parce que sscanf a défini i sur 1, la valeur renvoyée par sscanf sera 1, ce qui signifie 1 champ analysé. Sscanf renvoyant 1, la partie de l’expression

 sscanf(s, "%d %n", &i, &n) == 1 

sera vrai. Par conséquent, l’autre partie de l’expression && sera exécutée. Et s [n] va accéder à un emplacement aléatoire en mémoire car n n’est pas initialisé.

Interprétation du format:

 "%d %n" 

Tente de numériser un nombre qui peut être un nombre décimal, un entier ou un numéro de notation scientifique. Le nombre est un entier, il doit être suivi d’au moins un espace blanc. Un espace blanc serait un espace, \ n, \ t et certains autres caractères non imprimables. Ce n’est que s’il est suivi d’un espace blanc qu’il définira n le nombre de caractères analysés jusqu’à cet endroit, y compris l’espace blanc.

Ce code pourrait être ce qui est destiné:

  static bool is_int(char const* s) { int i; int fld; return (fld = sscanf(s, "%i", &i)) == 1; } int main(int argc, char * argv[]) { bool ans = false; ans = is_int("1"); ans = is_int("m"); return 0; } 

Ce code est basé sur, si s est un entier, alors sscanf le scannera et fld sera exactement un. Si s n’est pas un entier, alors fld sera égal à zéro ou -1. Zéro s’il y a autre chose, comme un mot; et -1 s’il n’y a rien d’autre qu’une chaîne vide.