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

Scandigt

47 réponses
Avatar
LMC
Bonjour,
Voici l'exercice que je tente de résoudre :
/* scandigt lit une saisie sans espaces de séparation et range les
caractères
identiques via une spécification de largeur, dans différentes variables
*/
#include <stdio.h> /* pour printf, scanf */
#include <stdlib.h>

int main(int argc, char *argv[])
{
long one, two, three, four, five;
printf("Entrez un nombre entier selon le modele \n");
printf(" abbcccddddeeeee\n");
printf("les lettres a, b, c, d, e designant\n");
printf("des chiffres identiques.\n");
scanf("%1ld %2ld %3ld %4ld %5ld\n", &one, &two, &three, &four,&five);
printf("%ld\n%ld\n%ld\n%ld\n%ld\n", one, two, three, four, five);

system("PAUSE");
return 0;

J'obtiens le résultat suivant après compilation :
Entrez un nombre entier selon le modèle
abbcccddddeeeee
les lettres a, b, c, d, e désignant
des chiffres identiques. j'appuie sur Enter et j'obtiens
122333444455555

mais je n'obtiens pas la suite qui devrait être
1
22
333
4444
55555
Merci pour toute aide.

--
@++
LMC

10 réponses

1 2 3 4 5
Avatar
LMC
RE,
"candide" a écrit dans le message de news:
48ba7b5c$0$32372$
LMC a écrit :

C'est quoi votre compilo ?



Je comprends très bien compilo,



Non, ce que tu as écrit ci-dessous prouve, comme je m'y attendais, que tu
ne sais pas ce qu'est un compilo, ne le prends pas mal, tous les débutants
sont passés par là.



car j'ai bavé dessus quand j'ai voulu apprendre le langage en 1999. C'est
la raison pour laquelle, je ne suis parvenu à étudier des langages de
programmation. Grâce au Site du Zéro et la découverte de 3 compilo, je
m'y suis remis. Voici l'identité des 3 : devcpp.exe, codeblocks et
microsoft visual C++. J'utilise le devcpp pour les exercices du livre.





Te complique pas la vie en utilisant 3 IDE, utilise-en un et apprends à
bien le connaître. Devcpp et codeblocks intègrent par défaut le même
compilateur. Quant à Visual C++, c'est une usine à gaz, pas l'IDE à
utiliser quand on apprends le C (ou alors à la fin de l'apprentissage).

Un truc fondamental est de savoir régler son compilateur pour qu'il envoie
les messages d'avertissement appropriés lorsque le code contient des
"anomalies". J'ai précisé l'importance de ces messages et détaillé comment
effectuer les réglages sur codeblocks et devcpp à l'url suivante :

http://www.siteduzero.com/forum-83-204912-les-options-de-compilation.html



J'ai mis l'adresse dans mes favoris.

--
@++
LMC
Avatar
Marc Boyer
On 2008-08-31, LMC wrote:
Bonjour,
Pour faire simple (puisque d'autres ont donné des détails
compliqués), le code que vous postez est correct, mais
visiblement, votre compilateur C a un bug. Mon compilo
(et celui de Marc Espie) donnent bien
1
22
333
4444
55555

C'est quoi votre compilo ?



Je comprends très bien compilo, car j'ai bavé dessus quand j'ai voulu
apprendre le langage en 1999. C'est la raison pour laquelle, je ne suis
parvenu à étudier des langages de programmation. Grâce au Site du Zéro et la
découverte de 3 compilo, je m'y suis remis. Voici l'identité des 3 :
devcpp.exe, codeblocks et microsoft visual C++. J'utilise le devcpp pour les
exercices du livre.



Essayez pour voir le même code avec les deux autres.
Ca *devrait* se passer mieux.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)
Avatar
Marc Boyer
On 2008-08-30, candide wrote:
Marc Boyer a écrit :

C'est quoi votre compilo ?



Je ne pense pas qu'il sache ce qu'est un compilo ni même un compilateur
(enfin à lui de dire)



En général, les débutants confondent IDE et compilateur, oui,
mais quand on demande quel est leur IDE, il ne savent même
pas ce que c'est, alors que compilateur, ils croient savoir.
Ceci dit, vu les autres réponses, ce n'est pas le cas de LMC.

ce qu'il a dit c'est qu'il est sous Devc++
autrement dit son compilateur est Mingw.



J'avais raté le message.

Je me rappelle quand j'étais tout débutant (avec quelques mois de C) le
mot "compilateur" m'impressionnait. Et je te raconte même pas avant
d'avoir commencé le C, je me sentais même pas le droit de prononcer ce mot.



Et tu utilisais quoi comme terme pour évoquer le truc avec lequel
tu programmais ?

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)
Avatar
Antoine Leca
En news:, LMC va escriure:
Mickaël Wolff a écrit dans le message
de news: 48b8641a$0$10414$
LMC a écrit :
Grand merci pour la réponse, mais malheureusement, je n'ai rien
compris. Je suis toujours débutant.



Ben en fait, ce qu'il faut comprendre c'est que scanf n'est pas un
outil destiné à interagir avec un humain. C'est un détournement
malheureux utilisé dans les exercice sur C.



scanf n'est pas un outil destiné à interagir avec un humain ==> je
suis au tout début de C, alors il m'est difficile de comprendre cette
explication. A quoi sert scanf alors ?



À relire des données en forme de texte qui ont été préalablement rangées par
printf.

En fait scanf est la version de fscanf qui sert quand tu écris un filtre, un
programme qui lit ses instructions sur l'entrée standard (stdin). Donc
devrait être enseigné _après_ fscanf.

D'après le livre, la fonction
scanf autorise la saisie formatée de données (depuis le clavier du
terminal) et on la désigne souvent comme le pendant de printf. Il est
également précisé que la différence fondamentale entre scanf et
printf réside dans la nature des arguments manipulés.



Oui, c'est une explication souvent fournie dans les livres pour débutants.
La véritable explication (ÀMHA) est que scanf() est une fonction facile à
appréhender pour un débutant en C qui connait Pascal (ou un autre langage de
3e génération, genre Fortran ou Cobol), à qui l'on vient d'enseigner
printf() : en effet, contrairement à la plupart des fonctions en C, scanf
(et printf) permettent de manipuler de manière semblable des données
structurellement différentes, y compris des entiers, des nombres avec
virgules ou des chaînes de caractères.

Sauf que...
Sauf que, comme tu le précises ci-dessus (ce qui est à l'honneur de l'auteur
du livre), scanf fonctionne avec des pointeurs plutôt que des données, et
que l'apparente symétrie est rompue à ce niveau ; surtout que les chaîne de
caractères, elles, sont toujours passées par elles-mêmes, puisque ce sont
des chaînes.
Sauf que les formats sont subtilement différents, surtout dès que l'on
complique un tout petit peu (*, précision)
Sauf que la valeur retournée est très différente, et si pour fprintf on peut
souvent l'ignorer, pour fscanf c'est indispensable pour savoir si tout s'est
bien passé (en fait, c'est aussi indispensable que de contrôler que malloc
ou fopen n'a pas renvoyé NULL)
Sauf que la gestion des espaces est différente, adaptée au cas d'emploi
normal de fscanf (la relecture de données écrites par un autre programme),
c'est-à-dire où l'espace est utilisé comme un séparateur entre deux données
(deux nombres, ou deux étiquettes); et la fin de ligne est un espace pour
scanf()
Sauf que le spécificateur %s de scanf est fait pour relire une étiquette qui
ne contient _pas_ d'espace

Tout cela pour dire que si la différence entre les types des arguments est
fondamentale, ce n'est pas la seule ; et tout cela devrait montrer que
l'étude de scanf dans un chapitre d'initiation au C est, ÀMHA toujours, une
erreur.


scanf va se mettre en attende du fichier stdin. scanf ne réagira
que lorsque des données seront écrites dans l'entrée standard. Alors
certes il ne réagit pas à la moindre saisie, mais c'est parce que
scanf attend une fin de ligne pour extraire l'information (ici un
entier).



je comprends très vaguement, mais pourquoi après avoir appuyé
plusieurs fois sur Enter, la fin ne vient pas. ( Les chiffres les uns
en dessous des autres)



Parce que scanf est encore dans sa boucle interne d'attente de données.
scanf est un automate de conversion d'entrée (encore un « détail » qui fait
que cette fonction n'est probablement pas adaptée aux débutants), et pour en
sortir, il faut soit avoir une erreur de traduction (mettre une lettre là où
il attend un chiffre), soit avoir tout converti (cas normal), soit ne plus
rien avoir à traduire parce qu'on a atteint la fin du fichier d'entrée.
Comme tu n'es dans aucun de ces trois cas (une fin de ligne n'est pas une
fin de fichier pour scanf, c'est un espace...), l'automate est dans sa
boucle, en attente de tes données, qui ne doivent pas être des espaces :
donc taper des fins de ligne n'a pas d'effet notable...


Antoine
Avatar
Antoine Leca
En news:g9904n$d7a$, Marc Espie va escriure:
In article , LMC wrote:
scanf("%1ld %2ld %3ld %4ld %5ldn", &one, &two, &three,



Chez moi, ca marche, a quelques details pres.


<snip>
- ton n a la fin du scanf va matcher un n....



Ah ?

D'après les spécifications de scanf, quand l'automate rencontre le n (qui
est classé comme caractère d'espacement), il va sauter tous les caractères
d'espacement (donc tu peux lui donner autant de fin de ligne que tu veux,
cela va lui être relativement égal) et s'arrêter au premier caractère qui ne
soit *pas* d'espacement, caractère qui va rester libre pour la lecture
suivante (/unread/ en anglais).

Le résultat net est qu'il faut donner autre chose qu'un caractère
d'espacement, mais que ce caractère va rester en l'air puisque scanf()
n'attend rien d'autre après ce n.

En d'autres termes, un n (ou un espace) en fin de chaîne de format de scanf
est probablement un bogue...


Antoine
Avatar
Antoine Leca
En news:, Thierry B. va escriure:
--{ candide a plopé ceci: }--

(enfin à lui de dire), ce qu'il a dit c'est qu'il est sous Devc++
autrement dit son compilateur est Mingw.



s/Mingw/Gcc/ ?



Non.
Dev-C++ est un environnement de programmation (relativement) ouvert, ce qui
fait que tu peux utiliser différents compilateurs, et Mingw est seulement
l'un d'entre eux, qui est livré avec l'environnement.

Quant à GCC, Mingw est (au sens de la norme C, et en négligeant le côté C++)
un environnement de programmation C, constitué d'une part d'un compilateur
indépendant (/free-standing/) qui s'appelle GCC, et d'autre part d'une
implémentation de la bibliothèque standard qui est celle fournie par
Microsoft avec la license Windows et qui s'appelle MSVCRT.
Comme en l'occurence la question porte sur la bibliothèque standard (scanf),
la réponse intéressante ici est MSVCRT, et surtout pas GCC qui ne rentre pas
en ligne de compte.

Aisni, Marc [E] utilise aussi GCC (et avec un peu de chance, une version
proche de celle de LMC), mais utilise une bibliothèque standard très
différente (celle d'OpenBSD, qu'il connaît par c½ur pour en avoir écrit des
pans entiers.)


Antoine
Avatar
LMC
Bonjour,
"Antoine Leca" a écrit dans le message de news:
g9g7ud$tep$
En news:, LMC va escriure:
Mickaël Wolff a écrit dans le message
de news: 48b8641a$0$10414$
LMC a écrit :
Grand merci pour la réponse, mais malheureusement, je n'ai rien
compris. Je suis toujours débutant.



Ben en fait, ce qu'il faut comprendre c'est que scanf n'est pas un
outil destiné à interagir avec un humain. C'est un détournement
malheureux utilisé dans les exercice sur C.



scanf n'est pas un outil destiné à interagir avec un humain ==> je
suis au tout début de C, alors il m'est difficile de comprendre cette
explication. A quoi sert scanf alors ?



À relire des données en forme de texte qui ont été préalablement rangées
par
printf.

En fait scanf est la version de fscanf qui sert quand tu écris un filtre,
un
programme qui lit ses instructions sur l'entrée standard (stdin). Donc
devrait être enseigné _après_ fscanf.

D'après le livre, la fonction
scanf autorise la saisie formatée de données (depuis le clavier du
terminal) et on la désigne souvent comme le pendant de printf. Il est
également précisé que la différence fondamentale entre scanf et
printf réside dans la nature des arguments manipulés.



Oui, c'est une explication souvent fournie dans les livres pour débutants.
La véritable explication (ÀMHA) est que scanf() est une fonction facile à
appréhender pour un débutant en C qui connait Pascal (ou un autre langage
de
3e génération, genre Fortran ou Cobol), à qui l'on vient d'enseigner
printf() : en effet, contrairement à la plupart des fonctions en C, scanf
(et printf) permettent de manipuler de manière semblable des données
structurellement différentes, y compris des entiers, des nombres avec
virgules ou des chaînes de caractères.

Sauf que...
Sauf que, comme tu le précises ci-dessus (ce qui est à l'honneur de
l'auteur
du livre), scanf fonctionne avec des pointeurs plutôt que des données, et
que l'apparente symétrie est rompue à ce niveau ; surtout que les chaîne
de
caractères, elles, sont toujours passées par elles-mêmes, puisque ce sont
des chaînes.
Sauf que les formats sont subtilement différents, surtout dès que l'on
complique un tout petit peu (*, précision)
Sauf que la valeur retournée est très différente, et si pour fprintf on
peut
souvent l'ignorer, pour fscanf c'est indispensable pour savoir si tout
s'est
bien passé (en fait, c'est aussi indispensable que de contrôler que malloc
ou fopen n'a pas renvoyé NULL)
Sauf que la gestion des espaces est différente, adaptée au cas d'emploi
normal de fscanf (la relecture de données écrites par un autre programme),
c'est-à-dire où l'espace est utilisé comme un séparateur entre deux
données
(deux nombres, ou deux étiquettes); et la fin de ligne est un espace pour
scanf()
Sauf que le spécificateur %s de scanf est fait pour relire une étiquette
qui
ne contient _pas_ d'espace

Tout cela pour dire que si la différence entre les types des arguments est
fondamentale, ce n'est pas la seule ; et tout cela devrait montrer que
l'étude de scanf dans un chapitre d'initiation au C est, ÀMHA toujours,
une
erreur.


scanf va se mettre en attende du fichier stdin. scanf ne réagira
que lorsque des données seront écrites dans l'entrée standard. Alors
certes il ne réagit pas à la moindre saisie, mais c'est parce que
scanf attend une fin de ligne pour extraire l'information (ici un
entier).



je comprends très vaguement, mais pourquoi après avoir appuyé
plusieurs fois sur Enter, la fin ne vient pas. ( Les chiffres les uns
en dessous des autres)



Parce que scanf est encore dans sa boucle interne d'attente de données.
scanf est un automate de conversion d'entrée (encore un « détail » qui
fait
que cette fonction n'est probablement pas adaptée aux débutants), et pour
en
sortir, il faut soit avoir une erreur de traduction (mettre une lettre là

il attend un chiffre), soit avoir tout converti (cas normal), soit ne plus
rien avoir à traduire parce qu'on a atteint la fin du fichier d'entrée.
Comme tu n'es dans aucun de ces trois cas (une fin de ligne n'est pas une
fin de fichier pour scanf, c'est un espace...), l'automate est dans sa
boucle, en attente de tes données, qui ne doivent pas être des espaces :
donc taper des fins de ligne n'a pas d'effet notable...


Antoine



J'ai tout lu. Bien sûr, pour moi qui commence, je ne comprends pas grand
chose maintenant. C'est un peu comme si j'apprenais le Dictionnaire sans
connaître l'alphabet !
Ce que je ne comprends, c'est que certains du forum obtiennent le résultat
et moi pas. Mon IDE (DevC++) n'est-il pas bon ? Pourtant, j'ai suivi les
conseils du Site du Zéro. Ou peut-être Windows XP Pro SP3 a des lacunes ?
Grand merci pour ton aide.

--
@++
LMC
Avatar
LMC
Bonjour,

"Marc Boyer" a écrit dans le message
de news:
On 2008-08-31, LMC wrote:
Bonjour,
Pour faire simple (puisque d'autres ont donné des détails
compliqués), le code que vous postez est correct, mais
visiblement, votre compilateur C a un bug. Mon compilo
(et celui de Marc Espie) donnent bien
1
22
333
4444
55555

C'est quoi votre compilo ?



Je comprends très bien compilo, car j'ai bavé dessus quand j'ai voulu
apprendre le langage en 1999. C'est la raison pour laquelle, je ne suis
parvenu à étudier des langages de programmation. Grâce au Site du Zéro et
la
découverte de 3 compilo, je m'y suis remis. Voici l'identité des 3 :
devcpp.exe, codeblocks et microsoft visual C++. J'utilise le devcpp pour
les
exercices du livre.



Essayez pour voir le même code avec les deux autres.
Ca *devrait* se passer mieux.



J'ai déjà essayé avec codeblocks et j'obtiens le même résultat. Je dois
encore tenter avec Microsoft Visual C++.


Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)





