Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: как не перепутать = и ==  (Прочитано 26677 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Olegator
Команда клуба

ru
Offline Offline
Пол: Мужской

« : 23-08-2005 01:13 » 

В книге по С++ я прочитал, что для того, чтобы не перепутать = и == можно записывать наоборот.
Т.е. вместо x == 7 записывать 7 == x. И тогда если ошибёшся и запишешь 7 = x, то компилятор выдаст ошибку.
Пользуется ли кто-нибудь этим способом?
« Последнее редактирование: 23-08-2005 01:32 от Olegator » Записан
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #1 : 23-08-2005 04:43 » 

ИМХО надо просто быть внимательней вместо того чтобы использовать сомнительные способы Улыбаюсь
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
Olegator
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 23-08-2005 04:54 » 

Этот сомнительный способ я вычитал из книги "Как программировать на C++, Дейтел Х., Дейтел П", Гл 2 стр 140.
А ты их всё время хвалишь.
Записан
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #3 : 23-08-2005 04:59 » 

Этот сомнительный способ я вычитал из книги "Как программировать на C++, Дейтел Х., Дейтел П", Гл 2 стр 140.
А ты их всё время хвалишь.
Я имел ввиду совсе другое Улыбаюсь
Смотри : x == 7 и 7 == x - в чём разница ? Ты путаешся с = и == ? Так ты итак итак будеш путаться Улыбаюсь Просто лично мне запись вида 7 == x как-то режет глаз неприятно Улыбаюсь

Здесь в любом случае внимательность нужна Улыбаюсь
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
Olegator
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 23-08-2005 05:15 » 

Так ты итак итак будеш путаться
Там написано только про один вариант.
А ты что не ошибаешься?
В этой книге написано, что на этой ошибке даже профессионалы спотыкаются. Почитай, если хочешь. Стр 140. глава 2.20.
Записан
Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 23-08-2005 05:51 » 

Смысл такого подхода не в том, чтобы не ошибиться в лексике языка.

Ошибки, которые может обнаружить компилятор - повседневные. Ошибся, откомпилировал, исправил, откомпилировал еще раз... Ерунда, а не ошибки Улыбаюсь

При использовании описанного подхода ты избавляешься от ошибок совсем другого рода - ошибок выполнения. Иногда очень трудно обнаружить ошибку вроде "if x = 7 { ... } ". Такой вариант компилятор обработает и даже глазом не моргнет. Откуда ему знать, что ты имел ввиду x == 7?

А когда ты используешь 7 == x, то этим ты как бы говоришь компилятору: "я, находясь в твердом уме и зравом рассудке, хочу, чтобы было проведено сравнение 7 и x". Компилятор, воспринимает такую запись, как руководство к действию и категорически пресекает все попытки ошибиться в записи "= или ==".

Мелочь, казалось бы, а опыт показывает, что такие ошибки как раз самые времяемкие при отладке, потому что визуально выявить их - практически нереально. То есть, поможет только пошаговое выполнение программы...

Приверженность к тому или иному стилю  - дело вкуса. Но исходя из собственного опыта могу твердо сказать - мне такой подход помогает.

Кстати, мэтры C/C++-программирования (например, Голуб и Мейерс) советуют поступать также.
В любом случае, окончательное решение только за тобой и неикто тебя не сможет заставить делать так, если вся твоя сущность этому противится Улыбаюсь
« Последнее редактирование: 23-08-2005 05:56 от Hooter » Записан
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #6 : 23-08-2005 05:52 » 

А ты что не ошибаешься?
Конечно ошибаюсь Улыбаюсь
В этой книге написано, что на этой ошибке даже профессионалы спотыкаются. Почитай, если хочешь. Стр 140. глава 2.20.
Спасибо, я уже читал Улыбаюсь

Ладно, хватит демагогии. Раз ты сам вывод не сделал, я тебе подскажу прямым ответом на твой вопрос :
как не перепутать = и ==  ?
НИКАК! Только внимательность при написании.
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #7 : 23-08-2005 05:55 » 

Приверженность к тому или иному стилю - дело вкуса.
Согласен Улыбаюсь
Кстати, мэтры C/C++-программирования (например, Голуб и Мейерс) советуют поступать также.
Кто ж спорит Улыбаюсь
В любом случае, окончательное решение только за тобой и неикто тебя не сможет заставить делать так, если вся твоя сущность этому противится Улыбаюсь
Вот вот Улыбаюсь И я о том же Улыбаюсь Ну может же мне не нравится консрукция вида 7==х Улыбаюсь Может я обожаю с дебагером возиться Улыбаюсь
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 23-08-2005 05:58 » 

Кто ж спорит Улыбаюсь
А никто и не спорит Улыбаюсь
Записан
Pu
Большой босс

ru
Offline Offline
78


« Ответ #9 : 23-08-2005 06:04 » 

Olegator, я так пишу и уже очень давно. Во всяком случае запись вида -
Код:
   if ( 0 == ( m_hThread = (HANDLE)_beginthreadex( (LPSECURITY_ATTRIBUTES) 0,
                                       0,
                                       (unsigned (__stdcall *) (void *))RunBuildProc,
                                       (void *)this,
                                        0, (unsigned *)&m_dwThreadID)))
        {
                return GetLastError();
        }

   

лично меня такая запись больше устраивает, но о вкусах не спорят Ага Хотя за всю свою историю не было случая чтобы я допустил эту ошибку.
« Последнее редактирование: 23-08-2005 06:09 от Pu » Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
Olegator
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 23-08-2005 06:36 » 

Hooter, я именно так всё и понял. Просто я хотел выяснить, пишет ли так хоть кто-нибудь. А то бы стал так писать, а потом бы это никто не принял. Я так и собираюсь писать.
В общем, часто ли вы встречали такое написание программ?
Не будет ли непонимания в этом для других людей?
Морозу например не нравится, как он перед этим написал.
Записан
Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 23-08-2005 07:00 » 

Hooter, я именно так всё и понял. Просто я хотел выяснить, пишет ли так хоть кто-нибудь.
Извини, я просто решил прояснить ситуацию Улыбаюсь

В общем, часто ли вы встречали такое написание программ?
К сожалению, не часто.

Не будет ли непонимания в этом для других людей?
Если ты спрашиваешь, личное мнение, то я считаю, что не будет. Для понимания программы нет разницы в "7 == х" и "х == 7".
А как для тебя будет правильно - со временем сам разберешься.
Записан
Alf
Гость
« Ответ #12 : 23-08-2005 07:20 » 

Этот сомнительный способ я вычитал из книги "Как программировать на C++, Дейтел Х., Дейтел П", Гл 2 стр 140.

Как мне доводилось читать, следование "этому сомнительному способу" учитывается при приеме на работу во многих западных фирмах. За запись вида (0 == i) начисляются дополнительные баллы.

Настоящий профи - не тот, кто никогда не ошибается, а тот, кто принимает все меры к тому, чтобы допущенные ошибки были выявлены как можно скорее и нанесли возможно меньший ущерб. Использование константы слева от оператора сравнения - одна из таких очень просто реализуемых и довольно эффективных мер.
Записан
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #13 : 23-08-2005 07:42 » 

Как мне доводилось читать, следование "этому сомнительному способу" учитывается при приеме на работу во многих западных фирмах. За запись вида (0 == i) начисляются дополнительные баллы.
Ребята, вы меня не так поняли Улыбаюсь Я имел ввиду только то, что если путается, то всё равно будет путаться Улыбаюсь И нету разницы пишеш х == 7 или 7 == х. Как пропускал, так и будеш. Вот я о чём. Тут только внимательность. И использование конструкции 7 == х поможет только легче находить такие ошибки, но не научит САБЖу темы этого поста. Ага
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 23-08-2005 09:34 » 

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

Код:
if (( m_hThread = (HANDLE)_beginthreadex( (LPSECURITY_ATTRIBUTES) 0,
                                       0,
                                       (unsigned (__stdcall *) (void *))RunBuildProc,
                                       (void *)this,
                                        0, (unsigned *)&m_dwThreadID)) == 0)
        {
                return GetLastError();
        }
При чтении надо относительно долго разбирать выражение, отделить присваивание от вызова, явно или неявно считать скобки, чтобы в конечном итоге добраться до главной мысли: если хэндл нового потока равен нулю, то бла-бла-бла.

Другую форму записи того же самого лично мне читать удобнее.
Код:
if ( 0 == ( m_hThread = (HANDLE)_beginthreadex( (LPSECURITY_ATTRIBUTES) 0,
                                       0,
                                       (unsigned (__stdcall *) (void *))RunBuildProc,
                                       (void *)this,
                                        0, (unsigned *)&m_dwThreadID)))
        {
                return GetLastError();
        }
Главная мысль здесь выражена в самом начале: ноль, хэндл нового потока, равны. Пусть это не так гладко звучит, как в первом случае, зато лучше видно Улыбаюсь
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #15 : 23-08-2005 09:54 » 

Я придерживаюсь как ни странно, не смотря на все плюсы "хитровыебанного" отслеживания Улыбаюсь методами МОРОЗа и не пользуюсь методом Пу.

У мення вознимает ошибка между = и == в 12 случае из 10 000 000 и при этом я ее нахожу достаточно легко, как ни странно.
Просто я обычно тестирую все ифы на оба случая (если это возможно) запуская проверку по проходам.
И это как раз помогает сразу увидеть почему я два раза прозожу в if а не по двум разным путям иду.

И главное!!!

Я пишу примерно так:
Код:
result = OK;
while(1){
     if (a == b) {result = ERROR1; break;}
     if (parametr == -1) {result = ERROR1; break;}
     if (param_pointer == NULL) {result = ERROR1; break;}

    /* Good condition - work */
     code of function
    break;
}

if (result !=OK)
{
      /* Error found deinit local pointers and uther initialized data */
}

return result;

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

Таким образом локализуется условие которое не сбылось.
Во вторых я унифицирую процесс поиска внутре функции.
В третьих, нет и не может быть ошибки по теме, ведь тогда всегда ошибка. И ясно где и можно просто посмотреть.

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

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

А птичку нашу прошу не обижать!!!
Pu
Большой босс

ru
Offline Offline
78


« Ответ #16 : 23-08-2005 10:17 » 

npak
Главная мысль здесь выражена в самом начале: ноль, хэндл нового потока, равны. Пусть это не так гладко звучит, как в первом случае, зато лучше видно Улыбаюсь

вот вот, я по этой причине и привел этот пример, если будет извращенец который не в несколько строк запишет это выражение а в одну, тогда вообще операция сравнения уйдет вправо из зоны видимости. А тут тебе пожалста все рядом. И вызов функции и сравнение и присваивание Улыбаюсь.

Гром, для меня вот такая форма записи -
Код:
result = OK;
while(1)
{
     if (a == b) { result = ERROR1; break;}
     if ( -1 == parametr) {result = ERROR1; break;}
     if ( 0 == param_pointer) {result = ERROR1; break;}

    /* Good condition - work */
     code of function
    break;
}

if ( OK != result)
{
      /* Error found deinit local pointers and uther initialized data */
}

return result;

ничуть не менее читабельна, все дело в привычке, Уже столько кода перечитано чужого, что уже без разницы, единственное к чему не могу привыкнуть это к открывающей скобке в конце строки аля
if(...) {
}
но это уже мои личные проблемы Улыбаюсь
Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 23-08-2005 10:41 » 

Код:
result = OK;
while(1){
 if (a == b) {result = ERROR1; break;}
 if (parametr == -1) {result = ERROR1; break;}
 if (param_pointer == NULL) {result = ERROR1; break;}

 /* Good condition - work */
 code of function
 break;
}

if (result !=OK)
{
 /* Error found deinit local pointers and uther initialized data */
}

return result;
...

В третьих, нет и не может быть ошибки по теме, ведь тогда всегда ошибка. И ясно где и можно просто посмотреть.

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

Имхо, данный код не является типичным. Слишком уж узкое применение условий. Гром, ты что, нигде больше условий не используешь, кроме как в таких конструкциях? Опять же, в коде цикла нет ветвления? Бесконечный цикл с инициализацией результата в OK, очень уж похож на программы для сигнальных процессоров. Слишком узкая специализация.
« Последнее редактирование: 23-08-2005 10:49 от Hooter » Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #18 : 23-08-2005 11:45 » 

Hooter
Хм - тебе привести код функции для мультипакетного поиска Full State  при парсинге стрима TCP/IP написанного именно в таком же стиле???

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


Бесконечный цикл здесь - это преимущество оператора break;


А говорить об узости применения такого кода Улыбаюсь это попросту малое колличество опыта....

ИМХО разумеется.
Такой код применим практически во всех функциях, у которых есть вход и выход и работа с сложными параметрами.
Записан

А птичку нашу прошу не обижать!!!
Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 23-08-2005 11:53 » 

Hooter
Хм - тебе привести код функции для мультипакетного поиска Full State при парсинге стрима TCP/IP написанного именно в таком же стиле???

Да уж.. Как говорится, на вкус и цвет... Улыбаюсь

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

Мои привычки прямо противоположны: при нормальности - продолжаю выполнение кода; если сбой - выход. Стараюсь избегать многоуровневых условий.
« Последнее редактирование: 23-08-2005 11:57 от Hooter » Записан
Mayk
Гость
« Ответ #20 : 23-08-2005 12:12 » 

Мне больше нравится ставить максимальный уровень предупреждений вместе с трактовкой предупреждений как ошибок(чтоб компилятор остановился в случае 0 ерроров и пары ворнов). Я свято верю в то,что компилятор предупредит меня, если я ошибусь Улыбаюсь
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #21 : 23-08-2005 13:03 » 

Hooter
Хм - тебе привести код функции для мультипакетного поиска Full State при парсинге стрима TCP/IP написанного именно в таком же стиле???

Да уж.. Как говорится, на вкус и цвет... Улыбаюсь

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

Мои привычки прямо противоположны: при нормальности - продолжаю выполнение кода; если сбой - выход. Стараюсь избегать многоуровневых условий.


Интересно.
Давай не будем говорить о вкусах. Причина проста. Любую программу на С++ можно записать в виде одной длинной строки.

Давай говорить об удобстве.
1. Имеется вполне реальный инструмент.
Привожу пример....


Код:
int * i = malloc(100);

if (!AllocateBuffer()) return FALSE;
if (!AllocateModule()) return FALSE;
if (!AllocateLibraryStruct()) return FALSE;
if (!AllocateInitData()) return FALSE;

return TRUE;

Понятно, что это псевдокод.
Пример нормальной функции аллокации памяти в различных модулях.
Каждый из них может быть и инициализатором объектов и памяти и всего чего угодно....
Каждая функция имеет два возвращаемых значения. Прошло - не прошло.

Авария в такой аллокации не является причиной выхода из программы, а просто ограничивает возможности девайса. Что тоже вполне реальное явление.

Теперь давай ка  рассмотрим код выше...

Зададимся вопросом - правилен ли он?
Отвечу - если ко мне придут и напишут на приеме на работу так как в моем примере - они не прошли ко мне.
Этот код не верен в корне.
При ошибке на втором и далее шагах инициализации при выходе неправильно - зависают некоторые элементы. А они все в одной ф-ии инициализации, и соответственно они должны быть убиты. Более того - аварийный выход должен сопровождаться присвоением 0 во все освобождаемые элементы...

Приведу пример правильно написания кода....

Код:
int result = 1;
while (1)
{
  int * i = malloc(100);

  if (!AllocateBuffer()){ result = 0;  break;}
  if (!AllocateModule()) { result = 0;  break;}
  if (!AllocateLibraryStruct()) { result = 0;  break;}
  if (!AllocateInitData()) { result = 0;  break;}
  break;
}

if (!result)
{
  FreeBuffer();
  FreeModule();
  FreeLibraryStruct();
  FreeInitData();
}
return result;


Если ф-ии аллокации и освобождения написаны так:

Код:
void * AllocSomeone()
{
     if (Someone =- malloc(sizeof(Someonetypedata));
     return Someone;
}

int FreeSomeOne()
{
   if (SomeOne != NULL)
   {
      free(SomeOne);
      SomeOne  = NULL;
   }
     
}

То вышеуказанный код никогда не упадет в рамках одного процесса (потока) разумеется.
А как бы это выглядело при твоей работе....

Код:
void Init()
{

  int * i = malloc(100);

  if (!AllocateBuffer())
      return FALSE;
  if (!AllocateModule())
  {
       FreeBuffer();
       return FALSE;
  }
  if (!AllocateLibraryStruct())
  {
      FreeBuffer();
      FreeModule();
     return FALSE;
  }
  if (!AllocateInitData())
  {
      FreeBuffer();
      FreeModule();
      FreeLibraryStruct();
      return FALSE;
  }

return TRUE;

}


И так во всех случаях.

А теперь представь что таких инициализаций не 4 - а 100 150 - вполне реальная ситуация.... или пусть 25.

И приходится вставлять МЕЖДУ  23 и 24 инитом - еще один инит, таким образом надо еще более расширить - переписать все нижестоящие освобождения дабы деинитить в нужном порядке (этот факт порядка кстати в примере никак не отражен)....

Короче говоря в твоем варианте все происходит именно так.... Колличество одинаковых выховов функций освобождения в зависимости от колличества инициализаций - растет.
А у меня нет вообще. Более того все прозрачно.


Теперь по пункту о невложенных условиях....

Полагаю, что возможность события в случаях:


if (i == 10)
if (pInter->pFilter->pData.setUsed == pInfo->mStringData->offset)
if (axcGetDataEvaluateResult(pFilter, pInfo->pInput) == TRUE)
if (regexTab == pRegex->Table[[Info->RegexCounter - pFilter->pData.Data] )


Все условия должны быть соблюдены ....
Код слегка упрощен от реального Улыбаюсь
Надеюсь не будешь писать одно уловие с &&  объединениями....




Записан

А птичку нашу прошу не обижать!!!
Pu
Большой босс

ru
Offline Offline
78


« Ответ #22 : 23-08-2005 13:30 » 

Код:
try
{
    int * i = malloc(100);
    if ( !AllocateBuffer())
       throw 1;
    if ( !AllocateModule())
       throw 2;
    if ( !AllocateLibraryStruct())
       throw 3;
    if ( !AllocateInitData())
       throw 4;
}
catch( int err)
{
  switch (err)
  {
    case 4:
         FreeInitData();
    case 3:
         FreeLibraryStruct();
    case 2:
       FreeModule();
    case 1:
       FreeBuffer();
    }
}

это я так делаю Улыбаюсь. Мне больше нравиться
« Последнее редактирование: 23-08-2005 13:33 от Pu » Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #23 : 23-08-2005 14:00 » 

Хм - не люблю обрабатывать эксепшн.
Записан

А птичку нашу прошу не обижать!!!
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #24 : 23-08-2005 16:48 » 

А я вообще не люблю С++ - выходит, что мне try-throw-catch не помогут, но есть простые конструкции С (которые и в С++ будут работать) - типа приведенных Громом. Кроме того, кроме С/С++ есть и другие языки.

Приведенный пример с хенделом я бы разделил на присвоение+вызов и сравнение - множество длинных параметров ф-ии делают конструкцию плохочитабельной.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #25 : 23-08-2005 20:02 » 

Гром, я предлагаю вынести это обсуждение в отдельный тред, чтоб не отвлекаться от исходной темы о "7 == х". Улыбаюсь

Мне пришло в голову около пяти вариантов решения твоей задачи.
Я попробую привести здесь только два. Остальные могу рассказать потом, если захочешь.

1. Исключения. Пример уже есть (Pu, спасибо) Улыбаюсь  Кстати, не понимаю, как нелюбовь к исключениям может привести к желанию писать нечитабельный код.

2. Давай теперь посмотрим на код, который ты считаешь единственно правильным.
Код:
int result = 1;
while (1)
{
  int * i = malloc(100);

  if (!AllocateBuffer()){ result = 0;  break;}
  if (!AllocateModule()) { result = 0;  break;}
  if (!AllocateLibraryStruct()) { result = 0;  break;}
  if (!AllocateInitData()) { result = 0;  break;}
  break;
}

if (!result)
{
  FreeBuffer();
  FreeModule();
  FreeLibraryStruct();
  FreeInitData();
}
return result;

Здесь даже вглядываться не надо, чтобы увидеть места, подлежащие рефакторингу.
Я не буду описывать по шагам, а приведу сразу, как бы сделал я.
Код:
// это вместо бесконечного цикла
if (!allocate_all ())
{
  free_all ();
}

...

bool allocate_all ()
{
  return AllocateBuffer()
    && AllocateModule()
    && AllocateLibraryStruct()
    && AllocateInitData();
}

void free_all ()
{
  FreeBuffer();
  FreeModule();
  FreeLibraryStruct();
  FreeInitData();
}

Это решение мне кажется более читабельным и удобным. Куда уж прозрачнее Ага

Остальные мои решения используют массивы указателей или объектов. Если интересно - приведу здесь.


Извини, Гром, но вот код который ты зачем-топриписал мне, я не написал бы Улыбаюсь

А как бы это выглядело при твоей работе....

Код:
void Init()
{

 int * i = malloc(100);

 if (!AllocateBuffer())
 return FALSE;
 if (!AllocateModule())
 {
 FreeBuffer();
 return FALSE;
 }
 if (!AllocateLibraryStruct())
 {
 FreeBuffer();
 FreeModule();
 return FALSE;
 }
 if (!AllocateInitData())
 {
 FreeBuffer();
 FreeModule();
 FreeLibraryStruct();
 return FALSE;
 }

return TRUE;

}
Я за такие вещи своих коллег по рукам бил Улыбаюсь
А вот за эти - тем более:
Код:
if (condition)
{
  if (condition)
  {
    if (condition)
    {
      if (condition)
      {
        if (condition)
        {
            ...
        }
      }
    }
  }
}

Гром, я прекрасно понимаю, что ты упростил код, и мое решение не подойдет к твоим задачам сразу. Однако, мне кажется, что мой подход теперь ясен (не так ли?), его можно адаптировать к любым другим аналогичным задачам.

По поводу пункта о невложенных условиях:
Полагаю, что возможность события в случаях:

if (i == 10)
if (pInter->pFilter->pData.setUsed == pInfo->mStringData->offset)
if (axcGetDataEvaluateResult(pFilter, pInfo->pInput) == TRUE)
if (regexTab == pRegex->Table[[Info->RegexCounter - pFilter->pData.Data] )

Все условия должны быть соблюдены ....
Код слегка упрощен от реального Улыбаюсь
Надеюсь не будешь писать одно уловие с && объединениями....

Видимо, ты здесь чего-то не дописал?
Объясни, плз, почему нельзя объединить все в один if?
« Последнее редактирование: 23-08-2005 20:12 от Hooter » Записан
Alf
Гость
« Ответ #26 : 23-08-2005 20:43 » 

IMHO тут не о чем ломать копья.

Помимо того, что решение, которое предложил Pu, весьма элегантно, оно еще и наиболее корректно из всех, которые я рассмотрел (извиняйте, если что недоглядел; слишком много букв, ниасилил).

В варианте с исключениями, если, скажем, при вызове AllocateModule() возникнет ошибка, то ее обработчик вызовет лишь две функции для освобождения ранее захваченных ресурсов - FreeModule() и FreeBuffer(), остальные вызываться не будут, поскольку нет никакой надобности отдавать обратно то, что ты не успел взять. Остальные варианты предлагают вызывать все функции освобождения ресурсов оптом, независимо от небоходимости. Это как минимум нерационально, а может и оказаться чревато (например, попытка закрыть неоткрытый файл может в свою очередь вызвать ошибку, которую также либо придется обработать, либо не допускать в принципе, явно проверяя состояние файла перед закрытием; в любом случае количество явно ненужных действий умножается).

Повторюсь, что, как и ожидалось, наиболее элегантное решение одновременно является и наиболее корректным. Таков уж закон природы (например, авиаконструкторы точно знают, что красивые самолеты летают лучше некрасивых).
Записан
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #27 : 24-08-2005 04:18 » 

Гром, я предлагаю вынести это обсуждение в отдельный тред, чтоб не отвлекаться от исходной темы о "7 == х". Улыбаюсь
ИМХО от темы отвлеклись сразу же. Опять же ИМХО единственный правильный ответ на САБЖ (причём сабж был вовсе не о "7 == х" как пишет Hooter) - это ВНИМАТЕЛЬНОСТЬ. Иначе всё равно будут проблемы.
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #28 : 24-08-2005 07:04 » 

Hooter
Твой метод переразбиения не катит.
Причина очень проста, мы говорим об устройстве одной функции, а не устройстве кода - верно.
Я сейчас нахожусь в ситуации на работе, когда каждая функция начинается с того, что не просто аллоцирует и проверяет параметры, но и работает с хеш таблицами, готовит под себя данные, что-то заполняет и вычисляет.
При этом каждая работает не с одинаковыми данными, а с разными.
Таким образом твой метод разбиения превратит сегодняшний файл с 20 функциями и длиной в 3-4 тышшы строк в файл с 100 функций и кучей ненужных передач параметров через стек, ведь аллокация нужна в локальном понимании, я взял буфер - обработал передал внутрь получил результаты освободил.

В твоем случае все подготовленные параметры будут аллоцироваться в другой функции передавться мне по поинтерам через стек и кучу параметров, потом так же заполнятся потом снова уходить в глубину возвращаться и потом передаваться в освобождающую функцию. Это не только не красиво, но и плохо вообще. С точки зрения реал-тайм я просто убъю стек кеш и все что только можно бесконечными ненужными действиями, котопрые делать не надо, вместо обычной проверки выхода while(1) и break безусловного однотактного прыжка.

Я уж не говорю, что ты пиешь о "нечитаемом" коде, когда создаешь сам ненужные функции....

Как может человек писать о нечитаемом коде когда предлагает объеденять сложные многоступенчатые вызовы в совершенно неудобочитаемый if Жаль

Вот тебе пример кода по твоему выбору....
Из реального кода между прочим
Код:
for ( j = 0; j < (*pRuleMap)->strData.nData; j++ )
  if (( ((*pRuleMap)->strData.pData[j].index >= pResData->rStartIdx) &&
       ((*pRuleMap)->strData.pData[j].index <= pResData->rEndIdx) ) ) ||
                       ((*pRuleMap)->strData.pData[j].index == pInfo->fState.pStrData) )
{
}

вот так выглядит любой объединенный if с многими условиями.
Интересно - как это можно назвать удобочитаемым кодом?Не понял

Так что давай не будем вешать ярлыки.

Кроме того - ты в другой теме обиделся на Мля... Жаль. Помочь можно 0 но
1. По теме
2. Если есть желание рассмотреть другую тему и показать как бы ты видел эту структуру по поводу библиотек - создавай другую тему и там можно писать все что уголдно....
Зачем обижаться?

Альф - я пишу на С - не на С++ так что красивое решение не катит.
А вот насчет вызова функций. Там приведена их внутренняя структура, т.е. проверка на необходимость удаления.
Лишняя проверка в данном случае не лишняя, она необходима всегда, поэтому как бы я не писал, но если я не знаю сколько мне надо вызвать функций , то могу вынести if который проверит необходимость вызова внизу перед функциями освобождения....

Хотя получится глупо....

Записан

А птичку нашу прошу не обижать!!!
Pu
Большой босс

ru
Offline Offline
78


« Ответ #29 : 24-08-2005 08:54 » 

если сказать о С - тот жеж пример я бы сделал так -
Код:
int f()
{
   int err;
   err = Allocate();
   if ( err)
     Deallocate(err);
}

int Allocate()
{
  int * i = malloc(100);
  if ( !AllocateBuffer())      return 1;
  if ( !AllocateModule())     return 2;
  if ( !AllocateLibraryStruct())  return 3;
  if ( !AllocateInitData())    return 4;
  return 0;
}

void Deallocate(int err)
{
  if ( !err)
    return;
  switch( err)
 {
  case 4:
    FreeInitData();
   case 3:
    FreeLibraryStruct();
  case 2:
    FreeModule();
  case 1:
     FreeBuffer();
  };
}
сорри, ну не люблю я конструкции использующие операторы не по назначению Улыбаюсь. Это я про while. Хотя решение достаточно интересное - сам никогда не пользовался  Отлично. Как это говориться  - изврат понравился Улыбаюсь. А также не люблю многовложенных ифов, вот конкретно, что делает программу плохопонимаемой, особенно вложенный в иф-блок кусок кода строк на 200-300 Улыбаюсь. и занимает практически все тело функции. Уж проще сразу обратное условие и с вещами на выход  Ага
Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines