有很多方法可以解决这个问题,但关键归结为使用getenv 获取所需的基本目录。它适用于windows和unix。您只需检查并找到每个操作系统下所需的环境变量的正确名称。
例如,要从用户主目录开始构建路径,您可以在 Linux 上使用环境变量 HOME 或在 Windows 上使用 USERPROFILE。
要将您的代码设置为自动使用适当的目录,您通常会使用预处理器检查来检查操作系统,然后设置一个定义来识别操作系统以在您的代码的其余部分中使用。 (您当然可以反复使用相同的测试,但标准做法只是为操作系统定义一个标识符,例如 Windows 上的 HAVEWIN 或各种 Unix 风格上的 HAVEUNIX。
我通常将它分成两部分,但您可以一次完成所有操作,例如
#if defined (_WIN32) || defined (_WIN64)
#define HAVEWIN 1
#elif defined (__unix__)
#define HAVEUNIX 1
#endif
#ifdef HAVEWIN
#define HOMEENV "USERPROFILE"
#elif HAVEUNIX
#define HOMEENV "HOME"
#endif
对于您的路径名分隔符,Windows 将允许您使用 POSIX 路径名分隔符 '/' 来分隔您的路径组件,但是当路径包含 spaces 时它会变得很挑剔(技术术语) .在这种情况下,使用正常的 DOS 反斜杠(在构建路径时必须将其转义),Windows 路径名解析会表现得更好。
例如,假设我们对驻留在用户主目录中的 Windows 和 Linux 上名为 testfile.txt 的文件感兴趣(例如,Windows 上的 C:\Users\username 和 Linux 上的 /home/username),例如
在微风中:
C:\users\david>type testfile.txt
hello windows
在 Linux 上:
$ cat ~/testfile.txt
hello unix
您可以使用sprintf 和足以容纳组件的缓冲区来构建到达每个组件的路径。 #include <limits.h> 提供了一个 PATH_MAX 常量以确保您有足够的空间用于文件名(通常是 4096 字符)。要构建路径,您可以执行以下操作:
#include <limits.h>
...
int main (void) {
char *home = getenv (HOMEENV);
char filename[PATH_MAX] = "";
char buf[BUFSIZ] = "";
FILE *fp;
if (!home) {
fprintf (stderr, "user home environment not found.\n");
return 1;
}
#ifdef HAVEWIN
sprintf (filename, "%s\\%s", home, FILENAME);
#elif HAVEUNIX
sprintf (filename, "%s/%s", home, FILENAME);
#endif
...
这几乎提供了(简而言之)您尝试对输入和输出文件执行的操作的基础知识。将所有部分放在一起,您可以执行以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define FILENAME "testfile.txt"
#if defined (_WIN32) || defined (_WIN64)
#define HAVEWIN 1
#elif defined (__unix__)
#define HAVEUNIX 1
#endif
#ifdef HAVEWIN
#define HOMEENV "USERPROFILE"
#elif HAVEUNIX
#define HOMEENV "HOME"
#endif
int main (void) {
char *home = getenv (HOMEENV);
char filename[PATH_MAX] = "";
char buf[BUFSIZ] = "";
FILE *fp;
if (!home) {
fprintf (stderr, "user home environment not found.\n");
return 1;
}
#ifdef HAVEWIN
sprintf (filename, "%s\\%s", home, FILENAME);
#elif HAVEUNIX
sprintf (filename, "%s/%s", home, FILENAME);
#endif
if (!(fp = fopen (filename, "r"))) {
fprintf (stderr, "error: file not found '%s'\n", filename);
return 1;
}
if (fgets (buf, sizeof buf, fp))
puts (buf);
return 0;
}
使用/输出示例
在微风中:
C:\users\david>Documents\src-c\bin\getenv_testfile.exe
hello windows
在 Linux 上:
$ ./src-c/bin/getenv_testfile
hello unix
如开头所述,有多种方法可以将所有部分组合在一起。您可能会发现将所有不同的 windows/unix 定义放在顶部会更干净,这样您在main() 中就没有任何预处理器条件,例如
...
#ifdef HAVEWIN
#define HOMEENV "USERPROFILE"
#define PATHFMT "%s\\%s"
#elif HAVEUNIX
#define HOMEENV "HOME"
#define PATHFMT "%s/%s"
#endif
int main (void) {
char *home = getenv (HOMEENV);
char filename[PATH_MAX] = "";
char buf[BUFSIZ] = "";
FILE *fp;
if (!home) {
fprintf (stderr, "user home environment not found.\n");
return 1;
}
sprintf (filename, PATHFMT, home, FILENAME);
if (!(fp = fopen (filename, "r"))) {
fprintf (stderr, "error: file not found '%s'\n", filename);
return 1;
}
if (fgets (buf, sizeof buf, fp))
puts (buf);
return 0;
}
(注意:虽然这看起来有点干净,但在较大的代码中这在很大程度上是不切实际的)
查看所有答案和 cmets,如果您有任何其他问题,请告诉我。