Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

scanf et fgets

38 réponses
Avatar
Julien
bonjour

Je fais actuellement les exercices de http://www.france-ioi.org/
d'ailleurs si vous avez d'autres sites avec des exercices, je suis
int=E9ress=E9.

Je me posais la question, un scanf est-il dangereux pour r=E9cup=E9rer un
entier saisi par l'utilisateur.

est ce que :=20

char chaine[1000];
signed int valeur;
=20
(void) fgets(chaine, (int) sizeof(chaine), stdin);
valeur =3D atoi(chaine);

est plus s=FBr que=20

signed int valeur;
scanf("%i",&valeur);

d'autant que l=E0 je ne peux pas mettre conna=EEtre la taille maximale de
l'entier.

J'ai essay=E9 un char chaine[INT_MAX] mais =E7a n'a pas compil=E9.

Merci de vos avis.

--=20
Julien <Juke@free.fr>

10 réponses

1 2 3 4
Avatar
Antoine Leca
En news:46f57376$0$13499$, Mickaël Wolff va escriure:

Ah bon ? Par convention sizeof(char) vaut 1, le char etant la
reference des tailles memoires.


Convention ne veut pas dire norme, hein ;)


En l'occurence, la convention est BEAUCOUP plus répandue que la norme.

On peut concevoir des compilateurs « pour langage genre C » avec un type
caractère (au hasard, UTF-16) différent du type base de l'adressage (/byte/
pour le langage C, octet pour les architectures courantes). Mais il se
trouve que par cohérence ou sympathie avec C, la plupart de ces langages
garde l'orthographe «char» pour désigner... les bytes ! (Exemple le plus
frappant, Java.)


Antoine


Avatar
Antoine Leca
En news:46f57267$0$32149$, Mickaël Wolff va escriure:
<http://www.network-theory.co.uk/docs/gccintro/gccintro_71.html>



Pourquoi serait-ce déplacé ? Ce sont des exemples de cas pratique,
pas des affirmations absolues :

« Most systems, including x86 GNU/Linux and Microsoft Windows, use
signed char, but those based on PowerPC and ARM processors typically
use unsigned char. »

« La plupart des systèmes, dont GNU/Linux x86 et Microsoft Windows,
utilisent signed char, mais ces systèmes d'exploitation utilisent des
unsigned char lorsqu'ils sont basés sur des processeurs PowerPC ou
ARM »


On a bien sûr le droit d'écrire ce que l'on veut. Mais en l'occurence, ce
qui est écrit là est inexact. Avec Microsoft Windows, tous les compilateurs
que j'ai vu passés ont un moyen ou un autre pour spécifier si le type char
est signé ou pas. Et le code du système ne fait soigneusement aucune
hypothèse à ce sujet, entre autres raisons parce qu'en fait pour le système
(hum, le noyau NT, en fait), un caractère est codé... comme un entier non
signé sur 16 bits. Pour ce qui concerne GNU/Linux, je ne pense pas que le
noyau Linux fasse la moindre hypothèse à ce sujet, une partie de Linux (les
pilotes clavier) assume certainement que les char peuvent être non signés
(car Linus vient d'Europe), et si un outil GNU était programmé comme étant
dépendant du signe du type char sur l'architecture, ce serait une bogue à
signaler.

Le code que propose l'auteur est rigolo, car sur une machine avec un type
char signé sur 9 bits ou plus, il annonce fièrement « char is unsigned ». Un
peu plus loin, l'auteur prévient de l'erreur que constitue l'affectation de
la valeur retournée par fgetc() et consorts à un char, mais attribue
erronément la cause de l'erreur. En effet, le programme proposé ne marche
pas pour lire le caractère 'xFF', qui intervient par exemple dans le nom de
ville /L'Haÿ-les-Roses/.


La présence de RMS également


Il n'est pas une référence ?


À quel titre ?
M. Stallman est trop souvent provocateur dans ses écrits pour ne pas
susciter une dose de méfiance.

Je crois qu'il connais assez intimement
le C pour pouvoir donner des explications sur ce que lui et ses
collaboateurs ont implémenté dans GCC.


Je me demande depuis combien d'années M. Stallman n'a pas codé GCC. Je sais
bien qu'au début il avait beaucoup d'influence directe sur ses «
collaborateurs », mais il me semble que les temps ont changé.

Particulièrement depuis le Coup d'État /egcs/.


Antoine



Avatar
Thierry PINELLI
Antoine Leca wrote:

En news:fd2cc1$9hs$, Thierry PINELLI va escriure:
Julien wrote:
signed int valeur;
que dit la norme au sujet de ce type ?



Que c'est un « /type entier signé standardisé/ » (C99 6.2.5a4).
L'alinéa suivant ajoute qu'un objet de ce type « a la taille naturellement
sugérée par l'architecture cible », moyennant la contrainte de contenir au
moins l'intervalle [-32767, +32767].
Pourquoi cette question ?


-1- Parce que je trouvais "signed int" un peu "pléonasmique"
-2- Que je ne l'ai jamais vu dans une source :)
-3- Que ce n'est pas un a priori
-4- Je n'ai pas la norme (c'est cher), mais une Rationale C99
(C99RationaleV5.10.pdf) qui dit bien que :

"For reasons of symmetry, the keyword signed is
allowed as part of the type name of other integer types. Two varieties
of the integer types are specified: signed and unsigned. If neither
specifier is used, signed is assumed. The only
unsigned type in K&R is unsigned int."

Donc, sauf indication contraire un entier est signé :)



Avatar
espie
In article <46f57376$0$13499$,
Mickaël Wolff wrote:

Ah bon ? Par convention sizeof(char) vaut 1, le char etant la reference
des tailles memoires.


Convention ne veut pas dire norme, hein ;)


Ca tombe bien, la norme dit la meme chose.

Si un compilateur ne respecte pas sizeof(char)=1, le langage qu'il compile
n'est pas du C ISO (ni du C++ ISO, d'ailleurs).


Avatar
Antoine Leca
En news:fd8r5p$uvm$, Thierry PINELLI va escriure:
Antoine Leca wrote:

En news:fd2cc1$9hs$, Thierry PINELLI va escriure:
signed int valeur;
que dit la norme au sujet de ce type ?

Pourquoi cette question ?



-1- Parce que je trouvais "signed int" un peu "pléonasmique"


Oui. Autant que short int.
Il y a plein de pléonasmes en C, signed ou auto ne sont que des pointes
émergées d'un énorme iceberg ; il ne faut pas s'en offusquer, car cela ne
sert à rien, sauf à déclencher des discussions sans fins ni intérêt (cf.
troll, flame wars) sur LE BON style.


-2- Que je ne l'ai jamais vu dans une source :)


http://www.google.com/search?q=malloc+%22signed+int%22
(J'ai pris malloc pour sélectionner des sources C; strlen est une bonne
alternative.)


-3- Que ce n'est pas un a priori


De quel /a priori/ parles-tu ? du caractère signé de int ? de celui que tu
sembles avoir envers cette syntaxe ou ce mot-clé ? De celui que tu me prêtes
(merci de me l'expliquer) ? Ou bien de celui que sous-entend ta lapidaire
question, à savoir que la formulation initiale est une erreur ?


-4- Je n'ai pas la norme (c'est cher),


Le texte actuel de la norme est suffisant pour l'étudier. Et il est
disponible gratuitement en téléchargement légal.

mais une Rationale C99 (C99RationaleV5.10.pdf)
[Anastasie sur un extrait qui n'a que peu de rapport avec la question

posée.]


Donc, sauf indication contraire un entier est signé :)


Ce que personne ne dispute, et je ne vois pas ce qui y est drôle.

Tu demandes lapidairement ce que dit la norme au sujet de la spécification
de type "signed int" (et déjà là, j'extrapole), CQFF&D. Ensuite, tu sembles
t'insurger contre les réponses parfois un peu ironiques qui te sont faites,
et autres a priori ; désolé, mais je ne suis pas bien ton raisonnement, et
je me permet donc de reposer gentiment ma question, pourquoi demander la
signification dans la norme, surtout quand il semble que tu connaisses la
réponse à la question que tu poses ?


Antoine




Avatar
Charlie Gordon
"Antoine Leca" a écrit dans le message de news:
fdahob$l93$
En news:fd8r5p$uvm$, Thierry PINELLI va escriure:

-4- Je n'ai pas la norme (c'est cher),


Le texte actuel de la norme est suffisant pour l'étudier. Et il est
disponible gratuitement en téléchargement légal.

La version la plus à jour du Standard C99 est disponible en téléchargement

gratuit sur le site du groupe de travail WG14 en charge du language C:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

C'est la version publiée de C99, avec les corrections des TC1, 2 et 3
intégrées dans le texte (552 pages !).

mais une Rationale C99 (C99RationaleV5.10.pdf)
[Anastasie sur un extrait qui n'a que peu de rapport avec la question

posée.]


Le Rationale C99RationaleV5.10.pdf, sorte de cahier des charges qui explique
les objectifs et la logique de certains choix, est également disponible au
même endroit.

--
Chqrlie.


Avatar
Thierry PINELLI
Antoine Leca wrote:

De quel /a priori/ parles-tu ? du caractère signé de int ? de celui que tu
sembles avoir envers cette syntaxe ou ce mot-clé ? De celui que tu me prêtes
(merci de me l'expliquer) ? Ou bien de celui que sous-entend ta lapidaire
question, à savoir que la formulation initiale est une erreur ?


Ce sont les apriori lancés par un posteur qui a disparu

Donc, sauf indication contraire un entier est signé :)


