在C ++中访问环境变量

时间:2009-03-10 18:31:47

标签: c++ environment-variables

我想在我正在编写的C ++程序中访问$HOME环境变量。如果我用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 ++中的环境变量吗?是否有任何我可能遇到的问题,我可以通过一些知识来避免这些问题?

6 个答案:

答案 0 :(得分:59)

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

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

答案 1 :(得分:21)

我会稍微重构一下代码:

std::string getEnvVar( std::string const & key ) const
{
    char * val = getenv( key.c_str() );
    return val == NULL ? std::string("") : std::string(val);
}

答案 2 :(得分:17)

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

  

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

from MSDN GetEnvironment

  

此功能可以检索a   系统环境变量或用户   环境变量。

答案 3 :(得分:10)

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

答案 4 :(得分:1)

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

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>替换上面对异常的使用,或者将来用examples替换例外(如果最终被标准化)。
  • 在这里,我选择了安全性而非信息性,因为它没有将密钥连接到异常的what-string中。如果您选择其他方法,请尝试限制从key到合理范围内的复制(例如100个字符?200个字符?),我还要检查这些字符是否可打印,以及std::expected这些字符。

答案 5 :(得分: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() 返回一个非常量 指针一样,这很容易导致坏习惯!