2012-10-31 7 views
1

다음은 현재 상황을 설명하는 최소 작동 예제입니다. 파일 MAIN.CPPargv로 변수 설정하기

#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는 외부 파일의 변수에로드하려고합니다. argv [1]로 print_from_external_file()을 호출하지 않고도이 작업을 수행 할 수 있습니까? 즉, "a"에 자동으로 "2"값을 부여 할 수 있습니까?

답변

2

네임 스페이스의 이름을 지정해야합니다. 명명 된 네임 스페이스는 번역 단위에 묶여 있으므로 다른 단위에서 변수에 액세스 할 수 없습니다.

귀하의 통화 당 :

#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을 사용하여 얻을 수 있습니다 :

통화 당

#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

변수 "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; 
} 
+1

이것은 a가 main과 동일한 범위에서 정의된다고 가정합니다. 그것은 내 MWE의 경우가 아닙니다. – BillyJean

0

. 당신이 std::atoi().

를 사용할 필요가 정수에 대한

그래서 코드가된다 : 간결성을 위해

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

Windows를 사용하는 경우,

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

내가 확인 모든 오류를 건너 뜁니다 .

+0

죄송합니다. 1이 아닌 0을 의미합니다. - CommandLineToArgvW (GetCommandLineW(), & nArgs) [1]); – nanda

1

나는 당신을 위해 무엇을 찾고있는 것은 통근 키워드를 사용하는 것입니다 생각합니다. 주 aextern 변수로 선언하는 경우 괜찮습니다.

#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; 
} 

편집이 예상대로 일 : 코드 네임 스페이스를 사용하여

파일 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; 
} 
+0

이것은 'a'가 이름없는 네임 스페이스 안에 있기 때문에 OP 케이스에서 사용될 수 없습니다. – SingerOfTheFall

+0

당신의 코멘트는 내 편집과 함께 도착했습니다 :) –

+0

이것은 컴파일되지 않습니다 :'../Test/main.cpp:12:4 : error : 'a'에 대한 참조가 모호합니다 ../Test/main.cpp:7 : 12 : 오류 : 후보자는 다음과 같습니다. int a ../Test/main.h:6:6 : 오류 : int {anonymous} :: a' – SingerOfTheFall

0

표준 연습은 argv을 사용하여 명령 줄 인수에 액세스하는 것입니다. 어떤 아키텍쳐에서는 다른 방법이 있다는 것을 알 수 있지만, 이식성이 없기 때문에 표준적인 방법으로는 가지 않을 이유가별로 없습니다. 당신이 사용할 수있는 하나의 int로 값을 읽으려면 strtol

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

(난 당신이 입력을 통해 좀 더 제어 및 오류 처리했습니다으로 atoistrtol을 사용하여 선호하는 경향이 있습니다 -하지만 많은되지 않음) 다음과 같이

또한 스트림을 사용할 수 있습니다

istringstream ss(argv[1]); 
long n; 
ss >> n; 
당신이 생각 뭘 하려는지에 대해 저를 염려 할 두 가지

: 첫째로 당신이 원하는 실행시 설정 변수 값은 함수 내에서 캡슐화한다 . 논리적으로 이것은 당신의 함수와 외부 영향 (명령 행 매개 변수) 사이에 보이지 않는 의존성이 있기 때문에 코드의 유지 보수성을 떨어 뜨릴 것이므로 함수의 결정 론적 속성이 손상 될 것입니다. 실제적으로, 이것은 당신의 함수를 테스트하는 것을 훨씬 더 어렵게 만들 것입니다 - 특히 자동화 된 유닛 테스트를 사용하기 전에 값을 프로그램 적으로 실행하는 방법이 없으므로이를 사용하십시오.

둘째로, 이것을 합성하는 것처럼, 변수 이름이 a 인 변수의 범위를 이름없는 네임 스페이스 내의 컴파일 단위로 제한하려고합니다. 이것은 두 가지 바람직하지 않은 영향을 미칩니다. 첫째, 자동화 된 UT 관점에서이 변수를 다시 볼 수있는 테스트 장치 또는 기타 코드가 없다는 것은 매우 나쁜 것입니다. 둘째, a은 컴파일 단위에서 효과적으로 '전역'이됩니다. 이 컴파일 단위의 함수 내에서 코드를 유지 관리하는 사람에게는 두통을 의미하는 a이 사용되는 방법과시기를 따르는 것이 매우 까다로울 것입니다. 나는 당신이 정말로 문제를 야기 할 멀티 쓰레딩을 사용하지 않는다고 가정 할 것이다.

argv[1]print_from_external_file()에 전달하고 싶지 않은 이유를 알고 싶습니다.하지만 실제로 이것이 최선이라고 생각합니다.

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

이것은 대부분의 숨 깁니다 : 당신은 당신이 문자열로 직접이 변수를 전달하거나 int로 변환 할 수 있다고 생각하지 않는 경우에 전달 될 수있는 명령 줄 매개 변수 또는 구성 객체를 생성 고려할 수 커맨드 라인을 파싱하는 일.CL 매개 변수에 실제 의미를 추가 할 수 있습니다.

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

을 한 후 접근이 추가되는 경우 :의이 a 변수가 카탈로그 번호를 표시한다고 가정 해 봅시다, 당신의 configuration 클래스의 생성자는 단순히이 작업을 수행 할 수 있습니다

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

을 그것은 훨씬 더 분명하게 in print_from_external_file() 우리가하는 일 :

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

을 사용해 주셔서 감사합니다. argv [1]을 함수에 넘기는 것을 피하려고하는 이유는 내 프로그램이 이미 만들어 졌기 때문이며,이 변경을 다시하는 데 많은 시간이 걸릴 것입니다. 네임 스페이스를 변경하는 것은 훨씬 빠른 수정이지만 이해할 수있는대로 가격이 책정됩니다. – BillyJean

+1

@ niles_1710373 : 이해합니다. 하나의 가능성은 값을 환경 변수로 설정하고 필요할 때 그것을 읽는데'getenv() '를 사용하는 것일 수도 있지만 이것은 위와 같은 * 기술적 부채 *를 포함합니다. 그것이 나라면, 나는 총알을 물고 그것을 할 것이다. 아마 당신이 상상했던 것만 큼 오래 걸리지 않을 것이며, 응용 프로그램의 저장 수명에 따라 설계를 간결하고 읽기 쉽게 유지함으로써 향후 유지 보수 시간 (명성뿐 아니라)을 거의 확실히 절감 할 수 있습니다. –

+1

덕분에 항상 전문적인 조언을 구하는 것이 좋습니다. – BillyJean

관련 문제