문제

C ++에서 비트 플래그를 더 잘 이해하기 위해 작은 클래스를 작성하려고합니다. 그러나 무언가가 작동하지 않습니다. 잘못된 값을 인쇄합니다. 문제는 어디에 있습니까? 깃발을 추가하는 방법을 오해 했습니까? 아니면 비트 필드에 가지고 있는지 확인하십시오.

그녀는 코드 :

#include <iostream>

enum flag
{
    A = 1, B = 2, C = 4
};

class Holder
{
public:
    Holder() : m_flags(A) {}
    ~Holder() {}

    void add_flag(flag f) { m_flags |= f; }
    bool has_flag(flag f) { return ((m_flags&f)==f); }
    void remove_flag(flag f) 
    {
        unsigned int flags = 0;
        for (int i = 1; i<=(int)C; i *= 2)
        {
            if ((flag)i!=f && has_flag(f))
                flags |= f;
        }
        m_flags = flags;
    }

    void print()
    {
        std::cout << "flags are now: " << m_flags << " | holding: "; 
        for (int i = 1; i<=(int)C; i *= 2)
        {
            if (has_flag((flag)i))
                std::cout << i << " ";
        }
        std::cout << std::endl;
    }

private:
    unsigned int m_flags;
};

int main()
{
    Holder h;
    h.print(); // should print 1

    h.add_flag(B);
    h.print(); // should print 1 2

    h.remove_flag(A);
    h.print(); // should print 2

    h.add_flag(C);
    h.print(); // should print 2 4

    h.remove_flag(B);
    h.print(); // should print 4
}

프로그램 출력 :

flags are now: 1 | holding: 1 
flags are now: 3 | holding: 1 2 
flags are now: 1 | holding: 1 
flags are now: 5 | holding: 1 4 
flags are now: 0 | holding: 
도움이 되었습니까?

해결책

개인적으로 나는 std :: vector <bool>을 사용하여 깃발을 처리 할 것입니다.

하지만:

나는 당신의 제거 깃발이 약간 복잡하다고 생각합니다. 대신 시도해보십시오.

void remove_flag( flag f ) 
{
   if ( has_flag( f ) == true )
   {
      m_flags ^= f;   // toggle the bit leaving all other unchanged
   } 
}

편집 : 댓글이 내가 왜하지 않았는지 물었습니다 do m_flags &= ~f. 나는 최적화 질문이 아닌 '학습자'질문으로 질문을했다. 나는 그의 코드를 빠르지 않고 올바르게 만드는 방법을 보여줍니다.

다른 팁

remove_flag () 메소드에는 버그가 있으므로 플래그 | = i;

그러나 다음과 같이 O (1)을 수행하십시오.

void remove_flag(flag f) { m_flags &= ~f; }

has_flag () 그리고 remove_flag () 잘못되었습니다. 그들은 다음과 같이 가야합니다.

bool has_flag(flag f) { return !!(m_flags & f); }
void remove_flag(flag f) 
{
    m_flags &= ~f;
}

모두가 이미 이것을 못 박았습니다 : 플래그 & = ~ f;

내 이전 게시물을 볼 수 있습니다.

HAS_FLAG () : F의 모든 비트가 설정되어 있으면 True를 반환하려고합니까? 아니면 그들 중 하나 이상이 설정되어 있다면? 플래그의 차이점 & f == F vs 플래그 & f! = 0입니다.

#include를 고려할 수 있습니다u003Ciomanip> 그리고 cout << hex <

열거는 클래스 보유자 안에있을 수 있습니다.

class Holder
{
public:
  enum flag { A=1, B=2, C=4; };
...
};

그런 다음 사용합니다 홀더 :: a 대신에 .

당신은 (i = 0; i에 사용하고 싶을 수도 있습니다.

Add_flag/has_flag/remove_flag 메소드가 열거 된 유형이 아닌 int를 가져 가기를 원할 수 있습니다. 그것은 많은 캐스팅을 제거합니다. 가능한 모든 int 값을 지원하지 않으려면 검증 방법과 거부 경로를 사용할 수 있습니다. 그건 그렇고, add_flag (플래그 (5736))를 부르는 것을 막는 것은 없습니다. 그리고 당신은 이미 Enum_flag에 캐스팅하고 있습니다.

m_flag 대신 mflag를 사용하고 싶을 수도 있습니다. 그것은 당신의 선택입니다. 그러나 글꼴에 따라 m_x*m_y-m_z*m_y-m_x*m_z와 같은 코드를 보면-에 대해 _. (혹은 그 반대로도.)

마찬가지로 Add_flag 대신 AddFlag를 고려하십시오. 이와 같은 것이 중요하지 않습니다. 그러나 설명 이름이 길면 밑줄이 추가되기 시작합니다. 그런 다음 유혹은 이름을 약칭하여 코드를 더 둔화시킵니다.

내 $ 0.02.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top