Ce que personne ne dispute, et je ne vois pas ce qui y est drôle.


Sissi, ça pinaille par ailleurs

Tu demandes lapidairement ce que dit la norme au sujet de la spécification
de type "signed int" (et déjà là, j'extrapole), CQFF&D. Ensuite, tu sembles
t'insurger contre les réponses parfois un peu ironiques qui te sont faites,
et autres a priori ; désolé, mais je ne suis pas bien ton raisonnement, et
je me permet donc de reposer gentiment ma question, pourquoi demander la
signification dans la norme, surtout quand il semble que tu connaisses la
réponse à la question que tu poses ?


il faudrait lire le premier post de cette enfilade dans lequel on
lançait un "signed int" qui m'a rendu MDR

a++;

TP


Avatar
Antoine Leca
En news:fdbfi3$p4$, Thierry PINELLI va escriure:
il faudrait lire le premier post de cette enfilade dans lequel on
lançait un "signed int" qui m'a rendu MDR


J'ai lu (et répondu, news:fd894c$1t2$) à
« Julien ». Mais si effectivement il y avait des choses bizarres dans son
message, ce n'est pas signed int qui m'a marqué, mais bien l'opposition
entre la volonté « sécuritaire » (un émule de nos politiques ?) à travers
ses questions sur scanf("&i"), et le code où un appel à fgets() sur un
buffer non initialisé était suivi de l'utilisation de ce buffer, sans aucun
contrôle de la réussite du fgets() !


Par ailleurs, signed int n'est ni dangereux, ni incompréhensible, ni quoi
que ce soit. Les seules choses que cela m'évoque est que c'est un effort
inutile à la frappe (anecdotiquement), et plus sérieusement le fait que cela
puisse susciter des « prises de tête » chez certains mainteneurs/relecteurs
(« mais pourquoi a-t-il écrit cela ? » « quel est le sens caché de cette
syntaxe » etc. ; un peu comme quand on lit du code 32 bits qui
mélange --apparemment aléatoirement-- int et long.)
Ce qui me paraît être le fond de ton attitude.

Maintenant, pour moi, cette syntaxe est ici à ranger dans le même sac que
sizeof(char), mettre des parenthèses autour de l'argument de return, passer
à la ligne avant { et un paquet d'autres, autrement dit je considère cela
comme une clause de style.
Vraiment pas de quoi mourir de rire.


Antoine

Avatar
Julien
Entre Charybde et Scylla... En fait, la première version est pire si
chaîne[] est une locale, avec une entrée vide cela donne généralement
SIGSEGV.


quelle est donc la meilleure façon de s'y prendre ?
que décris tu par « si chaine[] est une locale » ?

Merci de vos réponses.

Avatar
Antoine Leca
En news:, Julien va escriure:
Entre Charybde et Scylla... En fait, la première version est pire si
chaîne[] est une locale, avec une entrée vide cela donne généralement
SIGSEGV.


quelle est donc la meilleure façon de s'y prendre ?


Je ne sais pas répondre à cette question superlative de manière absolue, en
particulier parce que je ne suis pas suffisament qualifié.

Mais je pense qu'il faut d'abord vérifier si les fonctions ont bien fait
leur travail, en particulier les fonctions d'entrées-sorties.
En ce qui concerne ton cas particulier, il y a deux façons classiques de
faire, la voie complète avec fgets()!=NULL suivi de strtol() suivi d'un test
sur la valeur retournée dans endptr pour vérifier que tout a bien été pris
en compte; ou 1==scanf(). La seconde écriture s'affranchit de la gestion de
certains cas particuliers de débordements et de syntaxes parasites (et est
en général plus boguée), mais elle est aussi nettement plus simple à lire.


que décris tu par « si chaine[] est une locale » ?


Si chaine[] est déclaré au niveau global (extern), il sera initialisé par le
système à un tableau rempli de caractères 0, donc le fait que fgets() ne
marche pas ne posera pas de problème grave, car le tableau chaine[] restera
une chaîne vide, et donc atoi() ne fera pas de malheur, retournera juste 0.

Si chaine[] est déclaré à l'intérieur d'une fonction, il ne sera pas
initialisé et le contenu sera pseudo-aléatoire. Si fgets() ne modifie pas ce
contenu parce qu'il n'y a rien à lire, chaine[] restera du n'importe quoi,
et à partir de là atoi() renvera vraiment n'importe quoi, voire essayera
peut-être de lire en dehors des limites autorisées.
De la même manière, un scanf("%i", &val) non vérifié (qui renverrait donc 0)
ne modifiera pas val, qui gardera silencieusement la valeur pseudo-aléatoire
présente auparavant.


Antoine


1 2 3 4