IPB

Bienvenue invité ( Connexion | Inscription )

 
Reply to this topicStart new topic
> Petit souci avec un petit programme en C, Mais attention je débute (un vrai novice)
Options
PapouMAC
posté 13 Nov 2014, 20:43
Message #1


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 336
Inscrit : 25 Sep 2004
Lieu : Occitanie
Membre no 24 178



Bonjour

Je vais vous exposer mon souci, mais avant je tiens à vous signaler que je suis un vrai débutant, donc peut-être que mon souci en fera rire plus d'uns, mais comme le ridicule ne tue pas, alors voici ce que je vous expose :
Je viens d'écrire ceci sous xcode en mode console :

#import <stdio.h>
int main ()
{
char c, reponse;
c = '*';
int i;

entree :

for ( i=1; i<=5; i++)
printf("%s", &c);
printf("\n");
printf("On recommence ?");
scanf("%c", &reponse);
if (reponse == 'O' || reponse == 'o') goto entree;

}

Je vous l'avez bien dit que je débutais.
j'en suis à la fonction goto (oui je sais certains me diront de ne pas l'utiliser, mais bon j'apprends)
Donc lorsque je lance le programme celui-ci m'affiche bien "*****", mais là ou ça ne va plus c'est au moment de scanf.
Quand je réponds "O" ou "o" le programme s'arrête. Pourquoi ?


--------------------
MAC PRO 2009 (MAC OS 10.14.6) 2 x 3,33 Ghz 6-CoreIntel Xeon(5.1), , 64 Go.Carte graphique NVIDIA GeForce GTX 680.

Mac Studio M2 Max, 32Go, 1To
Go to the top of the page
 
+Quote Post
schlum
posté 13 Nov 2014, 22:25
Message #2


Terminaltor
Moderating Machine
*****

Groupe : Admin
Messages : 24 449
Inscrit : 25 Oct 2002
Lieu : Jeumont (59)
Membre no 4 319



Il y a plusieurs problèmes dans ce code :
* Le plus grave : printf("%s", &c); -> va lire une chaîne commençant à l’adresse mémoire de c ; en fonction de ce qu’il y a derrière, ça va afficher n’importe quoi ; au pire, ça ne trouvera pas de '\0' avant une zone protégée, et ça fera core dump ; utiliser à la place printf("%c",c);
* Ne pas utiliser goto tongue.gif (surtout pour un cas pareil), préférer un do { } while() ou un while() { }
* S’il n’y a pas de flush, le second passage dans "scanf" va lire le caractère de retour qui a été tapé précédemment avec le 'O' ou 'o' ; il faut vider stdin avec quelque chose comme :
char ff;
while((ff=getchar())!='\n'&&ff!=EOF);

Mais de manière générale, scanf c’est moisi…


--------------------
          I think therefore I Mac          
Go to the top of the page
 
+Quote Post
PapouMAC
posté 13 Nov 2014, 23:55
Message #3


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 336
Inscrit : 25 Sep 2004
Lieu : Occitanie
Membre no 24 178



Je te remercie pour ces explications, il va falloir que je décortique tout ça, car pour moi il y a des explications qui me sont incompréhensibles (du moins pour le moment). sad.gif


--------------------
MAC PRO 2009 (MAC OS 10.14.6) 2 x 3,33 Ghz 6-CoreIntel Xeon(5.1), , 64 Go.Carte graphique NVIDIA GeForce GTX 680.

Mac Studio M2 Max, 32Go, 1To
Go to the top of the page
 
+Quote Post
schlum
posté 14 Nov 2014, 05:09
Message #4


Terminaltor
Moderating Machine
*****

Groupe : Admin
Messages : 24 449
Inscrit : 25 Oct 2002
Lieu : Jeumont (59)
Membre no 4 319



En gros, le programme correct donne ça :

Code
#import <stdio.h>

int main()
{
    char c='*', reponse, f;
    int i;
    do {
        for (i=1;i<=5;i++)
            printf("%c",c);
        printf("\n");
        printf("On recommence ?");
        scanf("%c",&reponse);
        while((f=getchar())!='\n'&&f!=EOF)
        ;
    } while(reponse=='O'||reponse=='o');
    return 0;
}


PS : j’ai déplacé le sujet car il n’y a aucun rapport avec la technologie Apple


--------------------
          I think therefore I Mac          
Go to the top of the page
 
+Quote Post
PapouMAC
posté 14 Nov 2014, 18:23
Message #5


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 336
Inscrit : 25 Sep 2004
Lieu : Occitanie
Membre no 24 178



Je te remercie (Je croyais que xCode était une technologie Apple).

