Langage C

Discutez d'informatique ici !
Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

Langage C

par Rockleader » 17 Sep 2013, 14:23

Bonjour à tous, je suis en train d'essayer quelques bidouillage en C pour essayer de me repérer par rapport à ce que j'ai appris l'an dernier.

Je ne comprends pas l'une des erreurs que le compilateur me sort sur une boucle while qui m'a pourtant l'air correcte.

Code: Tout sélectionner
int N;
printf ("Entrez un nombre :",N);
    scanf("%d",&N);
    int i=0;
    While (N>=1)
    {
     N=floor(N/10); /*partie entière de la division de N par 10*/
     i=i++;
    }
    printf("La puissance est de %d", i);


En erreur j'obtiens 2 warnings; et une erreur.

L'erreur étant que le compilateur semble me dire que je doive mettre un ; avant l'ouverture de mon accolade; soit après le while. Hors je ne crois pas que cette syntaxe soit correcte.



Un warning me dit que je fais une déclaration de fonction implicite avec mon while...là dessus c'est normal; mais je cherche pas à en faire une fonction, seulement à tester un code, donc je ne me fais pas de soucis pour ce warning là.

Le second warning me dit que j'ai trop d'argument pour le format: [Wformat-extra-args]
Celui ci j'avoue que je ne le comprends pas vraiment; il pointe la ligne de mon affichage pour la saisie de N.




Bref, j'aimerais comprendre l'erreur qui empêche la compilation; ainsi que si possible la raison du 3ème warning.

Merci à vous !
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !



Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 08:03

par ampholyte » 17 Sep 2013, 14:33

Bonjour,

1) Pour récupérer une saisie on utilise scanf :

Code: Tout sélectionner
int N = 0;
printf("Entrez un nombre : "); /* et non printf("Entrez un nombre :", N);
scanf("%d", &N);


2) Il n'y a pas de majuscule au while (ce qui te provoque une erreur puisqu'il croit que While est une instruction qui se finit donc par un ";")

Code: Tout sélectionner
while (N>=1) {
    /* suite du code */
}


3)
Code: Tout sélectionner
/* Soit
i = i + 1;

/* Ou */
i++;

