Witam .
Czy można w c++ takie wyrażenie np
if (liczba==0 || liczba==2 || liczba ||43 itd)
zastapic cos w stylu if (liczba in(0,2,43))???
awalknek napisał(a)
if (liczba in(0,2,43))???
Obawiam się, że takie coś to tylko w C# ;-)
Spróbuj czegoś takiego:
bool warunek = false;
int liczba;
int liczby[] = {0, 2, 43};
for (int i = 0; i < sizeof(liczby)/sizeof(int); i++)
warunek |= ( liczba == liczby[i] );
if (warunek) { /*...*/ }
ewentualnie możesz sobie na to makro napisać
no właśnie, może taką funkcję wstawić:
template<class Type, class Element, int n>
bool in_group(const Type value, const Element (&array)[n]) {
return std::find(array, array+n, value) != array+n;
}
// i później jechać...
int array[] = { 3,5,7,2 };
if( in_group(4, array) ) { /* ... */ }
ewentualnie, jak muusowo musisz mieć wszystko w ifie, to możesz takie coś wykombinować, ale nie licz na to, że to będzie efektywniejsze:
template<class Type>
class in_group_helper {
private:
Type value;
mutable bool result;
public:
in_group_helper(const Type& v) : value(v), result(false) { }
const in_group_helper& operator|(const Type& n) const {
result |= (value==n);
return *this;
}
operator bool() const { return result; }
};
template<class Type>
in_group_helper<Type> in_group(const Type& value) {
return in_group_helper<Type>(value);
}
i później chcąc sprawdzić, czy 4 leży w zbiorze {3,5,7,2} piszesz:
if( in_group(4) | 3|5|7|2 ) /* ... */
ot, takie sobie dwie koncepcje-snippety, bo mi się nudzi ;)
Jest gotowy standardowy szablon: std::set<>, ale w twoim przypadku może być to za duża armata.
Inne rozwiązanie to standardowe algorytmy:
const int Zbior1[] = {3,7,2,5};
if(std::find(Zbior1,Zbior1+4,2))
....
MarekR22 napisał(a)
Inne rozwiązanie to standardowe algorytmy:
const int Zbior1[] = {3,7,2,5};
if(std::find(Zbior1,Zbior1+4,2))
....
A jak liczb jest dużo, to można je posortować i wyszukiwać binarnie.
Btw, te liczby są całkowicie przypadkowe, czy mają jakieś wspólne cechy ?
a czemu nie zastosować w tym przypadku zwykłego switcha ?
np.
switch(liczba) {
case 2 :
case 4 :
case 42 :
robiCostam();
break;
}
zauważ że po case 2 4 nie ma "break";
zrobi swoje a na pewno dodać jedną linijke w razie potrzeby np "case 6 " to nie problem. Chyba że to ma być coś dynamicznego ale troche mało danych :P
temu - ze rozwiazania ze switchem nie da sie przeniesc np. na stringi ;)
Ale tu nie mamy stringów :>
no ale cholera wie, czy jutro nie będzie trzeba pracować na floatach...
poza tym - wcale nie jest krótszy co tu dużo mówić, to już chyba lepiej
if( (a==x) || (b==x) || (c==x) ) { /* ... */ }
niż
switch(x) {
case a:
case b:
case c:
/* ... */
}
no tak ale z tego co pisał kolega w 1 poście chodzi mu o wygodniejsze i czytelniejsze dodawanie czegoś w stylu OR a switch tak zadziała w tym przypadku.
Do głowy przychodzi mi jeszcze rozwiązanie z funkcją o zmiennej ilości parametrów, np. coś takiego:
template<typename T>
bool in( const T& zmienna, ... )
{
va_list parametry;
T test;
va_start( parametry, zmienna );
while( (test = va_arg( parametry, T )) != INT_MAX )
if( zmienna == test )
{
va_end( parametry );
return true;
}
va_end( parametry );
return false;
}
Zyskujesz ładne wywołanie (in<typ>( co, gdzie, gdzie, gdzie ), ale tracisz bardzo dużo, podobnie jak w poprzednich wersjach mnóstwo zbędnych konstruktorów kopiujacych, wykluczasz jedną wartość (INT_MAX) ze zbioru wartości i tracisz sprawdzanie typów. Ogólnie rzecz biorąc, skoro to będą ify w takiej postaci, jak podałeś, czyli nie trzymasz danych w tabeli, to ja bym rozważył napisanie zestawu funkcji w stylu
template<typename T>
bool in( const T& co, const T& gdzie ) { return co==gdzie; }
n argumentowych i do tego inline. Sugeruję to, bo skoro chcesz pisać to w ifach, to liczba argumentów jest raczej skończona i znana z góry, więc wygenerowanie tych funkcji to nie problem. W ten sposób nie tracisz w ogóle wydajności, nie omijasz sprawdzania typów i w ogóle jest fajnie poza tym, że gdzieś musisz te funkcje trzymać i jakoś je (innym programem? :P) wygenerować.