Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.037 c
3-1100620186
Богдан
2004-11-16 18:49
2004.12.12
Поля TDBGrid


4-1098947073
Ivolg
2004-10-28 11:04
2004.12.12
Ярлык


1-1101732768
Dmitry_04
2004-11-29 15:52
2004.12.12
Как проверить свою программу на баги?


9-1087490521
Drinkins
2004-06-17 20:42
2004.12.12
Зацените Кубик-Рубик (http://NikoVOsade.narod.ru/Cub__r.rar)


1-1101395047
denis24
2004-11-25 18:04
2004.12.12
Qrreport-html





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский