![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Ошибка в delphi 7 [D7, WinXP]
Sicilla © (2004-11-17 18:34:00)Привет всем. Постваил себе delphi 7 взамен delphi 5. delphi 5 не удалял. И теперь ошибка: при отладке F7 например в переменной i значение 2, а кажет, что там 10 или -5. Хотя считает правильно в целом.
Palladin (2004-11-18 01:11:00) [101]
> [36] Игорь Шевченко © (18.11.04 01:02)
Ну что же Вы так... Мечом то сразу по узлу... :)
Palladin (2004-11-18 01:04:00) [102]Ну конечно это не проблема. Если ProceedCommand процедура. Но если это все таки функция, которая возвращает результат выполнения команды? Но не булевский, а, скажем Integer, который потом нужно еще и анализировать и который влияет на выход из тела цикла при определенных условиях...
Кстати, в A) была допущена ошибка. Устройство ведь нужно проверить на готовность перед записью... но в принципе это ерунда, в and это увязывается. Еще момент: вы уверены, что команды выполнятся именно в том порядке в котором они записаны? Я почему то нет... Кто его знает, этот оптимизатор... Ну это тоже черт с ним... Правда ошибку искать потом неудобно будет...
Повторюсь, это ведь простейший пример. На его, так сказать, "оптимизацию" к нестабильной не гибкой форме, у вас ушло времени гораздо больше чем у меня на вариант A)... Как вы думаете... Это хорошо?
Игорь Шевченко (2004-11-18 01:02:00) [103]Я бы код организовал следующим образом
ConnectDevice;
try
try
while true do begin
ReadCommand;
ProceedCommand;
WriteCommand;
end;
except
on E: EDeviceNotConnected do
....
finally
DisconnectDevice;
end;
А внутри ReadCommand и WriteCommand написал бы
if not DeviceConnected then
raise EDeviceNotConnected.Create(...);
.....
Игорь Шевченко (2004-11-18 00:55:00) [104]Defunct © (18.11.04 00:47) [32]
Код в D отличается от кода А по логике. То есть, гарантировано работает не так, как оригинал. Хотя и более удобочитаем.
> Только за то, что там указывается "полнота" языка паскаль?
Это не "полнота". Такие советы давались на заре программирования или в эпоху структурного программирования. После этого пришли к выводу, что введение операторов управления (Break, Continue, Exit) улучшает удобочитаемость кода.
Defunct (2004-11-18 00:52:00) [105]> :) К сожалению ProceedCommand это не функция, результат выполнения не влияет на выход/продолжение цикла.
;)
Это не проблема:
function ProceedCommand:boolean;
begin
<код процедуры>;
Result := True
end;
Palladin (2004-11-18 00:49:00) [106]
> [32] Defunct © (18.11.04 00:47)
:) К сожалению ProceedCommand это не функция, результат выполнения не влияет на выход/продолжение цикла.
Defunct (2004-11-18 00:47:00) [107]Palladin © (18.11.04 00:34) [29]
Соблюдаю последовательность действий:
D)
DeviceConnect;
NoError := True;
Try
while NoError and DeviceConnected do
NoError := ReadCommand and ProceedCommand and WriteCommand
Finally
TryDisconnectDevice;
End;
Игорь Шевченко © (18.11.04 00:40) [30]
> Главное в коде - его удобочитаемость
Об этом и речь.
Done - образный пример.
Неужели пример D) менее нагляден чем A) [22]
> Выкинь книгу на помойку. Искренний совет.
Только за то, что там указывается "полнота" языка паскаль?
Palladin (2004-11-18 00:42:00) [108]Причем сильно, ибо при чтении приходится прослеживать за ее изменением в теле цикла. Иногда это становится сущим адом.
Игорь Шевченко (2004-11-18 00:40:00) [109]
> А я вам гарантирую, что без Break, Continue, Goto, Exit,
> Inline и прочее упомянутое можно запросто обойтись, причем
> всегда. (написано в любой книге по паскалю в разделе операторы).
Выкинь книгу на помойку. Искренний совет.
Главное в коде - его удобочитаемость, а с введением дополнительных переменных типа Done она ухудшается.
Palladin (2004-11-18 00:34:00) [110]Нет, чтение команды, исполнение, запись команды.
Defunct (2004-11-18 00:28:00) [111]Gero © (18.11.04 00:16) [26]
> Потому что нет необходимости.
Я принимаю ваш аргумент.
Тоже самое ("нет необходимости") имеем и в случае с break и continue.
> Невозможно продумать ведь все ньюансы алгоритма наперед, кроме того, возможно его придется править.
А я вам гарантирую, что без Break, Continue, Goto, Exit, Inline и прочее упомянутое можно запросто обойтись, причем всегда. (написано в любой книге по паскалю в разделе операторы).
Palladin © (18.11.04 00:17) [27]
Ок, с учетом немедленного выхода:
C)
DeviceConnect;
NoError := True;
Try
while NoError and DeviceConnected do
begin
if Not ReadCommand then NoError := False else
if Not WriteCommand then NoError := False else
ProceedCommand
end;
Finally
TryDisconnectDevice;
End;
Palladin (2004-11-18 00:17:00) [112]К сожалению если команда не прочиталась нужно немедленно выйти...
Gero (2004-11-18 00:16:00) [113]
> while NoError(Arr[i]) and (i<High(Arr)) do
> Begin
> <Код>
> end;
Этот код совсем не соответствует моему.
> Если так рассуждать, то почему бы не использовать Label?
> Язык ведь позволяет. Почему бы не использовать Inline?
Потому что нет необходимости.
Лично у меня нет принципов, будет мне удобнее с Label - сделаю с Label, будет удобнее с Inline - сделаю Inline, так же и Continue, Break, и пр.
Невозможно продумать ведь все ньюансы алгоритма наперед, кроме того, возможно его придется править.
И чтобы не переписывать всю логику работы, порой достаточно просто поставить в нужном месте Break...
Defunct (2004-11-18 00:13:00) [114]Palladin © (17.11.04 23:53) [22]
> Для моего восприятия A) понятней чем B),
Честно сказать я соглашусь с этим (в вашей реализации B действительно оказался менее наглядным чем A), но я ниже предлагаю вариант C), который IMHO не менее прозрачен чем A), и для моего восприятия более понятен.
C)
DeviceConnect;
NoError := True;
Try
while NoError and DeviceConnected do
begin
if ReadCommand then ProceedCommand;
if Not WriteCommand then NoError := False
end;
Finally
TryDisconnectDevice;
End;
Defunct (2004-11-17 23:55:00) [115]> for i := 0 to High(Arr) do
> begin
> if IsError(Arr[i]) then Break;
> <Код>
> end;
> Реализуйте это красивее без Break.
while NoError(Arr[i]) and (i<High(Arr)) do
Begin
<Код>
end;
> Если язык позволяет - то почему бы не использовать?
Если так рассуждать, то почему бы не использовать Label? Язык ведь позволяет. Почему бы не использовать Inline? Почему бы всю программу не написать на Asm? Почему бы не писать все операторы в одну строку? Язык ведь и это все позволяет. Точнее не язык, а компилятор.
Я отвечу на все эти вопросы так:
Потому что НЕ используя все это, программа будет выглядеть куда более удобочиемой, и более доступной для понимания. Углядеть логику (алгоритм) программы будет намного проще, соответственно найти возможную ошибку в коде будет намного проще.
Palladin (2004-11-17 23:55:00) [116]Упс.. ошибочка... из толпы условий Not нужно поубирать... и из условия While тоже...
Palladin (2004-11-17 23:53:00) [117]Можно, еще как можно. Тоже IMHO.
Конструкция с Done не прокатывает в случае с "многозадачным" циклом. Не в том смысле что потоковым или нитевым, а в том что в цикле выполняется задача разбитая на подзадачи. Простейший пример.
A)
DeviceConnect;
Try
While True Do
Begin
If Not IsDeviceConnected Then Break;
If Not ReadCommand Then Break;
ProceedCommand;
If Not DeviceConnected Then Break;
If Not WriteCommand Then Break;
End;
Finally
TryDisconnectDevice;
End;
B)
Var
isDone:Boolean;
Begin
DeviceConnect;
Try
While Not isDone Do
Begin
isDone:=IsDeviceConnected;
If isDone Then isDone:=ReadCommand;
If Not isDone Then ProceedCommand;
If Not isDone Then isDone:=DeviceConnected;
If Not isDone Then isDone:=WriteCommand;
End;
Finally
TryDisconnectDevice;
End;
Для моего восприятия A) понятней чем B), да и надежней если придется добавлять код, разбиратся в толпе условий зависящих от установленной ранее булевой переменной. А между прочим это простейший пример, в сложных алгоритмах простой цепочкой условий не обойтись. Так же break сэкономит время выполнения... просто выйдя за цыкл, не проходя толпу условий..
jack128 (2004-11-17 23:51:00) [118]Gero © (17.11.04 23:41) [20]
При отсутствии Goto - это необходимость. как выполнить <оператор> N раз подряд??(N - переменная)
Gero (2004-11-17 23:41:00) [119]
> Я все же придерживаюсь позиции, что break и cont. абсолютно
> излишние операторы.
Любой оператор цикла не есть необходимостью.
Все можно сделать через if'ы.
Defunct (2004-11-17 23:38:00) [120]Palladin © (17.11.04 23:13) [15]
Я все же придерживаюсь позиции, что break и cont. абсолютно излишние операторы.
Ведь никто не мешает построить тело цикла так:
procedure Cycle;
var Done : boolean;
begin
Done := not <множество условий запуска>;
while not Done do
begin
...
Done := <множество условий выхода>
end;
end;
...
Cycle;
что же касается
> While True Do
то настал мой черед удивляться, т.к. IMHO такое вообще нельзя писать.