2014-06-24 4 views
3

아마도 좋은 프로그래밍 방법은 아니지만 for 루프 매크로를 정의 할 수 있습니까?C++에서 'for'루프 매크로 정의

예를 들어

,

#define loop(n) for(int ii = 0; ii < n; ++ ii) 

작품 완벽하게,하지만 당신은 변수 이름 ii을 변경할 수있는 기능을 제공하지 않습니다.

loop(5) 
{ 
    cout << "hi" << " " << "the value of ii is:" << " " << ii << endl; 
} 

을하지만 이름/기호 ii의 선택의 여지가 없다 :

그것은 사용할 수 있습니다.

이렇게 할 수 있습니까?

loop(symbol_name, n) 

프로그래머가 "symbol_name"에 기호 이름을 삽입합니다.

사용 예제는 :

loop(x, 10) 
{ 
    cout << x << endl; 
} 

답변

21
#define loop(x,n) for(int x = 0; x < n; ++x) 
1
#define loop(VARIABLE, n) for(int VARIABLE = 0; VARIABLE < n; ++ VARIABLE) 

이 작업을 시도 할 수 있습니다.

+1

매개 변수 (OP가 요청한대로)에서 사용할 심볼 이름을 사용하는 것이 더 나은 이유는 무엇입니까? –

+0

@ πάντα ῥεῖ 당신이 옳습니다. 감사! 나는 그것을 개정했다. –

5
#define loop(x, n) for(int x = 0; x < n; ++ x) 

Something like this? 가장 경험이 풍부한 프로그래머가 따라 규칙이,

#define loop(variable, n) for(int variable = 0; variable < n; ++variable) 

주 - 매크로 대문자 식별자를 사용

#include <iostream> 
using namespace std; 

#define loop(x, n) for(int x = 0; x < n; ++ x) 

int main() { 

    loop(i, 10) 
    { 
     cout << i << endl; 
    } 

    return 0; 
} 
+2

예를 들어 주셔서 감사합니다. – Mannu

2

당신은 매크로에 대한 첫 번째 매개 변수로 변수 이름을 정의 할 수 있습니다.

#define loop(variable, n) for(int variable = 0; variable < n; ++variable) 

void loop(); 

지금 코드에서 그 함수를 호출하고 점점 추한 어떤 오류 메시지를보고 시도 : 귀하의 경우에, 당신은 함수와 매크로를 상상한다. 그들 중 일부는 전혀 이해하기 쉽지 않을 수 있습니다. 더 나쁜 것은 클래스의 네임 스페이스 또는 메서드에서 루프 함수를 사용하는 데 전혀 도움이되지 않습니다.

그래서 적어도이 방법이 있습니다

#define LOOP(variable, n) for(int variable = 0; variable < n; ++variable) 

을하지만, 더 나은 전혀 사용하지 마십시오.

+1

이것은'++ variable'이 아니어야합니까? –

+0

예 감사합니다. 고정 – Slava

10
오늘날의 C에서

++ 우리는이에 대한 매크로를 사용하지 것이다, 그러나 우리는 템플릿과 펑터 (이 람다의 포함) 사용하십시오 :

template<typename FUNCTION> 
inline void loop(int n, FUNCTION f) { 
    for (int i = 0; i < n; ++i) { 
    f(i); 
    } 
} 
// ... 
loop(5, [](int jj) { std::cout << "This is iteration #" << jj << std::endl; }); 

loop 기능은 내부적으로 변수 i 사용하지만, 람다 그걸 보지 못해. loop 내부입니다. 대신 람다는 인수 jj을 정의하고 그 이름을 사용합니다.

람다 대신 단일 정수 인수를 허용하는 한 모든 함수를 전달할 수 있습니다.std::to_string<int>을 전달할 수도 있습니다 - 그 결과 loop이 결과 문자열에 유용한 기능을 수행하지는 않지만 구문에 허용됩니다.

+1

답변을 연장 할 수 있습니까? 전처리 기가 정의하는 것보다 나은 이유는 무엇입니까? 의도가 단지 N 번 반복하는 경우? –

+6

@chuckleplant : 타입 안전하고 적절한 구문 분석, 이름 누출 없음. – MSalters

+0

이것은 제한적으로 사용됩니다. 당신의 목적이 배열을 초기화하는 것이라면,이 템플릿 함수 밖의 배열에 대한 액세스가 필요합니다. 배열을 함수의 인수로 추가하지 않으면 불가능합니다. 이렇게하면 템플릿 함수의 일반/유용성이 떨어집니다. 나는이 경우 오래된 C 매크로가 승리한다고 믿는다. – Taozi

