OVH Cloud OVH Cloud

Probleme avec scanf

118 réponses
Avatar
Bakounine
bonjour

je suis en train de faire un petit programme client et serveur qui echange
des messages. Dans cetains messages il y a deux valeur separer par des deux
points.

ex:

valeurun:valeurdeux

j'aimerais savoir si sscanf permet de gerer le separateur : ou faut il
utiliser une autre fonction? j'ai utilise sscanf("%s:%s", var1, var2); mais
ca ne marche pas.

Merci d'avance pour votre reponse.

10 réponses

8 9 10 11 12
Avatar
Emmanuel Delahaye
Charlie Gordon wrote on 29/04/05 :
Ou alors c'est le syndrome 9/11 = 8601...


Peux-tu développer ce point ?


September the 11th... ?

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.


Avatar
Charlie Gordon
"Emmanuel Delahaye" wrote in message
news:
Charlie Gordon wrote on 29/04/05 :
Ou alors c'est le syndrome 9/11 = 8601...


Peux-tu développer ce point ?


September the 11th... ?


Certes, mais pourquoi 8601 ?

Chqrlie.



Avatar
Emmanuel Delahaye
Charlie Gordon wrote on 29/04/05 :
"Emmanuel Delahaye" wrote in message
news:
Charlie Gordon wrote on 29/04/05 :
Ou alors c'est le syndrome 9/11 = 8601...


Peux-tu développer ce point ?


September the 11th... ?


Certes, mais pourquoi 8601 ?


ISO 8601, normalisation des dates ?

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.




Avatar
Marc Boyer
Targeur fou wrote:
Je suis d'accord pour dire que c'est difficile pour un débutant (hors
de portée me parait exagéré, sinon je n'aurais pas pu le faire ;-),
j'ai lu la spec de scanf et je me suis démerdé avec.


Quelle spec ? Il existe une page de man lisible sur le sujet
ou tu a trouvé dans un bouquin ? Et dans ce cas, lequel.

Marc, intéressé
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.

Avatar
Targeur fou
Marc Boyer wrote:
Targeur fou wrote:
Je suis d'accord pour dire que c'est difficile pour un débutant
(hors


de portée me parait exagéré, sinon je n'aurais pas pu le faire
;-),


j'ai lu la spec de scanf et je me suis démerdé avec.


Quelle spec ? Il existe une page de man lisible sur le sujet
ou tu a trouvé dans un bouquin ? Et dans ce cas, lequel.


A propos de spec je parlais de la draft C99 que je possède. Mais ce
n'est pas pour la fonction scanf() que tout ça est bien expliqué,
c'est pour la fonction fscanf(). Je n'ai pas le K&R sous la main :(
mais je crois que les spécificateurs de format y sont à peu près
tous présentés sans toutefois faire apparaître les détails qui sont
dans la norme.

Un bouquin comme "The C book" (Banahan, Brady, Doran, chez
Addisson-Wesley mais plus publié) explique AMA bien plus clairement la
bibliothèque standard que la norme (tordue par endroits). Le contenu
est accessible gratuitement ici :
http://publications.gbdirect.co.uk/c_book

En lisant bien, on comprend vite qu'utiliser scanf("%s", mon_tampon);
est aussi idiot et dangereux que d'utiliser gets(). Par contre, si je
veux mettre au maximum 50 caractères de stdin dans un tampon (bien
dimensionné à 51 avec '' à la fin), il suffit de se dire "Je veux
tout mettre dans mon tampon sauf un n" qui se traduit en %50[^n] puis
"je lis tout le reste sauf n, sans le mettre dans mon tampon" qui se
traduit en %*[^n], on obtient un beau format "%50[^n]%*[^n]". Un
fois que l'a compris [] (= classe de caractères), ^ (négation de
classe de car.), le * (je veux lire ce qui est indiqué par le format
mais pas le prendre), on peut se débrouiller proprement avec les
'scanf (c'est cryptique mais pas plus dégueu que Perl par exemple).
Par contre %s est à bannir et les autres flags de lecture d'entiers,
de flottants et compagnie aussi si on ne lit pas un format fixe bien
déterminé. Mieux vaut lire des données conditionnées par des
classes de caractères et utiliser par la suite des fonctions comme
strtod, strtol et cie, sans oublier de tester avant le code de retour
de la fonction 'scanf pour vérifier si toutes les conversions ont
été effectuées avec succès.

