1

这是描述我当前情况的最小工作示例。文件 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”吗?

4

6 回答 6

2

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

一些1.cpp:

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

一些2.cpp:

namespace some {
   int a;
}

主.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;
}
于 2012-10-31T10:22:54.760 回答
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;
}

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

.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
于 2012-10-31T10:27:22.677 回答
1

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

#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;
}
于 2012-10-31T10:28:05.937 回答
0

是的你可以。

对于你必须使用的整数std::atoi().

所以代码变成:

int a = std::atoi(argv[1]);
于 2012-10-31T10:24:06.537 回答
0

如果您使用的是窗户,

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

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

于 2012-10-31T10:26:24.740 回答
0

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

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

(请注意,我倾向于使用strtolto,atoi因为您对输入和错误处理有更多的控制 - 但不多)

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

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;
}
于 2012-10-31T11:39:34.343 回答