CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[C] Problème Boucle Infini

edouarddu91
edouarddu91
Niveau 10
21 mai 2011 à 20:49:05

Bonjour, j'ai actuellement un soucis avec un programme en c que j'essaie de coder. Le but de ce programme dans l'état actuel est de récupérer une chaine de chaine de caractère puis de l'afficher

Voici le code en question :

  1. include <stdio.h>
  2. include <stdlib.h>
  3. include <unistd.h>
  4. include <wait.h>
  5. include <string.h>

int main () {

int ret, cpt=0, cpt2=0;
char c;

char *demande="Veuillez saisir la commande à exécuter : ";
char mot[20];
char *commande[10];

write(1, demande, strlen(demande));

ret=read(0, &c,1);

while (ret == 1) {

if (c == ' ') {

mot[cpt]='\0';
strcpy(commande[cpt2],mot);

cpt=0;
cpt2++;

}

else {

mot[cpt]=c;
cpt++;

}

ret=read(0, &c,1); }

write (1, commande[0], strlen (commande[0]));

exit (0);

}

Donc voila quant j'essaie de l'éxécuter, j'obtient une belle boucle infini. Je pense que le problème doit être tout bête mais je vois vraiment pas d'où il pourrait venir.

Je vous remercie d'avance pour votre aide et vous souhaite une bonne journée. :)

stationessence
stationessence
Niveau 8
21 mai 2011 à 21:03:40

Explique nous ce qu'est censé faire ton programme au moins?
Il ne suffit pas de mettre un bout de code avec "ca ne amrche pas " pour avoir des réponses pertinente...

On fait ca seulement si le programme est très bien commenté et que les variables sont explicite ce qui n'est pas trop le cas ici.

Eclaire moi pour que je puisse t'eclaire :)

stationessence
stationessence
Niveau 8
21 mai 2011 à 21:06:04

Oups désolé, ma phrase peut être mal interprete.

Quand je disais :Explique nous ce qu'est censé faire ton programme au moins? je voulais dire, explique nous les mécanismes du programme, les fonctions que tu as le droit d'utiliser et celle que tu n'as pas le droit d'utiliser.
Parce que dans le fond, c'est assez simple de recuperer une chaine de caractere et de l'afficher.

edouarddu91
edouarddu91
Niveau 10
21 mai 2011 à 21:28:40

Le but de mon programme est de réaliser un mini shell.

Donc voici mon résonnement :

Je demande à l'utilisateur de saisir une commande simple (du style ls -l). Le programme lit ensuite la saisie de l'utilisateur caractère par caractère. Dès lors qu'un nouveau mot est rencontré (le caractère lu est alors un espace), on envoit le mot stocké dans mon tableau 1D dans mon tableau de string.

Voila en gros. :)

edouarddu91
edouarddu91
Niveau 10
21 mai 2011 à 21:30:52

A la fin du traitement j'essaie ensuite d'afficher le tableau de string. :)

hyrulink2
hyrulink2
Niveau 7
21 mai 2011 à 21:42:51

A première vue c'est normal qu'il y ai une boucle infinie puisque tu lit sur STDIN_FILENO, essaie de faire un Ctrl-D pour lui indiquer un symbole EOF.
Et ta variable commande m'a l'air bien suspecte, tu l'utilise comme un tableau de tableau mais seule commande[0] est utilisable car les autres cases ne sont pas allouées, et si un mot de plus de 9 lettres est entrées ça va faire des trucs étranges.
As-tu certaines bibliothèque interdites ou peut-tu utiliser ce que tu veux, voire du C++? Je t'aiderai bien mais faut que je connaisse tes outils.

edouarddu91
edouarddu91
Niveau 10
21 mai 2011 à 22:03:00

Euh non je ne peux pas utiliser de c++ dans ce programme. En ce qui concerne les librairies, je peux utiliser les librairies de base offertes par un système linux. :)

stationessence
stationessence
Niveau 8
21 mai 2011 à 22:19:44

Pourquoi déclare tu ton tableau comme ceci : char *commande[10]; sans allouer l'espace mémoire ?

Soit tu fais comme ca :"char* commande[10][20] par exemple (10 mots de 20 caractères) soit tu alloues pour chaque case un espace memoire :

comme ceci : int i = 0 ; for(i=0; i<9;i++) commande[i] = malloc(SIZE*sizeof(char)) ;

