C++ C程序,打印其可执行文件名

C++ C程序,打印其可执行文件名,c++,c,C++,C,假设源代码文件名为test.cpp。编译时,它会生成test.exe文件。当我执行它时,它应该识别它的文件名,即test.exe,并打印它 我可以使用以下代码获取当前目录中存在的所有文件和目录的列表: DIR * directory; struct dirent * direct; direct = readdir(directory); 但是,如何识别关联的文件名,在本例中是“test.exe”?在主函数中,argv[0]是命令行中可执行文件的名称 #include <stdio.h&

假设源代码文件名为
test.cpp
。编译时,它会生成
test.exe
文件。当我执行它时,它应该识别它的文件名,即
test.exe
,并打印它

我可以使用以下代码获取当前目录中存在的所有文件和目录的列表:

DIR * directory;
struct dirent * direct;
direct = readdir(directory);

但是,如何识别关联的文件名,在本例中是
“test.exe”

在主函数中,
argv[0]
是命令行中可执行文件的名称

#include <stdio.h>
int main(int argc, char ** argv)
{
    printf("%s", argv[0]);
    return 0;
}
#包括
int main(int argc,字符**argv)
{
printf(“%s”,argv[0]);
返回0;
}

这将打印命令名,即相对于当前工作目录的目录,以及可执行文件名(如果可用,则不保证) 要获取当前工作目录,请使用
getcwd()
标准库C函数

argv[0]
中的命令路径提取文件名是特定于平台的:unix使用斜杠“
/
”,windows允许斜杠
/
和反斜杠
\
混合使用,任何其他平台都可以使用任何其他路径分隔符。从路径中提取文件名需要跨平台库,如Qt或Boost。在POSIX环境上,可以使用basename

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("%s\n", argv[0]);
    return 0;
}
在这种情况下,您可以使用
strrchr
获取名称:

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char *appname;

    appname = strrchr(argv[0], '/'); /* '\\' on Windows */
    printf("%s\n", appname ? ++appname : argv[0]);
    return 0;
}
#包括
#包括
int main(int argc,char*argv[])
{
char*appname;
appname=strrchr(argv[0],“/”);/*“\\”在Windows上*/
printf(“%s\n”,appname?++appname:argv[0]);
返回0;
}

在构建可执行文件时,您知道该文件的名称;这个 最简单的解决方案是使用
-D
/D
选项在命令行上定义宏

除此之外,一般的答案是不可能:

按照标准
  • argv[0]
    应包含用于调用 程序(无论这意味着什么)。这很好,但一点也不公平 可在Unix下实现,2)在大多数系统下,有各种 别名的定义,这意味着用于调用程序的名称 与可执行文件的名称没有关系
窗下
  • 有一个系统函数
    GetModuleFileName
    ,可用于 获取可执行文件的路径。一旦你找到了路,最后一个 路径的元素是可执行文件的名称
在Unix下
  • 这根本不可能。启动新进程时,Unix 为可执行文件的路径和执行的内容提供单独的参数 在argv[0]中结束,因此它们可能与 彼此这完全取决于谁开始了你的过程<代码>bash将 将可执行文件的完整路径放入环境变量
    “\uquot
    , 因此,您可以使用
    getenv
    获取它。但只有当你的程序 由
    bash
    启动。在大多数Unice上,您也可以在
    /proc
    文件系统,如果你知道你的方法;但是 不同Unix的组织结构各不相同。还要注意 由于硬链接,您的可执行文件可能不止一个 名字
真正的问题是你为什么要这样做。你有什么问题
在Linux系统中,我认为您也可以使用, 请尝试
$man basename

删除任何前导目录组件后打印名称。如果指定,还应删除尾随后缀

我试着这样做:

// filename.c
#include<stdio.h>
#include<stdlib.h>
#include<libgen.h>
int main(int argc, char* argv[]){
    char* exe_name = basename(argv[0]);
    printf(" Executable Name: %s", exe_name);
    printf("\n");
    return EXIT_SUCCESS;
}
现在在当前目录中运行它:

taxspanner@:~$ ./filename 
 Executable Name: filename
使用绝对路径:

taxspanner@:~$ pwd
/home/taxspanner
taxspanner@:~$ /home/taxspanner/filename 
 Executable Name: filename
相对路径:

taxspanner@:~$ cd study/divide-5/
taxspanner@:~/study/divide-5$ pwd
/home/taxspanner/study/divide-5
taxspanner@:~/study/divide-5$ ls ../../filename*
../../filename  ../../filename.c
taxspanner@:~/study/divide-5$ ../../filename
 Executable Name: filename