/* Ou encore


Très souvent en corrigeant les warnings, les erreurs partiront également. LA preuve avec le warning que tu pensais être inutile ,)

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 17 Sep 2013, 15:07

Bonjour,
Tout à fait d'accord avec ampholyte.
Je voudrais juste ajouter un mot. Dans les exercices, je constate très souvent l'utilisation de scanf(). Il est généralement déconseillé d'utiliser cette fonction, il faut lui préférer gets() suivi de sscanf().
gets() lit une ligne, et sscanf() transforme la chaine lue en valeurs conformément au format indiqué. La raison en est que si la correspondance entre les valeurs attendues et les valeurs présentes n'est pas parfaite, le résultat peut être désastreux.

Le code serait le suivant
Code: Tout sélectionner
char Ligne[80];
char *ret = gets(Ligne); // l) on peut tester ret ou tout simplement l'omettre.
int N1, N2;
float V;
char Txt[16];
sscanf(Ligne,"%d %f %d",&N1,&V,&N2,Txt);

Version lecture sur fichier
Code: Tout sélectionner
          FILE *Cible=fopen("./Savane/Tirge13C.txt","rt");
          char txt[12];
          fgets(txt,11,Cible);
          sscanf(txt,"%d %d",&Xcible,&Ycible);


A mon avis, il ne faut jamais laisser un Warning sans savoir pourquoi il est là. Il peut arriver d'en laisser, mais ça doit être rare et toujours en connaissance de cause.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 17 Sep 2013, 15:29

Merci Dlzlogic, mais je pense ne pas en être là pour le moment; cela dit ça méritera surement d'y revenir plus tard :lol3:

Le W du while :marteau: ça c'est l'habitude d'ada qui ne faisait pas la différence entre majuscule et minuscule du coup je mettais toujours des majuscules au while je crois.

Merci beaucoup.

Et le printf, je sais pas comment ça a pu m'échapper :marteau: :marteau:

Tout va mieux merci !
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 17 Sep 2013, 15:33

Rockleader a écrit:Merci Dlzlogic, mais je pense ne pas en être là pour le moment; cela dit ça méritera surement d'y revenir plus tard :lol3:

Le W du while :marteau: ça c'est l'habitude d'ada qui ne faisait pas la différence entre majuscule et minuscule du coup je mettais toujours des majuscules au while je crois.
Oui, mais je crois qu'il faut éviter de prendre de mauvaises habitudes.

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 08:03

par ampholyte » 17 Sep 2013, 15:58

Dlzlogic a écrit:Bonjour,
Tout à fait d'accord avec ampholyte.
Je voudrais juste ajouter un mot. Dans les exercices, je constate très souvent l'utilisation de scanf(). Il est généralement déconseillé d'utiliser cette fonction, il faut lui préférer gets() suivi de sscanf().
gets() lit une ligne, et sscanf() transforme la chaine lue en valeurs conformément au format indiqué. La raison en est que si la correspondance entre les valeurs attendues et les valeurs présentes n'est pas parfaite, le résultat peut être désastreux.



Tout à fait d'accord avec Dlzlogic, j'aurais pu prévenir que scanf n'était pas recommandé et pas très sécurisé. J'y penserais la prochaine fois x).

Par contre je ne recommande pas l'utilisation de gets vu qu'il peut très facilement y avoir un dépassement de buffer.

Il vaut mieux utiliser fgets par exemple :

Code: Tout sélectionner
#define MAX_SIZE 50

char buffer[MAX_SIZE + 1] = {0};

fgets(buffer, MAX_SIZE + 1, stdin);


Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 17 Sep 2013, 16:04

Salut ampholyte,
Complètement d'accord, mais moi aussi j'essaye d'y aller à petits pas.
En plus, je constate avec plaisir que même si on a suivi une formation et des chemins complètement différents, on arrive aux mêmes conclusions.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 17 Sep 2013, 16:54

Je tombe sur un problème qui parle de compter le nombre de mot entré lors d'une saisie; c'est possible de faire ça ?

Je suppose qu'on fait la saisie d'une chaine de caractère avec un char qui doit se déclarer un peu comme un tableau; puis essayer de repérer lorsque l'on a un espace dans la saisie; mais ça me parait être une méthode un peu barbare nan ? =) Il doit surement exister une méthode un peu mieux.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 08:03

par ampholyte » 17 Sep 2013, 17:02

Rockleader a écrit:Je tombe sur un problème qui parle de compter le nombre de mot entré lors d'une saisie; c'est possible de faire ça ?

Je suppose qu'on fait la saisie d'une chaine de caractère avec un char qui doit se déclarer un peu comme un tableau; puis essayer de repérer lorsque l'on a un espace dans la saisie; mais ça me parait être une méthode un peu barbare nan ? =) Il doit surement exister une méthode un peu mieux.


De base scanf coupe dès qu'il obtient un retour à la ligne ou un espace. Pour t'en rendre compte essaye le code suivant.

Code: Tout sélectionner
#include
#include <stdlib.h

int main(int argc, char *argv[]) {
    char test[100 + 1] = {0};
    scanf("%s", test); /* J'aime les mathématiques */

    printf("%s\n", test); /* Affiche J'aime */
 
    return EXIT_SUCCESS;
}



Essaye de saisir "J'aime les mathématiques". Tu devrais obtenir l'affichage "J'aime" et c'est tout !

Il y a plusieurs solutions pour compter le nombre de mot.

Soit tu utilises la fonction fgets avec une boucle et tu fais un découpage par espace.

Code: Tout sélectionner
#define TBUFFER 1024

char ligne[TBUFFER + 1] = {0};

while (fgets(ligne, TBUFFER + 1, stdin) != NULL) {
    /* Traitement */
}



