2013-03-03 17 views
8

Một vài lần trong chương trình của tôi, tôi đã phải kiểm tra xem một biến có phải là một trong nhiều tùy chọn hay không. Ví dụ:C++ Cách hiệu quả nhất để so sánh biến với nhiều giá trị?

if (num = (<1 or 2 or 3>)) { DO STUFF } 

Tôi đã nhầm lẫn với 'HOẶC, nhưng dường như không có gì đúng. Tôi đã thử

if (num == (1 || 2 || 3)) 

nhưng không có gì. Hãy giúp tôi! Cảm ơn trước.

P.S. Tôi cần phải phân biệt giữa nhiều nhóm. Ví dụ:

if (num = (1,2,3)) 

else if (num = (4,5,6)) 

else if (num = (7,8,9)) 
+2

là 'nếu (num == 1 || num == 2 || num == 3)' hoặc 'if (num> = 1 && num <= 3) 'quá nhiều đánh máy? Nếu nó dài hơn, bạn luôn có thể tạo một số mảng và sử dụng 'std :: find'. – chris

+1

Xem http://stackoverflow.com/q/14368525/726361 –

+0

Cảm ơn bạn đã trả lời nhanh. @ Chris, tôi chỉ đang tìm kiếm thứ gì đó thanh lịch hơn một chút. –

Trả lời

6

Nếu các giá trị bạn muốn kiểm tra là đủ nhỏ, bạn có thể tạo một mặt nạ bit của các giá trị mà bạn tìm kiếm và sau đó kiểm tra bit đó được thiết lập.

Giả sử, bạn quan tâm đến một vài nhóm.

static const unsigned values_group_1 = (1 << 1) | (1 << 2) | (1 << 3); 
static const unsigned values_group_2 = (1 << 4) | (1 << 5) | (1 << 6); 
static const unsigned values_group_3 = (1 << 7) | (1 << 8) | (1 << 9);  
if ((1 << value_to_check) & values_group_1) { 
    // You found a match for group 1 
} 
if ((1 << value_to_check) & values_group_2) { 
    // You found a match for group 2 
} 
if ((1 << value_to_check) & values_group_3) { 
    // You found a match for group 3 
} 

Cách tiếp cận này phù hợp nhất với các giá trị không vượt quá kích thước tự nhiên mà CPU của bạn muốn làm việc. Điều này thường sẽ là 64 trong thời hiện đại, nhưng có thể khác nhau tùy thuộc vào các chi tiết cụ thể của môi trường của bạn.

+0

Tuyệt. Điều đó làm cho mọi thứ dễ dàng. Nếu tôi muốn xem "nếu 1; nếu khác 2, nếu khác nếu 3;" làm thế nào tôi sẽ làm điều đó? Tôi sẽ cần một mặt nạ bit mới, hoặc tôi có thể chỉ cần thêm vào "(2 << n)"? –

+0

Nếu bạn muốn kiểm tra giá trị 1, 2 và 3, thì mặt nạ bit của bạn sẽ trở thành giá trị này thay vì values_i_like = (1 << 1) | (1 << 2) | (1 << 3) ;. –

+0

không, bạn hiểu lầm. Tôi muốn có thể khác với (1,2,3) và (4,5,6) –

4

Bạn phải so sánh với từng giá trị. Ví dụ.

if (num == 1 || num == 2 || num == 3) { stuff } 

Bạn cũng có thể xem xét chuyển đổi và cố ý rơi qua các trường hợp (mặc dù tôi không nghĩ đó là giải pháp tốt nhất cho những gì bạn đang nói).

switch (num) { 
    case 1: 
    case 2: 
    case 3: 
     {DO STUFF} 
     break; 

    default: 
     //do nothing. 
} 
+0

Vâng, không chính xác những gì tôi đang tìm kiếm. Dù sao cũng cảm ơn! –

+1

Umm, không, bạn không _have_ để làm điều đó. – einpoklum

2

Bạn có thể định nghĩa một tập hợp các số nguyên, thêm các giá trị mong muốn với nó, và sau đó sử dụng phương pháp tìm để xem nếu giá trị trong câu hỏi là trong tập

std::set<int> values; 
// add the desired values to your set... 
if (values.find(target) != values.end()) 
    ... 
+0

Đó là một cách thú vị để làm mọi thứ ... Tôi sẽ thử, cảm ơn! –

+0

Xin lỗi, tôi vừa nhận được rất nhiều lỗi. Làm thế nào chính xác để bạn sử dụng này? Bạn có thể đưa ra một ví dụ? –

+2

lol, thiên tài trong sự đơn giản của nó! @TheWalkingCactus chỉ sử dụng 'count' thay vì với' set'. –

14

Đây là một cách trong C++ 11, sử dụng std :: initializer_list:

#include <initializer_list> 

template <typename T> 
bool is_in(const T& val, const std::initializer_list<T>& list) 
{ 
    for (const auto& i : list) { 
     if (val == i) { 
      return true; 
     } 
    } 
    return false; 
} 

với điều đó, bạn có thể làm:

if (is_in(num, {1, 2, 3}) { DO STUFF } 

Lưu ý tuy nhiên rằng những thứ như <1 là không thể.

+0

Điều đó có vẻ thuận tiện, nhưng tôi không sử dụng 11. Tôi chỉ trong đồng bằng ol 'C++. –

3

Tôi chỉ có một vấn đề tương tự và tôi đã đến các giải pháp C++ 11:

template <class T> 
struct Is 
{ 
    T d_; 
    bool in(T a) { 
    return a == d_; 
    } 
    template <class Arg, class... Args> 
    bool in(Arg a, Args... args) { 
    return in(a) || in(args...); 
    } 
}; 

template <class T> 
Is<T> is(T d) { 
    return Is<T>{d}; 
} 

Hoặc như thay thế mà không đệ quy phương pháp chấm dứt. Lưu ý rằng ở đây thứ tự so sánh là không xác định và điều này không chấm dứt sớm nếu kết quả khớp đầu tiên được tìm thấy. Nhưng mã nhỏ gọn hơn.

template <class T> 
struct Is { 
    const T d_; 
    template <class... Args> 
    bool in(Args... args) { 
    bool r{ false }; 
    [&r](...){}(((r = r || d_ == args), 1)...); 
    return r; 
    } 
}; 

template <class T> 
Is<T> is(T d) { 
    return Is<T>{d}; 
} 

Vì vậy, cho cả hai giải pháp mã sẽ trông như thế:

if (is(num).in(1,2,3)) { 
    // do whatever needs to be done 
} 
0

tôi cần phải làm điều gì đó tương tự cho sự đếm. Tôi có một biến và muốn thử nghiệm nó với một phạm vi giá trị.

Ở đây tôi đã sử dụng hàm mẫu variadic. Lưu ý chuyên môn cho loại const char*, do đó is_in(my_str, "a", "b", "c") có kết quả mong đợi cho thời điểm my_str cửa hàng "a".

#include <cstring> 

template<typename T> 
constexpr bool is_in(T t, T v) { 
    return t == v; 
} 

template<> 
constexpr bool is_in(const char* t, const char* v) { 
    return std::strcmp(t,v); 
} 

template<typename T, typename... Args> 
constexpr bool is_in(T t, T v, Args... args) { 
    return t==v || is_in(t,args...); 
} 

Ví dụ sử dụng:

enum class day 
{ 
    mon, tues, wed, thur, fri, sat, sun 
}; 

bool is_weekend(day d) 
{ 
    return is_in(d, day::sat, day::sun); 
}