taxspanner@:~/study/divide-5$ 
再次尝试使用带后缀的可执行文件名:

taxspanner@:~$ gcc -std=gnu99 -Wall -pedantic filename.c -o filename.out
taxspanner@:~$ ./filename.out 
 Executable Name: filename.out
taxspanner@:~$ cd study/divide-5/
taxspanner@:~/study/divide-5$ ../../filename.out 
 Executable Name: filename.out
:无论是
dirname()
还是
basename()
都可能修改path的内容,因此在调用其中一个函数时可能需要传递一个副本

试试看

特别是在Linux上: 您可以使用和
/proc/self/exe
符号链接,因此请在上面使用。一旦您这样做了,您就可以在获得的符号链接上使用或

但是,请注意,程序可能并不总是具有文件路径。它可能有多个文件路径(例如,
/bin/rbash
是指向
/bin/bash
的符号链接,当作为
rbash
bash
调用时,shell进程的行为不同)。有时一个给定的文件(实际上是一个,请参见)有几个硬链接指向它。在奇怪的情况下,根本没有。 可能会发生这样的情况:一个程序被-ed,然后被删除(可能是从计划在您之前运行的另一个进程中删除),等等

(顺便说一句,您的问题是特定于操作系统的;是POSIX还是有些操作系统甚至没有目录,标准中没有提到
readdir
;请通过阅读进行检查)

我尝试了以下(病理学)
/selfremove
程序(在我的
/home/basile/tmp/
目录中),该程序删除了自己的二进制文件:

 // file selfremove.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>

 int
 main (int argc, char **argv)
 {
   char selfpath[128];
   memset (selfpath, 0, sizeof (selfpath));
   if (readlink ("/proc/self/exe", selfpath, sizeof (selfpath) - 1) < 0)
     {
       perror ("first readlink");
       exit (EXIT_FAILURE);
     };
   printf ("initial /proc/self/exe -> %s\n", selfpath);
   if (unlink (argv[0]))
     {
       fprintf (stderr, "unlink %s: %m\n", argv[0]);
       exit (EXIT_FAILURE);
     };
   printf ("%s unlinked\n", argv[0]);
   if (readlink ("/proc/self/exe", selfpath, sizeof (selfpath) - 1) < 0)
     {
       perror ("second readlink");
       exit (EXIT_FAILURE);
     };
   printf ("final /proc/self/exe -> %s\n", selfpath);
   return 0;
 }    
因此,即使使用
/proc/self/exe
,您也无法始终相信结果

如果您假设您的程序已经被某个shell(或类似的程序)编译过,但情况并非总是如此,那么可能已经使用了(如果没有
/
,则从
argv[0]
)。您可以使用as
getenv(“PATH”)
从您的环境中获取它(有关更多信息,请参阅)。通常设置并使用
$PATH
,但它们也是病理病例

因此,一般来说,无法可靠地打印它自己的可执行文件(正如我的
selfremove.c
演示的那样)。在大多数情况下,您可以找到它(例如,通过
/proc/self/exe的
readlink
,或者使用
argv[0]
$PATH
中搜索)。

为什么您的C源代码
taxspanner@:~$ gcc -std=gnu99 -Wall -pedantic filename.c -o filename.out
taxspanner@:~$ ./filename.out 
 Executable Name: filename.out
taxspanner@:~$ cd study/divide-5/
taxspanner@:~/study/divide-5$ ../../filename.out 
 Executable Name: filename.out
 // file selfremove.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>

 int
 main (int argc, char **argv)
 {
   char selfpath[128];
   memset (selfpath, 0, sizeof (selfpath));
   if (readlink ("/proc/self/exe", selfpath, sizeof (selfpath) - 1) < 0)
     {
       perror ("first readlink");
       exit (EXIT_FAILURE);
     };
   printf ("initial /proc/self/exe -> %s\n", selfpath);
   if (unlink (argv[0]))
     {
       fprintf (stderr, "unlink %s: %m\n", argv[0]);
       exit (EXIT_FAILURE);
     };
   printf ("%s unlinked\n", argv[0]);
   if (readlink ("/proc/self/exe", selfpath, sizeof (selfpath) - 1) < 0)
     {
       perror ("second readlink");
       exit (EXIT_FAILURE);
     };
   printf ("final /proc/self/exe -> %s\n", selfpath);
   return 0;
 }    
 % ./selfremove 
 initial /proc/self/exe -> /home/basile/tmp/selfremove
 ./selfremove unlinked
 final /proc/self/exe -> /home/basile/tmp/selfremove (deleted)