Regis


Avatar
Marc Boyer
Targeur fou wrote:
Marc Boyer wrote:
Targeur fou wrote:
Je suis d'accord pour dire que c'est difficile pour un débutant
(hors


de portée me parait exagéré, sinon je n'aurais pas pu le faire
;-),


j'ai lu la spec de scanf et je me suis démerdé avec.


Quelle spec ? Il existe une page de man lisible sur le sujet
ou tu a trouvé dans un bouquin ? Et dans ce cas, lequel.


A propos de spec je parlais de la draft C99 que je possède. Mais ce
n'est pas pour la fonction scanf() que tout ça est bien expliqué,
c'est pour la fonction fscanf().


Mais ça exclue beaucoup de débutants, qui travaillent avec des
livres à grand tirage ou avec les pages de man.

Je n'ai pas le K&R sous la main :(
mais je crois que les spécificateurs de format y sont à peu près
tous présentés sans toutefois faire apparaître les détails qui sont
dans la norme.


Dans mon souvenir, c'est "à peu près".

Un bouquin comme "The C book" (Banahan, Brady, Doran, chez
Addisson-Wesley mais plus publié) explique AMA bien plus clairement la
bibliothèque standard que la norme (tordue par endroits). Le contenu
est accessible gratuitement ici :
http://publications.gbdirect.co.uk/c_book


Je connaissais pas, je prends note. M'enfin en ce qui nous
concerne, pour comprendre la sémantique de scanf("%50s",buf)
ou %50[^n] juste à partir de la partie I/O de ce bouquin,
faut s'accrocher.

Pour ma part, c'est le "Harbison & Steele" qui me sert, mais
bon, il lui faut 14 pages sur printf et 8 sur scanf pour
présenter les choses (et il écrit pas gros).

En lisant bien, on comprend vite qu'utiliser scanf("%s", mon_tampon);
est aussi idiot et dangereux que d'utiliser gets(). Par contre, si je
veux mettre au maximum 50 caractères de stdin dans un tampon (bien
dimensionné à 51 avec '' à la fin), il suffit de se dire "Je veux
tout mettre dans mon tampon sauf un n" qui se traduit en %50[^n] puis
"je lis tout le reste sauf n, sans le mettre dans mon tampon" qui se
traduit en %*[^n], on obtient un beau format "%50[^n]%*[^n]". Un
fois que l'a compris [] (= classe de caractères), ^ (négation de
classe de car.), le * (je veux lire ce qui est indiqué par le format
mais pas le prendre), on peut se débrouiller proprement avec les
'scanf (c'est cryptique mais pas plus dégueu que Perl par exemple).


Le * a été introduit quand ? C'est du C99 non ? En tout cas,
"The C book" ne semble pas en parler.

Par contre %s est à bannir et les autres flags de lecture d'entiers,
de flottants et compagnie aussi si on ne lit pas un format fixe bien
déterminé. Mieux vaut lire des données conditionnées par des
classes de caractères et utiliser par la suite des fonctions comme
strtod, strtol et cie, sans oublier de tester avant le code de retour
de la fonction 'scanf pour vérifier si toutes les conversions ont
été effectuées avec succès.


Ce qui fait une lecture en 2 temps:
1 - parsing
2 - conversion
Je vois la logique.

Marc
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.



Avatar
Targeur fou
Marc Boyer wrote:
Targeur fou wrote:
Marc Boyer wrote:
Targeur fou wrote:
Je suis d'accord pour dire que c'est difficile pour un débutant
(hors


de portée me parait exagéré, sinon je n'aurais pas pu le
faire




;-),
j'ai lu la spec de scanf et je me suis démerdé avec.


