2009-12-20 6 views
5

Je passe de C# à Delphi 2009, je l'aime beaucoup jusqu'à présent. J'ai écrit une procédure de recherche binaire, qui fonctionne très bien. J'ai ajouté une simple instruction if-else à la fin de mon proc et elle ne tire tout simplement pas! Je ne vois rien de mal à cela et je suis gêné de devoir dire que je suis coincé. S'il vous plaît aider!Pourquoi mon instruction "if" semble-t-elle ne pas fonctionner?

procedure BinSearch; 
var 
    min,max,mid, x: integer; 
    A : array[0..4] of integer; 
    rslt : integer; 

begin 

    writeln('binary search'); 
    A[0] := 34; A[1] := 65; A[2] := 98; A[3] := 123; A[4] := 176; 
    listarray(a); 
    x := 62; 
    min := 0; 
    max := 4; 

    repeat 
    begin 
    mid := (min + max) div 2; 
    if x > A[mid] then 
     min := mid + 1 
    else 
     max := mid - 1; 
    end; 
    until (A[mid] = x) or (min > max); 

    writeln(mid); 
    writeln(a[mid]); 

    if A[mid] = x then 
    rslt := mid 
    else 
    rslt := not mid; 

    if 54 = 65 then 
    rslt := mid 
    else 
    rslt := not mid; 

end; 

Il est celui if A[mid] = x then qui ne se déclenche pas. Lorsque le débogage ne déclenche ni branches vraies ni fausses, le débogueur saute juste au-dessus d'elles. Aussi le if 54 = 65 then qui est juste un test fait la même chose.

Le si à l'intérieur de ma boucle de répétition fonctionne bien cependant.

Si je copie le problème if instruction dans un mini proc de test, puis appelez le proc cela fonctionne, donc ça me fait penser qu'il est quelque chose d'autre dans le proc comme un ; manquant causant quelque chose d'étrange, mais je ne le vois pas . S'il vous plaît aider!

+6

Comme rslt n'est jamais utilisé ailleurs que dans l'instruction d'affectation, le compilateur Delphi supprime ce fragment de code dans le cadre des optimisations. Il n'a pas d'impact sur le code source, n'écrit simplement pas ce code dans le fichier objet. Vous avez probablement un compilateur avertissant que la variable rslt n'est jamais utilisée ... – Sparky

+5

Bienvenue dans StackOverflow, et à Delphi. –

+1

Juste un conseil, vous n'avez pas besoin d'une paire begin-end dans une boucle repeat-until. – Todd

Répondre

4

Il se peut que le débogueur saute simplement ces instructions même si elles sont en cours d'exécution. Assurez-vous que toutes les options sont activées dans les options de débogage. Dans Delphi 7, ils sont sous Project \ Options sous l'onglet Compilateur.

+0

Merci pour votre réponse rapide. Tout va bien - ça fonctionnait tout le temps! Je ne pouvais pas voir quoi que ce soit à changer dans les options du débogueur, mais il était en effet en train de tirer et de sauter dans le débogueur. Je suppose que si ... sinon ...; est une déclaration est quelque chose à faire avec elle, mais c'est très étrange comment le débogueur va entrer dans le code identique dans d'autres endroits, et pas sur les autres. La principale chose est que cela fonctionne. Je ne suis plus perplexe et c'est la chose principale, merci pour votre aide et sry pour ma question d'âne. – user235325

+0

Oui, l'optimiseur Delphi dans les versions de débogage semble parfois un peu trop agressif pour moi. –

14

Le compilateur Delphi est assez intelligent, et il enlèvera heureusement le code inutilisé. Quand je compile votre code, je reçois des indices de compilation disant "Valeur assignée à 'rslt' jamais utilisée". Puisque la valeur n'est jamais utilisée, le compilateur ignore ces instructions.

Si vous ajoutez un Writeln(rslt); à la fin de votre procédure, vous constaterez que le débogueur va maintenant suivre votre instruction if.

+0

J'ai déjà vu ce comportement, et je parie que c'est exactement ce qui se passe! –

0

L'instruction "Begin" juste après l'instruction "Repeat" ne devrait pas être présente. Une "répétition" n'utilise pas de début. Je voudrais l'enlever juste pour être sûr que cela ne pose aucun problème.

0

"rslt" n'est pas utilisé. Par conséquent, Delphi l'optimise.

Évidemment, vous voulez retourner votre résultat. Donc changer votre déclaration:

procedure BinSearch(var rslt: integer); 

ou mieux, en faire une fonction:

function BinSearch: integer; 

et à la fin mis en:

Result := rslt; 

Est-ce que ce soit de ce qui précède, et vous Je constaterai que ces instructions ne sont plus ignorées car rslt est maintenant utilisé.

Mais, vous vous trouverez aurez un problème avec votre déclaration:

rslt := not mid; 

parce que le milieu est un entier. Je ne suis pas sûr de ce que vous voulez retourner ici, mais je sais que vous ne voulez pas que l'opérateur "non" soit appliqué à "mi".


Regardez ce code que I got from wikibooks. Cela pourrait vous aider à comprendre.

(* Returns index of requested value in an integer array that has been sorted 
in ascending order -- otherwise returns -1 if requested value does not exist. *) 

function BinarySearch(const DataSortedAscending: array of Integer; 
const ElementValueWanted: Integer): Integer; 
var 
    MinIndex, MaxIndex: Integer; 
    { When optimizing remove these variables: } 
    MedianIndex, MedianValue: Integer; 
begin 
    MinIndex := Low(DataSortedAscending); 
    MaxIndex := High(DataSortedAscending); 
    while MinIndex <= MaxIndex do begin 
     MedianIndex := (MinIndex + MaxIndex) div 2; (* If you're going to change 
     the data type here e.g. Integer to SmallInt consider the possibility of 
     an overflow. All it needs to go bad is MinIndex=(High(MinIndex) div 2), 
     MaxIndex = Succ(MinIndex). *) 
     MedianValue := DataSortedAscending[MedianIndex]; 
     if ElementValueWanted < MedianValue then 
      MaxIndex := Pred(MedianIndex) 
     else if ElementValueWanted = MedianValue then begin 
      Result := MedianIndex; 
      Exit; (* Successful exit. *) 
     end else 
      MinIndex := Succ(MedianIndex); 
    end; 
    Result := -1; (* We couldn't find it. *) 
end;