Форум: "Основная";
Текущий архив: 2004.12.12;
Скачать: [xml.tar.bz2];
ВнизОшибка в delphi 7 Найти похожие ветки
← →
Sicilla (2004-11-17 18:34) [0]Привет всем. Постваил себе delphi 7 взамен delphi 5. delphi 5 не удалял. И теперь ошибка: при отладке F7 например в переменной i значение 2, а кажет, что там 10 или -5. Хотя считает правильно в целом.
← →
begin...end © (2004-11-17 18:49) [1]
> Sicilla (17.11.04 18:34)
i - это не счётчик цикла случайно?
← →
Sicilla (2004-11-17 19:07) [2]Да, в основном этот глюк в цикле. И еще не реагирует в циклах на команду Continue. Сволочь:((
← →
begin...end © (2004-11-17 19:11) [3]
> [2] Sicilla (17.11.04 19:07)
> Да, в основном этот глюк в цикле.
В случае цикла это нормальное поведение.
> И еще не реагирует в циклах на команду Continue.
Приведи код.
← →
Sicilla (2004-11-17 20:01) [4]
function Tform1.change_record(num: byte): integer;
var
x,i,j: Integer;
last, now_1: byte;
begin
for x := 1 to prov do
begin
way_old[x] := prov_info.way[x];
prov_info.way[x] := 0;
end;
for i := 1 to num do
for x := 1 to prov do
begin
if prov_info.P[x,1] = lstEntries.Items.Strings[i-1] then
prov_info.way[i] := x;
end;
j := num - ini.kol_prov;
for x := 1 to num do
begin
if (prov_info.way[x] = 0) and (abs(j) > 0) then
begin
prov_info.way[x] := abs(j) + ini.kol_prov;
if j > 0 then dec(j);
if j < 0 then inc(j);
if i = 0 then break;
end;
end;
j := num - ini.kol_prov; // отсюда глюки
if j > 0 then
begin
for i := num downto 1 do
for x := prov downto 1 do
if (way_old[x] = prov_info.way[i]) and (prov_info.way[i] <> 0) and (way_old[x] <> 0) then
begin
last := way_old[x];
now_1 := i;
form1.Change(num,last,now_1);
end;
end;
if j < 0 then
begin
for i := 1 to num do
for x := 1 to prov do
if (way_old[x] = prov_info.way[i]) and (prov_info.way[i] <> 0) and (way_old[x] <> 0) then
begin
last := way_old[x];
now_1 := i;
form1.Change(num,last,now_1);
end;
end;
EXE.P[last] := prov_info.p[now_1];
//
for i := 1 to prov do
Prov_info.P[i,1] := "";
for i := 1 to lstEntries.Items.Count do
begin
Prov_info.P[i,1] := lstEntries.Items.Strings[i-1];
prov_info.way[i] := i
end;
ini.kol_prov := lstEntries.Items.Count;
change_prov(col);
end;
первые пару циклов нормальон кажет, потом начинается фигня.type
PRI = record
P : array[1..prov,1..20] of string[50];
way: array[1..prov] of byte;
end;
Prov_info, Exe: PRI;
const prov = 9
← →
Anatoly Podgoretsky © (2004-11-17 20:09) [5]Continue в коде не обнаружилось
← →
begin...end © (2004-11-17 20:12) [6]
> Continue в коде не обнаружилось
Так что глюк уже не в Delphi.
← →
Defunct © (2004-11-17 21:41) [7]а зачем Continue вообще нужен?
также как и Goto и Exit его место на помойке IMHO.
← →
Gero © (2004-11-17 21:46) [8]
> Defunct © (17.11.04 21:41)
Тогда уж и Break в придачу.
А можно и циклы вобще выкинуть. Нафиг они нужны?
Имхо
← →
Defunct © (2004-11-17 22:01) [9]> Тогда уж и Break в придачу.
Абсолютно точно, и break туда же.
IMHO те кто пользуется
Goto, Break, Continue, Exit
просто не могут нормально реализовать логику программы.
> А можно и циклы вобще выкинуть. Нафиг они нужны?
не извращайте идею.
C помощью 7-ми операторов можно реализовать любую логику:
1. пустой оператор - ;
2. оператор присваивания :=
3. Условный оператор if <> then <оператор> else <оператор>
4. Оператор цикла с пердусловием while <условие> do <оператор>
5. Оператор цикла с постусловием repeat <оператор> until <условие>
6. Оператор цикла с границами for <от> to <до> do <оператор>
7. Составной оператор begin <оператор>.. end.
два доп. оператора case и with можно применять для красоты и наглядности программы.
Continue, Break, Goto, Exit лишь запутывают логику программы и делают программу трудно читаемой.
← →
Defunct © (2004-11-17 22:02) [10][9]
4. LOL суперопечатка.
← →
Defunct © (2004-11-17 22:14) [11]2 Gero,
[2] кстати демонстрирует то о чем я говорю.
Код трудночитаем.
и по всей видимости вообще неправильно работает и на D5 и на D7:
for i := 1 to lstEntries.Items.Count do
← →
jack128 © (2004-11-17 22:28) [12]Defunct © (17.11.04 22:01) [9]
А зачем целых 3(!!!) вида цикла?? Вполне достаточно одного while.
← →
jack128 © (2004-11-17 22:29) [13]Defunct © (17.11.04 22:14) [11]
Код трудночитаем.
Код трудночитаем из-за нестандартных отступов, ИМХО.
← →
Defunct © (2004-11-17 22:35) [14]for x := 1 to num do
begin
if (prov_info.way[x] = 0) and (abs(j) > 0) then
begin
prov_info.way[x] := abs(j) + ini.kol_prov;
if j > 0 then dec(j);
if j < 0 then inc(j);
if i = 0 then break;
end;
end;
что мешает этот цикл записать так:
if i<>0 then
for x := 1 to num do
if (prov_info.way[x] = 0) and (abs(j) > 0) then
begin
prov_info.way[x] := abs(j) + ini.kol_prov;
if j > 0 then dec(j) else inc(j)
end;
и не надо никаких Break"ов, и кода меньше.
Хотя возможно автор допустил ошибку именно в строке с Break (вероятно там не if i = 0, а должно было быть if j=0)
но и в этом случае, можно обойтись без Break:
x := 1;
Repeat
if (prov_info.way[x] = 0) and (abs(j) > 0) then
begin
prov_info.way[x] := abs(j) + ini.kol_prov;
if j > 0 then dec(j) else inc(j)
end;
inc(x);
Until (x>=num) or (j=0);
А теперь давайте подумаем, что лучше для понимания и отладки:
- ровная логика с условием выхода, записанным в одной строке
- или кривая логика с возможностью выпрыгнуть из цикла прямо из тела цикла.
← →
Palladin © (2004-11-17 23:13) [15]
> [14] Defunct © (17.11.04 22:35)
Зачем break и continue? Ну уж от вас таких заявлений не ожидал.
Цикл While. Обработка чего угодно, множество условий выхода из цикла. Множество условий для возврата исполнения на начало тела цикла. Выход один. While True Do и использование Break и Continue.
← →
Defunct © (2004-11-17 23:19) [16]> А зачем целых 3(!!!) вида цикла??
На все случаи жизни ;>
Вопрос в другом, зачем имея аж 3 оператора цикла применять какие-то Continue, break и т.п?
← →
Gero © (2004-11-17 23:35) [17]
> IMHO те кто пользуется
> Goto, Break, Continue, Exit
> просто не могут нормально реализовать логику программы.
Неужели в борланде работают именно такие?
Всем из вышеперечисленного(кроме goto) активно пользуюсь, и не сказал бы, что код получается хуже по читаемости чем без них, а порой и лучше.
Простейший пример:
for i := 0 to High(Arr) do
begin
if IsError(Arr[i]) then Break;
<Код>
end;
Реализуйте это красивее без Break.
← →
Gero © (2004-11-17 23:37) [18]
> IMHO те кто пользуется
> Goto, Break, Continue, Exit
> просто не могут нормально реализовать логику программы.
Да, кстати, с таким же успехом можно утверждать, что нормально реализовать логику программы не могут те, кто не использует Goto, Break, Continue и Exit.
Если язык позволяет - то почему бы не использовать?
← →
Defunct © (2004-11-17 23:38) [19]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 такое вообще нельзя писать.
← →
Gero © (2004-11-17 23:41) [20]
> Я все же придерживаюсь позиции, что break и cont. абсолютно
> излишние операторы.
Любой оператор цикла не есть необходимостью.
Все можно сделать через if"ы.
← →
jack128 © (2004-11-17 23:51) [21]Gero © (17.11.04 23:41) [20]
При отсутствии Goto - это необходимость. как выполнить <оператор> N раз подряд??(N - переменная)
← →
Palladin © (2004-11-17 23:53) [22]Можно, еще как можно. Тоже 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 сэкономит время выполнения... просто выйдя за цыкл, не проходя толпу условий..
← →
Defunct © (2004-11-17 23:55) [23]> 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) [24]Упс.. ошибочка... из толпы условий Not нужно поубирать... и из условия While тоже...
← →
Defunct © (2004-11-18 00:13) [25]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;
← →
Gero © (2004-11-18 00:16) [26]
> while NoError(Arr[i]) and (i<High(Arr)) do
> Begin
> <Код>
> end;
Этот код совсем не соответствует моему.
> Если так рассуждать, то почему бы не использовать Label?
> Язык ведь позволяет. Почему бы не использовать Inline?
Потому что нет необходимости.
Лично у меня нет принципов, будет мне удобнее с Label - сделаю с Label, будет удобнее с Inline - сделаю Inline, так же и Continue, Break, и пр.
Невозможно продумать ведь все ньюансы алгоритма наперед, кроме того, возможно его придется править.
И чтобы не переписывать всю логику работы, порой достаточно просто поставить в нужном месте Break...
← →
Palladin © (2004-11-18 00:17) [27]К сожалению если команда не прочиталась нужно немедленно выйти...
← →
Defunct © (2004-11-18 00:28) [28]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:34) [29]Нет, чтение команды, исполнение, запись команды.
← →
Игорь Шевченко © (2004-11-18 00:40) [30]
> А я вам гарантирую, что без Break, Continue, Goto, Exit,
> Inline и прочее упомянутое можно запросто обойтись, причем
> всегда. (написано в любой книге по паскалю в разделе операторы).
Выкинь книгу на помойку. Искренний совет.
Главное в коде - его удобочитаемость, а с введением дополнительных переменных типа Done она ухудшается.
← →
Palladin © (2004-11-18 00:42) [31]Причем сильно, ибо при чтении приходится прослеживать за ее изменением в теле цикла. Иногда это становится сущим адом.
← →
Defunct © (2004-11-18 00:47) [32]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:49) [33]
> [32] Defunct © (18.11.04 00:47)
:) К сожалению ProceedCommand это не функция, результат выполнения не влияет на выход/продолжение цикла.
← →
Defunct © (2004-11-18 00:52) [34]> :) К сожалению ProceedCommand это не функция, результат выполнения не влияет на выход/продолжение цикла.
;)
Это не проблема:
function ProceedCommand:boolean;
begin
<код процедуры>;
Result := True
end;
← →
Игорь Шевченко © (2004-11-18 00:55) [35]Defunct © (18.11.04 00:47) [32]
Код в D отличается от кода А по логике. То есть, гарантировано работает не так, как оригинал. Хотя и более удобочитаем.
> Только за то, что там указывается "полнота" языка паскаль?
Это не "полнота". Такие советы давались на заре программирования или в эпоху структурного программирования. После этого пришли к выводу, что введение операторов управления (Break, Continue, Exit) улучшает удобочитаемость кода.
← →
Игорь Шевченко © (2004-11-18 01:02) [36]Я бы код организовал следующим образом
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(...);
.....
← →
Palladin © (2004-11-18 01:04) [37]Ну конечно это не проблема. Если ProceedCommand процедура. Но если это все таки функция, которая возвращает результат выполнения команды? Но не булевский, а, скажем Integer, который потом нужно еще и анализировать и который влияет на выход из тела цикла при определенных условиях...
Кстати, в A) была допущена ошибка. Устройство ведь нужно проверить на готовность перед записью... но в принципе это ерунда, в and это увязывается. Еще момент: вы уверены, что команды выполнятся именно в том порядке в котором они записаны? Я почему то нет... Кто его знает, этот оптимизатор... Ну это тоже черт с ним... Правда ошибку искать потом неудобно будет...
Повторюсь, это ведь простейший пример. На его, так сказать, "оптимизацию" к нестабильной не гибкой форме, у вас ушло времени гораздо больше чем у меня на вариант A)... Как вы думаете... Это хорошо?
← →
Palladin © (2004-11-18 01:11) [38]
> [36] Игорь Шевченко © (18.11.04 01:02)
Ну что же Вы так... Мечом то сразу по узлу... :)
← →
Defunct © (2004-11-18 01:15) [39]Игорь Шевченко © (18.11.04 00:55) [35]
> гарантировано работает не так, как оригинал.
Я не знаю как работает оригинал, потому что не знаю сколько там устройств на самом деле. Начало DeiveConnect и секция finally дает понять, что устройство одно, но почему-то присутствует две функции IsDeviceConnected и DeviceConnected. Спрашивается зачем две функции когда устройство одно? Если уж полностью соблюсти логику примера A) получим:while NoError do
NoError :=
IsDeviceConnected and
ReadCommand and
ProceedCommand and
DeviceConnected and
WriteCommand
И Break по сути не нужен.
> Такие советы давались на заре программирования или в эпоху структурного программирования.
Возможно.
> что введение операторов управления улучшает удобочитаемость кода.
IMHO для кого как.
Вот хоть я в основном и пищу на асм (а там сами понимаете сплошные "goto"), но когда дело касается паскаля стараюсь соблюдать рекомендации прошлого (пишу без использования Break, Cont., goto, exit). И код получается вполне удобочитаемым и главное по коду сразу видно алгоритм, за это мне и нравится паскаль.
← →
Palladin © (2004-11-18 01:19) [40]IsDeviceConnected и DeviceConnected - аналогичны... просто во второй раз Is забыл написать...
Страницы: 1 2 3 4 вся ветка
Форум: "Основная";
Текущий архив: 2004.12.12;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.036 c