установка переменных с помощью argv

Вот минимальный рабочий пример, описывающий мою текущую ситуацию. Файл 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, которое я хочу загрузить в переменную во внешнем файле. Есть ли способ сделать это без необходимости вызывать print_from_external_file () с argv [1]? Другими словами, может ли «а» автоматически быть присвоено значение «2»?

1

Решение

Вы должны будете назвать свое пространство имен. Безымянные пространства имен привязаны к их единицам перевода, поэтому вы не сможете получить доступ к переменной в ней из другого модуля.

Ваш .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

.час:

#include <iostream>
using namespace std;

int a;
//the rest goes unchanged
2

Другие решения

Если вы можете изменить файл, в котором определена переменная «a», поместите переменную в неанонимное пространство имен или определите экспортированный метод получения в том же файле (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;
}
2

Я думаю, что вы ищете, это использование внешний ключевое слово.
Если вы объявите в своем основном 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;
}
1

Если вы используете Windows,

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

Ради краткости я пропустил все проверки ошибок.

0

Да, ты можешь.

для целых чисел вы должны использовать std::atoi().

поэтому код становится:

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

Стандартная практика заключается в использовании argv чтобы получить доступ к аргументам командной строки. На некоторых архитектурах вы можете обнаружить, что есть другие способы сделать это, но они вряд ли будут переносимыми, и здесь, кажется, нет особых причин не придерживаться стандартной практики. Чтобы прочитать значение в int, вы можете использовать strtol

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

(обратите внимание, что я предпочитаю использовать strtol в 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;
}
0
По вопросам рекламы [email protected]