0

경쟁 프로그래밍에서 가능한 한 빨리 코드를 작성해야합니다. 코딩 속도를 높이는 한 가지 방법은 매크로를 사용하는 것입니다. 경쟁 프로그래머는 "루프"축약 아래 매크로를 사용 :

#define For(i,j,n) for(int i=(j);i<((int)n);++i) 

예를 들어 아래의 코드는 1

#include <stdio.h> 
#define For(i,j,n) for(int i=(j);i<((int)n);++i) 

int main(void) 
{ 
    For(i, 1, 11) 
    { 
     printf("%d\t", i); 
    } 
} 

그러나 매크로, 위험 까다 롭고, 그리고 그냥 안전하지 않습니다 (10)에 인쇄됩니다. 나는 당신이 당신의 프로젝트에서 그것들을 사용하지 않기를 정말로 권합니다. 이 문제를 표시하려면 아래 코드를 고려하십시오. 당신이 코드를 실행하면 예상 할 수 있지만

#include <stdio.h> 
#define For(i,j,n) for(int i=(j);i<((int)n);++i) 

int main(void) 
{ 
    int end = 10; 
    For(i, 1, end++) 
    { 
     printf("%d\t", i); 
    } 
} 

, 당신은 프로그램이 작동하지 않을 것을 볼 수 있습니다 그 출력해야 같은 1

1

사용 10 :

#include <vector> 
#include <cstdio> 

using std::printf; 

#define FOR(TYPE, IDENT, BEGIN, END) for(TYPE IDENT = BEGIN, IDENT##_end = static_cast<decltype(IDENT)>(END); IDENT < IDENT##_end; ++IDENT) 
#define FOR_STEP(TYPE, IDENT, BEGIN, END, STEP) for(TYPE IDENT = (TYPE)(BEGIN), IDENT##_end = static_cast<decltype(IDENT)>(END); IDENT < IDENT##_end; IDENT += STEP) 
#define FOR_ITER(IDENT, BEGIN, END) for(auto IDENT = BEGIN, IDENT_end = END; IDENT != IDENT_end; ++IDENT) 

int main() { 
    FOR(int, i, 0, 10) { 
    printf("FOR i: %d\n", i); 
    printf("we can even access i_end: %d\n", i_end); 
    } 

    FOR(auto, i, 0, 10) { 
    printf("FOR auto i: %d\n", i); 
    } 

    std::vector<int> vec = {4, 5, 7, 2, 3, 1, 4, 9, 8, 6}; 

    printf("FOR with iterator: {"); 
    FOR(auto, it, vec.begin(), vec.end()) { 
    printf("%d, ", *it); 
    } 
    printf("}\n"); 

    printf("FOR with non constant end:\n"); 
    FOR(long, i, 0, vec.size()) { 
    printf("vec[%ld] = %d\n", i, vec[i]); 
    } 
    printf("\n"); 


    // You can set a step size 
    printf("FOR_STEP(double, d, 0, 20, 2.1): "); 
    FOR_STEP(double, d, 0, 20, 2.1) { 
    printf(" %f ", d); 
    } 
    printf("\n"); 

    // It works with iterators that don't have "<" but only "!=" 
    // defined, but you probably want to use a range-based 'for' anyway. 
    printf("FOR_ITER(auto, it, vec.begin(), vec.end()): "); 
    FOR(auto, it, vec.begin(), vec.end()) { 
    printf("%d, ", *it); 
    } 
    printf("\n"); 
} 

이것은 C++ 11 타겟에 대해 생각해 낼 수있는 최선의 방법입니다. END 인수는 한 번만 평가되며 beginend은 항상 동일한 유형을 필요로합니다. 그들은 지금 < 운영자가 정의가 필요하기 때문에 당신이 == 또는 != 운영자, FOR 매크로 비교에 대한 < 연산자를 사용하는 기본과 평등에 두 배를 테스트하지 말아야 때문에

,이, 반복자의 매크로의 사용을 제한 , 너무. 나는 이중 임의의 반복자와 비슷하게 작동하는 하나의 솔루션을 생각해 낼 수 없었다. 당신은 당신의 필요에 더 잘 맞는 하나의 매크로를 선택할 수 있습니다.

하지만 대부분의 요구 사항에 맞는 매크로 정의 하나만 있으면 코드를 훨씬 쉽게 읽을 수 있기 때문에 모든 매크로를 코드에 포함하면 안됩니다.