Justement le cours ne me dit rien par rapport à cela. Ce n'est pas un exercice du cours mais juste un exercice d’entraînement que je fais.
Comment faudrait il l'écrire ?
Bonjour Marotte,
Mon problème se situe précisément au niveau de l'allocation dynamique pour le buffer que je n'arrive pas à traduire en C. Je cherche à le faire pour m'exercer. C'est l'exo qui me demande de l'écrire dans les deux langages. Ce que j'ai fait:
#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <string.h>intmain(void){char*pointeur=malloc(20*sizeof(char));FILE*f=fopen("fichier.txt","r");if(!f){printf("Impossible d'ouvrir le fichier\n");return1;}else{fgets(pointeur,20*sizeof(pointeur),f);intk=0;while(pointeur[k])printf("%d\t",(int)pointeur[k++]);free(pointeur);}fclose(f);return0;}while(pointeur[k]){printf("%d\t",(int)(pointeur[k]));++k;}
C'était plutot comment faire caar en fonction ou avec # define.
Comment tu l'écrirais la fonction caar (l'extraction du premier élément de la sous liste) ?
Salut lolop,
J'ai réussi à créer ma fonction cons(), car() et cdr() avec ce que tu m'a proposé et un main pour appelé ces fonctions afin d'afficher leur résultat.
Par ailleurs, comment procéder si je voudrais faire mon car et mon cdr à l'aide de # define et non des fonctions ?
Par contre comment pourrais je implémenter mon main pour réussir à compiler mon programme afin d'afficher une liste quelconque, son car ou son cdr ? C'est un peu un casse tete cet exercice en fin de compte.
Merci lolop, ça correspond parfaitement aux spécifications.
Mais il y a une ligne que je n'ai pas comprise dans ton code:
Double dbl = malloc(sizeof(struct Doublet)); //le Double est ce une erreur de ta part ? ou il correspond à quoi ? ce ne serai pas list à la place ?
Aussi si je voudrais plutot utiliser des #define à la place des fonctions pour le car et le cdr comment traduirais je cela ?
```Il manquerait un main pour finir afin de faire appel à cette fonction cons je pense …
Pour les sous listes justement l'exo d'après demande de definir à l'aide de #define, caar et cadr et construire une liste pour les tester et afficher leur résultat. Mais avant je dois parvenir à faire pour une liste simple.
Tu m'as l'air de très bien maitriser les listes chainées en C. Ton code me donne une idée mais l'exercice demande:
Construire en C une liste L à quatre éléments dans le code du programme à l'aide de cons. Testez car(L), car(cdr(L), car(cdr(cdr L)), car(cdr(cdr(cdr L))), en affichant leur résultat.
Donc je dois suivre les spécifications et adapter par rapport à l'énoncé.
car(L) extrait le premier élément de notre liste L
car(cdr(L) extrait le deuxième
car(cdr(cdr L)) extrait le troisième
car(cdr(cdr(cdr L))) extrait le quatrième
Comme en Langage Lisp.
Voilà pourquoi je dois adapter ces spécifications et compléter ce qui m'a été donné comme indice et exemple pour pouvoir réussir à le faire.
typedef struct Doublet {void * car ; struct Doublet * cdr ;} * list ; // la structure de base ; list est un pointeur sur un doublet
#define car(doublet)((doublet)->car)
//macro plutôt que fonction, pour écrire car(x) = ...
#define cdr(doublet) ((doublet)->cdr)
list cons(void *, const list);
// prototype de la fonction cons
...
// Définition de la fonction cons ; elle renvoie un pointeur sur un doublet
list cons(void * elt, const list L)
{ list Cons = malloc(sizeof(struct Doublet));
// alloc mémoire d'un doublet
car(Cons) = elt ;
cdr(Cons) = L ;
return Cons ; }
Et ma difficulté se repose justement au niveau de cette adaptation avec ces indices données pour répondre au besoin de l'exercice.
car et cdr c'est justement pour extraire respectivement le premier élément de ma liste et le reste de la liste comme en Lisp.
Et en parlant de libération de la mémoire tu fais allusion à free() je suppose.
Il y a t-il quelque chose qui m'aurait encore echappé ?
Et en ce qui concerne le main qui ferait appel à ma fonction pour l'affichage comment tu le verrais ?
Ok merci briaeros007. Par ailleurs comment pourrais je le traduire sous forme de code pour etre plus concret ? Si tu pourrais me donner un exemple ça m'aiderait.
Merci d'avance
Dans mon cas, je ne cherche pas à généraliser. Ce n'est que le nom de la voie qui prévoit des espaces, déjà il faudrait que j'arrive à régler ce problème moins délicat que la généralisation.
Je l'ai inseré à la place du scanf pour parser chaque ligne mais malheureusement je sais pas ou ça bloque car l'affichage n'est pas du tout délicat.
Exemple de l'affichage:
Numéro : 75019
Voie : 75019
Nom de la voie :(null)
Ville :(null)
Code postale : (null)
Numéro : 75019
Voie : 75019
Nom de la voie :(null)
Ville :(null)
Code postale : (null)
…..
Si tu pourrais m'aider à corriger mon erreur.
Merci d'avance !!
Merci Corentin !
En tenant compte de tes suggestions, j'ai finalement pu ajouter quelques instructions au niveau du parent:
if(tmp!=0){// parent : attendre la fin de l'enfantif(*mot[i-1]=='&'){*mot[i-1]='\0';pid_tpid,pid1;intetat;if((pid1=fork())==0)exit(1);elseif((tmp)==0)sleep(2),exit(2);else{pid=waitpid(tmp,&etat,0);printf(" fils termine %d son etat %d \n",pid,etat);}}continue;}
En essayant quelques exemples sur le mini shell, j'ai ces résultats:
? echo essai1 &
essai1 &
fils termine 21473 son etat 0
? echo essai2 &
essai2 &
fils termine 21475 son etat 0
? echo essai3 &
essai3 &
fils termine 21480 son etat 0
Au vue des résultats, mes instructions sont-elles optimales surtout pour la gestion de plusieurs processus en arrière plan ? Aussi pourquoi en affichant l'echo, il affiche avec le symbole '&' à la fin ? C'est un peu désagréable, comment me débarrasser de cela ? Merci
" Pour le symbole "&", il faut penser à le supprimer de la ligne de commande avant d'appeler execv, le remplacer par un caractère espace est suffisant."
Qu'est ce que cela voudrait dire ? Sur ma ligne de commande je dois remplacer & par un espace de quelle manière ?
D'accord je comprends à peu près ce que tu veux dire.
Mais est ce possible d'etre plus explicite de façon concrète avec quelques modifications apportées au niveau de mon code ? sur l'appel du waitpid pour l'arrière plan.
Ca m'éclaircirait davantage. Merci
J'ai finalement résolu mon problème pour le programme moncd précédent merci pour les explications, elles m'ont servi de bcp pour la compréhension.
Par ailleurs, si j'ai un programme C qui a pour but d'exécuter le fonctionnement d'un mini shell comment pourrais je le modifier afin de rajouter la possibilité de lancer des processus en arrière-plan quand la ligne de commande se termine par un & ? L'indication est de ne pas faire le wait dans le parent.
Le but c'est de pouvoir faire un mini shell complet à partir de celui ci voilà pourquoi j'avais besoin de créer un programme moncd pour simuler le fonctionnement de cd.
Le programme est le suivant(il lit une ligne de commande, la découpe avec la fonction découper, fabrique un nouveau processus avec fork et tente d'y lancer la commande en allant chercher un fichier du même nom dans chacun des répertoires indiqué par PATH.):
# include <stdio.h># include <stdlib.h># include <unistd.h># include <sys/types.h># include <sys/wait.h># include <assert.h># include <string.h>enum{MaxLigne=1024,// longueur max d'une ligne de commandesMaxMot=MaxLigne/2,// nbre max de mot dans la ligneMaxDirs=100,// nbre max de repertoire dans PATHMaxPathLength=512,// longueur max d'un nom de fichier};voiddecouper(char*,char*,char**,int);# define PROMPT "? "intmain(intargc,char*argv[]){charligne[MaxLigne];charpathname[MaxPathLength];char*mot[MaxMot];char*dirs[MaxDirs];inti,tmp;/* Decouper PATH en repertoires */decouper(getenv("PATH"),":",dirs,MaxDirs);/* Lire et traiter chaque ligne de commande */for(printf(PROMPT);fgets(ligne,sizeofligne,stdin)!=0;printf(PROMPT)){decouper(ligne," \t\n",mot,MaxMot);for(i=0;mot[i]!=0;i++);if(mot[0]==0)// ligne videcontinue;tmp=fork();// lancer le processus enfantif(tmp<0){perror("fork");continue;}if(tmp!=0){// parent : attendre la fin de l'enfantwhile(wait(0)!=tmp);continue;}// enfant : exec du programmefor(i=0;dirs[i]!=0;i++){snprintf(pathname,sizeofpathname,"%s/%s",dirs[i],mot[0]);execv(pathname,mot);}// aucun exec n'a fonctionnefprintf(stderr,"%s: not found\n",mot[0]);exit(1);}printf("Bye\n");return0;}/* decouper -- decouper une chaine en mots */voiddecouper(char*ligne,char*separ,char*mot[],intmaxmot){inti;mot[0]=strtok(ligne,separ);for(i=1;mot[i-1]!=0;i++){if(i==maxmot){fprintf(stderr,"Erreur dans la fonction decouper: trop de mots\n");mot[i-1]=0;}mot[i]=strtok(NULL,separ);}}
J'ai pensé à introduire au niveau du parent l'instruction:
if(*mot[i-1]!='&')
Mais l'exécution me produit une erreur.
roger@roger-1005PX:~/Bureau$ gcc -g -Wall shell.c -o shell
roger@roger-1005PX:~/Bureau$ ./shell
? #notre mini shell
? echo essai #test avec echo
? essai
? sleep 10&#test arrière plan
sleep: intervalle de temps «&» incorrect.Saisissez « sleep --help » pour plus d'informations.
Merci pour ta réponse.
Donc l'une des solutions serait de faire une fonction C qui génère un nouveau shell pour l'exécuter avec le programme moncd ? C'est bien cela….
Merci pour la réponse. Donc si j'ai bien compris en gros la commande cd est une commande interne à mon shell.
Mais comment faire justement pour constater ce changement ?
Moi je n'arrive malheureusement pas à le constater.
Quand par exemple j'exécute j'ai ce résultat:
roger@roger-1005PX:~/Bureau$ gcc -g -Wall cp-moncd.c -o moncd
roger@roger-1005PX:~/Bureau$ ./moncd #exécution de la commande
roger@roger-1005PX:~/Bureau$_#prompt
Si elle fonctionne, comment dois-je faire pour constater ce fonctionnement ? Je dois modifier ma fonction en rajoutant la commande getcwd() à l'intérieur ? Si c'est bien cela, à quel niveau de la fonction je dois l'insérer. Si c'est possible d'avoir une illustration avec le code, ça faciliterait ma compréhension.
[^] # Re: exercice d'entrainement
Posté par roger91 . En réponse au message Commande if à écrire. Évalué à 1.
Oui chimrod je pense.
Je l'écrirai de la sorte:
./commandecrire
if [ $? -eq 0 ]; then
echo réussi
else
echo raté
fi
[^] # Re: exercice d'entrainement
Posté par roger91 . En réponse au message Commande if à écrire. Évalué à 1.
Bonjour BAud,
Merci pour ta réponse.
Justement le cours ne me dit rien par rapport à cela. Ce n'est pas un exercice du cours mais juste un exercice d’entraînement que je fais.
Comment faudrait il l'écrire ?
Merci
[^] # Re: Bonjour
Posté par roger91 . En réponse au message Traduction d'un programme C++ en C. Évalué à 2. Dernière modification le 30 décembre 2015 à 08:32.
Bonjour Marotte,
Mon problème se situe précisément au niveau de l'allocation dynamique pour le buffer que je n'arrive pas à traduire en C. Je cherche à le faire pour m'exercer. C'est l'exo qui me demande de l'écrire dans les deux langages. Ce que j'ai fait:
Merci !
# Exo résolu
Posté par roger91 . En réponse au message Affichage listes chainées en C. Évalué à 1.
Résolu !!
Merci pour l'aide ;)
[^] # Re: car et cdr avec # define
Posté par roger91 . En réponse au message Affichage listes chainées en C. Évalué à 1.
Erreur de ma part. Ce n'est pas car et cdr mais…
C'était plutot comment faire caar en fonction ou avec # define.
Comment tu l'écrirais la fonction caar (l'extraction du premier élément de la sous liste) ?
Merci
[^] # car et cdr avec # define
Posté par roger91 . En réponse au message Affichage listes chainées en C. Évalué à 1.
Salut lolop,
J'ai réussi à créer ma fonction cons(), car() et cdr() avec ce que tu m'a proposé et un main pour appelé ces fonctions afin d'afficher leur résultat.
Par ailleurs, comment procéder si je voudrais faire mon car et mon cdr à l'aide de # define et non des fonctions ?
Merci
[^] # Re: Retour papier
Posté par roger91 . En réponse au message Affichage listes chainées en C. Évalué à 1.
Merci lolop pour le retour.
La compilation passe plutot lorsque j'ai:
list dbl = malloc(sizeof(struct Doublet));
et je pense que c'est cela.
Tu pourras jeter un coup d'oeil là:
http://dept-info.labri.fr/~strandh/Teaching/MTP/Common/Strandh-Tutorial/list.html
Par contre comment pourrais je implémenter mon main pour réussir à compiler mon programme afin d'afficher une liste quelconque, son car ou son cdr ? C'est un peu un casse tete cet exercice en fin de compte.
Merci d'avance.
[^] # Re: Retour papier
Posté par roger91 . En réponse au message Affichage listes chainées en C. Évalué à 1.
Merci lolop, ça correspond parfaitement aux spécifications.
Mais il y a une ligne que je n'ai pas comprise dans ton code:
Double dbl = malloc(sizeof(struct Doublet)); //le Double est ce une erreur de ta part ? ou il correspond à quoi ? ce ne serai pas list à la place ?
Aussi si je voudrais plutot utiliser des #define à la place des fonctions pour le car et le cdr comment traduirais je cela ?
En gros ma fonction serait:
```
#define
#define
```Il manquerait un main pour finir afin de faire appel à cette fonction cons je pense …
Pour les sous listes justement l'exo d'après demande de definir à l'aide de #define, caar et cadr et construire une liste pour les tester et afficher leur résultat. Mais avant je dois parvenir à faire pour une liste simple.
[^] # Re: liste chainé bon exo
Posté par roger91 . En réponse au message Affichage listes chainées en C. Évalué à 0.
Tu m'as l'air de très bien maitriser les listes chainées en C. Ton code me donne une idée mais l'exercice demande:
Construire en C une liste L à quatre éléments dans le code du programme à l'aide de cons. Testez car(L), car(cdr(L), car(cdr(cdr L)), car(cdr(cdr(cdr L))), en affichant leur résultat.
Donc je dois suivre les spécifications et adapter par rapport à l'énoncé.
car(L) extrait le premier élément de notre liste L
car(cdr(L) extrait le deuxième
car(cdr(cdr L)) extrait le troisième
car(cdr(cdr(cdr L))) extrait le quatrième
Comme en Langage Lisp.
Voilà pourquoi je dois adapter ces spécifications et compléter ce qui m'a été donné comme indice et exemple pour pouvoir réussir à le faire.
Et ma difficulté se repose justement au niveau de cette adaptation avec ces indices données pour répondre au besoin de l'exercice.
[^] # Re: Retour papier
Posté par roger91 . En réponse au message Affichage listes chainées en C. Évalué à 1. Dernière modification le 23 décembre 2015 à 21:20.
Dans elt de ma structure Doublet,je stocke un pointeur.
J'aurai plutot:
typedef struct Doublet {void *elt;struct Doublet *cdr;} * list;
Pour car(doublet) si j'ai bien compris ta remarque, j'aurais donc:
Puis:
car et cdr c'est justement pour extraire respectivement le premier élément de ma liste et le reste de la liste comme en Lisp.
Et en parlant de libération de la mémoire tu fais allusion à free() je suppose.
Il y a t-il quelque chose qui m'aurait encore echappé ?
Et en ce qui concerne le main qui ferait appel à ma fonction pour l'affichage comment tu le verrais ?
Merci d'avance.
[^] # Re: backward....
Posté par roger91 . En réponse au message Un petit problème avec mon programme C. Évalué à 1.
Ok merci briaeros007. Par ailleurs comment pourrais je le traduire sous forme de code pour etre plus concret ? Si tu pourrais me donner un exemple ça m'aiderait.
Merci d'avance
[^] # Re: CSV
Posté par roger91 . En réponse au message Un petit problème avec mon programme C. Évalué à 1.
Justement, tu as tout juste Joalland. Pourrais tu me suggerer une solution ? ;)
[^] # Re: Séparateur
Posté par roger91 . En réponse au message Un petit problème avec mon programme C. Évalué à 0.
Dans mon cas, je ne cherche pas à généraliser. Ce n'est que le nom de la voie qui prévoit des espaces, déjà il faudrait que j'arrive à régler ce problème moins délicat que la généralisation.
[^] # Re: Séparateur strtok()
Posté par roger91 . En réponse au message Un petit problème avec mon programme C. Évalué à 1.
Merci pour ta réponse.
Justement j'avais pensé à strtok():
Adresse[n].num = strtok(ligne,"\t");
Adresse[n].voie = strtok(ligne,"\t");
Adresse[n].nomVoie = strtok(NULL,"\t");
Adresse[n].ville = strtok(NULL,"\t");
Adresse[n].codPostale = strtok(NULL,"\n");
Je l'ai inseré à la place du scanf pour parser chaque ligne mais malheureusement je sais pas ou ça bloque car l'affichage n'est pas du tout délicat.
Exemple de l'affichage:
Numéro : 75019
Voie : 75019
Nom de la voie :(null)
Ville :(null)
Code postale : (null)
Numéro : 75019
Voie : 75019
Nom de la voie :(null)
Ville :(null)
Code postale : (null)
…..
Si tu pourrais m'aider à corriger mon erreur.
Merci d'avance !!
[^] # Re: Fonction mini shell
Posté par roger91 . En réponse au message Commande qui ne fonctionne pas. Évalué à 1. Dernière modification le 03 décembre 2015 à 23:29.
Merci Corentin !
En tenant compte de tes suggestions, j'ai finalement pu ajouter quelques instructions au niveau du parent:
En essayant quelques exemples sur le mini shell, j'ai ces résultats:
Au vue des résultats, mes instructions sont-elles optimales surtout pour la gestion de plusieurs processus en arrière plan ? Aussi pourquoi en affichant l'echo, il affiche avec le symbole '&' à la fin ? C'est un peu désagréable, comment me débarrasser de cela ? Merci
[^] # Re: Fonction mini shell
Posté par roger91 . En réponse au message Commande qui ne fonctionne pas. Évalué à 1.
" Pour le symbole "&", il faut penser à le supprimer de la ligne de commande avant d'appeler execv, le remplacer par un caractère espace est suffisant."
Qu'est ce que cela voudrait dire ? Sur ma ligne de commande je dois remplacer & par un espace de quelle manière ?
[^] # Re: Fonction mini shell
Posté par roger91 . En réponse au message Commande qui ne fonctionne pas. Évalué à 1.
D'accord je comprends à peu près ce que tu veux dire.
Mais est ce possible d'etre plus explicite de façon concrète avec quelques modifications apportées au niveau de mon code ? sur l'appel du waitpid pour l'arrière plan.
Ca m'éclaircirait davantage. Merci
# Fonction mini shell
Posté par roger91 . En réponse au message Commande qui ne fonctionne pas. Évalué à 1. Dernière modification le 03 décembre 2015 à 23:31.
J'ai finalement résolu mon problème pour le programme moncd précédent merci pour les explications, elles m'ont servi de bcp pour la compréhension.
Par ailleurs, si j'ai un programme C qui a pour but d'exécuter le fonctionnement d'un mini shell comment pourrais je le modifier afin de rajouter la possibilité de lancer des processus en arrière-plan quand la ligne de commande se termine par un & ? L'indication est de ne pas faire le wait dans le parent.
Le but c'est de pouvoir faire un mini shell complet à partir de celui ci voilà pourquoi j'avais besoin de créer un programme moncd pour simuler le fonctionnement de cd.
Le programme est le suivant(il lit une ligne de commande, la découpe avec la fonction découper, fabrique un nouveau processus avec fork et tente d'y lancer la commande en allant chercher un fichier du même nom dans chacun des répertoires indiqué par PATH.):
J'ai pensé à introduire au niveau du parent l'instruction:
Mais l'exécution me produit une erreur.
Merci d'avance …
[^] # Re: ça marche
Posté par roger91 . En réponse au message Commande qui ne fonctionne pas. Évalué à 1.
Merci pour ta réponse.
Donc l'une des solutions serait de faire une fonction C qui génère un nouveau shell pour l'exécuter avec le programme moncd ? C'est bien cela….
[^] # Re: ça fonctionne
Posté par roger91 . En réponse au message Commande qui ne fonctionne pas. Évalué à 1. Dernière modification le 03 décembre 2015 à 23:30.
Merci pour la réponse. Donc si j'ai bien compris en gros la commande cd est une commande interne à mon shell.
Mais comment faire justement pour constater ce changement ?
Moi je n'arrive malheureusement pas à le constater.
Quand par exemple j'exécute j'ai ce résultat:
Si elle fonctionne, comment dois-je faire pour constater ce fonctionnement ? Je dois modifier ma fonction en rajoutant la commande getcwd() à l'intérieur ? Si c'est bien cela, à quel niveau de la fonction je dois l'insérer. Si c'est possible d'avoir une illustration avec le code, ça faciliterait ma compréhension.