J'ai moi aussi effectué une modification (celle-ci radicale), car j'ai aussi employé do...while.


Code
#import <stdio.h>


int main ()
{
     char c;
     c = '*';
     int i, ii, r =0;
    
    do
    {
        for ( i=1; i<=10; i++)
            printf(" %d", i);
        printf("\n");
        {
            for (ii=1; ii<=20; ii++)
            printf("=");
            printf("=\n\n");
        }
    do
    {
        printf("On recommence ?\n");
        printf("1 - Oui\n");
        printf("2 - Non\n");
        printf("Votre choix : ");
        scanf("%d", &r);
    } while (r > 2 || r < 1);
    } while (r == 1);

}


Et ça marche. smile.gif


--------------------
MAC PRO 2009 (MAC OS 10.14.6) 2 x 3,33 Ghz 6-CoreIntel Xeon(5.1), , 64 Go.Carte graphique NVIDIA GeForce GTX 680.

Mac Studio M2 Max, 32Go, 1To
Go to the top of the page
 
+Quote Post
schlum
posté 14 Nov 2014, 20:38
Message #6


Terminaltor
Moderating Machine
*****

Groupe : Admin
Messages : 24 449
Inscrit : 25 Oct 2002
Lieu : Jeumont (59)
Membre no 4 319



Le char « c » n’est plus utilisé

La première boucle do … while est une boucle infinie ; si (r > 2 || r < 1) est faux (et donc qu’on sort de la seconde boucle do … while), ça veut dire que r==1, donc tu n’en sortiras jamais.

Si le but était vraiment de faire une boucle infinie, il y a plus simple wink.gif for(;;) { }

PS : Xcode n’est pas une technologie, c’est un IDE ( https://fr.wikipedia.org/wiki/Environnement..._développement )


--------------------
          I think therefore I Mac          
Go to the top of the page
 
+Quote Post
PapouMAC
posté 14 Nov 2014, 23:55
Message #7


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 336
Inscrit : 25 Sep 2004
Lieu : Occitanie
Membre no 24 178



Exact c n'est plus utilisé, j'ai tout simplement oublié de la retirer.

Pourtant lorsque la 1ere boucle se termine, le programme s'arrête et attend une entrée.
Donc quand je tape 1 (pour Oui) la boucle recommence.
Tandis que quand je tape 2 (pour Non) le programme s'arrête. huh.gif


--------------------
MAC PRO 2009 (MAC OS 10.14.6) 2 x 3,33 Ghz 6-CoreIntel Xeon(5.1), , 64 Go.Carte graphique NVIDIA GeForce GTX 680.

Mac Studio M2 Max, 32Go, 1To
Go to the top of the page
 
+Quote Post
schlum
posté 15 Nov 2014, 09:41
Message #8


Terminaltor
Moderating Machine
*****

Groupe : Admin
Messages : 24 449
Inscrit : 25 Oct 2002
Lieu : Jeumont (59)
Membre no 4 319



Ah oui, ça veut être 2 aussi, je ne l’ai pas compilé, juste regardé rapidement ^^

dans ce cas, j’aurais fait un for(;;) { [...] if(r==2) break; } pour plus de clarté (mais après c’est une question de goût)


--------------------
          I think therefore I Mac          
Go to the top of the page
 
+Quote Post
noop
posté 15 Nov 2014, 11:47
Message #9


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 964
Inscrit : 3 Nov 2005
Membre no 49 239



un petit conseil en passant:
mettre toujours les {} pour definir les blocs même s'il n'y a qu'une seule instruction. par exemple ton

Code
for(...)
     printf(...)

devrait s'ecrire
Code
for (...) {
   printf(...)
   ...
}

Go to the top of the page
 
+Quote Post
PapouMAC
posté 16 Nov 2014, 00:20
Message #10


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 336
Inscrit : 25 Sep 2004
Lieu : Occitanie
Membre no 24 178



Je vous remercie tous les deux pour vos suggestions. Comme quoi j'ai encore pas mal de chemin à faire pour maitriser le C. Mais je suis persévérant.


--------------------
MAC PRO 2009 (MAC OS 10.14.6) 2 x 3,33 Ghz 6-CoreIntel Xeon(5.1), , 64 Go.Carte graphique NVIDIA GeForce GTX 680.

Mac Studio M2 Max, 32Go, 1To
Go to the top of the page
 
+Quote Post
No6
posté 16 Nov 2014, 13:20
Message #11


Oui ?
*****

Groupe : Membres
Messages : 3 889
Inscrit : 24 Jun 2003
Lieu : BZH
Membre no 8 224




J'ai moi même pas mal galéré lors de l'apprentissage du langage C...

Pourtant j'étais loin d'être un novice en programmation.

Un bouquin qui m'avait vraiment aidé à l'époque s'intitule :

"Langage C : les finesses d'un langage redoutable"

ISBN : 2200210957
auteur : Jacquelin CHARBONNEL

Le titre parle de lui même, il n'est pas réédité, mais tu devrais pouvoir en trouver d'occasion; ce genre de livre ne se jette pas... wink.gif


--------------------
"Je sais que vous croyez comprendre ce que vous pensez que j'ai dit, mais je ne suis pas sûr que vous réalisiez que ce que vous avez entendu n'est pas ce que je pense."
(Alan Greenspan)
Go to the top of the page
 
+Quote Post
PapouMAC
posté 16 Nov 2014, 20:16
Message #12


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 336
Inscrit : 25 Sep 2004
Lieu : Occitanie
Membre no 24 178



Merci pour cette recommandation. Pour ma part j'ai acheté :

Programmer en langage C par Claude Delannoy (5e édition).


--------------------
MAC PRO 2009 (MAC OS 10.14.6) 2 x 3,33 Ghz 6-CoreIntel Xeon(5.1), , 64 Go.Carte graphique NVIDIA GeForce GTX 680.

Mac Studio M2 Max, 32Go, 1To
Go to the top of the page
 
+Quote Post
Jaypee
posté 17 Nov 2014, 10:31
Message #13


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



Excellent choix !
J'allais fouiller dans mes archives pour retrouver cet auteur...
J'ai trouvé son style très didactique, normal pour un prof chercheur smile.gif

Dans un autre genre, utile mais extrêmement pointu (sur les pointeurs)
The C Puzzle Book (ISBN-10: 0201604612 / ISBN-13: 978-0201604610)
Alan Feuer

Des exemples à s'arracher les cheveux. J'en avais déjà soumis un il y a longtemps à Schlum smile.gif http://forum.macbidouille.com/index.php?sh...p;hl=alan+feuer
Du genre: il faut s'intéresser précisément au comportement du pré-processeur, qui ignore le C, il ne fait que pré-processer

#define negation(x) -x

int y = 5;
y = negation(-y);

On obtient quoi?
y = -(-5) ou --y = 3?

Heureusement, les pré-processeurs sont prévisibles aujourd'hui.
J-P

Ce message a été modifié par Jaypee - 17 Nov 2014, 11:15.
Go to the top of the page
 
+Quote Post
PapouMAC
posté 17 Nov 2014, 13:10
Message #14


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 336
Inscrit : 25 Sep 2004
Lieu : Occitanie
Membre no 24 178



Bonjour,

Par moment je m'arrache les cheveux, donc pour le moment je vais rester petit. J'ai bien le temps de grandir. wink.gif


--------------------
MAC PRO 2009 (MAC OS 10.14.6) 2 x 3,33 Ghz 6-CoreIntel Xeon(5.1), , 64 Go.Carte graphique NVIDIA GeForce GTX 680.

Mac Studio M2 Max, 32Go, 1To
Go to the top of the page
 
+Quote Post
schlum
posté 18 Nov 2014, 04:51
Message #15


Terminaltor
Moderating Machine
*****

Groupe : Admin
Messages : 24 449
Inscrit : 25 Oct 2002
Lieu : Jeumont (59)
Membre no 4 319



Aaaaah, une macro sans variable parenthésée, vade retro laugh.gif

Une petite astuce pour les macros « multi-lignes » :

Code
#define LIGNES(x) do { <blabla1>; <blabla2>; } while(0)


Marchera dans tous les cas genre :
Code
LIGNES(1);
if(toto)
    LIGNES(2);
else if(titi) {
    LIGNES(3);
   <balbla>;
} else
    LIGNES(4);


--------------------
          I think therefore I Mac          
Go to the top of the page
 
+Quote Post
Jaypee
posté 18 Nov 2014, 11:35
Message #16


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



Je dois un peu diluer la sauce pour le bénéfice de PapouMAC :

En C, on peut parfois ne pas utiliser une fonction mais une macro.
La macro va fabriquer le code C qui sera ensuite compilé.

Par exemple, si on souhaite du code super efficace, minimisant l'accès à la mémoire, et éviter de stocker une variable souvent utilisée, on peut définir la valeur comme une macro:
Code
#include <stdio.h>

#define PI 3.1415

int main (int argc, char* argv[] ) {
    float rayon = 1.50;
    float perimetre = 2 * PI * rayon;
    printf("%f\n", perimetre);
}

PI n'est pas gardé en mémoire, la pré-compilation (invisible et automatique) fait une substitution globale de PI par sa valeur dans le source.

Si on utilise la commande qui fait la pré-compilation ou qui lance le pré-processeur seul cpp, on le voit:
Code
# 493 "/usr/include/stdio.h" 2 3 4



# 2 "preproc.c" 2



int main (int argc, char* argv[] ) {
    float rayon = 1.50;
    float perimetre = 2 * 3.1415 * rayon;
    printf("%f\n", perimetre);
}

Ce que Schlum partage généreusement, c'est un truc pour faire une macro plus complexe, sur plusieurs lignes, qui va être acceptée au milieu de n'importe quel code C:
- en début de code
- au milieu
- ou à la fin

C'est l'idée d'un bout de code "passe-partout". A quoi ça peut-il servir ?
Parfois, dans certain type de code très pointu (un pilote, un driver) le seul moyen de déboguer, c'est d'écrire des traces avec des printf.
On peut donc imaginer une macro qui affiche l'état du programme, de ses variables essentielles.
Donc on parsème le code de cette macro. Elle doit pouvoir être insérée partout.

Une fois le problème débogué, rigoureusement, il faudrait supprimer la macro, mais par paresse ou prévision d'un besoin futur, on pourra redéfinir la macro avec un commentaire englobant sa définition pour ne pas générer les traces dans le code qui ira en production (c'est pas super propre mais c'est une possibilité)

Au passage, petite explication sur le piège de la macro sans parenthèses: Autrefois, les pré-compilateurs C, faisant un peu ce qu'ils voulaient, ou alors il fallait préciser leur comportement par une option:
Code
#include <stdio.h>

#define PI 3.1415
#define NEGATION(x) -x
int main (int argc, char* argv[] ) {
    float rayon = 1.50;
    float perimetre = 2 * PI * rayon;
    printf("%f\n", NEGATION(-perimetre));
}

Et voici ce qu'a produit le pré-processeur, tout va bien, on voit l'espace après le -, mais rien ne l'y obligeait :
Code
# 2 "preproc.c" 2



int main (int argc, char* argv[] ) {
    float rayon = 1.50;
    float perimetre = 2 * 3.1415 * rayon;
    printf("%f\n", - -perimetre);
}

Pour conclure, deux bonnes pratiques :
- Les MACROS sont écrites en majuscules pour bien rappeler qu'elles ne sont pas des fonctions
- Les variables dans la définition à droite, doivent toujours recevoir des parenthèses, c'est une sécurité.
Code
#define NEGATION(x) -(x)

Et le code produit sera sans ambiguité :
Code
int main (int argc, char* argv[] ) {
    float rayon = 1.50;
    float perimetre = 2 * 3.1415 * rayon;
    printf("%f\n", -(-perimetre));
}

Voilà,
J-P

Ce message a été modifié par Jaypee - 18 Nov 2014, 11:55.
Go to the top of the page
 
+Quote Post
PapouMAC
posté 18 Nov 2014, 16:22
Message #17


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 336
Inscrit : 25 Sep 2004
Lieu : Occitanie
Membre no 24 178



Bonjour

Ouh là là ! Où est l'aspirine SVP ? sad.gif

Enfin, si j'ai bien compris, il vaut mieux utilise #define pour définir une valeur que de la ranger dans une variable.

Ce message a été modifié par PapouMAC - 18 Nov 2014, 16:25.


--------------------
MAC PRO 2009 (MAC OS 10.14.6) 2 x 3,33 Ghz 6-CoreIntel Xeon(5.1), , 64 Go.Carte graphique NVIDIA GeForce GTX 680.

Mac Studio M2 Max, 32Go, 1To
Go to the top of the page
 
+Quote Post
Jaypee
posté 18 Nov 2014, 17:27
Message #18


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



Si c'est une constante, oui.

Sinon une variable classique est nécessaire pour changer la valeur initiale.

J-P
Go to the top of the page
 
+Quote Post
PapouMAC
posté 18 Nov 2014, 22:31
Message #19


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 336
Inscrit : 25 Sep 2004
Lieu : Occitanie
Membre no 24 178



J'avais bien saisi que c'était préférable pour une constante.

Et merci à tous pour ces précieux renseignements, qui me font avancer dans la compréhension du langage C.

Ce message a été modifié par PapouMAC - 18 Nov 2014, 22:32.


--------------------
MAC PRO 2009 (MAC OS 10.14.6) 2 x 3,33 Ghz 6-CoreIntel Xeon(5.1), , 64 Go.Carte graphique NVIDIA GeForce GTX 680.

Mac Studio M2 Max, 32Go, 1To
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 utilisateur(s) sur ce sujet (1 invité(s) et 0 utilisateur(s) anonyme(s))
0 membre(s) :

 



Nous sommes le : 24th April 2024 - 10:01