2013-11-06 2 views
2

Я пытаюсь удалить повторяющиеся строки из моего кода. В настоящее время, это выглядит следующим образом:Вложенные или последовательные логические блоки

if (FALSE == DoFoo(strFile1, strData1)) 
{ 
    return (FALSE); 
} 
if (FALSE == DoFoo(strFile2, strData1)) 
{ 
    return (FALSE); 
} 
if (FALSE == DoFoo(strFile3, strData1)) 
{ 
    return (FALSE); 
} 
if (FALSE == DoBar(strData1)) 
{ 
    return (FALSE); 
} 
if (FALSE == DoFoo(strFile4, strData2)) 
{ 
    return (FALSE); 
} 
if (FALSE == DoFoo(strFile5, strData2)) 
{ 
    return (FALSE); 
} 
if (FALSE == DoFoo(strData1, strData2)) 
{ 
    return (FALSE); 
} 
if (FALSE == DoBar(strData2)) 
{ 
    return (FALSE); 
} 
return (TRUE); 

Я изменил его выглядеть следующим образом:

if (DoFoo(strFile1, strData1)) 
{ 
    if (DoFoo(strFile2, strData1)) 
    { 
     if (DoFoo(strFile3, strData1)) 
     { 
      if (DoBar(strData1)) 
      { 
       if (DoFoo(strFile4, strData2)) 
       { 
        if (DoFoo(strFile5, strData2)) 
        { 
         if (DoFoo(strData1, strData2)) 
         { 
          if (DoBar(strData2)) 
          { 
           return (TRUE); 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
} 
return (FALSE); 

Есть ли стандарт для гнездового МФСА? Существует ли общая договоренность? Обычно это может сбивать с толку вложенное, но поскольку нет ничего сложного, никаких лишних строк кода, кажется, все еще ясно. Какой путь лучше? Или есть ли другой способ сделать это, который был бы более аккуратным и/или короче любого из них?

+0

Вы считаете исключения ... – forsvarir

+0

Что не так с оригинальной серией? Это вполне читаемо и имеет смысл. С серьезным отступом, если читать, по-моему, труднее. –

ответ

1

Там есть лучший способ:

if(DoFoo(strFile1, strData1) && DoFoo(strFile2, strData1) && //etc... 
    return true; 

Или:

if(!DoFoo(strFile1, strData1) || !DoFoo(strFile2, strData1) || //etc... 
    return false; 
+1

Я бы не сказал &&, || было бы лучше, ваш бы сказал, если условие 1 и условие истинны, верните false, где используется || скажет или, что-то похоже на то, к чему он стремится. –

+0

@Sythnet Я разъяснил это. – nhgrif

3

Я бы реализовать его следующим образом:

bool func() { 
    return DoFoo(strFile1, strData1) 
    && DoFoo(strFile2, strData1) 
    && DoFoo(strFile3, strData1) 
    && DoBar(strData1) 
    && DoFoo(strFile4, strData2) 
    && DoFoo(strFile5, strData2) 
    && DoFoo(strData1, strData2) 
    && DoBar(strData2); 
} 
1

Возможно, что-то вроде следующего, который является другая возможность, что избавляется от вложенных операторов if.

Существует уродливый подход, похожий на C, чтобы заставить таблицу выйти правильно, и мы предполагаем, что наличие дополнительных неиспользуемых аргументов не будет проблемой.

Это компилируется и, кажется, работает с Microsoft Visual Studio 2005 в качестве консольного приложения Windows при запуске в отладчике. Разумеется, DoFoo() и DoBar() - это оба заглушки в этом примере, и предполагаемые указатели на символы не указывают ни на что, кроме структуры.

bool DoFoo (char *s1, char *s2) 
{ 
    return true; 
} 
bool DoBar (char *s1) 
{ 
    return true; 
} 

char *strData1; 
char *strData2; 
char *strFile1; 
char *strFile2; 
char *strFile3; 
char *strFile4; 
char *strFile5; 

typedef bool (*xFunc)(char *s1, char *s2); 

typedef struct { 
    xFunc pF; 
    char *s1; 
    char *s2; 
} TableItem; 

bool myFunc(void) 
{ 
TableItem fArray[] = { 
    { DoFoo, strFile1, strData1}, 
    { DoFoo, strFile2, strData1}, 
    { DoFoo, strFile3, strData1}, 
    { (xFunc)DoBar, strData1, NULL}, 
    { DoFoo, strFile4, strData2}, 
    { DoFoo, strFile5, strData2}, 
    { DoFoo, strData1, strData2}, 
    { (xFunc)DoBar, strData2, NULL} 
}; 

bool bRet = true; 
int i = 0; 
for (i = 0; bRet && i < sizeof(fArray)/sizeof(fArray[0]); i++) { 
    bRet = fArray[i].pF(fArray[i].s1, fArray[i].s2) && bRet; 
} 

return bRet; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    myFunc(); 
    return 0; 
} 

EDIT - Еще одна возможность

Другой способ сделать это будет выглядеть следующим образом. Это не требует применения стиля C.

bool DoFoo (char *s1, char *s2) 
{ 
    return true; 
} 
bool DoBar (char *s1) 
{ 
    return true; 
} 

char *strData1; 
char *strData2; 
char *strFile1; 
char *strFile2; 
char *strFile3; 
char *strFile4; 
char *strFile5; 

typedef enum {funcType1 = 1, funcType2} funcType; 

typedef struct { 
    funcType fType; 
    char  *s1; 
    char  *s2; 
} TableItem; 

bool myFunc(void) 
{ 
TableItem fArray[] = { 
    { funcType1, strFile1, strData1}, 
    { funcType1, strFile2, strData1}, 
    { funcType1, strFile3, strData1}, 
    { funcType2, strData1, NULL}, 
    { funcType1, strFile4, strData2}, 
    { funcType1, strFile5, strData2}, 
    { funcType1, strData1, strData2}, 
    { funcType2, strData2, NULL} 
}; 

bool bRet = true; 
int i = 0; 
for (i = 0; bRet && i < sizeof(fArray)/sizeof(fArray[0]); i++) { 
    switch (fArray[i].fType) { 
     case funcType1: 
      bRet = DoFoo (fArray[i].s1, fArray[i].s2); 
      break; 
     case funcType2: 
      bRet = DoBar (fArray[i].s1); 
      break; 
     default: 
      break; 
    } 
} 

return bRet; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    myFunc(); 
    return 0; 
} 

EDIT - Еще одна возможность

Другой способ сделать это будет выглядеть следующим образом. Это довольно прямой C++.

bool DoFoo (char *s1, char *s2) 
    { 
     return true; 
    } 
    bool DoBar (char *s1) 
    { 
     return true; 
    } 

    char *strData1; 
    char *strData2; 
    char *strFile1; 
    char *strFile2; 
    char *strFile3; 
    char *strFile4; 
    char *strFile5; 

class funcObj { 
public: 
    funcObj (bool (*pf) (char *s1, char *s2), char *s1, char *s2); 
    funcObj (bool (*pf) (char *s1), char *s1); 
    funcObj(); 
    ~funcObj() {} 
    bool eval(); 
private: 
    bool (*m_dofoo) (char *s1, char *s2); 
    bool (*m_dobar) (char *s1); 
    char *m_s1; 
    char *m_s2; 
}; 

funcObj::funcObj (bool (*pf) (char *s1, char *s2), char *s1, char *s2) 
{ 
    m_dofoo = pf; 
    m_dobar = 0; 
    m_s1 = s1; 
    m_s2 = s2; 
} 
funcObj::funcObj (bool (*pf) (char *s1), char *s1) 
{ 
    m_dofoo = 0; 
    m_dobar = pf; 
    m_s1 = s1; 
    m_s2 = 0; 
} 

funcObj::funcObj() 
{ 
    m_dofoo = 0; 
    m_dobar = 0; 
    m_s1 = 0; 
    m_s2 = 0; 
} 

bool funcObj::eval() 
{ 
    bool bRet = false; 

    if (m_dofoo) 
     bRet = m_dofoo(m_s1, m_s2); 
    else if (m_dobar) 
     bRet = m_dobar (m_s1); 
    return bRet; 
} 

typedef struct { 
    funcObj fObj; 
} TableItem; 

bool myFunc(void) 
{ 
    funcObj fArray[] = { 
     funcObj(DoFoo, strFile1, strData1), 
     funcObj(DoFoo, strFile2, strData1), 
     funcObj(DoFoo, strFile3, strData1), 
     funcObj(DoBar, strData1), 
     funcObj(DoFoo, strFile4, strData2), 
     funcObj(DoFoo, strFile5, strData2), 
     funcObj(DoFoo, strData1, strData2), 
     funcObj(DoBar, strData2) 
    }; 

    bool bRet = true; 
    int i = 0; 
    for (i = 0; bRet && i < sizeof(fArray)/sizeof(fArray[0]); i++) { 
     bRet = fArray[i].eval(); 
    } 

    return bRet; 
} 
    int _tmain(int argc, _TCHAR* argv[]) 
    { 
     myFunc(); 
     return 0; 
    } 
+0

Действительно интересная идея, и это умный трюк с 'bRet' в условии for. Но зачем включать его в строку назначения? –

+0

@JoeMajsterski, это очень хороший вопрос, и ответ заключается в том, что я был так взволнован по поводу кода, что я не делал окончательной проверки стола! Вы правы, bRet в задании не требуется. Назовите это мозговой икать. –

2

Для этого нет стандарта. Вы можете делать все, что захотите, пока не будете работать над кодом.

Но большинство людей рекомендует избегать этого (ограничивая себя 1-2 уровнями гнездования), потому что такой код трудно читать. Практика показывает, что в большинстве случаев это возможно.

В вашем случае, например, вы можете использовать & & оператор:

if (DoFoo(strFile1, strData1) && 
    DoFoo(strFile2, strData1) && 
    DoFoo(strFile3, strData1) && 
    DoBar(strData1) && 
    DoFoo(strFile4, strData2) && 
    DoFoo(strFile5, strData2) && 
    DoFoo(strData1, strData2) && 
    DoBar(strData2) 
    ) { 
    return FALSE; 
} 

см? Это значительно упрощает код.

В других случаях вы можете использовать

  1. переключатель (...) оператора.
  2. Else, если состав:

    if (A) { 
    
    } else if (B) { 
    
    } else if (C) { 
    ... 
    
  3. Вызовы функций:

    void CheckCoor(...) { 
        if (coor >= ...) { 
        CheckAngle(...); 
        else { 
        CheckPosibilityToChangeCoor(...); 
        } 
    } 
    

Обычно эти 4 варианта достаточно, чтобы избежать более одного уровня вложенности.

Смежные вопросы