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.exe2」のようなコマンドラインでこのプログラムを実行したいと思います。外部ファイルの変数aにロードしたい整数2 。argv [1]でprint_from_external_file()を呼び出さなくても、これを実現する方法はありますか?つまり、「a」に値「2」を自動的に与えることはできますか?

4

6 に答える 6

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;
}
于 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キーワードの使用だと思います。メインでextern変数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;
}

編集

2 番目のファイルでは、名前空間を削除するか、その名前を指定する必要があります。2番目のファイルに次のコードを使用してテストしたところ、期待どおりに機能しました

#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

Windows を使用している場合は、

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;

ただし、あなたがやろうとしていることについて2つのことが気になります。まず、実行時に設定された変数値を関数内にカプセル化する必要があります。論理的には、関数と外部の影響 (コマンド ライン パラメーター) の間に目に見えない依存関係があるため、コードの保守性が低下します。そのため、関数の決定論的プロパティが損なわれます。実際には、これにより関数のテストがはるかに困難になります。特に、実行前にプログラムで値を設定する方法がないため、自動化された単体テストを使用する場合はそうです。

a第二に、これを複雑にするかのように、名前のない名前空間内のコンパイル単位に変数のスコープを制限しようとしています。これには、2 つの望ましくない影響があります。まず、テスト ハーネスやその他のコードはこの変数を認識できないため、自動化された 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 に答える