【问题标题】:setenv, and getenv documentationsetenv 和 getenv 文档
【发布时间】:2015-08-26 15:09:06
【问题描述】:

我知道这对于假设在堆栈溢出上发布的内容有点偏离主题,但我想知道这些示例是否做得很好。

setenv:

man page - setenv

包括: #include <stdlib.h>

声明: int setenv(const char *v_name, const char *v_value, int overwrite);

返回:如果成功返回零,否则返回-1,并设置errno以指示错误原因。

getenv:

man page - getenv

包括: #include <stdlib.h>

声明: char *getenv(const char *name)

返回:如果成功返回一个指向环境中值的指针,如果没有匹配则返回NULL。

示例

char *ppath 在以下示例中用作变量。

示例 1:此示例显示当 overwrite 参数为非零且 v_name 具有值时发生的情况。

ppath = getenv("PWD");                  //puts the environment of $PWD into ppath
if(ppath == NULL)                       //error checking
  perror("getenv");   
cout << "$PWD = " << ppath << endl;     //prints the environment of $PWD 

这段代码的输出是 $PWD = /class/classes/username/CS100 这是因为 char 变量 ppath 正在获取 来自getenv("PWD") 的环境和$PWD 的环境是/class/classes/username/CS100。因此ppath 指向那个 环境。还有适当的错误检查以确保$PWD 有一个环境,如果它没有perror 被调用。

ppath = getenv("HOME");                 //gets the environment of the $HOME
if(ppath == NULL)                       //error checking
  perror("getenv");
cout << "$HOME = " << ppath << endl;    //prints the environment of $PWD

这段代码的输出是 $HOME = /class/classes/username 这是因为 char 变量 ppath 正在获取 来自getenv("HOME") 的环境和$HOME 的环境是/class/classes/username。因此ppath 指向那个 环境。还有适当的错误检查以确保$HOME 有一个环境,如果它没有perror 被调用。

if(-1==setenv("PWD",ppath,1))           //since the overwrite parameter is non-zero it replaces environment 
  perror("setenv");                     //of $PWD with the value of ppath which is defined by the environment 
                                        //of $HOME

这是为了更改$PWD 的环境,在这种情况下,它采用ppath 指向的值,在这种情况下是/class/classes/username,也是$HOMEoverwrite参数非零,所以将$PWD的环境替换为ppath

ppath = getenv("PWD");                  //gets the environment of $PWD
if(ppath == NULL)                       //error checking
  perror("getenv");
cout << "$PWD = " << ppath << endl;     //the value should now be the same as the value of $HOME

这段代码的输出是 $PWD = /class/classes/username 这是因为 char 变量 ppath 正在获取 来自getenv("PWD") 的环境和$PWD 的环境是/class/classes/username。因此ppath 指向那个 环境。还有适当的错误检查以确保$PWD 有一个环境,如果它没有perror 叫做。示例 1 的完整输出如下。

输出 1:

$PWD = /class/classes/username/CS100
$HOME = /class/classes/username
$PWD = /class/classes/username

示例 2:此示例显示当 overwrite 参数为非零且 v_name 具有空值(如 v_name = "" 中的空字符串)时会发生什么情况。

ppath = getenv("PWD");                  
if(ppath == NULL)
  perror("getenv");
cout << "$PWD = " << ppath  << endl;    //in this case ppath ="" because the environment of $PWD is not set

以下代码的输出将是$PWD = 这是因为$PWD 的环境在这种情况下设置为"",它使ppath 指向一个空字符串。因此它不会抛出错误的原因,但是如果 $PWD 是未定义的变量,则调用 perror

ppath = getenv("HOME"); 
if(ppath == NULL)
  perror("getenv");
cout << "$HOME = " << ppath << endl;

输出:这段代码是 $HOME = /class/classes/username 这是因为 char 变量 ppath 正在获取 来自getenv("HOME") 的环境和$HOME 的环境是/class/classes/username。因此ppath 指向那个 环境。还有适当的错误检查以确保$HOME 有一个环境,如果它没有perror 被调用。

if(-1==setenv("PWD",ppath,1))           //since the overwrite parameter is non-zero it replaces environment 
  perror("setenv");                     //of $PWD with the value of ppath which is defined by the environment 
                                        //of $HOME 

由于 overwrite 参数为 1,因此将 $PWD 设置为前面示例中定义的 ppath 并不重要。

ppath = getenv("PWD");                  
if(ppath == NULL)
  perror("getenv");  
cout << "$PWD = " << ppath << endl;     //the value should now be the same as the value of $HOME

以下代码的输出是$PWD = /class/classes/username 这是因为setenv 将过去代码块中定义的$PWD 的值更改为ppath

输出 2:

$PWD =
$HOME = /class/classes/username
$PWD = /class/classes/username

示例 3:此示例显示当 overwrite 参数为零且 v_name 确实有值时会发生什么。

ppath = getenv("PWD"); 
if(ppath == NULL)
  perror("getenv");
cout << "$PWD = " << ppath << endl;

在这种情况下,ppath 设置为$PWD 的环境。这个代码块的输出是 $PWD = /class/classes/username/CS100.

ppath = getenv("HOME"); 
if(ppath == NULL)
  perror("getenv");
cout << "$HOME = " << ppath << endl;

在此代码块中,ppath 设置为$HOME 的环境。以下代码块的输出将是 $HOME = /class/classes/username.

if(-1==setenv("PWD",ppath,0))           //since the overwrite parameter is zero it does not replaces  
  perror("setenv");                     //environment of $PWD with ppath.

这里有一个overwrite 参数为零的新情况。在这种情况下,ppath 是什么并不重要,因为 零标志使得$PWD 不会被ppath 替换,除非$PWD 是未定义的变量,在这种情况下 $PWD 将被赋予 ppath 的值。