--
@++
LMC
Avatar
Antoine Leca
En news:, LMC va escriure:

Ce que je ne comprends, c'est que certains du forum obtiennent le
résultat et moi pas. Mon IDE (DevC++) n'est-il pas bon ?



Enlève le n à la fin de la chaîne de format de scanf, et ne met pas non
plus d'espace ; c'est cela qui cause le comportement (apparamment)
incompréhensible.

Et si tu ne devais retenir qu'une seule chose de cet exercice, c'est qu'il
ne faut jamais mettre un espace ou un n à la fin d'une chaîne de format de
scanf.
En fait, c'est ce que _moi_ je vais retenir de cette enfilade :-)

Un autre manière d'en faire profit serait de retenir que scanf est une
fonction complexe, avec beaucoup de possibilités de mal la mettre en ½uvre.


Antoine
Avatar
candide
Marc Boyer a écrit :

Et tu utilisais quoi comme terme pour évoquer le truc avec lequel
tu programmais ?




J'évitais soigneusement les situations où j'aurais eu à évoquer ce
"truc" et donc je me contentais de préciser les effets de mon code au
niveau de son exécution.


Au demeurant, je considère un débutant comme un utilisateur et donc à
ce titre, il n'a rien à connaître de la mécanique interne, de la même
façon que quelqu'un qui voyage en voiture d'un point A à un point B n'a
pas à connaître le nombre de cylindres, il a juste besoin de communiquer
avec la voiture avec certains instruments, certaines interfaces disons
(les pédales, le volant, les voyants et témoins, le bouchon d'essence,
etc), à la limite, il n'a même pas besoin de savoir qu'il y a un moteur.
Idem pour le C-utilisateur même si ma comparaison n'est pas absolue.
1 2 3 4 5