Bonjour J'ai un problème quant à l'initialisation de mes variable avec NULL.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int nombre = NULL;
return 0;
}
Me renvoie l'erreur ci-dessous
gcc main.c -o -wall main
main.c: In function ‘main’:
main.c:6:22: warning: initialization of ‘int’ from ‘void *’ makes integer from pointer without a cast [-Wint-conversion]
6 | int nombre = NULL;
| ^~~~
/usr/bin/ld: cannot find main: No such file or directory
collect2: error: ld returned 1 exit status
NULL est (parfois) déclaré en tant que pointeur, style #define NULL ((void *)0). Alors l'assigner à un integer provoque le message. Pourquoi ne pas écrire int nombre=0; ?
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
D'accord je comprend mieux, je suis en train d'apprendre le C et c'étais un peu la confusion dans ma tête.
Merci à vous deux !
Ca m'amène à un second problème voici le code
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
int main(int argc, char *argv[]){
int n1 = 0, n2 = 0, resul = 0;
char carac;
printf("Donne moi une première valeur\n");
scanf("%d", &n1);
printf("Donne moi l'operateur (+\\-\\*\\/\\%%)\n");
scanf("%c", &carac);
printf("Donne moi une deuxième valeur\n");
scanf("%d", &n2);
printf("%d %c %d = ma bite", n1, carac, n2);
return 0;
}
Le code s'éxécute mais lorsque je rentre la première valeur il me demande directement les deux printf suivant d'affiler sans me laisser ecrire quel operateur je souhaite
Je compile avec gcc
gcc main.c -o -wall main
Ca me renvoit cette erreur
/usr/bin/ld: cannot use executable file 'main' as input to a link
collect2: error: ld returned 1 exit status
Ah, lire un caractère avec 'scanf'... J'ai essayé autrefois, et souvent (toujours ?) j'avais le même problème.
Je ne sais plus exactement, mais c'est parce que pour saisir un caractère il faut taper "Entrée", or le caractère '\n' ne fait pas partie de la donnée saisie, contrairement au cas de la saisie d'un entier ou d'une chaîne de caractères, du coup il est laissé dans le tampon et lu au 'scanf' suivant, quelque chose comme ça.
Suggestion : lire une chaîne :
char operateur[2]; // un 'char' suivi de '\0'
printf("Donne moi l'operateur (+\\-\\*\\/\\%%)\n");
scanf("%1s", operateur); // on lit une chaine de 1 caractère
Mais je ne suis pas sûr que ça permette de contourner le problème.
(Sinon il faut vider le tampon. C'est un grand classique des questions sur le C.)
Deux raisons à cela: - rewind(stdin) n'est pas portable. Donc pour certaines bibliothèques C cela ne fonctionnera pas. - si stdin n'est pas directement sur une console, comme la redirection d'un flux ou d'un fichier, l'appeler aura une conséquence désastreuse.
On peut vider le buffer de manière portable en quelque lignes de code, et l'utilisation de l'espace est tout à fait portable et est suffisante dans les cas simples. Dans tous les cas, vider le buffer est surtout une bidouille liée au fait que scanf() est une fonction non adaptée à l'interaction avec un utilisateur. Le couple fgets()/sscanf() est bien plus sûr.
... The header <stddef.h> defines the following macros and declares the following types. Some are also defined in other headers, as noted in their respective subclauses. ...
The macros are NULL which expands to an implementation-defined null pointer constant; ...
Le problème c'est qu'il peut rester d'avantage de choses que le retour chariot ou des caractères "blancs" (espaces, tabulations) qui seront les seuls consommés par cette syntaxe.
Cette "astuce" ne traite donc qu'une partie du problème.
Par exemple, si je demande un int et que je tape 12,57, scanf() va s'arrêter à la virgule, qui va rester dans le tampon stdin avec tout ce qui va suivre, y compris le \n terminant la ligne.
Après chaque appel à scanf(), pour purger le tampon stdin, il suffit de faire :
{
int c;
while((c = getchar()) != '\n' && c != EOF)
/* discard */ ;
}
http://c-faq.com/stdio/stdinflush2.html
On peut utiliser cela tel quel ou, mieux, se faire une fonction.
Le problème ne concerne pas juste scanf() qui est souvent décriée (voire honnie), c'est la même chose avec fgets() si la ligne qui est tapée dépasse la taille passée en paramètre, alors le reste va rester dans le tampon de la même manière.
Le cas où fgets() laisse des choses dans le tampon est, en fait, plus compliqué à gérer correctement, car ce n'est pas systématique.
Et dans le cas où la saisie ne dépasse pas la capacité passée à fgets(), un autre problème de cette fonction est qu'elle capture le \n dans la chaîne récupérée, ce qui n'est souvent pas souhaité et qu'il faut penser à retirer en modifiant la chaîne récupérée avant de pouvoir l'exploiter.
Disons que la solution de Dalfab fonctionne si l'utilisateur tape un truc correct.
Car rappelons qu'à l'origine, le programme de Nuvenco ne marche pas lorsque l'utilisateur tape un truc correct. Et c'est pour ça qu'il demandait de l'aide.
(Pour cette raison, je pense que la saisie rigoureuse est hors-sujet : ça ne va servir qu'à embrouiller.)
@rouIoude : oui, c'est déjà mieux même si c'est un peu ésotérique ;-)
@robun : si on veut faire simple, sans faire quelque chose de "rigoureux", alors il faut supposer que l'utilisateur est discipliné et fait ce qu'on lui demande de faire. Dans ce contexte limité, pour régler le problème des scanf() qui "sautent", on pourrait préférer se contenter de consommer le '\n' qui est sensé être juste après ce qu'a récupéré le scanf() avec un simple getchar().
printf("Donne moi une première valeur\n");
scanf("%d", &n1);
getchar();
cela permet de virer le '\n' tout de suite, au lieu de compter sur le fait de se rappeler l'éliminer dans le futur au prochain appel à scanf() en espérant ne pas oublier de précéder mes spécificateurs d'un espace vide.
Bien sûr c'est juste une rustine juste pour que "çà marche".
AMHA, les (vrais) programmes de ligne de commande qui attendent des saisies d'utilisateurs, il n'y en pas pas tant que cela. Ce n'est pas pratique (difficilement scriptable). Les inputs utilisateurs sont la plupart du temps limités à des options de ligne de commande (ou ce sont des démons et ils interagissent via le réseau), et s'il y a vraiment une interaction à gérer à l'écran on devrait penser à utiliser des choses plus robustes que les fonctions standard (du genre getline() sur les systèmes POSIX ou carrément une bibliothèque comme ncurses si on a une TUI à gérer).
/usr/bin/ld: cannot use executable file 'main' as input to a link
collect2: error: ld returned 1 exit status
Je ne comprend pas..
- Edité par Nurvenco 13 juin 2022 à 20:48:08
Tes options sont dans le désordre.
l'option -o doit être suivie immédiatement du nom de fichier à fabriquer
avec ta commande, il faudrait fabriquer le fichier qui s'appellerait "-wall" à partir de main, qui se trouve être un exécutable. Ca va pas du tout. A sa place on protesterait aussi, avec le même message : on ne peut pas utiliser un exécutable comme entrée de l'édition des liens.
l'option pour les avertissements, c'est -Wall avec une majuscule
La commande correcte c'est
gcc -o main -Wall main.c
ou toute autre permutation des trois éléments "-o main" "-Wall" "main.c"
---
A propos de la lecture, une de mes idées fixes, c'est que si on cause avec un utilisateur en mode texte à coup de scanf printf, aller faire des getchar() c'est du bricolage maladroit. Tant pis pour vous, je ne peux pas résister :
Le fonctionnement typique en "dialogue texte sur stdin/stout", c'est que quand le programme pose une question, l'utilisateur répond en tapant une LIGNE.
Et donc la bonne approche, c'est de lire d'abord la LIGNE COMPLETE de réponse, et ENSUITE d'analyser son contenu pour voir si on peut en faire quelque chose. Pas de lire un truc et se garder un bout de ligne pour plus tard, qu'on grignoterait peut être avec une boucle sur getchar != EOL.
Donc typiquement getline ou readline, puis sscanf.
Evidemment, jusqu'ici getline() c'est pas dans la bib standard C, ça serait trop facile, merci le comité de normalisation, mais bon, c'est dans POSIX depuis 2008. Et c'est quand même pas difficile à implémenter soi-même.
Evidemment, jusqu'ici getline() c'est pas dans la bib standard C, ça serait trop facile, merci le comité de normalisation, mais bon, c'est dans POSIX depuis 2008. Et c'est quand même pas difficile à implémenter soi-même.
Pour un débutant qui ignore ce qu'est un pointeur et qui n'a sans doute jamais utilisé malloc() / realloc(), ça doit être extremement compliqué à écrire ;-)
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Ou alors on lit simplement dans un buffer jugé assez grand pour contenir une ligne tapée par l'utilisateur de taille raisonnable pour ce qui n'est qu'un exercice, genre 1Ko.
Des qu'on a besoin de scanf, il vaut mieux au moins faire semblant de savoir ce qu'est une adresse.
Pour les premiers exercices de débutant, il ne faut pas chercher à "securiser". Les moyens disponibles à ce niveau sont une galère que ce soit la boucle pour bouffer la fin de ligne ou les autres.
Déjà que "sécuriser", ça voudrait dire avoir prealablement pris la peine de définir précisément le comportement du programme en cas de saisie invalide.
Initialiser une variable avec la valeur 'NULL'
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
En recherche d'emploi.
En recherche d'emploi.
Le Tout est souvent plus grand que la somme de ses parties.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Le Tout est souvent plus grand que la somme de ses parties.