Chemin absolu de l'application [Résolu]

Signaler
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
-
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
-
bonjour,

J'ai un problème sur l'ouverture d'un fichier :
j'ai un attribut de ma classe m_FileName = "data/test.txt"
Dans une méthode, je fais un myFile.Open(m_FileName.c_str(), ios::out | ios::trunc)
et ça ne marche pas. Apparemment, il y a un soucis sur le chemin du fichier, puisque quand je renomme le fichier en "test.txt" tout court, tout va bien...
Donc, existe-t-il un moyen de récupérer le chemin absolu de l'application de façon à le rajouter devant le nom de fichier ?

Merci d'avance


Simon

17 réponses

Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Oui, en effet, j'avais pas fait attention que tu étais sous linux...
Je ne m'y connais pas trop pour Linux mais il semblerait qu'il n'y ai pas d'équivalent direct: (Il faut utiliser argv[0])
http://www.gamedev.net/community/forums/topic.asp?topic_id=459511
A+


____________________________________________________________________________
Logiciel en traitement de l'image gratuit et open source.
Messages postés
3817
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
2 septembre 2020
112
Au temps pour moi, je n'avais pas fait attention !
Je regarde peu souvent cette partie de la page (elle n'est pas souvent respectée par ceux qui postent, j'ai appris à ne plus m'y fier).
Pour Boost, ton prof devrait en avoir une copie, tout simplement. Mais c'est un autre débat.

Pour répondre à ta question, le plus simple, et le plus rapide reste ceci:
#include 
#include <dirent.h>

int main()
{
  char buff[256] = {0};

  getcwd(buff, 256);

  std::cout << buff << std::endl;

  return 0;
}




_____________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
11
Pour Windows, mieux vaut mettre un ifdef et utiliser GetModuleFileName !

Désolé, j'ai attendu lundi pour avoir quelques OS sous la main.

La norme :
The value of argc shall be nonnegative. argv[argc] shall be a null pointer.
If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-de?ned values by the host environment prior to program startup. The intent is to supply to the program information determined prior to program startup from elsewhere in the hosted environment. If the host environment is not capable of supplying strings with letters in both uppercase and lowercase, the implementation shall ensure that the strings are received in lowercase.
If the value of argc is greater than zero, the string pointed to by argv[0] represents the program name; argv[0][0] shall be the null character if the program name is not available from the host environment. If the value of argc is greater than one, the strings pointed to by argv[1] through argv[argc-1] represent the program parameters.
The parameters argc and argv and the strings pointed to by the argv array shall be modi?able by the program, and retain their last-stored values between program startup and program termination.


Donc si argc <= 0, alors argv[0], n'est pas défini. Et "program name" ne veut pas dire grand chose...

Mais le fait est que les quelques unices que j'ai essayé semble relativement cohérent les uns par rapport aux autres !

Reste juste le problème du PATH :

prompt>cat test.c
#include <stdio.h>

int main(int argc, char** argv)
{
  puts(argv[0]);
  return 0;
}
prompt>mkdir sub
prompt>gcc test.c -o sub/test.exe
prompt>sub/test.exe
sub/test.exe
prompt>export PATH=sub:$PATH
prompt>test.exe
test.exe
prompt>


Le programme lancé trouve test.exe dans argv[0], pourtant getcwd/test.exe n'existe pas, le fichier étant dans getcwd/sub.

Il faut donc prendre en compte PATH en traitant les chemins dans l'ordre, et utiliser getcwd quand on tombe sur ".". Sachant qu'on peut tomber sur ce genre de truc : PATH=./sub., ou encore PATH=../dir/sub.

Bref, il doit y avoir moyen de s'en sortir, mais faut bien envisager tous les cas...
Messages postés
3817
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
2 septembre 2020
112
@rt15: Très bonne analyse, très rigoureuse :) Un petit détail tout de même: argc ne peut être < 1. Donc argv[0] existe toujours.
Si en crois les systèmes qui respectent la norme ANSI, argc > 0:
http://notabug.com/2002/coherent/man/argc.html

De plus, d'après Kernigan:
By convention, argc is greater than zero; the first s argument (in argv[0]) is the command name itself.

Source: http://www.lysator.liu.se/c/bwk-tutor.html

Ceci devrait faire ton bonheur (à part pour le problème du PATH):
#include 
#include <cstring>
#include <cstdlib>
#include <libgen.h>

int main(int, char** argv)
{
  std::string path(argv[0]);

  char* tmpCpy = strdup(path.c_str());
  std::cout << "Dirname of " << path << " => " << dirname(tmpCpy) << std::endl;
  free(tmpCpy);

  return 0;
}


(La copie est malheureusement nécessaire, vu que dirname modifie la chaîne. Une fonction à l'aide de substring serait préférable).
A noter tout de même que si le binaire est dans le path, on peut faire un which dessus ou un locate. Et le cas que présente simonpelloquin ne devrait pas poser ce problème.

La bonne manière de faire, reste d'avoir un fichier de conf généralement dans ~/.nom_du_prog, qui contient de façon sure, ce genre d'information.

Pour windows, en revanche, je ne sais pas.
_____________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Salut

C'est la fonction GetModuleFileName()

A+


____________________________________________________________________________
Logiciel en traitement de l'image gratuit et open source.
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
merci pour ta réponse et ta réactivité !

euh... je suppose que je dois ajouter un "include" ?
il semble que ce soit pour windows... et je suis sous linux
une autre idée ?


Simon
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
ok, merki, je vais fouiller

Simon
Messages postés
3817
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
2 septembre 2020
112
Si j'avais sur que c'était sous Unix, je t'aurais répondu :)

Alors, tu as: Boost::FileSystem: http://www.boost.org/doc/libs/1_42_0/libs/filesystem/doc/index.htm
Ou alors tu regardes dans unistd.h et dirent.h et tu va trouver tout plein de choses intéressantes, comme par exemple: getcwd: http://linux.die.net/man/3/getcwd

_____________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
eh eh, c'était marqué dans le type du forum :
Accueil > Forum > C++ & C++ .NET > Linux > Fichier & Disque > chemin absolu de l'application
Merci CptPingu, je prends note pour la prochaine fois. Malheureusement, pour ce projet, nous avons pris la décision de ne pas utiliser boost. On doit envoyer les sources au prof et comme je n'ai pas trouvé comment ne pas lui envoyer la myriade de fichiers de cette bibliothèque (ça pourrait le saouler) ...

Simon
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
NICKEL !!!

merci beaucoup !

Simon
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
question subsidiaire : (comme tu m'as l'air assez calé !)

connais-tu une fonction équivalente au ExtractFilePath() de Delphi ? (qui retourne la partie répertoire d'un nom de fichier)

Après je t'embete plus (c'est le week end, quand même)

Simon
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
parce que si je lance mon prog par bin/monprog et bien le chemin ne tient pas compte du bin/
apparemment, getcwd retourne le répertoire de lancement de l'appli et non là ou elle se trouve...

Simon
Messages postés
3817
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
2 septembre 2020
112
Absolument. getcwd récupère le chemin courant.
Pour avoir le nom et l'emplacement de l'exécutable, il faut se servir de argv[0].
Pour "ExtractFilePath", il suffit de faire un substring entre 0 et lastIndexOf('/'); (Voir classe String).
Ou alors regarde du côté de "dirname" et "basename".

_____________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
11
Salut,

connais-tu une fonction équivalente au ExtractFilePath()

Même si une fonction standard est souvent à privilégier pour gérer les cas tordus, cette fonction là n'est pas trop dur à recoder.

Concernant le chemin de l'exe et non le dossier courant, tu peux faire un readlink de /proc/self/exe. Mais ça ne fonctionnera que sous Linux.
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
11
Post croisé avec CptPingu...
argv[0] est plus portable mais plus risqué car il peut contenir un peu n'importe quoi et surtout juste le nom de l'exécutable sans le chemin. Déduire ensuite le chemin complet avec le PATH ou un which est aussi hasardeux...
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
Merci beaucoup pour vos réponses pleines de bon sens.

Effectivement, la fonction extractfilepath n'a pas l'air trop dur à recoder, mais si on peut éviter de "réinventer la roue", mieux vaut ne pas s'en priver...

@rt15 : Pourquoi est-ce hasardeux ? Apparemment, le argv[0] contient bien le nom de l'appli si je l'appelle directement dans son répertoire, et présente bien le chemin complet si je l'appelle depuis "home" par exemple. Il me semble qu'en combinant le getcwd et un "ExtractFilePath(argv[0])", j'arrive bien à ce que je recherche. As-tu un exemple pour lequel ça peut planter ? (humm, sous windows peut être ? )

Simon
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
13
waouh !
Merci beaucoup !

Simon