用argv设置变量

时间:2012-10-31 10:18:54

标签: c++ argv argc

这是一个描述我当前情况的最小工作示例。文件main.cpp

#include <iostream>
void print_from_external_file();

using namespace std;

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

    return 0;
}

包含print_from_external_file()

的文件
#include <iostream>
using namespace std;

namespace
{
    int a;
}

void print_from_external_file()
{
    cout << a << endl;
}

这是我的目标:我希望通过命令行运行此程序,如“test.exe 2”。我希望将整数2加载到外部文件中的变量 a 中。有没有办法实现这一点,而无需使用argv [1]调用print_from_external_file()?换句话说,“a”可以自动赋值“2”吗?

6 个答案:

答案 0 :(得分:2)

如果您可以更改定义变量“a”的文件,则将该变量放入非匿名命名空间或在同一文件中定义导出的getter(下面的same1.cpp或same2.cpp)。否则你将无法按照自己的方式进行设置。

some1.cpp:

namespace {
   int a;
}
void set_a(int a_) { a = a_; }

some2.cpp:

namespace some {
   int a;
}

main.cpp中:

#include <cstdlib>

namespace some {
  extern int a;
}

int main(int argc, char** argv) {
  assert(argc == 2);

  some::a = atoi(argv[1]);
  // or: set_a(atoi(argv[1]));
  return 0;
}

答案 1 :(得分:2)

您必须为命名空间命名。未命名的命名空间与其翻译单元相关联,因此您将无法从其他单元访问其中的变量。

你的.cpp:

#include <iostream>
#include <stdlib.h>
#include "main.h"
void print_from_external_file();

using namespace std;
using ddd::a;

int main( int argc, char* argv[])
{
    a = atoi( argv[1] );
    print_from_external_file();

    return 0;
}

你的.h:

#include <iostream>
using namespace std;

namespace ddd
{
    int a;
}
using ddd::a;

void print_from_external_file()
{
    cout << a << endl;
}

或者,您可以删除命名空间,并在.cpp文件中使用extern int a来访问变量:

的.cpp

#include <iostream>
#include <stdlib.h>
#include "main.h"
void print_from_external_file();

using namespace std;
extern int a;
//the rest goes unchanged

·H:

#include <iostream>
using namespace std;

int a;
//the rest goes unchanged

答案 2 :(得分:1)

我认为您正在寻找的是使用 extern 关键字。 如果您在主a中声明为 extern 变量,那么您应该没问题。

#include <iostream>
void print_from_external_file();

using namespace std;

extern int a;

int main( int argc, char* argv[])
{
   //set value of a
   a = atoi(argv[1]); //atoi is deprecated but is easier to use in an example

    print_from_external_file();

    return 0;
}

修改

在第二个文件中,您需要删除命名空间或为其指定名称。 我使用以下代码测试第二个文件,它按预期工作

#include <iostream>
using namespace std;

namespace
{
    int a;
}

void print_from_external_file()
{
    cout << a << endl;
}

编辑2:使用命名空间的代码

文件1

#include <iostream>
void print_from_external_file();

using namespace std;

namespace TEST
{
    extern int a;
}

int main( int argc, char* argv[])
{
    //set value of a
    TEST::a = atoi(argv[1]); //atoi is deprecated but is easier to use in an example

    print_from_external_file();

    return 0;
}

文件2

#include <iostream>
using namespace std;

namespace TEST
{
    int a;
}

void print_from_external_file()
{
    cout << TEST::a << endl;
}

答案 3 :(得分:0)

是的,你可以。

对于整数,您必须使用std::atoi().

所以代码变成:

int a = std::atoi(argv[1]);

答案 4 :(得分:0)

如果您使用的是Windows,

namespace
{
    int nArgs = 0;
    int a = wtoi(CommandLineToArgvW(GetCommandLineW(), &nArgs)[0]);
}

为了简洁起见,我跳过了所有错误检查。

答案 5 :(得分:0)

标准做法是使用argv来访问命令行参数。您可能会在某些架构上发现还有其他方法可以做到这一点,但它们不太可能是可移植的,并且似乎没有太多理由不遵循标准做法。要将值读入int,您可以使用strtol

long n = strtol( argv[1], NULL, 0 );

(请注意,我倾向于使用strtolatoi,因为您可以更多地控制输入和错误处理 - 但不是很多)

您还可以按如下方式使用流:

istringstream ss( argv[1] );
long n;
ss >> n;

关于你正在尝试做什么,有两件事让我感到担忧:首先你需要一个变量值,在运行时设置封装在一个函数中。逻辑上,这将使您的代码不易维护,因为您的函数和外部影响(命令行参数)之间将存在不可见的依赖关系 - 因此您的函数的确定性属性将受到损害。实际上,这将使测试您的功能变得更加困难 - 尤其是使用自动单元测试,因为在运行之前无法以编程方式设置值。

其次,好像要复合它,您正在寻求将a变量的范围限制在未命名的命名空间中的编译单元。这有两个不良影响。首先,从自动化UT的角度来看,没有任何测试工具或任何其他代码能够再次看到这个变量,这非常糟糕。其次,a在您的编译单元中实际上变为“全局”。在这个编译单元的函数中,遵循如何以及何时使用a对于维护代码的任何人来说都是一件令人头疼的事情将会非常棘手。我假设你没有使用会导致问题的多线程。

我很想知道你不想将argv[1]传递给print_from_external_file()的原因,但我认为这是最好的办法。如果您不认为可以直接将此变量作为字符串传递或转换为int,则可以考虑创建可以传入的命令行参数或配置对象:

configuration c( argc, argv ); // This contains the hard work of parsing the CL
print_from_external_file( c );

这隐藏了解析命令行的大部分艰苦工作。更好的是,它允许您为CL参数添加真正的含义。假设a变量表示目录号,configuration类的构造函数可以简单地执行此操作:

configuration::configuration( int argc, char* argv[] )
{
    // ...
    catalogNo_ = strtol( argv[1], NULL, 0 );

然后如果添加了访问者:

int configuration::get_catalog_no() const { return catalogNo_; }

然后在print_from_external_file()我们正在做的事情变得更加明显:

void print_from_external_file( const configuration& c )
{
    cout << c.get_catalog_no() << endl;
}