Chủ đề của bài viết này xuay quanh cách giải quyết vấn đề nhỏ sau: ta có 1 enum định nghĩa các trạng thái như bên dưới.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum FileAccess { | |
READ, // file có thể đọc | |
WRITE, // file có thể viết | |
MODIFY, // file có thể được chỉnh sửa | |
EXECUTE // file có thể được thực thi | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FileAccess mState; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mState = READ;// bây giờ biến mState lưu giá trị READ(số 1) | |
mState = WRITE;// bây giờ biến mState lưu giá trị WRITE(số 2) | |
mState = MODIFY;// bây giờ biến mState lưu giá trị MODIFY(số 4) |
Để sử dụng được kỷ thuật này ta cần thay đổi chút ít ở FileAccess và biến mState như sau:
Đối với FileAccess ta định nghĩa lại với giá trị được set cứng như bên dưới.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum FileAccess { | |
READ = 0x01,// file có thể đọc | |
WRITE = 0x02,// file có thể viết | |
MODIFY = 0x04,// file có thể được chỉnh sửa | |
EXECUTE = 0x08 // file có thể được thực thi | |
}; |
int mState;Ok! bước chuẩn bị đã xong, giờ ta xem tại sao lại set giá trị cho các giá trị của FileAccess là giá trị của 2^x nhé. Các giá trị 2^x rất đặt biệt: 1(2^0), 10(2^1), 100(2^2), 1000(2^3)...Như đã thấy thì giá trị của nó luôn chỉ chứa 1 số 1 ở đầu sau đó là các số 0. Giả sử ta OR 2 giá trị 1000(8) và 10(2) với nhau ta sẽ có giá trị mới là 1010(10), giờ ta muốn biết giá trị 1010(10) có chứa 10(2) ở bên trong không thì ta chỉ cần AND giá trị 1010(10) với giá trị 10(2) và kiểm tra kết quả có bằng 10(2) hay không, như ở đây thì 1010 AND 0010 sẽ cho kết quả là 10. Như để biết được 1 giá trị 2^x có ở trong 1 biến được combine từ các giá trị 2^x hay không ta chỉ cần AND biến đó với giá trị 2^x cần kiểm tra rồi so sánh kết quả với giá trị 2^x đó, nếu bằng thì nghĩa là giá trị 2^x có trong biến combine...Ta có code ví dụ như bên dưới:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
int main() { | |
int mState; | |
int val_2 = 2; // 00010 | |
int val_4 = 4; // 00100 | |
int val_8 = 8; // 01000 | |
int val_16 = 16;// 10000 | |
mState = val_2 | val_4 | val_16; | |
if((mState & val_4) == val_4) | |
printf("Has val_4\n"); | |
else | |
printf("Hasn't val_4\n"); | |
if((mState & val_8) == val_8) | |
printf("Has val_8\n"); | |
else | |
printf("Hasn't val_8\n"); | |
} |
Như ở trên ta chỉ combine các giá trị 2, 4 và 16 nên kết quả kiểm tra cho ta biết "Has val_4" và "Hasn't val_8"
Giả sử ta có giá trị sau khi combine là 1010 được combine từ 8 và 2, giờ ta lại muốn xóa số 2 trong biến đã combine đó thì ta chỉ cần đảo bit số 2 sau đó AND nó với 10 nghĩa là 1010 AND (~0010) = 1010 AND 1101 = 1000. Ta có code ví dụ như sau:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
int main() { | |
int mState; | |
int val_2 = 2; // 00010 | |
int val_4 = 4; // 00100 | |
int val_8 = 8; // 01000 | |
int val_16 = 16;// 10000 | |
mState = val_2 | val_4 | val_16; | |
mState &= ~val_4; | |
if((mState & val_4) == val_4) | |
printf("Has val_4\n"); | |
else | |
printf("Hasn't val_4\n"); | |
if((mState & val_8) == val_8) | |
printf("Has val_8\n"); | |
else | |
printf("Hasn't val_8\n"); | |
} |
Rỏ ràng là giá trị val_4 đã bị remove khỏi biến mState.
Tiếp theo ta sẽ áp dụng nó vào bài toán FileAccess ở đầu bài viết. Trước khi áp dụng vào bài toán bên trên, ta sẽ viết thêm 1 số hàm hổ trợ như sau:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// kiểm tra xem có giá trị flag trong state không | |
bool hasFlag(int state, int flag) { | |
return (state & flag) == flag; | |
} | |
// thêm 1 giá trị flag vào state | |
void addFlag(int& state, int flag) { | |
mState |= flag; | |
} | |
// xóa 1 giá trị flag trong state | |
void removeFlag(int& state, int flag) { | |
mState &= ~flag; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
enum FileAccess { | |
READ = 0x01,// file có thể đọc | |
WRITE = 0x02,// file có thể viết | |
MODIFY = 0x04,// file có thể được chỉnh sửa | |
EXECUTE = 0x08 // file có thể được thực thi | |
}; | |
bool hasFlag(int state, int flag) { | |
return (state & flag) == flag; | |
} | |
void addFlag(int& state, int flag) { | |
state |= flag; | |
} | |
void removeFlag(int& state, int flag) { | |
state &= ~flag; | |
} | |
int main() { | |
int mState = WRITE; | |
addFlag(mState, READ); | |
addFlag(mState, EXECUTE); | |
if(hasFlag(mState, READ)) | |
printf("Has READ\n"); | |
else | |
printf("Hasn't READ\n"); | |
if(hasFlag(mState, MODIFY)) | |
printf("Has MODIFY\n"); | |
else | |
printf("Hasn't MODIFY\n"); | |
removeFlag(mState, EXECUTE); | |
if(hasFlag(mState, EXECUTE)) | |
printf("Has EXECUTE\n"); | |
else | |
printf("Hasn't EXECUTE\n"); | |
} |
Như thế là từ 1 biến mState ta có thể lưu rất nhiều trạng thái khác nhau nhờ vào việc combine các bit giá trị của 2^x.
0 nhận xét :
Post a Comment