nested - resueltos - Reemplazar declaraciones anidadas si
funcion si con varias condiciones y varias respuestas (11)
Las tablas de decisión son donde almacena la lógica condicional en una estructura de datos en lugar de dentro del código mismo .
Entonces, en lugar de esto (usando el ejemplo de @ Pax):
if (i == 1) {
// action 1
} else {
if (i == 2) {
// action 2
} else {
if (i == 3) {
// action 3
} else {
// action 4
}
}
}
haces algo como esto:
void action1()
{
// action 1
}
void action2()
{
// action 2
}
void action3()
{
// action 3
}
void action4()
{
// action 4
}
#define NUM_ACTIONS 4
// Create array of function pointers for each allowed value of i
void (*actions[NUM_ACTIONS])() = { NULL, action1, action2, action3 }
// And now in the body of a function somewhere...
if ((i < NUM_ACTIONS) && actions[i])
actions[i]();
else
action4();
Si las posibilidades para i
no son números enteros de bajo número, entonces podría crear una tabla de búsqueda en lugar de acceder directamente al elemento i
ésimo de la matriz de actions
.
Esta técnica se vuelve mucho más útil que anidada if
s o switch
enunciados cuando tiene una decisión sobre docenas de valores posibles.
Esto está relacionado con un capítulo de código hermoso . Y en ese capítulo leí sobre los ifs anidados.
El autor estaba hablando de if profundamente anidados como orginator de errores y menos legible. Y él estaba hablando de reemplazar los ifs anidados con declaraciones de casos y tablas de decisiones.
¿Alguien puede ilustrar cómo eliminar if anidados con mayúsculas y minúsculas (mayúsculas y minúsculas) y tablas de decisiones?
¿Qué hay de ifs encadenados?
Reemplazar
if (condition1)
{
do1
}
else
{
if (condition2)
{
do2
}
else (condition3)
{
do3;
}
}
con
if (condition1) {
do1;
} else if (condition2) {
do2;
} else if (condition3) {
do3;
}
Esto es muy parecido a la declaración de cambio para condiciones complejas.
Convierta la condición en booleanos y luego escriba la expresión booleana para cada caso.
Si el código fue:
if (condition1)
{
do1
}
else
{
if (condition2)
{
do2
}
else (condition3)
{
do3;
}
}
Uno puede escribirlo como:
bool cond1=condition1;
bool cond2=condition2;
bool cond3=condition3;
if (cond1) {do1;}
if (!cond1 and cond2) {do2;}
if (!cond1 and cond3) {do2;}
Las instrucciones if y switch no son puramente OO. Son una lógica de procedimiento condicional, pero ¡haz un muy buen trabajo! Si desea eliminar estas declaraciones para un enfoque más OO, combine los patrones ''Estado'' y ''Descriptor'' .
Otro ejemplo que algunos idiomas permiten es esto
switch true{
case i==0
//action
break
case j==2
//action
break
case i>j
//action
break
}
También podría considerar usar el patrón Visitor .
Un ejemplo que siempre trato de hacer es reemplazar los anidados muy anidados si es así (en realidad, este no es tan malo, pero los he visto hasta 8 o 9 niveles en la naturaleza):
if (i == 1) {
// action 1
} else {
if (i == 2) {
// action 2
} else {
if (i == 3) {
// action 3
} else {
// action 4
}
}
}
con este:
switch (i) {
case 1:
// action 1
break;
case 2:
// action 2
break;
case 3:
// action 3
break;
default:
// action 4
break;
}
También trato de mantener las acciones lo más pequeñas posible (las llamadas a función son las mejores para esto) para mantener comprimida la instrucción de conmutación (para que no tenga que avanzar cuatro páginas para ver el final).
Las tablas de decisiones, creo, simplemente están configurando indicadores que indican qué acciones deben tomarse más adelante. La sección "más adelante" es una secuencia simple de acciones basadas en esos indicadores. Podría estar equivocado (no será la primera ni la última vez :-).
Un ejemplo sería (la fase de establecimiento de la bandera puede ser complicada si es porque sus acciones son muy simples):
switch (i) {
case 1:
outmsg = "no paper";
genmsg = true;
mailmsg = true;
phonemsg = false;
break;
case 2:
outmsg = "no ink";
genmsg = true;
mailmsg = true;
phonemsg = false;
break;
default:
outmsg = "unknown problem";
genmsg = true;
mailmsg = true;
phonemsg = true;
break;
}
if (genmsg)
// Send message to screen.
if (mailmsg)
// Send message to operators email address.
if (phonemsg)
// Hassle operators mobile phone.
Anidado si es equivalente al operador lógico Y
if (condition1)
{
if (function(2))
{
if (condition3)
{
// do something
}
}
}
Código equivalente:
if (condition1 && function(2) && condition3)
{
// do something
}
En ambos casos, cuando una expresión evalúa falsa, la expresión subsiguiente no será evaluada. Por ejemplo, si la condición1 es falsa, la función () no se invocará y la condición3 no se evaluará.
Solo puede romper una vez que una parte de la validación falló, por ejemplo.
function validate(){
if(b=="" || b==null){
alert("Please enter your city");
return false;
}
if(a=="" || a==null){
alert("Please enter your address");
return false;
}
return true;
}
Bueno, no es una respuesta directa a su pregunta ya que específicamente pregunta acerca de las declaraciones de cambio / caso, pero aquí hay una pregunta similar.
Invierta la instrucción "if" para reducir la anidación
Esto habla sobre la sustitución de if anidados con resúmenes, que regresan temprano, en lugar de verificar progresivamente más y más cosas antes de establecer un valor de retorno.
Para tablas de decisiones, vea mi respuesta a esta pregunta , o mejor aún, lea el capítulo 18 en Code Complete 2 .