всем привет. в общем, хочется узнать, кто и как привык организовывать некоторые аспекты кода. понимаю, что тема очень расплывчатая, но все же. просто я замайнался с этим делом: напишу с кучей if-ов допустим как в варианте 1.а), а на след. день гляну и все переделаю в вариант 1.б). посему обращаюсь ко всем вам, чтобы вы подсказали как лучше все организовывать, и ответили - как вы поступаете в таких вещах. вот некоторые примеры, которые можно запрограммировать по-разному: пример1: куча if-Ов вариант 1.а) ... if ( OK1() ) { //продолжаем прогу ... ... if ( OK2() ) { //продолжаем прогу ... ... if ( OK3() ) { //продолжаем прогу ... ... ... } else { msgError3(); } } else { msgError2(); } } else { msgError1(); } ... ps: особенно интересен, когда вместо msgErrorX() нужно вообще завершить прогу. в таком случае пришлось бы прописывать кучу однообразных функций выхода ( вместо msgErroX() ), тем самым увеличивая код или использовать устаревший goto на этот выход. как-то некрасиво ИМХА. хотя тот же выход можно было бы "зашить" в msgErrorX(). вариант 1.б) if ( !OK1() ) msgError1(); //продолжаем прогу ... ... if ( !OK2() ) msgError2(); //продолжаем прогу ... ... if ( !OK3() ) msgError3(); //продолжаем прогу ... ... ... ps: а здесь все кажется более просто и красиво. проблему с выходом можно было бы решить как и в варианте 1.a - либо перепрыгивать через goto сразу на выход, либо "зашить" этот выход в msgErrorX(); пример 2: возвращаемые значения. вариант 2.а) BOOL myProc(); BOOL myProc() { if (smth) return TRUE; return FALSE; } main() { ... if ( myProc() ) myProc2(); //что-то делаем else myProc3(); //или это делаем ... return 0; } вариант 2.б) void myProc(); void myProc() { if (smth) myProc2(); else myProc3(); } main() { ... myProc(); ... return 0; } т.е. в варианте 2.б) мы всю логику программы "заворачиваем" в myProc() которая в зависимости от ситуации направляет ход программы либо в myProc2(), либо в myProc3(). а в варианте 2.а) мы всю эту логику по перенаправлению выносим прям в main(), тем самым оставляя функциям "вида" myProc() генерацию самого "дальнейшего направления хода программы", который уже в main() анализируем и исходя из этого строим дальнейшие действия проги. пока что только 2 примера привел, но их гораздо больше. вопрос ко всем - какие варианты реализаций вы бы выбрали в примере 1 и 2? неужели также как и я 1.б и 2.б ? ps: пардон если тема совсем ламская.
тема не про низкоуровневого программирования это точно почитай что нибудь про стандарты и способы кодирования на с ps/ можно исмользовать исключения - они для того и придуманы
staier, поэтому она и в HEAP'e. что тут противозаконного? ты прочитай описание к этому разделу, если что не понимаешь...
противозаконного ничего нет только уж лучше в дзен ... а насчет совета - я серьёзно есть много книг типа "верёвка достаточной длины чтобы вастрелить себе в ногу" , например там есть про то что лучше сделать по варианту 1.б и про исключения я серьёзно . привет.
staier вот, теперь хоть что-то по делу. спасибо, постараюсь достать эту книгу. а про стандарты - не подскажете, где почитать о них можно? т.е. мне вообще-то наджо как бы не про саму алгоритмизацию, а про то - как лучше, целесообразней и правильней написать. т.к. одно и то же написать можно 10ю разными способами. вот.
Вот интересный вариант с макросами: Код (Text): #define BEGIN_BLOCK int iErrCode=0; while (1) { #define END_BLOCK break; } #define RETURN return iErrCode; #define VERIFY(expression,error_code) if (! (expression)) { iErrCode = error_code; break; } int Function () { // declare resources... BEGIN_BLOCK VERIFY (... any expression/function call... , error code for this situation) VERIFY (... any expression/function call... , error code for this situation) VERIFY (... any expression/function call... , error code for this situation) END_BLOCK // Release resources if needed RETURN } Достоинства: 1. Читаемость 2. Нет утечки ресурсов 3. Возврат из функции в единственном числе 4. Всегда правильный код возврата/ошибки (0 - ошибок нет)
varnie Басни про "устаревший goto" это страшилка для начинающих программистов. Посмотри asm-реализацию любого сложного ветвления и перед каждым логическим else\elseif увидишь безусловный jmp, от которого никуда не деться. В частности "запутанный" вариант 1.а) преобразуется компилятором в более простую и наглядную псевдо-asm реализацию: Код (Text): if !OK1 //test goto _msgErr1 //jz ... if !OK2 //test goto _msgErr2 //jz ... if !OK3 //test goto _msgErr3 //jz ... goto _end //jmp _msgErr3: ... goto _end //jmp _msgErr2: ... goto _end //jmp _msgErr1: ... _end: Спрашивается зачем наворачивать многочисленные else, если можно написать проще и понятнее как в асме. Если к тому же "завернуть" все MsgErrorX() в одну MsgError(int ErrCode), тогда вообще все будет просто и наглядно: Код (Text): int ErrCode = 1 if (!OK1()) goto _msgErr ... ErrCode = 2 if (!OK2()) goto _msgErr ... ErrCode = 3 if (!OK3()) goto _msgErr //ErrCode = 0 ... //return X или goto _end _msgErr: MsgError(ErrCode) _end: Получим ту же самую asm-реализацию, только все переходы jz будут идти на одну метку _msgErr
про устаревший goto: Первым от него призвал отказаться Вирт, авторитетно заявив, что goto портит стиль программирования. На C это может и не так заметно, но на Паскале - брр... В языках высокого уровня читабельность кода достаточно высокий критерий - особенно если скомпилировано будет так же как и с goto - так зачем тогда извращаться...
напиши для начала словесно алгоритм. Глаголы в предложении будут функциями. Если не вру, Кнут даже написал какую-то шнягу для литературного программирования. Она используется для разработки сложных алгоритмов.
varnie Напиши задачу, простую,но где будет столько ветвений сколько нужно и дай эту задачу 5рым друзьям, вот тебе и будет не ординарность ибо каждый программер свой огород окучивает, а от сюда и выбор, может и найдешь чего ищешь