2010-06-11 13 views
7

Qu'est-ce qui est considéré comme une bonne pratique lorsqu'on se réfère au nom d'un programme? Je l'ai vu:Meilleure pratique pour faire référence au nom d'un programme dans C

#define PROGRAM_NAME "myprog" 
printf("this is %s\n", PROGRAM_NAME); 

ainsi que:

printf("this is %s\n", argv[0]); 

Je sais que la deuxième approche me donnera ./myprog plutôt que myprog lorsque le programme est appelé de ne pas $PATH et que la première approche garantira la cohérence quant au nom du programme.

Mais y a-t-il autre chose qui rend une approche supérieure à l'autre?

+0

Si vous voulez une constante, utilisez une constante (c'est-à-dire au niveau global, 'const char * const PROGRAM_NAME =" myprog ";'). Cela garantira que la chaîne n'est stockée qu'une seule fois en mémoire. – mk12

Répondre

5

La deuxième approche est supérieure lorsque vous avez des liens multiples. Dans les systèmes * nix, le comportement dépend parfois de la façon dont vous appelez un programme. Donc coder dur le nom du programme serait clairement un problème - il ne pourrait jamais vérifier cela.

+0

qu'est-ce que cela signifie "le comportement dépend de la façon dont vous appelez un programme"? Je ne peux pas vraiment comprendre. – guest

+0

@guest: par exemple, 'gcc' et' g ++' pourraient être le même exécutable, qui vérifie le nom avec lequel il a été appelé et modifie les options de l'éditeur de liens en conséquence. Je ne me souviens pas si c'est effectivement ou non. –

+0

Exemple: par défaut, grep imprime les lignes correspondantes. De plus, trois programmes variants egrep, fgrep et rgrep sont disponibles. egrep est le même que grep -E. fgrep est le même que grep -F. rgrep est le même que grep -r. –

0

Le premier est supérieur au dernier lorsque vous n'avez pas argv à portée de main.

#define PROGRAM_NAME "myprog" 

void salute() 
{ 
    // no argv available 

    printf("Hello from %s\n", PROGRAM_NAME); 
} 

void main(int argc, char** argv) 
{ 
    salute(); 
} 
+0

cela fait-il une si grande différence? Je ne pense pas 'argc' et' argv' coûtent trop – guest

+0

ah. Je comprends ce que tu veux dire maintenant. oui, ça a du sens – guest

+1

Je comprends ce que vous voulez dire, mais dans votre exemple, vous créez une variable globale. Si vous avez besoin de nom_programme, passez le (argv) en paramètre à salute() et votre problème est résolu. – MJB

0

dépend si argv est portée ou non ...

5

J'ai essayé de prendre le meilleur des deux mondes:

char const * program_name; 

int main(int argc, char **argv) { 
    program_name = argv[0]; 
    //... 
} 

Si vous avez besoin program_name être disponible dans un autre fichier, vous pouvez le déclarer comme ceci:

extern char const * program_name; 

Je déclare « char const * "parce que je veux que ce soit un pointeur qui pointe vers les données const. Je ne suis pas sûr si j'ai bien fait cette partie.

+0

Pas mal.Sidesteps la question de ce qui est mieux en répondant "à la fois", mais pas mal. – MJB

1

La deuxième approche pourrait vous donner aussi des chaînes comme /usr/bin/myprog si vous l'avez exécuté de cette façon; basename devrait donner le nom de l'exécutable (que vous pourriez considérer comme le nom de votre programme) ... à moins qu'il ne soit symétrique ... (dans ce cas, vous avez le nom du lien ... qui pourrait être utilisé faire des choix quelconques dans le comportement du programme).

La première approche « fixe » le nom du programme à ce que le programmeur voulait, peu importe la façon dont l'utilisateur renommé le fichier exécutable ou un lien symbolique (ou même un lien fixe)

+0

Oui, j'ai utilisé des produits où il semble que vous ayez plusieurs exécutables, mais en réalité c'est seulement un avec plusieurs liens. Cela peut sembler fou, mais c'est un bon moyen de synchroniser plusieurs outils à travers plusieurs révisions. –

2

J'utilise habituellement argv[0] ou basename(argv[0]) si possible. À partir du POV de l'utilisateur, je pense que s'ils renomment ou exécutent un exécutable (ou que quelqu'un d'autre le fait pour eux), alors ils veulent que les messages apparaissent sous le nom qu'ils utilisent, et pas sous un autre nom. qu'ils peuvent ou ne peuvent pas savoir. De même, si vous découvrez à l'avenir que vous voulez compiler votre programme sous des noms différents avec des options différentes, vous voulez envelopper #ifndef autour de #define et assurez-vous qu'il est défini via la ligne de commande du compilateur : -DPROGRAM_NAME=myprog_demo, ou voulez-vous juste le faire et ça marche? L'exception pourrait être que si vos instructions d'utilisation sont extraites d'une page de manuel ou d'une autre documentation, alors vous voudrez peut-être connecter le nom du programme à cela. Mais alors vous n'utiliserez probablement pas le #define non plus.

Les implémentations ne doivent pas nécessairement fournir argv[0], donc, pour les meilleures pratiques portables, gérer également ce cas. Là encore, si votre système ne le fournit pas, il est probable que l'utilisateur ne verra pas non plus les messages sur n'importe quel terminal.

Soit dit en passant:

#define PROGRAM_NAME "myprog" 
puts("this is " PROGRAM_NAME); 
+0

'basename' n'est pas portable. C'est seulement requis par POSIX (dans libgen.h). De plus, gardez à l'esprit qu'il peut modifier la chaîne que vous lui donnez, et le pointeur retourné peut être un décalage par rapport au pointeur d'origine, ou une chaîne allouée statiquement (donc n'essayez pas de libérer ce qu'il vous donne, et don n'essayez pas de libérer ce que vous avez * donné * immédiatement après). Je l'éviterais à moins que vous ne soyez sûr à 100% que vous compreniez la gestion de la mémoire impliquée et que vous vous fiez à la portabilité. – mk12

+1

Par conséquent, "si possible". Mais vous avez raison de dire que 'basename (argv [0])' est lui-même une expression un peu douteuse, il suppose que vous ne prévoyez pas d'utiliser les arguments à nouveau. –

1

Il ne répond pas exactement à votre question pour les meilleures pratiques de programmation, mais je pense que vous devriez garder à l'esprit ce qui est mieux pour l'utilisateur. Personnellement, je préfère les programmes se référant à eux-mêmes en utilisant argv[0], c'est-à-dire la commande que j'appelais, et non un nom aléatoire que le codeur codé en dur dans le programme. Quelques exemples où un nom est ennuyeux hardcoded ou du moins utile:

  • J'ai créé un lien vers un programme
  • J'ai renommé le fichier binaire pour une raison quelconque
  • J'ai plusieurs executables avec les mêmes noms de base dans différents répertoires dans mon $PATH
  • Un programme me donne des indications sur d'autres façons de l'appeler, par exemple dans les messages "usage"

La seule situation où je préférerais un nom de programme codé en dur est lorsque j'utilise des applications graphiques. Je ne voudrais pas voir "~/foo/bar.pl" comme titre de fenêtre.