位域 (Bit field)


  最近開始看編程之美這本書,里面有一道關於中國象棋將帥位置的簡單問題,如下圖所示,寫一個程序輸出將、帥的合法位置。

  

  分析與解法

  問題的本身並不復雜,只要把所有A、B 互相排斥的條件列舉出來就可以完成本題的要 求。由於本題要求只能使用一個變量,所以必須首先想清楚在寫代碼的時候,有哪些信息需 要存儲,並且盡量高效率地存儲信息。稍微思考一下,可以知道這個程序的大體框架是:

  遍歷A的位置 

    遍歷B的位置  

      判斷A、B的位置組合是否滿足要求

        如果滿足,則輸出

  因此,需要存儲的是A、B 的位置信息,並且每次循環都要更新。為了能夠進行判斷, 首先需要創建一個邏輯的坐標系統,以便檢測 A 何時會面對 B。這里我們想到的方法是用 1~9的數字,按照行優先的順序來表示每個格點的位置。這樣,只需要用 模余運算就可以得到當前的列號,從而判斷A、B 是否互斥。 

  

  若題目要求只用一個變量,但是我們卻要存儲 A 和 B 兩個子的位置信息,該怎么辦呢?
  可以先把已知變量類型列舉一下,然后做些分析。
  對於bool類型,估計沒有辦法做任何擴展了,因為它只能表示true和false 兩個值;而 byte 或者 int 類型,它們能夠表達的信息則更多。事實上,對本題來說,每個子都只需要 9 個數字就可以表達它的全部位置。
  一個8位的byte類型能夠表達28=256個值,所以用它來表示A、B的位置信息綽綽有余, 因此可以把這個字節的變量(設為b)分成兩部分。用前面的4 bit表示A的位置,用后面的 4 bit表示B的位置,那么4個bit可以表示16個數,這已經足夠了。

  那么:如何使用bit級的運算將數據從這一byte變量的左邊和右邊分別存入和讀出呢?

  大家容易想到的是對那個變量進行各種位運算,最后輸出結果。

  但是其實C語言中還提供了一種存在於結構體中叫做位域的類型,因此程序就變得簡單多了。關於位域更多的用法規則,詳見:C位域

#include <stdio.h>
struct bf{
    unsigned char a:4;
    unsigned char b:4;
}i;  /*定義位域結構*/
int main()
{
    for(i.a = 1; i.a <= 9; i.a++)
    {
        for(i.b = 1; i.b <= 9; i.b++)
        {
            if(i.a % 3 != i.b %3)
                printf("A = %d, B = %d\n", i.a, i.b);
        }
    }
    return 0;
}

  另一巧妙解法:

int main()
{
    unsigned char i = 81;
    while(i--)
    {
        if(i/9%3 != i%9%3)
            printf("A = %d, B = %d\n", i/9+1, i%9+1);
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM