tecla studio selecciono rango qué pulso programacion para ocurre móviles f11 español edición desarrollo datos curso aplicaciones c++ switch-statement

c++ - studio - programacion android pdf 2018



¿Cómo selecciono un rango de valores en una instrucción de cambio? (18)

Cuando intento compilar me sale este error:

1>------ Build started: Project: snake, Configuration: Debug Win32 ------ 1> exercise.cpp 1>c:/users/robin/documents/visual studio 2010/projects/snake/snake/exercise.cpp(13): error C2059: syntax error : ''>='' 1>c:/users/robin/documents/visual studio 2010/projects/snake/snake/exercise.cpp(16): error C2059: syntax error : ''>='' 1>c:/users/robin/documents/visual studio 2010/projects/snake/snake/exercise.cpp(19): error C2059: syntax error : ''>='' 1>c:/users/robin/documents/visual studio 2010/projects/snake/snake/exercise.cpp(22): error C2059: syntax error : ''>='' 1>c:/users/robin/documents/visual studio 2010/projects/snake/snake/exercise.cpp(25): error C2059: syntax error : ''>'' 1>c:/users/robin/documents/visual studio 2010/projects/snake/snake/exercise.cpp(28): error C2059: syntax error : ''=='' 1>c:/users/robin/documents/visual studio 2010/projects/snake/snake/exercise.cpp(34): warning C4065: switch statement contains ''default'' but no ''case'' labels ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Código:

#include <iostream> using namespace std; int main(){ int score; //Vraag de score cout << "Score:"; cin >> score; //Switch switch(score){ case >= 100: cout << "a"; break; case >= 50: cout << "b"; break; case >= 25: cout << "c"; break; case >= 10: cout << "d"; break; case > 0: cout << "e"; break; case == 0: cout << "f"; break; default: cout << "BAD VALUE"; break; } cout << endl; return 0; }

¿Como puedo solucionar este problema? Es una aplicación de consola, Win32 y mi IDE es Windows Enterprise C ++ 2010.

Estoy aprendiendo desde el inicio de C ++ a través de la programación del juego .


¿Algo como esto?

case ''A''..''Z'' where a not in [''I'',''L'',''O'']:

Desafortunadamente, ningún compilador que conozco implementa esa extensión en particular, aunque GCC puede hacer rangos como lo indican otras respuestas. Para la portabilidad, puede cortar y pegar este fragmento de código con licencia DWTFYW. Si está utilizando una enumeración personalizada, puede recurrir a la generación de código para hacer algo similar.

#define CASE_NUMBER / case''0'':case''1'':case''2'':case''3'':case''4'':/ case''5'':case''6'':case''7'':case''8'':case''9'' #define CASE_ALPHA_LOWER / case''a'':case''b'':case''c'':case''d'':/ case''e'':case''f'':case''g'':case''h'':/ case''i'':case''j'':case''k'':case''l'':/ case''m'':case''n'':case''o'':case''p'':/ case''q'':case''r'':case''s'':case''t'':/ case''u'':case''v'':case''w'':case''x'':/ case''y'':case''z'' #define CASE_ALPHA_UPPER / case''A'':case''B'':case''C'':case''D'':/ case''E'':case''F'':case''G'':case''H'':/ case''I'':case''J'':case''K'':case''L'':/ case''M'':case''N'':case''O'':case''P'':/ case''Q'':case''R'':case''S'':case''T'':/ case''U'':case''V'':case''W'':case''X'':/ case''Y'':case''Z'' #define CASE_ALPHA CASE_ALPHA_UPPER:CASE_ALPHA_LOWER #define CASE_ALPHANUM CASE_ALPHA:CASE_NUMBER

Si accede a GHCI, como la versión en línea en https://ghc.io/ , puede generar lo que necesita y pegarlo en un encabezado, por ejemplo

foldl (++) "" ["case" ++ show x ++ ":" | x <- [''A''..''Z''], not $ x `elem` [''I'',''L'',''O'']]


Algunos compiladores admiten rangos de casos como case x ... y como una extensión del lenguaje C ++.

Ejemplo:

#include <iostream> using namespace std; int main(){ int score; //Vraag de score cout << "Score:"; cin >> score; //Switch switch(score){ case 0: cout << "a"; break; case 0 ... 9: cout << "b"; break; case 11 ... 24: cout << "c"; break; case 25 ... 49: cout << "d"; break; case 50 ... 100: cout << "e"; break; default: cout << "BAD VALUE"; break; } cout << endl; return 0; }