Quelle spec ? Il existe une page de man lisible sur le sujet
ou tu a trouvé dans un bouquin ? Et dans ce cas, lequel.


A propos de spec je parlais de la draft C99 que je possède. Mais
ce


n'est pas pour la fonction scanf() que tout ça est bien expliqué,
c'est pour la fonction fscanf().


Mais ça exclue beaucoup de débutants, qui travaillent avec des
livres à grand tirage ou avec les pages de man.


C'est vrai.


Je n'ai pas le K&R sous la main :(
mais je crois que les spécificateurs de format y sont à peu près
tous présentés sans toutefois faire apparaître les détails qui
sont


dans la norme.


Dans mon souvenir, c'est "à peu près".

Un bouquin comme "The C book" (Banahan, Brady, Doran, chez
Addisson-Wesley mais plus publié) explique AMA bien plus
clairement la


bibliothèque standard que la norme (tordue par endroits). Le
contenu


est accessible gratuitement ici :
http://publications.gbdirect.co.uk/c_book


Je connaissais pas, je prends note. M'enfin en ce qui nous
concerne, pour comprendre la sémantique de scanf("%50s",buf)
ou %50[^n] juste à partir de la partie I/O de ce bouquin,
faut s'accrocher.

Pour ma part, c'est le "Harbison & Steele" qui me sert, mais
bon, il lui faut 14 pages sur printf et 8 sur scanf pour
présenter les choses (et il écrit pas gros).


C'est encore mieux. Pour moi, l'info, c'est beaucoup de curiosité et
de lecture de doc approfondie, même (et surtout) pour un débutant, il
faut être autodidacte.

En lisant bien, on comprend vite qu'utiliser scanf("%s",
mon_tampon);


est aussi idiot et dangereux que d'utiliser gets(). Par contre, si
je


veux mettre au maximum 50 caractères de stdin dans un tampon (bien
dimensionné à 51 avec '' à la fin), il suffit de se dire "Je
veux


tout mettre dans mon tampon sauf un n" qui se traduit en %50[^n]
puis


"je lis tout le reste sauf n, sans le mettre dans mon tampon" qui
se


traduit en %*[^n], on obtient un beau format "%50[^n]%*[^n]". Un
fois que l'a compris [] (= classe de caractères), ^ (négation de
classe de car.), le * (je veux lire ce qui est indiqué par le
format


mais pas le prendre), on peut se débrouiller proprement avec les
'scanf (c'est cryptique mais pas plus dégueu que Perl par
exemple).



Le * a été introduit quand ? C'est du C99 non ? En tout cas,
"The C book" ne semble pas en parler.


Si si,

conversion specification
This is a % character, followed by an optional * character (which
suppresses the conversion), followed by an optional nonzero decimal
integer specifying the maximum field width, an optional h, l or L to
control the length of the conversion and finally a non-optional
conversion specifier. Note that use of h, l, or L will affect the type
of pointer which must be used.


Par contre %s est à bannir et les autres flags de lecture
d'entiers,


de flottants et compagnie aussi si on ne lit pas un format fixe
bien


déterminé. Mieux vaut lire des données conditionnées par des
classes de caractères et utiliser par la suite des fonctions comme
strtod, strtol et cie, sans oublier de tester avant le code de
retour


de la fonction 'scanf pour vérifier si toutes les conversions ont
été effectuées avec succès.


Ce qui fait une lecture en 2 temps:
1 - parsing
2 - conversion
Je vois la logique.


Tout à fait. Mon approche des fonctions 'scanf ressemble beaucoup à
l'approche expression rationnelle.

Regis




Avatar
Marc Boyer
Targeur fou wrote:
Un bouquin comme "The C book" (Banahan, Brady, Doran, chez
Addisson-Wesley mais plus publié) explique AMA bien plus
clairement la


bibliothèque standard que la norme (tordue par endroits). Le
contenu


est accessible gratuitement ici :
http://publications.gbdirect.co.uk/c_book


Je connaissais pas, je prends note. M'enfin en ce qui nous
concerne, pour comprendre la sémantique de scanf("%50s",buf)
ou %50[^n] juste à partir de la partie I/O de ce bouquin,
faut s'accrocher.

Pour ma part, c'est le "Harbison & Steele" qui me sert, mais
bon, il lui faut 14 pages sur printf et 8 sur scanf pour
présenter les choses (et il écrit pas gros).


C'est encore mieux. Pour moi, l'info, c'est beaucoup de curiosité et
de lecture de doc approfondie, même (et surtout) pour un débutant, il
faut être autodidacte.


Avec la grande difficulté quand on débute de savoir à quel
source on peut faire confiance.

Le * a été introduit quand ? C'est du C99 non ? En tout cas,
"The C book" ne semble pas en parler.


Si si,

conversion specification
This is a % character, followed by an optional * character (which
suppresses the conversion), followed by an optional nonzero decimal
integer specifying the maximum field width, an optional h, l or L to
control the length of the conversion and finally a non-optional
conversion specifier. Note that use of h, l, or L will affect the type
of pointer which must be used.


"which suppresses the conversion"... C'est minimaliste comme
présentation...

Ce qui fait une lecture en 2 temps:
1 - parsing
2 - conversion
Je vois la logique.


Tout à fait. Mon approche des fonctions 'scanf ressemble beaucoup à
l'approche expression rationnelle.


OK, je vois. Je me demande si je vais ajouter un truc dans ce sens
dans mon cours.

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.



Avatar
Antoine Leca
En <news:, Emmanuel Delahaye
va escriure:
"Emmanuel Delahaye" wrote in message
news:
Ou alors c'est le syndrome 9/11 = 8601...


September the 11th... ?

ISO 8601, normalisation des dates ?




Bravo Emmanuel. Heureusement qu'il y en a un qui suit!


Antoine





Avatar
Antoine Leca
En <news:d4tqfh$251$, Charlie Gordon va escriure:
"Antoine Leca" wrote in message
news:d4t18f$9vd$

En supposant que la structure ftime est bien celle de MS-DOS (5
bits, 4 bits, 7 bits), tous inférieurs à 16, donc les valeurs
seront promues en int et non pas en unsigned [...]
Donc non, c'est bien %d qu'il faut utiliser;


Non, le fait que les champs soient unsigned fait qu'un compilateur
comme gcc qui vérifie la cohérence du format de printf avec le type
des arguments passés (-Wall bien sur) va produire un avertissement si
on utilise pas %u.


En ce cas il aurait tord. Mauvais compilateur, changer de compilateur
(d'ailleurs, mes versions de GCC sont silencieuses...)


6.3 Conversions
6.3.1 Arithmetic operands
6.3.1.1 Boolean, characters, and integers
[2] The following may be used in an expression wherever an *int* or
*unsigned int* may be used:
-- [non applicable]
-- A bit-field of type *_Bool*, *int*, *signed int*, or *unsigned int*.
If an *int* can represent all values of the original type, the value is
converted to an *int*; otherwise, it is converted to an *unsigned int*.
These are called the /integer promotions/*). All other types are unchanged
by the integer promotions.


6.5.2.2 Function calls
[7] If the expression that denotes the called function has a type that does
include a prototype, the arguments are implicitly converted, as if by
assignment, to the types of the corresponding parameters, taking the type of
each parameter to be the unqualified version of its declared type. The
ellipsis notation in a function prototype declarator causes argument type
conversion to stop after the last declared parameter. The default argument
promotions are performed on trailing arguments.


Autrement dit, ftimep.ft_day est un argument de type int dans l'appel à
printf(). ÀMHA.


Rajouter des 0u ou 1980u n'est pas nécessaire.


C'est de la lecture pédante de la norme, de toutes manières, donc certes.
Mais si tu vas pour utiliser %u, moi je le jouerai bretelles-et-ceinture, et
je forcerai le type unsigned dans l'appel à printf(); car je ne me fie pas à
ce que l'ensemble des écrivains de compilateurs comprennent le paragraphe
ci-dessus de la même manière; d'ailleurs tes doutes en sont la démonstration
la plus éclatante.


Antoine


8 9 10 11 12