Bon maintenant que j'ai un peu plus compris ce que tu désire faire, je vais jetter un oeil. En tout cas, à première vu sur le code, tu te prends beaucoup la tête :P

edouarddu91
edouarddu91
Niveau 10
21 mai 2011 à 22:26:00

C'est bon j'ai reussi à régler mon problème. Je te remercie de ton aide et te souhaite une bonne soirée. :)

hyrulink2
hyrulink2
Niveau 7
21 mai 2011 à 22:26:44

Si tu peux utiliser la lib C, tu devrai:
1)arrêter d'utiliser write pour écrire sur stdout et utiliser printf
2)utiliser malloc pour allouer dynamiquement tes chaines de caractères, le mieux est que tu te code une bibliothèque de listes chainées et de chaines variables mais si veux rester simple et que tu considères que l'utilisateur ne dépassera jamais 5 mots de 9 lettres par exemple, déclare commande comme ça:
char commande[5][10];

edouarddu91
edouarddu91
Niveau 10
22 mai 2011 à 11:54:07

Un nouveau problème se présente : la phase exec. :-(

Donc voici mon code :

  1. include <stdio.h>
  2. include <stdlib.h>
  3. include <unistd.h>
  4. include <wait.h>
  5. include <string.h>

int main () {

int ret, cpt=0, cpt2=0, cpt3=0;
char c;
pid_t idproc;

char *demande="Veuillez saisir la commande à exécuter : ";
char *err="Erreur ! Fork échoué \n";
char *err2="Erreur ! Exec échoué \n";
char commande[20][20];

write(1, demande, strlen(demande));

ret=read(0, &c,1);

while (ret == 1) {

if (c == ' ') {

commande[cpt][cpt2]='\0';
cpt=cpt++;
cpt2=0;

}

else {

commande[cpt][cpt2]=c;
cpt2++;

}

ret=read(0, &c,1); }

cpt++;

commande[cpt][0]='N';
commande[cpt][1]='U';
commande[cpt][2]='L';
commande[cpt][3]='L';
commande[cpt][4]='\0';

write (1, "\n", 1);

while (cpt3<=cpt) {

write (1, commande[cpt3], strlen (commande[cpt3]));
write (1, "\n", 1);

cpt3++;

}

idproc=fork();

if (idproc == -1) {

write(2, err, strlen(err));
exit (1);

}

if (idproc == 0) {

execv (commande[0], commande);

write(2, err2, strlen(err2));
exit (2);

}

wait(NULL);

exit (0);

}

J'explique ce mon programme est sensé faire maintenant. Le programme demande à l'utilisateur de saisir une commande. Des lors que la fin de la saisie est annoncée par l'utilisateur(via ctrl-d), le programme lit la commande caractère par caractère afin de pouvoir l'exploiter plus tard dans un execv. Pour cela, je crée un tableau de string qui met dans chaque ligne un mot de la commande. Après avoir lu la commande dans sa totalité, j'ajoute une dernière ligne à mon tableau : NULL afin de lancer correctement le execv qui suit.

Seulement le execv n'accepte pas ma synthaxe et lors de la compilation, j'obtiens le message d'erreur suivant : :-(

mini_shell.c: In function ‘main’:
mini_shell.c:72:1: warning: passing argument 2 of ‘execv’ from incompatible pointer type
/usr/include/unistd.h:560:12: note: expected ‘char * const*’ but argument is of type ‘char (*)[20]’

Je vous remercie de votre aide et vous souhaite une bonne journée. :)

stationessence
stationessence
Niveau 8
22 mai 2011 à 12:21:41

Très simple, il suffit de regarder le prototype de execv :
int execv(const char *path, char *const argv[]);

Premier paramètre, un pointeur sur char, tu l'as bien respecté.
Deuxième paramètre, un tableau de pointeur.
Or commande n'est pas un tableau de pointeur mais un tableau 2D.

Il aurait fallut déclarer commande comme ca :

char *commande[20];
for(i=0 ; i<20 ; i++) { commande[i] = malloc(sizeof(char)) ; }

Pour que ca compile.

stationessence
stationessence
Niveau 8
22 mai 2011 à 12:23:11

Ne pas oublier de mettre la taille de chaque pointeur en facteur de sizeof(char), chose que je n'ai pas fait.

stationessence
stationessence
Niveau 8
22 mai 2011 à 12:26:55

Et un petit conseil, quand tu utilises des fork(), mieux vaut structurer ton programme à l'aide de switch.

Beaucoup plus lisible que des if.

Egalement, pout tester les codes d'erreur, utilise perror mince alors !

Tu as des outils, c'est pour les utiliser. La variable ernno initialise automatique le message d'erreur, et la cible de facon fiable à la place d'utiliser toujours la même erreur "exec a echoué" et ensuite, pour debugger, tu te met à mettre des printfs partout pour localiser l'endroit où ca a planté...

edouarddu91
edouarddu91
Niveau 10
22 mai 2011 à 13:09:18

Je te remercie de ton aide. Je vais tenir compte de tes conseils. :)

stationessence
stationessence
Niveau 8
22 mai 2011 à 13:44:39

Très heureux de t'avoir aidé.
Up ce topic si tu as d'autres problèmes. J'essaierai de passer pour voir de temps en temps :)

edouarddu91
edouarddu91
Niveau 10
22 mai 2011 à 14:16:49

J'ai une nouvelle fois besoin de ton aide.

Voici la dernière version de mon code :

  1. include <stdio.h>
  2. include <stdlib.h>
  3. include <unistd.h>
  4. include <wait.h>
  5. include <string.h>

int main () {

int ret, cpt=0, cpt2=0, cpt3=0, i;
char c;
pid_t idproc;

char *demande="Veuillez saisir la commande à exécuter : ";
char *err="Erreur ! Fork échoué \n";
char *err2="Erreur ! Exec échoué \n";

char *commande[20];
char mot[20];

for( i=0 ; i<20 ; i++)

commande[i] = malloc(sizeof(20));

write(1, demande, strlen(demande));

ret=read(0, &c,1);

while (ret == 1) {

if (c == ' ') {

mot[cpt2]='\0';
strcpy(commande[cpt], mot);

cpt++;
cpt2=0;

}

else {

mot[cpt2]=c;
cpt2++;

}

ret=read(0, &c,1); }

if (c != ' ') {

mot[cpt2]='\0';
strcpy(commande[cpt], mot);

}

while (cpt3<=cpt) {

write (1, commande[cpt3], strlen (commande[cpt3]));
write (1, "\n", 1);

cpt3++;

}

idproc=fork();

if (idproc == -1) {

write(2, err, strlen(err));
exit (1);

}

if (idproc == 0) {

execvp (commande[0], commande);

write(2, err2, strlen(err2));
exit (2);

}

wait(NULL);

exit (0);

}

Tout passe correctement sauf les paramètres ! :-( Par exemple j'essaie de tapper la commande suivante : gedit test.c et bien la commande est bien réalisée mais elle tente également de m'ouvrir mon répertoire personnel. La commande ls me dit que mes paramètres sont inconnus (ls -l par exemple) ou que le répertoire demandé n'a pas été trouvé (ls / par exemple).

edouarddu91
edouarddu91
Niveau 10
22 mai 2011 à 14:18:11

J'avais placé un NULL dans la dernière ligne de mon tableau mais gedit m'ouvrait un fichier appelé NULL en plus donc je l'ai enlevé pour le moment. :)

hyrulink2
hyrulink2
Niveau 7
22 mai 2011 à 18:15:14

En fait tu dois donner le nom du fichier contenant le programme à exécuter et pas juste la commande, par exemple si ls est dans /bin/ls alors ton tableau doit être {"/bin/ls", "args1", NULL}.
Il faut donc que tu résolves les noms des programmes que l'utilisateur te demande en utilisant les variables d'environnement (getenv il me semble...) ou, plus bourrin, en la donnant en dur(strcpy(commande[0], chemin_binaires) au début puis strcpy(commande[0], mot) au moment où tu le copies).

Et remet le NULL à la fin du tableau, il y en a besoin.

edouarddu91
edouarddu91
Niveau 10
22 mai 2011 à 18:46:21

Je me suis rendu compte du problème lié à NULL. Je le posais en chaine de caractère dans mon tableau ce qui n'est pas du tout son but. :sarcastic:

Sinon hyrulink2, j'utilise avec la commande execvp le path donc je n'ai pas besoin de mettre le chemin complet non ? :)

Sous forums
  • Aide à l'achat Mac
  • Internet
  • Macintosh
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Steam Deck
  • Hardware
La vidéo du moment