Rien de standard n'est garanti donner un chemin absolu.
Mais sous Windows, tu peux utiliser GetModuleFileName() pour ça.
Version imprimable
Rien de standard n'est garanti donner un chemin absolu.
Mais sous Windows, tu peux utiliser GetModuleFileName() pour ça.
C'est à dire que sous windows, je n'ai pas ce problème là. Je suis toujours dans le bon dossier. Et donc les programmes ne traitent que des chemins relatifs.
Tandis que là je dois spécifier explicitement le dossier dans lequel il doit travailler.
Il n'existe pas un équivalent à pwd?
Car utiliser directement pwd serais très lourd, puisque je devrais rediriger la sortie dans un fichier avant de pouvoir l'exploiter.
Merci souviron34, c'est effectivement le genre "d'équivalent" à PWD que je cherchais ;)
En ajoutantJ'obtiens bien le chemin absolu, c'est parfais.Code:char *pwd = getenv("PWD");
Juste un détail, c'est PWD et non $PWD, sous risque de se retrouver avec un (NULL).
Je vais, dés ce soir, coder une fonction pour englober l'ensemble de l'exécution sous xterm. Que je vous soumettrais. Ce sera, de plus, sans nul doute utile à ceux qui me reliront.
Merci à tous.
Le coup du getenv c'est un peu crade quand même. Sur les systèmes POSIX il y a la fonction getcwd() qui retourne le répertoire courant.
Celà dit connaitre le répertoire courant ne règle pas ton problème. Pour peu que ton programme soit dans le PATH de l'utilisateur, il peut tout à fait le lancer d'un autre répertoire que le répertoire où se trouve le programme.
Le répertoire courant est par définition le répertoire d'où il a été lancé.
Mon problème, c'est que je n'arrive pas à comprendre le problème que tu cherches à résoudre -- le modèle d'Unix t'est étranger, mais tes hypothèses me le sont aussi. Pour commencer, pourquoi est-ce que ton programme ne pourrait pas être lancé avec les entrées et sorties standards redirigées vers des fichiers?
Comme je le précisais plus en avant dans cette discussion. Ces programmes, le plus souvent, attendent une saisie de la part de l'utilisateur. De ce fait, l'utilisateur doit se trouver derrière son clavier pour y répondre. Ce qui exclut dans ce cas de rediriger la sortie vers un fichier. D'une part, l'utilisateur ne peut répondre si il ne peut lire ce qu'on lui demande. Et d'autre part le programme attendra la saisie de l'utilisateur pour avancer.
Certains de ces programmes pourrait être appelé en ligne de commande car les demandes sont simple (par exemple le chemin d'un fichier à traiter). Ceux-ci peuvent être au choix démarré au "double-clic" puis en notant le chemin. Ou alors lancé en ligne de commande avec le chemin en argument. Dans ce dernier cas, le résultat est automatiquement redirigé vers un fichier.
En clair, de manière générale les programmes ne fonctionneraient pas si on redirigeait leur sortie vers un fichier. Et ceux pour lesquels ce serait intéressant de le faire le font déjà d'eux-même.
Si ces programmes utilisent un terminal, c'est uniquement parce que la création d'une interface graphique est bien loin dans la liste de mes préoccupations.
J'espère avoir répondu à ta question. Je reste à ta disposition pour d'autres éclaircissements.
Voilà donc ma fonction pour l'exécution sous xterm qui fonctionne... à moitié...
Le code fonctionne parfaitement lorsque le programme est démarré depuis la konsole (en faisant sauté if(!isatty(1)) évidemment), le pwd est correct et l'affichage se fait dans une fenêtre xterm.Code:
1
2
3
4
5
6
7
8
9
10
11
12 void startxterm (char *argv0) { char *pwd = getenv("PWD"); //pwd prend le chemin absolu de l'exécutable char prog[4096]; int i; if(!isatty(1)) { argv0 = strrchr(argv0,'/'); //Efface jusqu'au dernier /, afin de ne garder que /fichier, sans le chemin sprintf(prog,"cd %s && .%s",pwd,argv0); execl("/usr/bin/xterm","/usr/bin/xterm","-e",prog,NULL); } }
Par contre, lorsque je le démarre en "double-clic", le fenêtre xterm se referme immédiatement. En regardant rapidement, le pwd donne encore une fois /home/maniack au lieu de /home/maniack/Bureau/FTP
Pourtant le programme démarre bien du bon dossier, je comprends donc pas l'erreur.
J'ai testé aussi avec getcwd, mais le résultat est le même :?.
Pour faire marcher ton truc il ne faut pas que tu jettes le chemin d'argv0, comme tu le fais avec strrchr(). Ce que tu dois faire c'est regarder si argv0 commence par un '/'. Si c'est le cas, tu l'exécutes directement car c'est un chemin absolu. Sinon, tu colles devant le répertoire courant retourné par getcwd(), de façon à transformer le chemin relatif en chemin absolu.
Ca règlera ton problème, mais encore une fois ça ne marchera jamais dans tous les cas (si ton programme est lancé via le PATH). Un programme n'a aucun moyen de connaitre avec certitude l'emplacement de son propre binaire.
J'ai modifier la fonction comme suit:
Et effectivement tu avais raison, ça fonctionne sans problème. Que ce soit depuis la konsole ou au "double-clic". Par contre, en faisant sauter le cd je perd le dossier courant une fois dans le programme. Mais ce n'est qu'une question de manipulation de chaine.Code:
1
2
3
4
5
6
7 if(argv0[0] != '/') { argv0 = strrchr(argv0,'/'); //Efface jusqu'au dernier /, afin de ne garder que /fichier, sans le chemin sprintf(prog,"%s%s",pwd,argv0); } else sprintf(prog,"%s",argv0);
Concernant l'exécution via le PATH, comme précisé précédemment le programme n'a pas pour vocation d'être exécuter via le PATH. De plus son environnement est essentiel (un bon millier de fichiers gravitent autours des exécutables). Donc je dirais simplement qu'il ne devra pas être exécuté via le PATH.
Enlève ce argv0 = strrchr(argv0,'/'), c'est incorrect. Il faut coller le argv0 complet derrière le répertoire courant.
J'ai hésité à le retirer. Mais le garder est simplement une sécurité.
Si je me retrouve avec ./programme, il est inutile en effet puisque qu'il supprime seulement le . qui sera rajouté ensuite par sprintf. (dans le cas de sprintf(prog,"cd %s; .%s",pwd,argv0); que je suis justement en train de replacer.)
Mais je n'ai pas la certitude (à titre personnel) que j'aurais soit le chemin complet soit ./programme.
C'est comme un doudou, c'est juste pour me rassurer :D!
Mais je pense qu'il n'altère pas le code?
Cela étant dit, en revenant au fonctionnement avec cd, je serais obligé de découper argv0 pour avoir le chemin et l'exécutable (pwd et argv0). Donc je me trouve obligé d'utiliser ce strrchr.
A moins que je ne fasse erreur.
Enfin je pense avoir une fonction qui marche sans problème, qui exécute dans un xterm seulement si le programme n'est pas démarré depuis le terminal. Et qui se trouve, lors de l'exécution dans le bon dossier.
Voila mon code:
Pour clarifier la fonction, je précise que la fonction index_ch est une fonction de mon cru qui stocke dans un tableau (ici int tab[50]; ) l'emplacement de toutes les occurrences de "/" trouvées dans pwd et renvoi le nombre d'occurrences trouvées.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> void startxterm (char *argv0); void startxterm (char *argv0) { char pwd[4096]; char prog[4096]; int tab[50]; if(!isatty(1)) { if(argv0[0] == '/') { strcpy(pwd,argv0); pwd[tab[index_ch(pwd,"/",tab)-1]] = '\0'; //Termine la chaine au dernier / } else getcwd(pwd,4096); //pwd prend le chemin absolu de l'exécutable argv0 = strrchr(argv0,'/'); //Efface jusqu'au dernier /, afin de ne garder que /fichier, sans le chemin sprintf(prog,"cd %s; .%s",pwd,argv0); execl("/usr/bin/xterm","/usr/bin/xterm","-e",prog,NULL); } }
Ici donc, tab[index_ch(pwd,"/",tab)-1] correspond à l'emplacement du dernier / trouvé dans pwd.
La fonction en elle-même semble à présent correcte. Mais je suis confronté à un nouveau problème, très souvent soulevé. C'est le problème de l'affichage des accents.
J'ai parcouru le forum, il y a plusieurs solutions mais aucune qui semble convenir à mon contexte. J'ai parcouru également le man de xterm et essayer les arguments -lc, -u8 et -8 mais aucun ne fonctionne.
Y a-t-il un moyen de spécifier une police ou un codage qui prend en compte les accents sur xterm?
Bonjour,
je me permet un pti UP
Es-ce que tous les codeurs ici, sortant sur un terminal, se privent des accents???
J'en profite pour poster également une nouvelle version de la fonction.
J'y ai ajouté un équivalent de start sous dos. C'est à dire que le programme peut être démarré dans une nouvelle fenêtre xterm (même si il se trouve déjà dans un terminal).
Et, plus intéressant, la prise en charge des arguments du programme lors de l'exécution de execl.
Pour l'exécution dans une autre fenêtre, il faut donner en premier argument au programme le terme swxterm. Ce dernier sera ensuite ignoré lors de l'appel de execl.
Soit: ./programme swxterm arg1 arg2 arg3 etc &
Tout ceci peut en intéresser d'autre.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 void startxterm (int argc,char *argv[]) { char pwd[4096]; char prog[4096]; char args[2048] = "\0"; int tab[50]; int sw=1; if(argv[1] != NULL) sw = strcmp(argv[1],"swxterm"); if(!isatty(1) || !sw) { if(argv[0][0] == '/') { strcpy(pwd,argv[0]); pwd[tab[index_ch(pwd,"/",tab)-1]] = '\0'; //Termine la chaine au dernier / } else getcwd(pwd,4096); //pwd prend le chemin absolu de l'exécutable argv[0] = strrchr(argv[0],'/'); //Efface jusqu'au dernier /, afin de ne garder que /fichier, sans le chemin if(argc > 1) //Seulement si plus d'un arg { if(argc == 2 && !sw) {/*2 arguments, mais le second est swxterm. Hors ce dernier ne doit pas être renvoyé au programme*/} else { //Prépare la construction de la chaine des arguments if(!sw) //argv[1] = swxterm, donc ignorer le premier argument sw=2; //La copie commencera au 3e arg, après swxterm. Sinon, sw=1, donc il commencera au 2e arg. strcpy(args,argv[sw++]); //Copie du premier argument for(;sw<argc;sw++) { strcat(args," "); //Ajoute un espace à la chaine des arguments strcat(args,argv[sw]); //Puis l'argument suivant } } } sprintf(prog,"cd \"%s\"; \".%s\" %s",pwd,argv[0],args); execl("/usr/bin/xterm","/usr/bin/xterm","-e",prog,NULL); } }
Non, on en met, mais ça soulève l'épineux problème du jeu de caractères utilisé et de son codage. En gros, chez nous, ISO-8859-15 ou UTF-8 ?
La tendance est désormais à l'UTF-8 mais ce n'est pas sans causer quelques soucis. D'une part, la longueur des caractères accentués est différente de celle des caractères normaux et, d'autre part, ça implique de recompiler l'application quand on veut l'intégrer à un système qui utilise l'ISO-8859, et vice-versa.
On va dire que pour tout ce qui est « messages à l'utilisateur », purement informatifs, on écrit en bon français, et dès que la sortie contient un minimum de données, on essaie de s'en tenir à l'ASCII de base. À noter que les données ne résident pas forcément dans le code du caractère. La longueur d'une ligne, par exemple, peut avoir de l'importance et il est important, dans ce cas, que cette longueur soit constante dans tous les cas de figure.
Merci de ta réponse Obsidian.
Quand tu parles de longueur de caractère, tu veux parler de longueur sur l'affichage? Ou de code ascii complexe sur 2 valeurs?
Si c'est un problème d'affichage, cela reste négligeable dans mon cas de figure.
Et comment spécifier le codage à utiliser?Citation:
Envoyé par Obsidian
Est-il possible de changer le codage de manière dynamique. Afficher une chaine avec un codage et une autre avec un autre codage?
J'avais essayer un codage UTF-8 avec xterm, en argument de ce dernier. Mais le résultat n'était pas convainquant...
De la longueur du code, sur plusieurs octets, oui.
C'est là que le bas blesse, selon les cas : il n'y a rien de spécial à préciser au niveau de ton code C. Si tu as passé tes chaînes, dans ton programme, en clair et encadrées par des guillemets (la manière normale de le faire, donc), elle sera compilée comme telle et la fonction restituera les caractères jusqu'au '\0'. C'est donc le codage de l'éditeur de texte que tu auras utilisé pour composer ton programme qui fera foi ... et tu ne sais pas a priori dans quel type de console ou terminal l'affichage aura lieu à l'exécution.Citation:
Et comment spécifier le codage à utiliser?
Est-il possible de changer le codage de manière dynamique. Afficher une chaine avec un codage et une autre avec un autre codage?
Tout mes programmes sont écrit et compilé avec Code:block, et je peux imaginer que le programme sera forcément exécuté dans un xterm!
Mais du coup, j'ai la certitude que le codage n'est pas le bon...
Mais qu'en est-il des fonctions comme mbstowcs?
J'ai essayer de l'utiliser,
Mais l'affichage est vide.Code:
1
2
3
4
5 char chaine[255] = "test d'affichage avec des accents éèçàùê etc"; wchar_t chaine_mod[512]; taille = strlen(chaine); mbstowcs(chaine_mod,chaine,taille); wprintf(chaine_mod);
Mon exploitation est-elle incorrect?
D'autres fonctions (Y'en a tout un tas dans le même genre) serait-elle plus efficace?