Здравствуйте, Rackshas, Вы писали:
R>goto-ненавистники, как вот такой код R>
R>void HZ()
R>{
R> if(!init1()) goto d1;
R> if(!init2()) goto d2;
R> if(!init3()) goto d3;
я так понимаю тут еще какой то код должен быть...
R>d3:
R> destroy3();
R>d2:
R> destroy2();
R>d1:
R> destroy1();
R>}
R>
R>Избавить от goto?
Лехко!
void HZ()
{
if (init1())
{
if(init2())
{
if(init3())
{
какой то код
}
destroy3();
}
destroy2();
}
destroy1();
}
или же для противников синтаксического оверхеда
void HZ()
{
if (init1()) {
if (init2()) {
if (init3()) {
какой то код
}destroy3();
}destroy2();
}destroy1();
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Rackshas, Вы писали:
R>goto-ненавистники, как вот такой код
[skip] R>Избавить от goto?
А зачем? Тебя устраивает как работает? — если да, то менять не надо. Хотя если этот код выполняет то, что я думаю (слишком мало информации) я бы написал так:
Здравствуйте, Timurka, Вы писали:
T>Здравствуйте, Rackshas, Вы писали:
R>>goto-ненавистники, как вот такой код T>[skip] R>>Избавить от goto?
T>А зачем? Тебя устраивает как работает? — если да, то менять не надо. Хотя если этот код выполняет то, что я думаю (слишком мало информации) я бы написал так: T>
Хрен это а не наглядней. Если уровень вложенности будет больше трех — устанешь читать.
В данном случае, это мое сугубо имхо — такой подход доупустим на все 200%. Естествено мы полгаем, что это С. а не С++.
Если интресуют большие подробности, то могу показать код, где это применяется на полную катушку
(код указанный выше) — ралдости от его использования ни на грош
На С++ это делается с помощью scope-guard'ов.
На С — можно наветвить условий. Кстати, если условий слишком много — не повод ли это задуматься о рефакторинге?
На ассемблере от goto вообще никуда не деться (что вы скажете, готоненавистники?) Хотя есть архитектуры, где деться можно — MIPS, кажется.
void YaZnayu()
{
int n = 2;
if(!init1()) n = 0;
else if(!init2()) n = 1;
else if(!init3()) n = 2;
switch(n)
{
case 2: destroy3();
case 1: destroy2();
case 0: destroy1();
}
}
R>
Здравствуйте, Rackshas, Вы писали:
R>goto-ненавистники, как вот такой код R>
Честно говоря — такой код просто кошмарно выглядит.
При этом код еще и неверен. Например при если init2 отработает неверно то должны вызваться destroy2 и destroy1...
+ еще нет вызовов destroyX в случае когда все initX отработали правильно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
CC>Честно говоря — такой код просто кошмарно выглядит. CC>При этом код еще и неверен. Например при если init2 отработает неверно то должны вызваться destroy2 и destroy1... CC>+ еще нет вызовов destroyX в случае когда все initX отработали правильно.
void HZ(){
int flag=0;
flag+=init1()?1:0+init2()?2:0+init3()?4:0;
switch(flag){
case 7:
case 6:
case 5:
case 4:destroy3();
case 3:
case 2:destroy2();
case 1:destroy1();break;
case 0://TODO...
}
}
void HZ(){
int flag=0;
for(int i=0;i<3;i++){
if(flag)
continue;
switch(i){
0:flag+=init1()?1:0;break;
1:flag+=init2()?2:0;break;
2:flag+=init3()?4:0;break;
}
}
switch(flag){
case 7:
case 6:
case 5:
case 4:destroy3();
case 3:
case 2:destroy2();
case 1:destroy1();break;
case 0://TODO...
}
}
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, Pyromancer, Вы писали:
P>>О! даже лучше придумал, чтоб и континуй воткнуть
CC>Ну что? делаем конкурс: кто еще сильнее запутает приведенный кусок кода?
Тот метод, который я приведу внизу, не является прямым эквивалентом этого кода. Но с помощью него можно избавиться от явных goto. Этот стиль обработки ошибок был и остаётся очень популярным на одной платформе (какой догадайтесь сами ).
HRESULT init(void **);
void destroy(void *);
// CHR - Check HRESULT#define CHR(x) \
do \
{ \
hr = x; \
if (FAILED(hr)) \
{ \
DebugLog(hr); \
goto Error; \
} \
} while (0)
HRESULT foo()
{
HRESULT hr = S_OK;
void * d1 = NULL;
void * d2 = NULL;
void * d3 = NULL;
CHR(init(&d1));
CHR(init(&d2));
CHR(init(&d3));
// .. some code
Error:
if (d1) destroy(d1);
if (d2) destroy(d2);
if (d3) destroy(d3);
return hr; // the only return statement in the function
}
Чтобы этот метод работал нужно следовать нескольким правилам:
1. в начале функции объявляется код возврата HRESULT hr = S_OK.
2. все ресурсы объявляются также в начале функции и инициализируются NULL.
3. в теле функции нет return statements. Единственный return — это return hr, который находится в конце функции.
4. метка Error зарезервированна для обработки ошибок.
5. нельзя объявлять переменные не POD классов внутри функции, только в начале. Такой код:
CHR(init(&d1));
RAIIClass obj;
Error:
if (d1) destroy(d1);
return hr;
может очень плохо отработать (или вообще не скомпилируется). Это наблюдение показывает, что данный метод — из разряда агрессивных C-style методов. Он не допускает использование типичных C++-style идиом.
Здравствуйте, Pyromancer, Вы писали:
P>>>О! даже лучше придумал, чтоб и континуй воткнуть CC>>Ну что? делаем конкурс: кто еще сильнее запутает приведенный кусок кода? P>А разве не это цель замены goto на непонятно что?
Неа. Цель — убрать goto так, чтобы код стал более читабелен.
ЗЫ: На реплики про "с goto код более читабелен чем без него" отвечать не стану.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
AS>>Только не MIPS (насколько я помню, мипс это просто некий сабсет RISC с длинным конвейером), а VLIW?
К>Перепутал. Не MIPS, а ARM.
Какое отношение приведенный код имеет к ARM? Архитектурно они обычные risk процессоры, насколько мне помнится. В твоем варианте, как я понимаю, основной упор на отсутствие переходов (хотя неявно они там есть, конечно) — так это машины с VLIW, где этим делом управляет компилятор — см. трансмета, IA64 и эльбрус 3.
Здравствуйте, Andrew S, Вы писали:
AS>Какое отношение приведенный код имеет к ARM? Архитектурно они обычные risk процессоры, насколько мне помнится. В твоем варианте, как я понимаю, основной упор на отсутствие переходов (хотя неявно они там есть, конечно) — так это машины с VLIW, где этим делом управляет компилятор — см. трансмета, IA64 и эльбрус 3.
AS>>Какое отношение приведенный код имеет к ARM? Архитектурно они обычные risk процессоры, насколько мне помнится. В твоем варианте, как я понимаю, основной упор на отсутствие переходов (хотя неявно они там есть, конечно) — так это машины с VLIW, где этим делом управляет компилятор — см. трансмета, IA64 и эльбрус 3.
К>Имеет такое отношение, что у этих процессоров есть условное исполнение команды. К>http://en.wikipedia.org/wiki/Acorn_RISC_Machine
Ну и какое отношение этот код имеет к ARM? На уровне компилятора, что if, что && в данном случае безразлично (у if семантика напротив более естественна для тех же addххх — см. тот же пример в википедии). Условное исполнение есть у многих процессоров, безотносительно их архитектуры. Зато я теперь понял, что это за код — это в стиле perl
Здравствуйте, unreg_flex, Вы писали:
_>Ну раз все так легко, то еще вот этот маленький кусочек тоже переведите, plz!
Можно тоже разрулить, нужно два булевых флага и пучок ифов и брейков,
только скажите куда этот код пойдёт, неохота потом попасть на работу, где надо будет его поддерживать
Здравствуйте, Kolhoz, Вы писали: K> Может хотя бы фамилия автора заставит их, дурачков, задуматься.
Может, хотя бы бан на 30 дней заставит тебя задуматься. Рекомендую освободившееся время, которое ты посвящал оскорблениям посетителей RSDN, потратить на изучение обязательных правил.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, Кодт, Вы писали: К>>Про goto мы уже поговорили, а вот теперь поговорим про МАКРОСЫ на пол-страницы
ДД>Дык повторно используемый код...
Любой объект в конструкторе инициализирует что надо, в деструкторе — разрушает. Если я понял автора первого поста, то ему надо, чтобы:
Был выдержан порядок при инициализации.
Между инициализацией и разрушением выполнилось какой-то действие.
Разрушилось только то, что было создано.
В буквальной же постановке задача смысла не имеет — goto действительно понятнее, чем все эти if'ы.
Возможно, что объект вызывает свой деструктор, если в конструкторе выкинуть исключение. Надо Стандарт смотреть. Если так, то следует убрать вызов Destroy перед throw.
Здравствуйте, Vova123, Вы писали:
V>Не могу вспомнить, а разбираться не хочу.
V>Возможно, что объект вызывает свой деструктор, если в конструкторе выкинуть исключение. Надо Стандарт смотреть. Если так, то следует убрать вызов Destroy перед throw.
Не вызывает. А если в конструкторе есть try/catch, то это плохой конструктор.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском