реклама на сайте
подробности

 
 
6 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> Оператор GoTo, безусловный переход или правила хорошего тона
J_B
сообщение Sep 29 2006, 15:13
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 20
Регистрация: 17-01-06
Пользователь №: 13 275



Почему считается, что "нехорошо" использовать данного оператора?
Go to the top of the page
 
+Quote Post
Yura_K
сообщение Sep 29 2006, 16:02
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 185
Регистрация: 5-05-06
Из: Ekaterinburg, Russia
Пользователь №: 16 821



Как я понимаю, этот оператор неявно присутствует в основных конструкциях структурированных языков. Цикл то не организовать без goto smile.gif. Хотя, например, в C оператор goto присутствует, просто им не рекомендуют пользоваться. Вообщем, все вопросы приходят к разговору о стиле, используемом при разработке ПО (структурированное, объектно-ориентированное программирование и т.д.).


--------------------
Чудес не бывает - бывает мало знаний и опыта!
Go to the top of the page
 
+Quote Post
J_B
сообщение Sep 29 2006, 16:22
Сообщение #3


Участник
*

Группа: Новичок
Сообщений: 20
Регистрация: 17-01-06
Пользователь №: 13 275



Полностью согласен, взять ассемблер - циклов без меток и переходов не бывает. А ПОЧЕМУ в С не рекомендуют, или так сложилось, как байте восемь бит?
Go to the top of the page
 
+Quote Post
ktod
сообщение Sep 29 2006, 16:46
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 27-09-05
Пользователь №: 8 979



Это филосовский вопрос. И ответ на него будет: "В силу некоторых особенностей человеческого разума/мышления".
Пока сами не почувствуете, объяснить более подробно будет сложно.

Сообщение отредактировал ktod - Sep 29 2006, 16:49


--------------------
Ignoramus et Ignorabimus
Go to the top of the page
 
+Quote Post
rezident
сообщение Sep 29 2006, 16:47
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Гм. Когда-то давно (больше 15 лет назад) у нас в универе был курс информатики, который включал в себя изучение языков BASIC и FORTRAN. Там без GOTO у меня как-то не получалось. Как-то совершенно естественно GOTO в структуру языка BASIC ложился. Я в общем и сейчас не профессионал в программировании. Уровень у меня скорее любительский. С языком СИ познакомился лет пять назад. Но ни разу за это время GOTO применять не приходилось и даже не возникало такой нужды. Видимо таковы особенности структуры именно этого языка программирования. ИМХО.
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Sep 29 2006, 16:47
Сообщение #6


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



Я слышал, что причина в том, что не известно будет "откуда" ты пришел в эту часть программы. Ну то есть если есть метка и где то в другом коде 2 ГоТу, то если программа перепрыгнула на метку, нельзя будет сказать откуда именно
Go to the top of the page
 
+Quote Post
bodja74
сообщение Sep 29 2006, 16:56
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 543
Регистрация: 22-10-05
Пользователь №: 9 984



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

ЗЫ Правила хорошего тона - это набитые шишки на ошибках,собственных или чужих.
Go to the top of the page
 
+Quote Post
CD_Eater
сообщение Sep 29 2006, 17:27
Сообщение #8


Частый гость
**

Группа: Новичок
Сообщений: 173
Регистрация: 3-09-04
Из: Moscow
Пользователь №: 595



Программу проще понять, если она состоит из стандартных функциональных блоков: циклов While с пред или пост-условием, циклов с фиксированным числом повтора, вызовов подпрограмм с единственной точкой выхода (а не как в Си), и т.д.

Соблюдение правил хорошего тона облегчает другим людям (да и вам самому по истечении длительного интервала времени) понять вашу программу. Других причин вроде нет.

Соответственно, разные языки с разной степенью удобства позволяют эти правила хорошего тона использовать. В некоторых (напр., BASIC), использовать эти правила очень затруднительно, равно как затруднительно понимать программу на таком языке.
Go to the top of the page
 
+Quote Post
muravei
сообщение Sep 29 2006, 17:31
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 538
Регистрация: 13-08-05
Пользователь №: 7 591



Цитата(CD_Eater @ Sep 29 2006, 21:27) *
В некоторых (напр., BASIC), использовать эти правила очень затруднительно, равно как затруднительно понимать программу на таком языке.

Время от времени пописываю на Визуал Бэйсике, но ГОУ ТО ни разу не использовал.
Go to the top of the page
 
+Quote Post
artem100
сообщение Sep 29 2006, 17:51
Сообщение #10


Участник
*

Группа: Новичок
Сообщений: 41
Регистрация: 20-08-06
Пользователь №: 19 688



go to
не явно присутствует во всех языках всегда
а идет это от гулявших ошибок перекрестных при применении нескольких go to на странице текста более чем 25 строк

конструкция
команда (условие){
что-то делать
}
логически читалась легче

в 1980-ых написаны книги по стилю написания и оформления кода
в 1988-мом Borland рекомендавал в TurboC2.0 постепенно переходить с goto на конструкции for, if и do ,а while еще не был придуман, try еще даже в мечтах не было
Borland извинялся за неоптимальность компилируемого двоичного кода с конструкцией goto
Вот с тех пор рекомендация на подсознательном уровне отложилась как правило для языков высокого уровня.

Жестко вроде нигде не запрещенно
Только рекомендации и извинения за возможные глюки
а кому глюки нужны
Тут бы быстрей как-то что-то

Так что пиши как хочешь и где хочешь, а возможные глюки в самых древних из самых древних библиотек на твоей совести будут tongue.gif
пожелтевшие бумажные 700 листов Borland-овского Help-а еще где-то лежат
но копаться и и цитировать лень
могу только полку показать Im sorry sad.gif

Сообщение отредактировал artem100 - Sep 29 2006, 18:02
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
singlskv
сообщение Sep 29 2006, 18:05
Сообщение #11


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата
Почему считается, что "нехорошо" использовать данного оператора?

Цитата из Бьерн Страуструп "Язык программирования С++" (типа один из разработчиков С++):

3.3.2 Оператор goto

Презираемый оператор goto все-таки есть в С++:

goto идентификатор;

идентификатор: оператор

Вообще говоря, он мало используется в языках высокого уровня, но
может быть очень полезен, если текст на С++ создается не человеком,
а автоматически, т.е. с помощью программы. Например,
операторы goto используются при создании анализатора по заданной
грамматике языка с помощью программных средств.
Кроме того, операторы goto могут пригодиться в тех случаях,
когда на первый план выходит скорость работы программы. Один из
них - когда в реальном времени происходят какие-то вычисления во
внутреннем цикле программы.
Есть немногие ситуации и в обычных программах, когда применение
goto оправдано. Одна из них - выход из вложенного цикла или
переключателя. Дело в том, что оператор break во вложенных циклах
или переключателях позволяет перейти только на один уровень выше.


Цитата(bodja74 @ Sep 29 2006, 20:56) *
Потому что оператор безусловного перехода не сохраняет адресс возврата в стеке,и если допустим
функция в Си физически выступает как подпрограмма ,переходить к ней по безусловному переходу
даже на асме крайне рискованое занятие ,так как в конце есть все шансы встретится с коммандой ret,
которая загрузит из стека адресс возврата неизвестно какого значения и прога уйдет в ступор.

Исчо критика smile.gif простите, если сможете smile.gif
В С/С++ goto не работает за пределами функции, так что проблем со стеком и с возвратом
по ret никогда не может возникнуть, единственная проблемма возникающия со стеком при
использовании goto заключается в следующем:
Код
  for (i=0;i<10;i++)
  {
    char ar[1000];
    if (i==5) goto label1;
  }
label1:

память занимаемая массивом ar[1000] будет возвращена системе только после выхода за
следующий блок { ... }
У Microsoft специально для этих целей вместо goto используется структурная
обработка ошибок (не только для этих целей):
__try {
......
if(...) __leave;
......
}
__finally {
......
}
которая корректно умеет обрабатывать стек.

НО, если Вы поизучаете код который пишет Microsoft, то например
в MFC Вы обнаружите более 70 файлов в которых используется оператор goto blink.gif
Go to the top of the page
 
+Quote Post
singlskv
сообщение Sep 29 2006, 18:39
Сообщение #12


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(J_B @ Sep 29 2006, 19:13) *
Почему считается, что "нехорошо" использовать данного оператора?

Да, забыл добавить:
Лично я считаю применение goto крайним случаем.
Иногда для скорости, а иногда чтобы не писать странные конструкции
которые позволят избежать использования goto.
Go to the top of the page
 
+Quote Post
Леонид Иванович
сообщение Sep 29 2006, 19:09
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 318
Регистрация: 21-07-06
Из: Минск
Пользователь №: 18 986



Единственная ситуация, когда нужен goto, это обработка ошибок. Но в C++ для этого придуманы исключения, которые позволяют обработать ошибки более изящно.


--------------------
Go to the top of the page
 
+Quote Post
bodja74
сообщение Sep 29 2006, 20:32
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 543
Регистрация: 22-10-05
Пользователь №: 9 984



Цитата(singlskv @ Sep 29 2006, 21:05) *
[Исчо критика smile.gif простите, если сможете smile.gif


Без проблем,у меня корона из головы не упадет. smile.gif

Соглашусь со всем так как в Си не силен.
Но позвольте высказать свое ИМХО. smile.gif
Какие операторы не писали и какие бы скобки не ставили,в конечном итоге все сводится к трем елементарным инструкциям переходов - условный,безусловный и переход на подпрограмму
(то есть опять же асм ,так как МК физически еще не научился понимать Си).
Тоесть как будут откомпелированы команды на Си в элементарные команды и будут ли они допущены вообще - это зависит
от интелекта компиллера Си ,а не от самого языка.

Для ПК я пишу на VB6 ,там также с помощью GOTO из функции или подпрограммы не выпрыгнеш и не запрыгнеш ,так как метки для них локальны,но это не значит что на старом и добром TB под ДОС
этого нельзя было делать.

ЗЫ Если кому хочется побольше увидеть команд Jmp под Win (тот же GOTO) - дизасемблируйте прогу,
их количество вас приятно удивит. smile.gif

ЗЫЫ Раскажите чайнику для чего нужен MFC?
Как то был интерес поизучать,зашел в книжный,как увидел габариты этого толмута,так сразу перехотелось,я на полном серьезе - этой книжицей с одного удара по голове можно убить человека.
И перехотелось не потому ,что представил ,как буду долго и нудно ее изучать,а потому что представил,если разгорится спор,как моя жонка будет гонятся с этим толмутом за мной по квартире. smile.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 29 2006, 21:57
Сообщение #15


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(bodja74 @ Sep 29 2006, 23:32) *
И перехотелось не потому ,что представил ,как буду долго и нудно ее изучать,а потому что представил,если разгорится спор,как моя жонка будет гонятся с этим толмутом за мной по квартире. smile.gif
Фигня. Задача решаема. На вопрос "что бы подарить мне на день Варенья" жена получила ответ "Трехтомник Кнута". Ничего, сижу, читаю. Жив :-) В смысле - это жена у меня спрашивала насчет подарка.

Сообщение отредактировал Сергей Борщ - Sep 29 2006, 21:58


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
_artem_
сообщение Sep 29 2006, 22:40
Сообщение #16


учащийся
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 29-10-05
Из: города контрастов
Пользователь №: 10 249



Сколько людей столько и мнений. Если не злоупотреблять, то goto иногда более удобный вариант чем циклы и свитчи с continue и break'ами (imho).

Есть еще другая истина в последней инстанции - файл должен помешаться на одну страницу текста - то есть полностью отображаться на экране дисплея . Так нет у некоторых на файл приходится по сотне килобайтов. Kрайности.

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

Скажу так - каждый прав по своему)


--------------------
Зачем лаять на караван , когда на него можно плюнуть?

Go to the top of the page
 
+Quote Post
J_B
сообщение Sep 30 2006, 04:24
Сообщение #17


Участник
*

Группа: Новичок
Сообщений: 20
Регистрация: 17-01-06
Пользователь №: 13 275



Спасибо высказавшимся, просто написал переход от двоичной в двоично-десятичную (для семисегментников), и вспомнил про гоуту...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Sep 30 2006, 06:10
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(_artem_ @ Sep 30 2006, 01:40) *
Была какая то статья, с которой весь этот садомазоэстетический спор в мире програмистов начался, не помню только ее название.

Началась это на моей памяти Виртом с обоснования теоретической базы "Паскаля" как попытки создать язык идеальный для толкования компилятором ну априори предполагаемый "удобным" для пользователя ввиду его однозначности. Для компилятора, спору нет, goto в большинстве случаев - проблема, ибо начисто ломает его все стандартные "домашние заготовки". Соответственно простые компиляторы давних времен генерили весьма поганый код. Компиляторы поумнели и стали нормально понимать удобные человеку конструкции, идеалисты от компиляции продолжают движение и дошли до "Оберона".
На сегодняшний день причин не использовать в "C" goto в удобном месте нет.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Petka
сообщение Sep 30 2006, 09:43
Сообщение #19


Профессионал
*****

Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886



Цитата(zltigo @ Sep 30 2006, 10:10) *
На сегодняшний день причин не использовать в "C" goto в удобном месте нет.


Хм.... Причина есть! И на сегодняшний день она ещё более актуальна! Дело в том, что сейчас серьёзный проект можно написать только работая в команде разработчиков. И для того, что бы в твоём коде можно было разобраться другому человеку, надо писать по общепринятым "правилам хорошего тона". Одним из правил является форматирование отступами вложенного кода (например тело цикла, условия - так проще найти глазами конец цикла и условия и т.д.). С использованием Goto такое форматирование осуществить в общем случае невозможно, что приводит полному мясу кода, который спустя некоторое время не только сторонний человек понять не сможет, но и даже сам разработчик. А компиляторы тут ни при чём, сейчас они умные. ИМХО любой логичный алгоритм можно изящно записать без Goto. Это как "любую мысль можно передать без мата".
Go to the top of the page
 
+Quote Post
zltigo
сообщение Sep 30 2006, 10:04
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Petka @ Sep 30 2006, 12:43) *
С использованием Goto такое форматирование осуществить в общем случае невозможно, что приводит полному мясу кода, который спустя некоторое время не только сторонний человек понять не сможет, но и даже сам разработчик.

Если выражаться коротко, то это бред.

Цитата
ИМХО любой логичный алгоритм можно изящно записать без Goto.
Это как "любую мысль можно передать без мата".

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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
CD_Eater
сообщение Sep 30 2006, 12:20
Сообщение #21


Частый гость
**

Группа: Новичок
Сообщений: 173
Регистрация: 3-09-04
Из: Moscow
Пользователь №: 595



Цитата(zltigo @ Sep 30 2006, 14:04) *
Цитата(Petka @ Sep 30 2006, 12:43) *

С использованием Goto такое форматирование осуществить в общем случае невозможно, что приводит полному мясу кода, который спустя некоторое время не только сторонний человек понять не сможет, но и даже сам разработчик.

Если выражаться коротко, то это бред.
А если не коротко ? Пока не видно Ваших аргументов. Ждём примера кода, который без GOTO хуже, нежели с GOTO.
imho, максимум, что может дать GOTO - это сократить код на 2-3 строки в ущерб читабельности программы.

Цитата(zltigo @ Sep 30 2006, 14:04) *
Цитата

Это как "любую мысль можно передать без мата".

Причем попав в такую ситуацию я предпочитаю четко и ясно выразить свлю мысль, например словом "пи....ц"
Не уподобляйтесь тем, у кого "косноязычие компенсируется скудоумием". Поверьте - русский язык велик и могуч. Хотя в Ваших краях, наверное, с его изучением туговато. smile.gif
Go to the top of the page
 
+Quote Post
goodwin
сообщение Sep 30 2006, 12:41
Сообщение #22


Местный
***

Группа: Свой
Сообщений: 481
Регистрация: 1-08-05
Пользователь №: 7 267



Совсем недавно была дискуссия на телесистемах по поводу возвращения к началу обработки из нескольких вложенных циклов в подпрограмме. Всякие флаги, исключения - вот где настоящий изврат, по сравнеию с goto...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Sep 30 2006, 12:52
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(CD_Eater @ Sep 30 2006, 15:20) *
А если не коротко ?

А не коротко, по поводу отцитированного ничего и не скажешь :-(.
Цитата
Хотя в Ваших краях, наверное, с его изучением туговато.

Тем не менее, я полагаю, что достаточно хорошо им (как в прочем и "C" ) владею и вполне внятно выразил причины использования и присутствия goto во всех реальных языках программирования не смотря на многодесятилетние теоретические размышления о "вреде", "возможности обойтись" и мифической "читабельности".
Цитата
Поверьте - русский язык велик и могуч.

И делает его могучим именно присутствие элементов живого языка, таких как обсуждаемый здесь goto, и выгодно отличает его от "легко читаемых" с выброшенными "ненужностями" искусственных языков, типа Эсперанто.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
J_B
сообщение Sep 30 2006, 14:27
Сообщение #24


Участник
*

Группа: Новичок
Сообщений: 20
Регистрация: 17-01-06
Пользователь №: 13 275



Особо переделкой без goto не занимался, но кто что скажет:
VAL=0;
X=100;
foR(I=0;I<=2;I++)
{
LABEL:
TMP_P=TMP;
TMP=TMP-X;
if(TMP<0)
{
SEG[i]=VAL;
VAL=0;
TMP=TMP_P;
X=X/10;
}
else
{
VAL=VAL++;
goto LABEL;
}

}

Смысл таков:
есть заранее неизвестное значение (16р) в диапазоне 0-999 - TMP.
Вывод на тройной индикатор SEG0-2. Идея:" Способ преобразования заключается в том, чтобы, вычитая из исходного числа число 100, сначала определить десятичную цифру десятков сотен. Затем находится цифра десятков последовательным вычитанием числа 10 и т. д. Вычитание каждый раз производится до получения отрицательной разности с подсчетом числа вычитаний. При переходе к определению каждого следующего десятичного разряда в регистрах исходного числа восстанавливается последняя положительная разность"
Go to the top of the page
 
+Quote Post
Petka
сообщение Sep 30 2006, 14:40
Сообщение #25


Профессионал
*****

Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886



Цитата(zltigo @ Sep 30 2006, 14:04) *
Цитата(Petka @ Sep 30 2006, 12:43) *

С использованием Goto такое форматирование осуществить в общем случае невозможно, что приводит полному мясу кода, который спустя некоторое время не только сторонний человек понять не сможет, но и даже сам разработчик.

Если выражаться коротко, то это бред.

Аргументы?
В электронику я перешёл из "программистов". Могу позволить себе утверждать, что Вы не до конца освоили работу в команде, как и отличие языков высокого уровня от низкого. Недавно в форуме пробегала ссылка на "косметику для программистов". Советую ознакомится.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Sep 30 2006, 14:56
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(J_B @ Sep 30 2006, 17:27) *
Смысл таков:

Если не касаться прочих многочисленных, назовем - странностей, то
просто вообще уберите две строки
label:
и
goto label;
и добавьте цикл с break;

Если зачем-то кто-то пишет такое, то я начинаю понимать Petka :-)


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
zltigo
сообщение Sep 30 2006, 15:07
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Petka @ Sep 30 2006, 17:40) *
Аргументы?

Попробуйте преречитать написанное Вами:
Цитата
Одним из правил является форматирование отступами вложенного кода (например тело цикла, условия - так проще найти глазами конец цикла и условия и т.д.). С использованием Goto такое форматирование осуществить в общем случае невозможно....

Я искренне не понимаю какие аргументы от меня требуются :-((((


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
xemul
сообщение Sep 30 2006, 15:45
Сообщение #28



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(J_B @ Sep 30 2006, 18:27) *
Особо переделкой без goto не занимался, но кто что скажет:
Код
VAL=0;
X=100;
for(I=0;I<=2;I++)
{
LABEL:
   TMP_P=TMP;
   TMP=TMP-X;
   if(TMP<0)
   {
      SEG[i]=VAL;
      VAL=0;
      TMP=TMP_P;
      X=X/10;
   }
   else
   {
      VAL=VAL++;
      goto LABEL;
   }
}

Смысл таков:
есть заранее неизвестное значение (16р) в диапазоне 0-999 - TMP.
Вывод на тройной индикатор SEG0-2. Идея:" Способ преобразования заключается в том, чтобы, вычитая из исходного числа число 100, сначала определить десятичную цифру десятков сотен. Затем находится цифра десятков последовательным вычитанием числа 10 и т. д. Вычитание каждый раз производится до получения отрицательной разности с подсчетом числа вычитаний. При переходе к определению каждого следующего десятичного разряда в регистрах исходного числа восстанавливается последняя положительная разность"

Скажу только, что
Код
      goto LABEL;

здесь абсолютно бессмысленен, т.к. точно такой же по смыслу переход уже присутствует в силу организации цикла.
По сути программы: если Вы хотели уйти от деления, Вам это таки не удалось.
Сделайте хотя бы так:
Код
   if(TMP<0)
   {
      SEG[i]=VAL;
      VAL=0;
      TMP=TMP_P;
      if(X==100) X=10;
      else if(X==10) X=1;
      else break;
   }

А еще проще посмотреть сорцы для BCD преобразования.

Бр-р-р. Не посмотрел на уловия цикла. Здесь и goto не поможетsmile.gif.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Sep 30 2006, 15:55
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Код
    seg[0] = tmp/100;
    seg[2] = tmp%10; tmp /= 10;
    seg[1] = tmp%10;


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
xemul
сообщение Sep 30 2006, 16:02
Сообщение #30



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(zltigo @ Sep 30 2006, 19:55) *
Код
    seg[0] = tmp/100;
    seg[2] = tmp%10; tmp /= 10;
    seg[1] = tmp%10;

Ну так не интересноsmile.gif. Без выподвывертов-то biggrin.gif.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Sep 30 2006, 16:08
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Выскажусь тоже про goto... так как несколько раз приходилось применять его в проектах на Си под х86 и AVR. Использовал его в вот в таком частном случае:

Код
// Глобальная переменная, изменяемая сторонним потоком
g_Value;

// Главный цикл
for(char x = 0; x < 100; x++)
{
выполняем полезную работу
......................

еще один цикл
for(char y = 0; y < 200; y++)
{
выполняем еще одну полезную работу
.....................

и еще один цикл
for(char i = 0; i < 300; i++)
{
// проверяем глобальную переменную
if(KILL_ALL_CYCLES == g_Value)
{
goto down;
}
else
{
выполняем еще одну полезную работу
}


}


}


}

down:
// едем дальше


--------------------
Go to the top of the page
 
+Quote Post
_artem_
сообщение Sep 30 2006, 17:08
Сообщение #32


учащийся
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 29-10-05
Из: города контрастов
Пользователь №: 10 249



Я использую goto, но это не тот случай. Не проверял на ошибки - проверьте все ли там холосо):


Код
for(I=0;I<=2;I++)
{
LABEL:
   TMP_P=TMP;
   TMP=TMP-X;
   if(TMP<0)
   {
      SEG[i]=VAL;
      VAL=0;
      TMP=TMP_P;
      X=X/10;
   }
   else
   {
      VAL=VAL++;
      goto LABEL;
   }
}


for(I=0;;)
{
   TMP_P=TMP;
   TMP=TMP-X;
   if(TMP<0)
   {
      SEG[i]=VAL;
      VAL=0;
      TMP=TMP_P;
      X=X/10;
      if(++I > 2)
         break;
   }
   else
      VAL=VAL++;
}


--------------------
Зачем лаять на караван , когда на него можно плюнуть?

Go to the top of the page
 
+Quote Post
WHALE
сообщение Sep 30 2006, 18:40
Сообщение #33


Знающий
****

Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768



2 artem_ Вы про цикл с постусловием do while слышали?В вашем случае goto абсолютно ни к селу
ни к городу.


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post
_artem_
сообщение Sep 30 2006, 19:55
Сообщение #34


учащийся
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 29-10-05
Из: города контрастов
Пользователь №: 10 249



WHALE, во первых я не из пешеры), во вторых это не мой случай а xemul'a,) в третьих я против использования
goto в этом примере) в четвертых был бы рад если Вы показали Ваш собственный вариант этой функции с использованием конструкции do/while.


--------------------
Зачем лаять на караван , когда на него можно плюнуть?

Go to the top of the page
 
+Quote Post
WHALE
сообщение Sep 30 2006, 21:25
Сообщение #35


Знающий
****

Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768



for(I=0;I<=2;I++)
{
do{
TMP_P=TMP;
TMP=TMP-X;
if(TMP>=0) ++VAL;
}
while(TMP>=0)
SEG[i]=VAL;
VAL=0;
TMP=TMP_P;
X=X/10;
}

_artem_Извиняюсь,погорячился,тоже кривовато получается,но все-таки можно и без GOTO cranky.gif
Еще раз извиняюсь,прочел предыдущую страницу,это все вообще не из той оперы.


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post
_artem_
сообщение Sep 30 2006, 22:17
Сообщение #36


учащийся
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 29-10-05
Из: города контрастов
Пользователь №: 10 249



Да никаких извинений не нужно, не обиделся.) Я сам грешу этим довольно таки часто.
Удачи.


--------------------
Зачем лаять на караван , когда на него можно плюнуть?

Go to the top of the page
 
+Quote Post
Rst7
сообщение Oct 1 2006, 06:54
Сообщение #37


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Господа, о чем речь? Посмотрите в исходники библиотеки - функция printf, а точнее _formatted_write - там с goto все в порядке - в смысле - дофига wink.gif


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
bve
сообщение Oct 1 2006, 15:19
Сообщение #38


Местный
***

Группа: Свой
Сообщений: 316
Регистрация: 20-02-05
Из: Ленинградская обл.
Пользователь №: 2 765



Мне кажется, что "ноги растут" от старинного труда Дейкстры"Структурное программирование".
В нем как раз обосновывались принципы написания кода, которые, в теории, должны были
уменьшить количество ошибок и облегчить жизнь программистам.
В том числе там рекомендовались и разбиение на куски ( процедуры ) размером не более экрана-двух,
стиль "программирование сверху-вниз" и "снизу-вверх", и т.д.
Оператор GOTO и попал там в опалу, поскольку нарушал стройность и красивость....
А по делу - пишите - как удобнее, только комментариев побольше.....
Go to the top of the page
 
+Quote Post
_artem_
сообщение Oct 1 2006, 15:39
Сообщение #39


учащийся
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 29-10-05
Из: города контрастов
Пользователь №: 10 249



Вы правы - http://en.wikipedia.org/wiki/GOTO

Но что интересно:

"there are some tasks that cannot be straightforwardly accomplished in many programming languages without the use of GOTO statements, such as breaking out of nested loops and exception handling."

и имхо это действительно так.


--------------------
Зачем лаять на караван , когда на него можно плюнуть?

Go to the top of the page
 
+Quote Post
_Bill
сообщение Oct 2 2006, 07:48
Сообщение #40


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(J_B @ Sep 29 2006, 18:13) *
Почему считается, что "нехорошо" использовать данного оператора?

Дурным тоном в программировании является не само использование оператора goto, а его частое и неоправданное использование. В таких случаях программа получается запутанной и трудной для понимания, а, стало быть, для отладки или соправождения. Современные языки программирования (Си в том числе) имеют управляющие конструкции, позволяющие в принципе обходится без goto. Однако в ряде случаев использование goto позволяет сделать программу более понятной. Речь идет о тех случаях, когда необходимо сделать выход из вложенных циклов. В таких случаях оператор goto позволяет исключить введение множества флагов, используемых для проверки условия принудительного выхода из циклов. При этом программа получается не только более наглядной, но и более эффективной.
Основное правило использования goto - переход только вперед. Если goto используется для перехода назад, то это означает, что необходимо воспользоваться каким-либо оператором цикла и/или оператором принудительного перехода к очередной итерации цикла - continue.
А вообще, непонятную и нечитаемую программу можно легко написать и не используя оператор goto. Это часто происходит потому, что человек еще не совсем представляет что именно ему нужно. Поэтому, прежде чем писать код, лучше сначала продумать структуру программы. Методы структурного программирования известны не один десяток лет. В современных языках программирования имеются все необходимые конструкции для создания структурированных программ: последовательно исполняемые операторы (простые и составные), операторы ветвления (if, if...else, switch (case), goto), цикла (while, do...while, for).
Мои размышления о "косметики" программ можно найти здесь.
Go to the top of the page
 
+Quote Post
AVNN
сообщение Oct 2 2006, 08:22
Сообщение #41


Участник
*

Группа: Участник
Сообщений: 34
Регистрация: 28-09-06
Из: Минск
Пользователь №: 20 776



Что касается AVR и goto, то при использовании оптимизации кода по размеру, этот оператор опасно использовать. При использавании Cross Call могут действительно возникнуть проблемы со стеком. Так что лучше не рисковать! Можно просто поэкпериментировать, компилируя программу с разными настройками оптимизации - хороший код должен работать в любом случае.
Go to the top of the page
 
+Quote Post
_Bill
сообщение Oct 2 2006, 08:35
Сообщение #42


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(AVNN @ Oct 2 2006, 11:22) *
Что касается AVR и goto, то при использовании оптимизации кода по размеру, этот оператор опасно использовать. При использавании Cross Call могут действительно возникнуть проблемы со стеком. Так что лучше не рисковать! Можно просто поэкпериментировать, компилируя программу с разными настройками оптимизации - хороший код должен работать в любом случае.

А какие тут могут бть проблемы?
Go to the top of the page
 
+Quote Post
defunct
сообщение Oct 2 2006, 10:12
Сообщение #43


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Всякий овощ полезен будучи приготовленным надлежащим образом. ©
Go to the top of the page
 
+Quote Post
ValBag
сообщение Oct 24 2007, 06:19
Сообщение #44


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 15-03-07
Пользователь №: 26 183



Во всех наставлениях по СИ для МК "...настоятельно не рекомендуется использовать оператор безусловного перехода goto, т.к. он затрудняет понимание программ и возможность их модификаций...". В то же время другими операторами СИ не всегда удобно осуществлять переходы, а в ассемблере применение команд jmp и rjmp ограничений почти нет.
Для примера в программе "кодовый замок" из книги Белова А.В., в небольшом тексте программы на CИ в модуле main 7 переходов. И все работает нормально. Может быть, кто то потвердит вводное утверждение и покажет как надо на приложенном тексте.
Прикрепленные файлы
Прикрепленный файл  Zamok.txt ( 4.23 килобайт ) Кол-во скачиваний: 84
 
Go to the top of the page
 
+Quote Post
bodja74
сообщение Oct 24 2007, 06:40
Сообщение #45


Знающий
****

Группа: Свой
Сообщений: 543
Регистрация: 22-10-05
Пользователь №: 9 984



В ассемблере вообще ни в чем ограничений нет smile.gif

Просто для себя нужно уяснить простую вещь,если вы перейдете на подпрограмму по jmp или rjmp
(тот же GOTO) ,вы из нее уже не вернетесь smile.gif
Go to the top of the page
 
+Quote Post
DASM
сообщение Oct 24 2007, 06:45
Сообщение #46


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



Чисто в лоб типа такого
Код
while (1)
{


    do
    {

        while (incod() != klfree); // Ожидание отпускания кнопок
        while (incod() == klfree); // Ожидание нажатия кнопок
        ii=0;    
        do
        {    
#asm("cli");               // Запрещаем прерывания
            wait(1);                   // Задержка 1-го типа
            codS=incod();              // Ввод кода и запись, как старого
            bufr[ii++]=codS;           // Запись очередного кода в буфер
            if (ii>=bsize) break;    // Проверка конца буфера
            wait(2);                        // Задержка 2-го типа    
            do
            {
                if (incod() != codS) break;   // Проверка не изменилось ли состояние

            } while((flz==0));  // Проверка окончания контрольного промежутка времени
        }
        while(1);    

        if (PINB.7==1)
        {
            if (klen!=ii) continue;              // Проверка длины кода
        }
        //------------------------------ Запись кода в EEPROM
        klen=ii;                                // Запись длины кода
        for (i=0; i<ii; i++)
            bufe[i]=bufr[i];  // Запись всех байтов кода
        break;

        //------------------------------ Проверка кода
        if (klen!=ii) continue;              // Проверка длины кода
        for (i=0; i<ii; i++)  
            if (bufe[i]!=bufr[i]) continue;  // Проверка самого кода
        break;
        //------------------------------ Открывание замка
    }
    while(1);
    PORTB.4=1;        // Открываем замок
    wait(3);          // Задержка 3-го типа
    PORTB.4=0;        // Закрываем замок
};

Может есть ошибки, да и упростить можно, но суть та же goto нафик не нужен
При чем тут AVR кстати ?

Цитата(ValBag @ Oct 24 2007, 10:19) *
В то же время другими операторами СИ не всегда удобно осуществлять переходы

Кто такое сказал, автор или Вы?
goto реально упрощает обработку чего-то экстраординарного, но для этого лучше применть блоки try catch в С++
Go to the top of the page
 
+Quote Post
alexander55
сообщение Oct 24 2007, 07:01
Сообщение #47


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(ValBag @ Oct 24 2007, 10:19) *

goto считаю атавизмом и С не использую, т.к. потребности никогда не возникает (а в Basic использовал).
Go to the top of the page
 
+Quote Post
IEC
сообщение Oct 24 2007, 07:07
Сообщение #48


Местный
***

Группа: Свой
Сообщений: 263
Регистрация: 22-03-05
Из: г. Харьков, Украина
Пользователь №: 3 598



Ну результат почти такой же. В текущем примере из-за goto тяжело понять логику, поэтому пришлось импровизировать. Пример можно еще оптимизировать.
А вообще-то стиль написания напомнил asm. Видимо человек до этого долго писал на нем, отсюда логика построения функции.

