88

我想访问$HOME我正在编写的 C++ 程序中的环境变量。如果我用 C 编写代码,我只会使用该getenv()函数,但我想知道是否有更好的方法来做到这一点。这是我到目前为止的代码:

std::string get_env_var( std::string const & key ) {                                 
    char * val;                                                                        
    val = getenv( key.c_str() );                                                       
    std::string retval = "";                                                           
    if (val != NULL) {                                                                 
        retval = val;                                                                    
    }                                                                                  
    return retval;                                                                        
}           

我应该使用getenv()C++ 访问环境变量吗?有没有一些我可能遇到的问题,我可以通过一点知识来避免?

4

6 回答 6

78

getenv()在 C++ 中使用没有错。它由 定义stdlib.h,或者如果您更喜欢标准库实现,您可以通过命名空间(即)包含cstdlib和访问该函数。这绝对没有错。实际上,如果您关心可移植性,则首选这两个版本中的任何一个。std::std::getenv()

如果您关心可移植性并且正在使用托管 C++,则可以使用 .NET 等效项 - System::Environment::GetEnvironmentVariable(). 如果您想要 Windows 的非 .NET 等效项,您可以简单地使用GetEnvironmentVariable()Win32 函数。

于 2009-03-10T18:45:44.600 回答
35

我会稍微重构一下代码:

std::string getEnvVar( std::string const & key ) const
{
    char * val = getenv( key.c_str() );
    return val == NULL ? std::string("") : std::string(val);
}
于 2011-03-23T05:30:25.707 回答
20

为什么在 Windows 中使用 GetEnvironmentVariable,来自 MSDN getenv

getenv 仅对运行时库可访问的数据结构进行操作,而不对操作系统为进程创建的环境“段”进行操作。因此,对 main 或 wmain 使用 envp 参数的程序可能会检索到无效信息。

来自 MSDN GetEnvironment

此函数可以检索系统环境变量或用户环境变量。

于 2009-03-10T18:44:08.520 回答
11

在 c++ 中,您必须使用 std::getenv 和#include <cstdlib>

于 2009-03-10T18:39:45.800 回答
1

@Vlad's answer的一个版本,带有一些错误检查,可以区分空值和缺失值:

inline std::string get_env(const char* key) {
    if (key == nullptr) {
        throw std::invalid_argument("Null pointer passed as environment variable name");
    }
    if (*key == '\0') {
        throw std::invalid_argument("Value requested for the empty-name environment variable");
    }
    const char* ev_val = getenv(key);
    if (ev_val == nullptr) {
        throw std::runtime_error("Environment variable not defined");
    }
    return std::string(ev_val);
}

笔记:

  • 您还可以将上述异常的使用替换为std::optional<std::string>或者,在将来,替换为std::expected(如果最终被标准化)。
  • 我在这里选择了安全性而不是信息性,而不是将密钥连接到异常的字符串中。如果您做出替代选择,请尝试将复制限制key在合理范围内(例如 100 个字符?200 个字符?),我还会检查这些字符是否可打印,并清理这些字符。
于 2020-08-11T14:25:12.383 回答
1

是的,我知道这是一个旧线程!
尽管如此,根据定义,常见错误并不新鲜。:-)

我看到的不只是使用 std::getenv() 的唯一原因是添加已知默认值或在框架中采用通用模式/API 。在这种情况下,我也会避免异常(尽管通常不是这样),因为非值返回通常足以对环境变量进行有效响应。增加处理异常的复杂性是违反直觉的

这基本上是我使用的:

const char* GetEnv( const char* tag, const char* def=nullptr ) noexcept {
  const char* ret = std::getenv(tag);
  return ret ? ret : def; 
}
    
int main() {
  int ret=0;
  if( GetEnv("DEBUG_LOG") )  {
    // Setup debug-logging
  } else {
     ...
  }
  return (-1==ret?errno:0);
}

这个和其他答案之间的差异可能看起来很小,但我发现当你养成编码习惯时,这些小细节是非常有益的。

就像 getenv() 返回一个非常量指针一样,这很容易导致坏习惯!

于 2021-01-31T09:00:58.340 回答