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

 
 
6 страниц V  « < 4 5 6  
Reply to this topicStart new topic
> Оператор GoTo, безусловный переход или правила хорошего тона
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  « < 4 5 6
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 12:16
Рейтинг@Mail.ru


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