А в бейсике без него сильно не поработаешь :-)
Прикрепленные файлы
Прикрепленный файл  Zamok_1.txt ( 4.44 килобайт ) Кол-во скачиваний: 99
 
Go to the top of the page
 
+Quote Post
dxp
сообщение Oct 24 2007, 07:19
Сообщение #49


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(ValBag @ Oct 24 2007, 13:19) *
Во всех наставлениях по СИ для МК "...настоятельно не рекомендуется использовать оператор безусловного перехода goto, т.к. он затрудняет понимание программ и возможность их модификаций...". В то же время другими операторами СИ не всегда удобно осуществлять переходы, а в ассемблере применение команд jmp и rjmp ограничений почти нет.

Существует очень мало ситуаций, где этот оператор действительно необходим. В ~90% случаев это выход из вложенных циклов. Собсно, для этого оператор и оставили в языке. При всяком его применении нужно минимум дважды задуматься, действительно ли он тут необходим или задача может быть решена другими средствами. И уж злоупотребление (т.е. применение где ни попадя) им во всяком случае должно быть предотвращено.

P.S. Вообще-то, это вопрос для FAQ, его постоянно задают начинающие. smile.gif И частенко обсуждения достоинств и недостатков этого оператора приводят к "религиозным" войнам, по какой причине в некоторых местах (например, в фидо-эхе su.c-cpp) обсуждение оператора goto объявлено офтопиком и преследуется модератором по закону. smile.gif


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 24 2007, 07:19
Сообщение #50


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Продолжаем в уже существующей ветке:
http://electronix.ru/forum/index.php?showt...l=goto&st=0


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
andron86
сообщение Oct 24 2007, 07:23
Сообщение #51


Местный
***

Группа: Участник
Сообщений: 406
Регистрация: 1-03-06
Пользователь №: 14 821



Цитата(ValBag @ Oct 24 2007, 08:19) *
Для примера в программе "кодовый замок" из книги Белова А.В., в небольшом тексте программы на CИ в модуле main 7 переходов. И все работает нормально. Может быть, кто то потвердит вводное утверждение и покажет как надо на приложенном тексте.


Работать goto будет всегда, если правильно запрограммировал! Просто суть в том, что человеку будет труднее понять вашу функцию с 7 ohmy.gif goto, хотя и спорно. Мне, например труднее понять с do while.

Вообщее это дело вкуса.
Go to the top of the page
 
+Quote Post
alexander55
сообщение Oct 24 2007, 07:58
Сообщение #52


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(andron86 @ Oct 24 2007, 11:23) *
Работать goto будет всегда, если правильно запрограммировал!

Я бы не был таким оптимистом. М.б. при использовании другого компилятора, будет как раз неправильно с использованием goto. Или небольшое изменение с добавлением скобочек {}, подумайте и станет печально. Разве это хорошо ?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 24 2007, 08:07
Сообщение #53


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(alexander55 @ Oct 24 2007, 10:58) *
М.б. при использовании другого компилятора....

Вот так и рождаются предрассудки sad.gif. Сказал "может быть", помянул всуе "компилятор" и все понеслось...


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
alexander55
сообщение Oct 24 2007, 08:13
Сообщение #54


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(zltigo @ Oct 24 2007, 12:07) *
Вот так и рождаются предрассудки sad.gif. Сказал "может быть", помянул всуе "компилятор" и все понеслось...

Я замолкаю. Такие темы меня заводят. smile.gif
Go to the top of the page
 
+Quote Post
andron86
сообщение Oct 24 2007, 08:38
Сообщение #55


Местный
***

Группа: Участник
Сообщений: 406
Регистрация: 1-03-06
Пользователь №: 14 821



Цитата(alexander55 @ Oct 24 2007, 09:58) *
подумайте и станет печально.

Печального ничего не будет, если всё правильно сделали wink.gif
Go to the top of the page
 
+Quote Post
ValBag
сообщение Oct 24 2007, 09:49
Сообщение #56


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 15-03-07
Пользователь №: 26 183



Прошу прощения за создание новой темы без поиска.
Как заметил IEC и andron86 я начинал с ASM-а, поэтому c GoTo программа читается "влет", а труднее понять с do while и т.п.

DASM
Просьба еще раз просмотреть Ваш код и поправить неточности. Для меня это было бы хорошим наглядным пособием!
То, что мне непонятно:
1. Нет выхода из последнего вложенного цикла while(1).
2. Как мы попадаем в сегмент проверки кода?
3. В предпоследнем операторе while(1) первый оператор continue должен передать управление на следующую итерацию упомянутого while(1), но это неверно по сути того, что должна делать программа. Должен быть переход на первый оператор while(1).
Может быть я ошибаюсь. Просьба меня поправить.
Go to the top of the page
 
+Quote Post
Maddy
сообщение Oct 24 2007, 10:02
Сообщение #57


Участник
*

Группа: Validating
Сообщений: 56
Регистрация: 15-10-06
Пользователь №: 21 335



А собственно чего все так на бедного goto оплчились ? IMHO Даден инструмент в языке - надо - пользуйся , только думай что делаешьwink.gif Молотком тоже можно самого себя прибитьwink.gif но их-же никто не запрещает...
А ведь были еще setjmp/longjmp wink.gif про них вообще можно много интересного рассказать wink.gif и тож goto в каком-то смысле wink.gif

Сообщение отредактировал Maddy - Oct 24 2007, 10:02
Go to the top of the page
 
+Quote Post
aesok
сообщение Oct 24 2007, 10:04
Сообщение #58


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



GCC Bugzilla:

Only very good and very bad programmers use goto in C
Go to the top of the page
 
+Quote Post
DASM
сообщение Oct 24 2007, 10:19
Сообщение #59


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



Не отношу себя ни к вери гуд ни вери бэд, но со временем согласен, все меньше следую умным книжкам и пользую то, что удобно.
ValBag - выходы там по break , но ошибки у меня есть точно, а голова после ночных посиделок не варит, попробуйте сами напрячься smile.gif
Go to the top of the page
 
+Quote Post
alexander55
сообщение Oct 24 2007, 10:21
Сообщение #60


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(aesok @ Oct 24 2007, 14:04) *
Only very good and very bad programmers use goto in C

Наверное, в этом все дело. a14.gif
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 24 2007, 11:46
Сообщение #61


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(IEC @ Oct 24 2007, 09:07) *
А вообще-то стиль написания напомнил asm.
Там комментарий есть такой вот
This program was produced by the CodeWizardAVR V1.24.4 Standard Automatic Program Generator
Не знаю - что за генератор и из чего он генерировал, но на "трансляцию" блок-схемы с ромбиками проверки условий очень похоже.
А транслятору блок-схем в С как промежуточный язык можно и разрешить ставить goto в немеряных количествах - пока получившийся текст не предназначен для чтения человеком и пока "сопровождается" блок-схема, а не сгенерированный из неё С-код.

Честно говоря, программа и организована как-то странно, "первым проходом" я её переписал бы так:
CODE
#define F_CPU 4000000UL
#include <tiny2313.h>

#define SYSTICK_MS 25 // приблизительно 24 мс период прерываний
// прескалер для таймера 1 1/64
#define SYSTICK_DELTA ((F_CPU / 64 * SYSTICK_MS + 500) / 1000) // смещение OCR
// времена в милисекундах, максимум SYSTICK_MS * 255
#define KEY_TIMEOUT (1000 / SYSTICK_MS)
#define LOCK_DELAY (3000 / SYSTICK_MS)
#define KEY_MASK 0x77F // маска используемых клавиатурой битов
#define BSIZE 30 // Размер буфера для хранения кода

unsigned int bufr[BSIZE]; // Буфер в ОЗУ для хранения кода
#pragma warn-
eeprom unsigned char klen; // Ячейка для хранения длины кода
eeprom unsigned int bufe[BSIZE]; // Буфер в EEPROM для хранения кода
#pragma warn+

volatile unsigned char timeout;
volatile unsigned key_filtered = 0;
volatile unsigned char key_changed = 0;

// Прерывание по совпадению в канале A Таймера 1
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
static unsigned prev;
unsigned current;

OCR1A += SYSTICK_DELTA;
if( timeout) --timeout;

// мне больше нравится, когда нажатая кнопка даёт единичку, ничего не нажато - нули
// поэтому инвертируем состояние PIN
current = KEY_MASK & ~((PINB << 8) | PIND);
if( current == prev ) { // не дребезжит
if( key_filtered != current) { // и поменялось
key_changed = 1;
key_filtered = current;
}
}
prev = current;
}

unsigned int get_key(void)
{
unsigned key = 0;
if( key_changed) {
#asm ("cli");
key = key_filtered;
key_changed = 0;
#asm ("sei");
}
return key;
}

// Основная функция
void main(void)
{
unsigned char key_index; // Указатель массива
unsigned char i; // Вспомогательный указатель
unsigned int key;

PORTB = 0xE7; // Порт B
DDRB = 0x18;

PORTD = 0x7F; // Порт D
DDRD = 0x00;

TCCR1A = 0x00; // Таймер/Счетчик 1
TCCR1B = 0x03;
TCNT1 = 0;
OCR1A = SYSTICK_DELTA;

ACSR = 0x80; // Аналоговый компаратор
#asm ("sei");

while (1) { // Главный цикл
key_index = 0;
// Пока буфер пуст либо начали набирать, но не кончился таймаут - ждём нажатий
while( key_index == 0 || timeout != 0 ) {
key = get_key();
if( key ) {
bufr[key_index] = key;
timeout = KEY_TIMEOUT;
if( ++key_index >= BSIZE)
break;
}
}

// полный буфер или пауза между клавишами > KEY_TIMEOUT, реакция на набранный код
if (PINB.7 == 1) { // Проверка переключателя режимов
//------------------------------ Проверка кода
if ( key_index != klen ) // Проверка длины кода
continue;
for (i = 0; i < key_index; i++)
if (bufe[i] != bufr[i]) // Проверка самого кода
continue;
} else {
//------------------------------ Запись кода в EEPROM
klen = key_index; // Запись длины кода
for (i = 0; i < key_index; i++)
bufe[i] = bufr[i]; // Запись всех байтов кода
}

//------------------------------ Открывание замка
// оставлено как было - замок открывается и после ввода нового кода, возможно,
// это было задумано как подтверждение замены.
PORTB.4 = 1; // Открываем замок
timeout = LOCK_DELAY;
while( timeout) ;
PORTB .4 = 0; // Закрываем замок
}
}

Количество строк С-программы ~ не изменилось, объём кода, думаю, не сильно изментися, но теперь можно независимо задавать время таймаута нажатия клавиш и время удержания замка открытым.
А вообще и проверку кода, и запись нового - я бы выделил в static inline функции (просто static для компилятора, до сих пор не поддерживающего С99) - вменяемый оптимизатор даже просто static функцию проинлайнил бы по месту и объём кода не изменился бы, а "читабельность" выросла бы.
Да и часть комментариев ушла бы за ненадобностью, так как
Код
    else
        write_new_code_to_eeprom()

столь же понятно, как и
Код
    else {
        //------------------------------ Запись кода в EEPROM


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
DASM
сообщение Oct 24 2007, 11:49
Сообщение #62


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



OFF - ReAL - а как код в трубочку свернули ?
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 24 2007, 11:55
Сообщение #63


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(dxp @ Oct 24 2007, 09:19) *
Существует очень мало ситуаций, где этот оператор действительно необходим. В ~90% случаев это выход из вложенных циклов.
Ещё в 9% случаев - слияния разных ветвей case в общие: после некоторых разных предварительных операций в относительно длинную общую часть - тогда для сопровождения проще не дублировать эту общую часть (а потом забыть одну из них модифицировать), а поставить несколько goto. Но это для "избранных" мест, старательно вылизываемого "где-то-библиотечного" кода.
Иногда - сведение ветвей многоступенчатых if, но это почти то же самое.

А вот в приведенной программе goto явно от неумения писать на С, а не от большого умения :-)



Цитата(DASM @ Oct 24 2007, 13:49) *
OFF - ReAL - а как код в трубочку свернули ?
Тег CODEBOX вместо CODE


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ValBag
сообщение Oct 24 2007, 12:06
Сообщение #64


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 15-03-07
Пользователь №: 26 183



Перечитал всю тему. На мой взгляд отказ от применения GoTo это стародавняя аксиома, которая в большинстве случаев многими принимается на веру. Тот же Страуструп (из топика #11) пишет:
Цитата
Кроме того, операторы goto могут пригодиться в тех случаях,
когда на первый план выходит скорость работы программы. Один из
них - когда в реальном времени происходят какие-то вычисления во
внутреннем цикле программы.
Есть немногие ситуации и в обычных программах, когда применение
goto оправдано. Одна из них - выход из вложенного цикла или
переключателя. Дело в том, что оператор break во вложенных циклах
или переключателях позволяет перейти только на один уровень выше.

Не считайте меня назойливым, еще раз обращаюсь к корифеям. Отредактируйте, пожалуйста текст программы (из топика #44) с пресловутым GoTo, чтобы она работала с другими операторами. Хочу увидеть разницу и приобрести некоторый опыт на живом примере. Ответы "сделай сам" не хотелось бы принимать. Все учились на чужих и своих примерах.
Спасибо!
Go to the top of the page
 
+Quote Post
DASM
сообщение Oct 24 2007, 12:09
Сообщение #65


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



А что по вашему ReAl сделал ?
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 24 2007, 12:27
Сообщение #66


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(ValBag @ Oct 24 2007, 14:06) *
Отредактируйте, пожалуйста текст программы (из топика #44) с пресловутым GoTo, чтобы она работала с другими операторами.
А чем не нравится мой вариант? Нужны шашечки или ехать? Я переписал не изменив "внешнюю" логику программы, но без goto, кто сказал, что оно должно выглядеть очень похоже на старое? Дословный перевод с языка на язык может либо исказить мысль больше, чем "правильный" перевод, либо выглядеть коряво. А тут мы переводим текст с чего-то типа бейсик-программы, записанной словами С на собственно С smile.gif

Тем более, что изменён только набор кода с клавиатуры, оставлено даже его поведение таким, как было, просто антидребезг и проверка нажатия новой клавиши реализованы несколько по-другому - гибче и расширяемее. Заодно убрана эту ужасающая задержка через wait() с "магическими числами". Всё остальное просто переписано без goto.
Ну вот "тупо" переведённый из goto-шного варианта в не-goto-шный:
CODE
/*****************************************************
This program was produced by the
CodeWizardAVR V1.24.4 Standard
Automatic Program Generator
© Copyright 1998-2004 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
e-mail:office@hpinfotech.com

Project : Пример 10
Version : 1
Date : 07.03.2006
Author : Belov
Company : Home
Comments:
Кодовый замок


Chip type : ATtiny2313
Clock frequency : 4,000000 MHz
Memory model : Tiny
External SRAM size : 0
Data Stack size : 32
*****************************************************/

#include <tiny2313.h>
#define klfree 0x77F // Код состояния при полностью отпущеных кнопках
#define kzad 3000 // Код задержки при сканировании
#define kandr 30 // Константа антидребезга
#define bsize 30 // Размер буфера для хранения кода

unsigned char flz; // Флаг задержки
unsigned int bufr[bsize]; // Буфер в ОЗУ для хранения кода
#pragma warn-
eeprom unsigned char klen; // Ячейка для хранения длины кода
eeprom unsigned int bufe[bsize]; // Буфер в EEPROM для хранения кода
#pragma warn+

// Прерывание по переполнению Таймера 1
interrupt[TIM1_OVF]
void timer1_ovf_isr(void)
{
flz = 1; // Устанавливаем флаг задержки
}

// Прерывание по совпадению в канале A Таймера 1
interrupt[TIM1_COMPA]
void timer1_compa_isr(void)
{
flz = 1; // Устанавливаем флаг задержки
}

// Функция опроса клавиатуры и антидребезга
unsigned int incod(void)
{
unsigned int cod0 = 0; // Локальные переменные
unsigned int cod1;
unsigned char k;

for (k = 0; k < kandr; k++) { // Цикл антидребезга
cod1 = PINB & 0x7; // Формируем первый байт кода
cod1 = (cod1 << 8) + (PIND & 0x7F); // Формируем полный код состояния клавиатуры
if (cod0 != cod1) { // Сравниваем со старым кодом
k = 0; // Если не равны, сбрасываем счетчик
cod0 = cod1; // И присваиваем новое значение старому коду
}
}
return cod1;
}


// Процедура формирования задержки
void wait(unsigned char kodz)
{
if (kodz == 1)
TIMSK = 0x40; // Выбор маски прерываний по таймеру
else
TIMSK = 0x80;
TCNT1 = 0; // Обнуление таймера
flz = 0; // Сброс флага задержки
#asm("sei"); // Разрешаем прерывания
if (kodz != 2)
while (flz == 0); // Цикл задержки
}


// Основная функция
void main(void)
{
unsigned char ii; // Указатель массива
unsigned char i; // Вспомогательный указатель
unsigned int codS; // Старый код

PORTB = 0xE7; // Порт B
DDRB = 0x18;

PORTD = 0x7F; // Порт D
DDRD = 0x00;

TCCR1A = 0x00; // Таймер/Счетчик 1
TCCR1B = 0x03;
TCNT1 = 0;
OCR1A = kzad;

ACSR = 0x80; // Аналоговый компаратор

while (1) { // Главный цикл
while (incod() != klfree); // Ожидание отпускания кнопок
while (incod() == klfree); // Ожидание нажатия кнопок
ii = 0;

// набор кода до конца буфера либо до таймаута между клавишами
while(1) {
#asm("cli"); // Запрещаем прерывания
wait(1); // Задержка 1-го типа
codS = incod(); // Ввод кода и запись, как старого
bufr[ii++] = codS; // Запись очередного кода в буфер
if (ii >= bsize) // Проверка конца буфера
break;

wait(2); // Задержка 2-го типа
while( flz == 0) { // пока не закончился интервал
if (incod() != codS) // Проверка не изменилось ли состояние
continue; // переход на набор кода
}
break; // таймаут - конец набора
}

// реакция на набранный код
if (PINB.7 == 1) { // Проверка переключателя режимов
//------------------------------ Проверка кода
if (klen != ii) // Проверка длины кода
continue; // главный цикл
for (i = 0; i < ii; i++)
if (bufe[i] != bufr[i]) // Проверка самого кода
continue; // главный цикл
} else { //------------------------------ Запись кода в EEPROM
klen = ii; // Запись длины кода
for (i = 0; i < ii; i++)
bufe[i] = bufr[i]; // Запись всех байтов кода
}

//------------------------------ Открывание замка
PORTB .4 = 1;
// Открываем замок
wait(3); // Задержка 3-го типа
PORTB .4 = 0; // Закрываем замок
}
}


p.s. сам я к этому вопросу не отношусь "религиозно" - goto применяю, но только если он действительно улучшает ситуацию.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ValBag
сообщение Oct 24 2007, 12:29
Сообщение #67


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 15-03-07
Пользователь №: 26 183



Цитата(DASM @ Oct 24 2007, 20:09) *
А что по вашему ReAl сделал ?

Прошу прощения, я его увидел после посылки своего предыдущего сообщения.
Проработаю. Спасибо ReAl
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 24 2007, 12:29
Сообщение #68


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(ValBag @ Oct 24 2007, 14:06) *
Тот же Страуструп (из топика #11) пишет:
Ну и где в приведённой программе то, о чём писал Страуструп (что-то очень быстрое или выход из нескольких вложенных циклов) ???


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
defunct
сообщение Oct 24 2007, 12:42
Сообщение #69


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(ValBag @ Oct 24 2007, 09:19) *
Для примера в программе "кодовый замок" из книги Белова А.В., в небольшом тексте программы на CИ в модуле main 7 переходов. И все работает нормально.

Программа содержит аж 2 артефакта, первый конечно же goto, а второй - переменная "ii", давненько уже такого не видал smile.gif
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 24 2007, 12:50
Сообщение #70


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Раз уж я тут застрял - что я имел ввиду под "ужасающим wait()"
Функция должна делать более-менее однотипную работу.
Поэтому передавать в функцию параметр, меняющий время задержки - это нормально, но нагружать эту же функцию только инициализацией таймаута, который будет проверяться в другом месте и другим образом - это сделать код плохо читаемым (то же относится к макросам в ассемблере).
На скорую руку предлагаемые изменения выглядят так:
CODE

typedef enum { delay_50ms, delay_1s } delay_code_t;
// Процедура формирования задержки
void init_timer(delay_code_t dly )
{
if (dly == delay_50ms)
TIMSK = (1 << OCIE1A); // Выбор маски прерываний по таймеру
else
TIMSK = (1 << TOIE1);
TCNT1 = 0; // Обнуление таймера
flz = 0; // Сброс флага задержки
#asm("sei"); // Разрешаем прерывания
}

#define init_timeout() init_timer(delay_1s)
#define is_expired() (flz==1)

void wait(delay_code_t dly )
{
init_timer( dly);
while ( ! is_expired() ); // Цикл задержки
}


// Основная функция
void main(void)
{
........

while (1) { // Главный цикл
.........
// набор кода до конца буфера либо до таймаута между клавишами
while(1) {
#asm("cli"); // Запрещаем прерывания
wait(delay_50ms); // Задержка 1-го типа
codS = incod(); // Ввод кода и запись, как старого
bufr[ii++] = codS; // Запись очередного кода в буфер
if (ii >= bsize) // Проверка конца буфера
break;

init_timeout(); // Задержка 2-го типа
while( ! is_expired() ) { // пока не закончился интервал
if (incod() != codS) // Проверка не изменилось ли состояние
continue; // переход на набор кода
}
break; // таймаут - конец набора
}

.............
//------------------------------ Открывание замка
PORTB .4 = 1;
// Открываем замок
wait(delay_1s); // Задержка 3-го типа
PORTB .4 = 0; // Закрываем замок
}
}


Прошу прощения, на ходу кое-что поменял в уже отправленном коде.

Цитата(defunct @ Oct 24 2007, 14:42) *
Программа содержит аж 2 артефакта, первый конечно же goto, а второй - переменная "ii", давненько уже такого не видал smile.gif
Ото ж я быстренько-быстренько оставил только i как "временный" счётчик цикла, а вторую переименовал в осмысленный key_index, чтобы в глазах от i ii iii не рябило smile.gif


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ValBag
сообщение Oct 24 2007, 13:09
Сообщение #71


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 15-03-07
Пользователь №: 26 183



ReAl
Цитата
А тут мы переводим текст с чего-то типа бейсик-программы, записанной словами С на собственно С

Неужели я применяю такой древний компилятор (такой же как в приложенном примере, кстати не моем, а указанного автора) который никто не знает. CodeVisionAVR это компилятор языка С http://www.hpinfotech.com У меня нет конкретного учителя. Подходящий для начинающих (по информации в литературе для новичков и ссылкам в сети) это CVAVR. Большинство утверждают, что самый лучший IAR, но по нему информации пользователя на русском нет, а уменя проблемы с английским. Вот такие дела! Спасибо за варианты, проработаю позже. С лету, как начинающий, не могу сразу оценить.

defunct А чему противоречит название переменной ii?
Go to the top of the page
 
+Quote Post
defunct
сообщение Oct 24 2007, 13:16
Сообщение #72


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(ValBag @ Oct 24 2007, 16:09) *
А чему противоречит название переменной ii?

Лишь только читаемости кода, которая приводит в последствии к страшным глюкам

сравните:
Код
ii += 1;
...
for(i = 0; i < ii; i++)



Код
i += 1;
...
for(i = 0; ii < ii; i++)


Код
ii += 1;
...
for(i = 0; i < ii; ii++)
Go to the top of the page
 
+Quote Post
ValBag
сообщение Oct 24 2007, 13:33
Сообщение #73


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 15-03-07
Пользователь №: 26 183



defunct Понятно, появляется рябь в глазах, а затем в коде.
Спасибо, учту в дальнейшем.
Попутно еще один вопрос. Не подскажете, можно ли найти толковое руское описание IAR? А то все меня пристыдили с CodeVisionAVR.
Go to the top of the page
 
+Quote Post
alexander55
сообщение Oct 24 2007, 13:44
Сообщение #74


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(ValBag @ Oct 24 2007, 17:33) *
defunct Понятно, появляется рябь в глазах, а затем в коде.
Спасибо, учту в дальнейшем.
Попутно еще один вопрос. Не подскажете, можно ли найти толковое руское описание IAR? А то все меня пристыдили с CodeVisionAVR.

Мне попалась книга П.П. Редькин "Микроконтроллеры ARM7 семейства LPC2000". Там страниц 100 про IAR. Где-то в интернете есть.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 24 2007, 13:46
Сообщение #75


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(ValBag @ Oct 24 2007, 15:09) *
ReAl
Неужели я применяю такой древний компилятор (такой же как в приложенном примере, кстати не моем, а указанного автора) который никто не знает.
Нет, при чём тут "древний"?

http://www.lib.ru/ANEKDOTY/non_pas.txt
Цитата
- поскольку в Фортране отсутствуют структурные операторы IF, REPEAT ... UNTIL или CASE, настоящим программистам не нужно беспокоиться, что они их не используют; кроме того эти операторы можно при необходимости симулировать с помощью присваиваемых GOTO.
...
Да и потом, закоренелый настоящий программист может написать фортрановскую программу на любом языке.
Именно это я имел ввиду - пример от "указанного автора" написан, как я сказал, "словами С но на другом языке". Довольно, на мой взгляд, грязный код, там кроме goto и ii есть что поругать (два прерывания там, где можно было обойтись одним - даже если писать не так, как написал я), лишние (с непонятной смысловой нагрузкой) вызовы inkey(), использование "магических чисел" там, где для упрощения понимания написанного и будущего развития надо применять именованные вещи, будь-то #define или enum.

К "свежести" используемого Вами С-компилятора это не имеет никакого отношения, я лично никого не "пристыдил" - я вообще только понаслышке знаю - кто такие ImageCraft-ы с CodeVision-ами, мне и gcc хватает smile.gif


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ValBag
сообщение Oct 24 2007, 14:01
Сообщение #76


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 15-03-07
Пользователь №: 26 183



Цитата(ReAl @ Oct 24 2007, 21:46) *
пример от "указанного автора" написан, как я сказал, "словами С но на другом языке".

"Указанный автор" это Белов А.В. Книга называется "Создаем устройства на микроконтроллерах". Это единственная книга, которую я нашел, с законченными примерами. Причем все примеры вначале приведены на ассемблере, а затем на С. Наверное этим и объясняется GoTO. Несмотря на это, кое что полезное я из нее извлек.
Go to the top of the page
 
+Quote Post
ValBag
сообщение Oct 25 2007, 12:45
Сообщение #77


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 15-03-07
Пользователь №: 26 183



REAL
Шашечек конечно не надо, но и ехать не получается. Глохнем на полпути. Это я так,
беззлобно, скорее в отношении себя.

1. Общие принципы избавления от GoTo мне понятны, но не до конца. Самое проблемное место,
переход из вложенных циклов вверх, более чем на начало вложенного цикла. Во втором и третьем Ваших вариантах первый оператор continue должен передаваь управление (по условию его действия) не на набор кода while(1), а на следующий цикл вложенного while(flz==0), в теле которого он появился? Буду рад, если ошибаюсь.
В первом варианте программы, еще не разобрался, комментарии Ваши не везде, а до Вашего мастерства мне далековато.

2. typedef enum {delay_50ms, delay_1s} delay_code. А typedef здесь зачем?, delay_code это
переменная объявленного перечисления с уже заданным типом.

Сообщение отредактировал ValBag - Oct 25 2007, 12:47
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 25 2007, 22:04
Сообщение #78


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(ValBag @ Oct 25 2007, 14:45) *
Самое проблемное место, переход из вложенных циклов вверх, более чем на начало вложенного цикла. Во втором и третьем Ваших вариантах первый оператор continue должен передаваь управление (по условию его действия) не на набор кода while(1), а на следующий цикл вложенного while(flz==0), в теле которого он появился?
Тьху, это я ошибся. Конечно, оно идёт не туда, куда надо :-(
Ну плохо "втупую" переводится "спагетти" из goto в циклы. В первом варианте, когда я "понял, что нужно и написал почти с нуля", надеюсь, ошибок нет :-)
А тут надо что-то в таком духе рожать:
Код
        init_timeout();    // Задержка 2-го типа
        while( incod() == codS && !is_expired() ); // пока клавиша не изменилась и таймаут не истёк - ждём
        if( is_expired() ) break; // если таки таймаут - конец набора
    } // это от while(1) "набор кода"


Цитата(ValBag @ Oct 25 2007, 14:45) *
2. typedef enum {delay_50ms, delay_1s} delay_code. А typedef здесь зачем?, delay_code это переменная объявленного перечисления с уже заданным типом.
Нет, если бы не было слова typedef, то это была бы переменная типа неименованного enum с таким-то набором.
А так это перечислимый тип - определяется typedef-ом для того, чтобы не писать лишний раз слово enum везде, где нужно завести переменную этого типа. Вместо
Код
enum moo { moo0, moo1 }; // только объявляем тип, не заводя переменных
void foo( enum moo m) // аргумент этого типа
{
   if( m == moo1) { ...
пишем
Код
typedef enum { moo0, moo1 } moo_t; // тоже объявляем тип, но имя типа теперь из одного слова, без ключевого слова enum
void foo( moo_t m) // аргумент этого типа
{
   if( m == moo1) { ...


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ValBag
сообщение Oct 27 2007, 08:58
Сообщение #79


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 15-03-07
Пользователь №: 26 183



ReAl
Теперь все понятно! Только наверное надо немного изменить этот оператор?
while ((incod() == codS) && (!is_expired()));
Спасибо за помощь!

Сообщение отредактировал ValBag - Oct 27 2007, 09:00
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 27 2007, 10:16
Сообщение #80


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(ValBag @ Oct 27 2007, 10:58) *
Только наверное надо немного изменить этот оператор?
while ((incod() == codS) && (!is_expired()));
Тут эти скобки не обязательны - согласно приоритету операций. А лишние скобки только мешают читать, особенно тут возле !is_expired()
Никто же не пишет ((a*b)+(c*d))


p.s. Да, это надо привыкнуть, что && и || имеют более низкий приоритет, чем == != > и т.д., а + - * / имеют более высокий, чем == != и т.д.
Но ведь в школе же привыкли к приоритетам арифметических операций :-)
Тем более, что логика в этих приоритетах есть, если словами сказать "если код не равен старому И не закончилось время" - это ведь в русском языке означаент не "если код не равен (старому и не закончилось)", а таки "(если не равен старому) и (не закончилось)"

Единственное, пожалуй, неудобное место по приоритетам операций в С - это соотношение сложения и сдвига
a << 5 + 1
означает
a << (5 + 1)
а не
(a << 5) + 1
По крайней мере мне кажется более естественным размещение приоритета сдвигов между умножением-делением и сложением-вычитанием, а не ниже сложения-вычитания, но K&R решили по-другому и сдвиг надо брать в скобки.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Oct 27 2007, 10:51
Сообщение #81


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
Тут эти скобки не обязательны - согласно приоритету операций. А лишние скобки только мешают читать

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


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Oct 28 2007, 11:32
Сообщение #82


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(ReAl @ Oct 24 2007, 14:55) *
Ещё в 9% случаев - слияния разных ветвей case в общие: после некоторых разных предварительных операций в относительно длинную общую часть - тогда для сопровождения проще не дублировать эту общую часть (а потом забыть одну из них модифицировать), а поставить несколько goto. Но это для "избранных" мест, старательно вылизываемого "где-то-библиотечного" кода.
Иногда - сведение ветвей многоступенчатых if, но это почти то же самое.


Мне как-то редко приходится использовать много вложенных циклов и я не объединяю (посредством GOTO) case-ы (сам IAR достаточно хорошо их объединяет).

В то же время изредка пользуюсь GOTO по причине которая уже указывалась. Обработка исключительных ситуаций. Причём в Pascal это используется чаще так как в Си можно сделать дополнительный return. Хотя этим нарушается ещё одно "золотое правило": Для каждой процедуры - один вход - один выход.

Конечно прямая обработка исключений - красивый выход как в С++ так и в Pascal, но иногда банально не хочется городить огород. К тому же я тоже считаю что основная причина - хорошая читаемость текста. С этой точки зрения вот такой текст к примеру - вполне укладывается
Код
procedure TForm1.mnuWriteClick(Sender: TObject);
label ExitSend;
const
       SmallTime     = 20;
       BigTime       = 400;
var
....
      if CountRep>3 then begin
          StatusBar1.Panels.Items[0].Text:= 'Ошибка! Кластер с запрошенным номером не отвечает';
          goto  ExitSend;
      end;
.....
        if CountRep>3 then begin
          StatusBar1.Panels.Items[0].Text:= 'Ошибка! Превышено количество повторов во время передачи';
          goto  ExitSend;
        end;
....
ExitSend:
  FComDriver.Active := false;
  FComDriver.Free;
  FComSettings.Free;
  StatusBar1.Panels.Items[0].Text:= '';
  Form1.StatusBar1.Panels.Items[1].Text:= '';
end
....


Сори - на Си не нашёл.

Понятно что всё это можно флагами сделать. Но нагляднее ли это будет?

На си решается так
Код
uint8_t    GetChar(void)
{
uint8_t        c;

if(Flag.SaveRollik) return    0;                            // Если идёт запись ролика, то выйти
c=GetCharInStream();
if(c != METKA) return c;
c=GetCharInStream();                                    // Взять следующий символ
if(c != METKA){
   Flag.ErrLoadKom = 1;                                    // Ошибка приёма данных, - пришла команда
   Kom = c;                                                // Досрочно
}
return    c;
}
Go to the top of the page
 
+Quote Post

6 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 23:36
Рейтинг@Mail.ru


Страница сгенерированна за 0.02543 секунд с 7
ELECTRONIX ©2004-2016