Soit tu utilises scanf (en cas d'obligation) et tu fais une boucle en testant le retour du scanf :

Code: Tout sélectionner
int nbMots = 0;
char mot[30 + 1] = {0};
while (scanf("%s", mot) != EOF) {
    nbMots++;
}


Autre solution tu récupères la ligne entière.

Code: Tout sélectionner
char texte[1024 + 1] = {0}
scanf("%[^\n]", texte);

/* Boucle qui compte dès qu'il y a un espace dans texte */

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 18 Sep 2013, 18:52

Bonsoir, une nouvelle fois je vous remercie pour votre réponse.

Malheureusement, au niveau où j'en suis actuellement je n'ai pas appris autre chose que scanf; donc je me contenterais de l'utiliser.
Dans ton code avec scanf; je ne comprends pas ce que signifie EOF.


Par ailleurs, je me posais une question, un peu en dehors du problème; linux ayant été fabriqué en C, il doit y avoir des fonctionnalité communes non ?
Par exemple, il serait peut être possible d'écrire la saisie dans un fichier; puis de se servir d'un grep ou d'une autre fonction de linux pour afficher le nombre de mot.
Ce n'est qu'une réflexion de ma part, je ne cherche pas spécialement à faire ça; l'idée derrière c'est surtout, concrètement est ce qu'un code de shell rentrerait dans un programme en C.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 18 Sep 2013, 19:16

Bonjour,
Je vais essayer quelques mots d'explication.
D'abord EOF qui veut dire End Of File, est un caractère qui indique la fin de fichier.
Si scanf est arrivé à la fin de fichier (stdin), alors la valeur retournée est EOF. Si rien n'a été lu, la valeur retournée est 0 (zéro), sinon, c'est le nombre de champs lus.
En fait EOF et 0 constituent des erreurs, puis qu'on a essayé de lire plus de champs que prévus.

Linux a été effectivement été "fabriqué" en C. Ce qui a été fabriqué, c'est l'OS (Opérating Sustème), ce qu'on te demande, c'est d'apprendre à programmer en C, ça n'a rien à voir avec le système.
Le langage C est compilé, lié et cela produit un exécutable. Une caractéristique du shell est d'être interprété.
Un programme écrit en C a des dizaines de milliers de lignes. Un shell peut lancer des exécutables, pas vraiment l'inverse.

Il s'agit là d'un exercice, surement pas d'un module qui pourrait être utilisable, pour la simple raison qu'il ne présente pas grand intérêt. Il faut savoir compter les mots d'une phrase, mais si ça ne sert pratiquement jamais.

Ampholyte t'a donné plusieurs exemple, tous aussi intéressants, à toi de les comprendre, disons, au moins les 2 derniers.

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 18 Sep 2013, 20:58

Par ailleurs, je me posais une question, un peu en dehors du problème; linux ayant été fabriqué en C, il doit y avoir des fonctionnalité communes non ?

Dans linux t'as un peu tout, du C, du python, du shell... Mais bon, par exemple tous tes outils en ligne de commande, ls, grep, etc, c'est du C.
Les fonctionnalités communes, oui. Tu vois bien que certains packages ont des dépendances vers d'autres packages. Idem du code est réutilisé.

Par exemple, il serait peut être possible d'écrire la saisie dans un fichier; puis de se servir d'un grep ou d'une autre fonction de linux pour afficher le nombre de mot.

oui c'est possible.

Ce n'est qu'une réflexion de ma part, je ne cherche pas spécialement à faire ça; l'idée derrière c'est surtout, concrètement est ce qu'un code de shell rentrerait dans un programme en C.

La question est trop vague. C peut appeler d'autres programmes. En particulier le programme qui execute tes scripts shell (mettons sh, ou bien ksh, etc) est susceptible d'etre appelé depuis C.
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 19 Sep 2013, 13:55

Je comprends mieux l'intérêt de linux quand à la programmation maintenant; je n'ai pas encore appris à travailler sur des fichiers en soit en dehors de mon compilateur ou de quelques instructions en shell; mais ça ne serait venir

Par exemple, tu m'aurais parlé de stdin il y a deux jours je n'aurais pas vraiment compris, mais j'en ai entendu parler plus tôt dans la journée pour la première fois.

J'en arrive donc à ma question; comment saura t'on dans la boucle que l'on arrive à la fin du fichier et qu'il faut arrêter de boucler. Il faut définir une sorte de caractère final qui fait office de fin ? Auquel cas je ne vois pas comment ça s'écrit. Car là ce que je comprend c'est que ça va boucler jusqu'à ce que la capacité du char mot sera pleine.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 08:03

par ampholyte » 19 Sep 2013, 14:27

Dès que tu crées un fichier, le caractère EOF se trouve à la fin de ce fichier. C'est un caractère que tu ne vois pas normalement.

Pour plus d'info : http://fr.wikipedia.org/wiki/End-of-file

Lorsque tu fais des tests en lançant ton executable sur linux une fois la liste de mot rentré il faut faire CTRL + D pour envoyer le caractère EOF et donc terminer la lecture de stdin.

Tu peux également stocker ton test dans un fichier et utiliser les redirections.

Code: Tout sélectionner
./mon_programme < test

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 19 Sep 2013, 14:49

Rockleader a écrit:Je comprends mieux l'intérêt de linux quand à la programmation maintenant; je n'ai pas encore appris à travailler sur des fichiers en soit en dehors de mon compilateur ou de quelques instructions en shell; mais ça ne serait venir

Par exemple, tu m'aurais parlé de stdin il y a deux jours je n'aurais pas vraiment compris, mais j'en ai entendu parler plus tôt dans la journée pour la première fois.

J'en arrive donc à ma question; comment saura t'on dans la boucle que l'on arrive à la fin du fichier et qu'il faut arrêter de boucler. Il faut définir une sorte de caractère final qui fait office de fin ? Auquel cas je ne vois pas comment ça s'écrit. Car là ce que je comprend c'est que ça va boucler jusqu'à ce que la capacité du char mot sera pleine.

L'OS (Linux, Windoxs - y'en a beaucoup - UNIX -y'en a aussi plusieurs - OS/2, DOS etc.) gère le mode d'exploitation, c'est à dire tout ce qui concerne le fonctionnement du matériel, y compris de la mémoire centrale, des périphériques etc.

Concernant la programmation, d'abord elle nécessite un éditeur, autrefois il n'y avait que VI sous unix, un compilateur et un éditeur de lien. Je suppose que tu utilises GCC. En fait et en gros, seules les bibliothèques et l'éditeur de lien dépendent de l'OS, c'est à dire ce qu'on pourrait appeler l'empaquetage. Tout le reste, c'est à dire toute la logique et la syntaxe dépendent du langage.

Tout ce qui concerne l'utilisation de Linux et d'UNIX est un peu trop loin pour moi.
Si tu as du mal à écrire l'algorithme et le code pour compter les mots d'une phrase, éteint ta machine, sur une feuille de papier tu écris "Ceci est une phrase complète, avec une fin."
Puis tu écris toutes les "choses" que tu devras faire pour compter les mots, en imaginant que tu ne saches pas lire ou que tu ne comprennes pas le français.

La traduction en code C viendra toute seule.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 19 Sep 2013, 19:08

Si j'ai bien compris avec cette commande EOF dans la boucle; en fait il s'agit d'une boucle qui ne s'arrêtera que lorsque l'on fera un ctrl D sur linux ou bien un ctrl Z sur windows ?

Mais dans ce cas là le programme dépend avant tout du SE puisque la condition d'arrêt au final ne sera pas la même pour linux que windows.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 19 Sep 2013, 19:31

Non, c'est pas ça.
EOF est le caractère renvoyé par scanf (et d'autres) lorsque la fin de fichier a été rencontrée. (ce n'est pas une commande).
Cela peut être une solution pour arrêter une lecture. Personnellement je ne l'utilise qu'à titre de sécurité. D'ailleurs, je n'emploies jamais scanf mais gets suivi de sscanf, ou plutôt fgets suivi de sscanf (voir les réponses précédentes).
La question posée par ton exercice est de compter le nombre de mots d'une phrase et non de détecter une fin de fichier. Au pire, il te manquera le décompte d'un mot.

Il est certain qu'on pourrait mieux deviner le sens exacte de l'exercice si on avait l'énoncé exact.
Peut-être faut-il le faire avec le main(int argc, char *argv[]) ?

PS: Par ailleurs, il serait intéressant qu'on sache si tu as déjà "fait" un exécutable en C.

PS2 : l'exécutable dépend du système d'exploitation cad de l'OS, mais le code sera toujours le même pour Unix, Linux, Windows, quelque soit le niveau.
Un fichier texte écrit sous Linux se lit sans problème sous Windows. La lin de fichier sera toujours la fin de fichier.

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 19 Sep 2013, 20:04

mais le code sera toujours le même pour Unix, Linux, Windows, quelque soit le niveau.

ou pas. C'est possible d'écrire du code plateform dependant. Et on en trouve assez facilement.

Mais bon je suis d'accord que Rockleader fait un peu trop de théorie et devrait tester sa fin de fichier lui même.
la vie est une fête :)

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 13:39

par Dlzlogic » 19 Sep 2013, 20:21

C'est possible d'écrire du code plateform dependant. Et on en trouve assez facilement.
Naturellement c'est possible, les directives de compilation sont faites pour ça. Est-ce le moment de compliquer les choses ?

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 19 Sep 2013, 20:52

Simplifier les choses ne veut pas dire débiter des boulettes.
Un fichier texte écrit sous Linux se lit sans problème sous Windows.

et pendant que j'y suis, non, ca dépend du système de fichier. ntfs windows, ext4 linux (par exemple), ya ptet intérêt à avoir des drivers de temps en temps...
Donc il faut quand même y aller molo sur les affirmations.
la vie est une fête :)

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 14 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite