2014-10-22 123 views
2

我的應用程序中有一個配置文件,如下所示。這個配置需要在構建程序之前完成。通過#defines迭代

#define NO_OF_COLORS 8 

#define COLOR_RESPONCE_1 'R' 
#define COLOR_RESPONCE_2 'G' 
#define COLOR_RESPONCE_3 'B' 
#define COLOR_RESPONCE_4 'M' 
#define COLOR_RESPONCE_5 'C' 
#define COLOR_RESPONCE_6 'Y' 
#define COLOR_RESPONCE_7 'O' 
#define COLOR_RESPONCE_8 'P' 

在類內我需要將這些值添加到std :: vector中。有沒有一種方法來遍歷這些定義。可能使用宏?

+0

我不認爲你可以迭代通過定義,因爲它是永久性的,不能被篡改 – 2014-10-22 05:55:59

+2

請有人可以告訴我爲什麼某些程序員喜歡宏 – 2014-10-22 05:56:10

+0

也可以轉換RGB和CMYK – 2014-10-22 05:59:45

回答

0

您無法通過宏進行迭代。預處理器編譯可能是多階段的,但名稱本身只能在第一階段(預處理階段)解決。

如果你這樣做更好的方式:

const char Colors[] = {'R','G','B','C','M','Y','O','P'}; 

然後用sizeof(Colors)/sizeof(Colors[0])找到此數組中元素的個數。重複使用循環:

for(size_t index = 0; index < sizeof(Colors)/sizeof(Colors[0]); ++index) 
{} 

或者,如果你使用的是C++編譯器11,支持for循環基於範圍的,你可以使用:

for(char color : Colors) 
{ 
    // Use 'color' 
} 

更簡單地說:

for(auto color : Colors) 
{ 
    // Use 'color' 
} 
0

看來你想遍歷一個枚舉。 C++不支持這種方法(其他語言,比如Java,默認情況下會有這種行爲)要解決這個問題,你需要創建一個迭代的數據結構,這個數據結構的長度不變,定義好,所以很容易維護。

對於,例如,可以將數據存儲在一個std::array(或C++ 11 std::tr1::array之前)

const std::array<BYTE,8> Colors = { { 'R','G','B','C','M','Y','O','P' } }; 

std::array具有迭代器,和操作者size(),所以可以做

for(std::array<BYTE,8>::const_iterator itr = Colors.begin(); 
    itr != Colors.end(); 
    ++itr) 
{ 
    // use (*itr) 
} 

或者,如果你想索引

for(std::size_t index = 0 ; index < Colors.size() ; ++index) 
{ 
    // use Colors[i] 
} 

c++11你可以使用:

for(auto color : Colors) 
{ 
    // use color  
} 

您還可以通過將其複製到std::vector

std::vector<BYTE> Colors_vector(Colors.begin(), Colors.end()); 
1

爲什麼不只是存儲這些在std::string而不是std::vector

const std::string COLDATA = "RGBMCYOP"; 

你仍然可以使用索引[]訪問它像一個std::vector

COLDATA[3]; // == 'M' 

或者,如果您仍然希望把在一個載體,你可以這樣做是這樣的:

const std::vector<char> COLDATAVEC(COLDATA.begin(), COLDATA.end()); 

如果您使用的是C++ 11,則可以將其放入std::vector而不使用std::string

const std::vector<char> COLDATAVEC = {'R', 'G', 'B', 'M', 'C', 'Y', 'O', 'P'}; 
1

您可以使用Boost.Preprocessor庫。它提供了模擬預處理器的控制結構和數據結構的宏。例如。您可以將顏色遍歷這樣的:

#include <iostream> 
#include <boost/preprocessor.hpp> 

#define NO_OF_COLORS 8 

#define COLOR_RESPONCE_1 'R' 
#define COLOR_RESPONCE_2 'G' 
#define COLOR_RESPONCE_3 'B' 
#define COLOR_RESPONCE_4 'M' 
#define COLOR_RESPONCE_5 'C' 
#define COLOR_RESPONCE_6 'Y' 
#define COLOR_RESPONCE_7 'O' 
#define COLOR_RESPONCE_8 'P' 

#define PRINT_COLOR(z, x, _)     \ 
    std::cout << BOOST_PP_CAT(COLOR_RESPONCE_, x) << std::endl; 

int main() 
{ 
    BOOST_PP_REPEAT_FROM_TO(1, NO_OF_COLORS, PRINT_COLOR, 0); 
} 

BOOST_PP_REPEAT_FROM_TO模擬環路與計數器,PRINT_COLOR宏實現了循環體。

就我個人而言,如果我沒有其他選擇,我會使用Boost.Preprocessor。它只模擬控制結構,並且有許多限制(例如,在多次循環迭代中),調試預處理器代碼並不比繁重的模板代碼簡單。

關於款式的說明。儘管預處理器是從C繼承而來的,並且對於單獨的(也是有條件的)編譯來說是必需的,但它與現代C++是不同的,事實上,即使對於98之前的C++也是如此。如果你需要的常量,你可以和應該常量枚舉(甚至更好枚舉類)或constexpr定義它們。這些常量可以放在名稱空間中以避免名稱衝突,它們可以保證只初始化一次(extern const)。

1

定義自己的迭代機械(限10次迭代):

#define ITER_0(MACRO, ACTION, DATA) 
#define ITER_1(MACRO, ACTION, DATA) ITER_0(MACRO, ACTION, DATA) ACTION(MACRO##1, DATA) 
#define ITER_2(MACRO, ACTION, DATA) ITER_1(MACRO, ACTION, DATA) ACTION(MACRO##2, DATA) 
#define ITER_3(MACRO, ACTION, DATA) ITER_2(MACRO, ACTION, DATA) ACTION(MACRO##3, DATA) 
#define ITER_4(MACRO, ACTION, DATA) ITER_3(MACRO, ACTION, DATA) ACTION(MACRO##4, DATA) 
#define ITER_5(MACRO, ACTION, DATA) ITER_4(MACRO, ACTION, DATA) ACTION(MACRO##5, DATA) 
#define ITER_6(MACRO, ACTION, DATA) ITER_5(MACRO, ACTION, DATA) ACTION(MACRO##6, DATA) 
#define ITER_7(MACRO, ACTION, DATA) ITER_6(MACRO, ACTION, DATA) ACTION(MACRO##7, DATA) 
#define ITER_8(MACRO, ACTION, DATA) ITER_7(MACRO, ACTION, DATA) ACTION(MACRO##8, DATA) 
#define ITER_9(MACRO, ACTION, DATA) ITER_8(MACRO, ACTION, DATA) ACTION(MACRO##9, DATA) 
#define ITER_10(MACRO, ACTION, DATA) ITER_9(MACRO, ACTION, DATA) ACTION(MACRO##10, DATA) 

#define ITER_I(ITERS, MACRO, ACTION, DATA) ITER_##ITERS(MACRO, ACTION, DATA) 
#define ITER(ITERS, MACRO, ACTION, DATA) ITER_I(ITERS, MACRO, ACTION, DATA) 

定義,將獲得在每次迭代調用的操作:

#define PRINT(MACRO, DATA) std::cout << MACRO; 
#define ADD_TO_VECTOR(MACRO, DATA) DATA.push_back(MACRO); 

使用像下面這些操作:

std::vector<char> v; 
ITER(NO_OF_COLORS, COLOR_RESPONCE_, ADD_TO_VECTOR, v) 

ITER(NO_OF_COLORS, COLOR_RESPONCE_, PRINT, ~) 

DEMO