ppath = getenv("PWD");                
if(ppath == NULL)
  perror("getenv");
cout << "$PWD = " << ppath << endl;     //the value should not be changed.

这个代码块的输出是$PWD = /class/classes/username/CS100。这是因为setenv 没有更改 $PWD 的环境,因为 overwrite 参数。

输出 3:

$PWD = /class/classes/username/CS100
$HOME = /class/classes/username
$PWD = /class/classes/username/CS100

示例 4:此示例显示当overwrite 参数为零非零且v_name 是未在环境中定义的参数时发生的情况。

ppath = getenv("HOME"); 
if(ppath == NULL)
  perror("getenv");
cout << "$HOME = " << ppath << endl;

在这种情况下 ppath 被赋予$HOME 的环境,还进行了适当的错误检查。代码的输出 块是$HOME = /class/classes/username

if(-1==setenv("random_name",ppath,0))   //since the overwrite parameter is zero and the variable     
perror("setenv");                       //$random_name is undefined, setenv makes the environment of 
                                        //$random_variable is the value of ppath. If the case where
                                        //there is a undefined variable the setenv behaves the
                                        //same way regardless of a non-zero or zero overwrites parameter. 
                                        

在这种情况下,overwrite 参数仍然为零,但 v_name 未声明,因此这是 overwrite 零参数有帮助的地方。在这种情况下,random_name 设置为ppath,它指向$HOME 的环境,即/class/classes/username

ppath = getenv("random_name");                  //gets the value of $PWD
if(ppath == NULL)
  perror("getenv");
cout << "$random_name = " << ppath << endl;     //the value should now be the same as the value of $HOME

ppath 包含$random_name 的环境,由前面代码块中的setenv 设置。输出 这个代码块是 $random_name = /class/classes/username

输出 4:

$HOME = /class/classes/username
$random_name = /class/classes/username

【问题讨论】:

  • Documentation for setenv 的可能副本
  • 我已经在您的duplicate question 中解决了其中的一些问题。你似乎没有注意到太多。
  • 实际上你可以注意到这两篇文章有非常不同的文档,因为在这篇文章中没有描述,只是示例和示例描述。
  • 如果您提供了指向真实文档的链接,则无需重复任何内容,否则您当然应该为所有参数提供文档。不清楚你在问什么。

标签: c++ linux environment-variables system-calls


【解决方案1】:

您正在使用 C++;您可以在编写时轻松声明变量。事实上,C99 和 C11 都允许您在使用变量时声明它们。

示例 1

示例 1:此示例显示了当 overwrite 参数为非零且 v_name 有值时会发生什么。

实际上,很难发现示例 1 中与 overwrite 参数有任何关系的代码。

ppath = getenv("PWD");                  //puts the environment of $PWD into ppath
if(ppath == NULL)                       //error checking
  perror("getenv");   
cout << "$PWD = " << ppath << endl;     //prints the environment of $PWD

当您确定它为 NULL 时,不应使用 ppath;这是一个普遍存在的问题。现在,你不应该使用nullptr,因为这是 C++ 吗?我认为这可能是:

const char *ppath = getenv("PWD");
if (ppath == nullptr)
    perror("getenv");   
else
    cout << "$PWD = " << ppath << endl;

如果您声明您正在为向后兼容性进行编码,那么使用 NULL 或 0 代替 nullptr 没有什么大问题。

事实上,你有三遍几乎相同的代码块;你需要写一个函数:

void show_env(const char *varname)
{
    const char *ppath = getenv(varname);
    if (ppath == nullptr)
        perror("getenv");   
    else
        cout << "$" << varname << " = " << ppath << endl;
}

这是对原代码的直接音译。它还说明了为什么perror() 是一个不好的函数;很难使错误消息有意义(它不包括变量名)。除此之外,getenv() 的 POSIX 规范并未指定 errnogetenv() 设置,我们应该将代码修改为:

void show_env(const char *varname)
{
    const char *ppath = getenv(varname);
    if (ppath == nullptr)
        cerr << "No value in the environment for $" << varname << endl;   
    else
        cout << "$" << varname << " = " << ppath << endl;
}

然后您可以调用:

show_env("PWD");
show_env("HOME");
…code using setenv()…
show_env("PWD");

等等。我不相信引用$HOME 的代码是相关的;你真的不用它。

就个人而言,我(非常)不喜欢您在 setenv() 的代码中使用的从后到前的比较风格。当尤达想说话时……

请注意,单独设置环境变量$PWD 不会更改当前工作目录。

示例 2

您的示例 2 没有清楚地显示 v_name 设置为空字符串。但是,setenv() 的 POSIX 规范涵盖了这种情况。这次定义了一个错误(errno 将被设置为EINVAL)。

重复的代码太多了,很难发现有趣的地方。

示例 3

你说:

示例 3:此示例显示当 overwrite 参数为零且 v_name 确实有值时会发生什么。

我想你的意思是:

示例 3:此示例显示当 overwrite 参数为零且由 v_name 标识的环境变量确实有值时会发生什么。

这可能在以前也适用。

示例 4

你说:

ppath = getenv("random_name");                  //gets the value of $PWD

注释与代码不符。

SO 风格

您应该为每个示例创建一个标题,并以### 作为行前缀。你可能有也可能没有超级标题## Examples。您可以模仿功能大纲的手册页的样式,或者您可以简单地省略除概要之外的所有内容,指的是定义功能行为的位置。

正如所写,很难找到这 4 个示例(直到在回答过程的后期我才意识到 有四个示例而不是三个)。你有很多重复。你也有很多噪音(引用$HOME的代码基本上是噪音。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-18
    • 2018-02-06
    • 1970-01-01
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 1970-01-01
    相关资源
    最近更新 更多