GCC 4.9 , Clang 3.5.1 y Intel C / C ++ Compiler 13.0.1 parecen admitirlo (probado en http://gcc.godbolt.org/ ). Por otro lado, Visual C ++ 19 no (probado en http://webcompiler.cloudapp.net/ ).


Aquí hay una manera que espero sea expresiva y simple de seguir.

Puede que te sorprenda lo lejos que puede optimizar gcc / clang, etc., el código que genera. Espero que sea al menos tan eficiente como un interruptor / caja.

#include <iostream> template<class Value> struct switcher { constexpr switcher(Value const& value) : value_(value) {} constexpr switcher(Value const& value, bool enabled) : value_(value), enabled(enabled) {} template<class From, class To, class F> constexpr auto in_range(From&& from, To&& to, F&& f) { if (enabled and (from <= value_ and value_ <= to)) { f(); return switcher(value_, false); } else { return *this; } }; template<class F> constexpr auto otherwise(F&& f) { if (enabled) f(); } Value const& value_; const bool enabled = true; }; template<class Value> constexpr auto decision(Value const& value) { return switcher<Value>(value); } void test(int x) { decision(x) .in_range(0, 10, [&] { std::cout << x << " maps to option A/n"; }) .in_range(11, 20, [&] { std::cout << x << " maps to option B/n"; }) .otherwise([&] { std::cout << x << " is not covered/n"; }); } int main(int argc, char **argv) { test(5); test(14); test(22); }


En C ++, las etiquetas de casos son expresiones constantes , no expresiones en general. Necesita una cadena de sentencias if-then-else para hacer lo que está tratando de hacer.

Alternativamente, puede enumerar los valores en el interruptor. Esto se ejecuta ligeramente más rápido (aunque no importa en casos como el suyo), pero es considerablemente menos legible:

switch(score) { case 0: cout << "f"; break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: cout << "e"; break; case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: cout << "c"; break; // ...and so on, you get the idea... }


En C ++, una instrucción de cambio solo puede coincidir con valores enteros constantes:

switch (i) { case 1: //... stuff break; case 2: //... stuff break; default: //... stuff }


Eso simplemente no es cómo funciona el interruptor. Solo toma valores únicos. Tendrás que usar los bloques if-elseif.


Esto es lo que funcionó para mí. dividiendo la marca por 10 y luego configurando el caso 10 y 9 para mostrar una "A" (esto mostrará una "A" para cualquier valor entre 90-100. Luego el caso 8 para mostrar "B", luego el caso 7 mostrará una " C "para los valores de 70-79 y así sucesivamente.

#include <iostream> using namespace std; main () { int mark; cout << "enter your mark: "; cin >> mark; switch (mark/10) { case 10: case 9: cout << "A"; break; case 8: cout << "B"; break; case 7: cout << "C"; break; case 6: cout << "D"; break; case 5: cout << "PASS"; break; default: cout << "FAIL"; break; } }



La norma no permite esto:

6.4.2 La instrucción switch [stmt.switch]

[...] Cualquier declaración dentro de la declaración de cambio se puede etiquetar con una o más etiquetas de casos de la siguiente manera:

case constant-expression :

donde la expresión constante será una expresión constante constante (5.19).

En otras palabras, solo puede usar valores de caso que se expanden en una constante de tiempo de compilación única, integral, "dura" (por ejemplo, case 5+6: enum {X = 3}; ... case X*X: .

La forma de evitar esto es utilizar sentencias if . Por ejemplo, para reemplazar

switch (x) case 0..100:

en su lugar

if (x>=0 && x<=100)

.


Las declaraciones de casos de cambio son un sustituto de las sentencias if largas que comparan una variable con varios valores "integrales" (los valores "integrales" son simplemente valores que pueden expresarse como un entero, como el valor de un carácter). La condición de una instrucción switch es un valor. El caso dice que si tiene el valor de lo que sea después de ese caso, haga lo que sigue a los dos puntos. La ruptura se utiliza para romper las declaraciones del caso.

Por lo tanto, no puede usar tales declaraciones condicionales en el caso.

La estructura selectiva: interruptor.


Puede solucionar este problema utilizando una serie de sentencias if / else if . Switch / case no se puede usar de esta manera en C ++.


Puedes hacer lo siguiente:

//summarize the range to one value If score < 0 score = -1 switch(score){ case 1: //... break; case 2: //... break; case -1: //complete neg. range //... break; //...

}


Sé que esta es una pregunta antigua, pero como las declaraciones de switch son envolturas alrededor de etiquetas, creo que goto puede ser de (bueno) uso aquí.

int value = 40; if (value < 10) { std::cout << "value < 10" << std::endl; goto end; } if (value < 50) { std::cout << "value < 50" << std::endl; goto end; } if (value > 30) { std::cout << "value > 30" << std::endl; goto end; } end: // resume

De esta manera, puedes omitir todos los else y mantenerlo compacto. Debes tener cuidado al usar goto (en general).


Se puede hacer usando un std::map with switch :

enum Interval { One, Two, Three, NotFound }; // [0,10[ is One, [10,30[ is Two, [30,55[ is Three std::map<int,Interval> imap { { { 0, One }, { 10, Two }, { 30, Three }, { 55, NotFound } }; Interval ivalue = NotFound; auto f = imap.lower_bound( value ); if( f != imap.end() ) ivalue = f->second; switch( ivalue ) { case One : ... case Two : ... case Three : ... default: ... }


Tuve el mismo problema con un problema basado en la puntuación y mientras que las declaraciones "if / elseif" fueron buenas de usar, por intervalos encontré que era la mejor opción (para mí al menos porque me gusta su aspecto y es más fácil para mí como un principiante para ver mis errores) es "1 ... 10". pero no olvide usar un espacio entre el número y los puntos o el programa pensará que su intervalo es un número y obtendrá un error "2 puntos decimales muchos ...". Espero eso ayude.

int score; int main() { cout<<"Enter score"<<endl; cin>>score; switch(score){ case 100: cout<<"Your score is Perfect"<<endl; break; case 90 ... 99: cout<<"You got A"<<endl; break; case 80 ... 89: cout<<"You got B"<<endl; break; case 70 ... 79: cout<<"You got C"<<endl; break; case 60 ... 69: cout<<"You got D"<<endl; break; case 50 ... 59: cout<<"You got E"<<endl; break; case 0 ... 49: cout<<"You got F"<<endl;} }


Una información potencialmente útil es que el switch acepta una expresión, por lo que puede plegar varios valores de entrada en un solo caso de conmutador. Es un gran feo, pero para su consideración:

switch (score / 10) { case 10: cout << "a"; break; case 9: case 8: case 7: case 6: case 5: cout << "b"; break; case 4: case 3: cout << "c"; break; case 2: if (score >= 25) { cout << "c"; break; } // else fall through... case 1: cout << "d"; break; case 0: cout << (score > 0 ? "e" : "f"); break; default: cout << "BAD VALUE"; break; }

Por supuesto, podría haber dividido por 5 y tener el case 4: (para 20-24) frente al case 5: (25-29) en lugar de un if interno case 2: pero /10 es posiblemente más intuitivo.


Switch-case no es una gran opción para probar rangos. La mejor opción es usar varios if :

if (score<0) cout << "BAD VALUE"; if (score == 0) cout << "f"; if (score>0 && score<10) cout << "e"; if (score>=10 && score <25) cout << "d"; if (score>=25 && score <50) cout << "c"; if (score>=50 && score <100) cout << "b";

Si el tiempo de ejecución es un problema, la siguiente solución es más rápida:

if (score == 0) cout << "f"; else if (score<10) cout << "e"; else if (score <25) cout << "d"; else if (score <50) cout << "c"; else if (score <100) cout << "b"; else if (score>=100) cout << "a"; else cout << "BAD VALUE";


std::map::upper_bound + C ++ 11 lambdas

https://.com/a/35460297/895245 mencionó lower_bound , pero también podemos deshacernos de la enum allí con lambdas (o herencia si no la tiene).

#include <functional> #include <iostream> #include <map> int main() { std::string ret; const std::map<int,std::function<void()>> m{ {0, [&](){ ret = "too small"; }}, {2, [&](){ ret = "[0,2)"; }}, {5, [&](){ ret = "[2,5)"; }}, {7, [&](){ ret = "[5,7)"; }}, }; const auto end = m.end(); for (auto i = -1; i < 8; ++i) { auto it = m.upper_bound(i); if (it == end) { ret = "too large"; } else { it->second(); } std::cout << i << " " << ret << std::endl; } }

Salida:

-1 too small 0 [0,2) 1 [0,2) 2 [2,5) 3 [2,5) 4 [2,5) 5 [5,7) 6 [5,7) 7 too large

Uso dentro de métodos con static

Para usar este patrón de manera eficiente dentro de las clases, inicialice el mapa lambda de forma estática, o de lo contrario pagará n log(n) cada vez que lo construya desde cero.

Aquí podemos salir con la inicialización {} de una variable de método static : variables estáticas en los métodos de clase , pero también podríamos usar los métodos descritos en: constructores estáticos en C ++? Necesito inicializar objetos estáticos privados

Era necesario transformar la captura de contexto lambda [&] en un argumento, o eso habría sido indefinido: const static auto lambda usado con captura por referencia

Ejemplo que produce el mismo resultado que arriba:

#include <functional> #include <iostream> #include <map> #include <string> class RangeSwitch { public: void method(int x, std::string &ret) { static const std::map<int,std::function<void(std::string&)>> m{ {0, [](std::string &ret){ ret = "too small"; }}, {2, [](std::string &ret){ ret = "[0,2)"; }}, {5, [](std::string &ret){ ret = "[2,5)"; }}, {7, [](std::string &ret){ ret = "[5,7)"; }}, }; static const auto end = m.end(); auto it = m.upper_bound(x); if (it == end) { ret = "too large"; } else { it->second(ret); } } }; int main() { RangeSwitch rangeSwitch; std::string ret; for (auto i = -1; i < 8; ++i) { rangeSwitch.method(i, ret); std::cout << i << " " << ret << std::endl; } }