Kontrol akışı - Control flow

Olarak bilgisayar biliminin , kontrol akış (veya kontrol akışı ) tek tek sıradır ifadeler , talimatlar veya işlev çağrısı bir bölgesinin zorunlu programı vardır yürütülür ya da değerlendirildi. Açık denetim akışına yapılan vurgu, zorunlu bir programlama dilini bildirim temelli bir programlama dilinden ayırır .

Zorunlu bir programlama dilinde , bir kontrol akışı ifadesi , iki veya daha fazla yoldan hangisinin izleneceğine dair bir seçimin yapılmasıyla sonuçlanan bir ifadedir. For olmayan katı diller, fonksiyonlar ve fonksiyonel dil yapıları aynı sonucu elde etmek için var, ancak genellikle denetim akışı ifadeleri adlandırılan değildir.

Bir dizi ifade, genellikle , gruplamaya ek olarak, sözlüksel bir kapsamı da tanımlayan bir blok olarak yapılandırılmıştır .

Kesintiler ve sinyaller , kontrol akışını bir alt programa benzer şekilde değiştirebilen düşük seviyeli mekanizmalardır , ancak genellikle bir satır içi işlemin yürütülmesinden ziyade bazı harici uyaranlara veya olaylara ( eşzamansız olarak gerçekleşebilen) bir yanıt olarak ortaya çıkar. kontrol akışı ifadesi.

Makine dili veya montaj dili düzeyinde , kontrol akışı talimatları genellikle program sayacını değiştirerek çalışır . Bazı merkezi işlem birimleri (CPU'lar) için mevcut olan tek kontrol akışı talimatları, atlamalar olarak da adlandırılan koşullu veya koşulsuz dal talimatlarıdır.

Kategoriler

Kontrol akışını gösteren bir akış şeması .

Farklı diller tarafından desteklenen kontrol akışı deyimlerinin türleri değişiklik gösterir, ancak etkilerine göre kategorilere ayrılabilir:

  • Farklı bir ifadede devam (koşulsuz dallanma veya atlama)
  • Yalnızca bazı koşullar karşılandığında bir dizi ifadeyi yürütmek (seçim - yani, koşullu dal )
  • Bir koşul karşılanana kadar bir dizi deyimi sıfır veya daha fazla kez yürütme (yani döngü - koşullu dal ile aynı )
  • Kontrol akışı genellikle (döndüren bundan sonra uzak tabloların bir dizi, yürütülmesi altyordamlarını , coroutines ve devamlarını )
  • Programı durdurma, daha fazla yürütmeyi önleme (koşulsuz durdurma)

İlkeller

Etiketler

Bir etiket içinde sabit bir pozisyona atanan açık ad veya numara olan kaynak kodu ve kaynak kodunda yerlerde görünüyorsa denetim akışı ifadeler tarafından başvurulan edilmiş olabilir. Etiket, kaynak kodundaki bir konumu işaretler ve başka bir etkisi yoktur.

Satır numaraları , bazı dillerde ( BASIC gibi ) kullanılan adlandırılmış etikete bir alternatiftir . Bunlar tam sayılar kaynak kodunda metnin her satırının başında yerleştirdi. Bunları kullanan diller, genellikle, satır numaralarının sonraki her satırda değerinin artması gerektiği, ancak bunların ardışık olmasını gerektirmediği kısıtlamasını getirir. Örneğin, BASIC'te:

10 LET X = 3
20 PRINT X

C ve Ada gibi diğer dillerde etiket , genellikle bir satırın başında görünen ve hemen ardından iki nokta üst üste gelen bir tanımlayıcıdır . Örneğin, C'de:

Success: printf("The operation was successful.\n");

ALGOL 60 dili , etiket olarak hem tam sayılara hem de tanımlayıcılara izin verdi (her ikisi de aşağıdaki ifadeye iki nokta üst üste işaretiyle bağlanmıştır), ancak diğer ALGOL türevleri tam sayılara izin veriyorsa çok azı . Erken Fortran derleyicileri yalnızca tam sayılara etiket olarak izin verirdi. Fortran-90'dan başlayarak, alfanümerik etiketlere de izin verildi.

git

Goto deyimi (İngilizce kelimelerin bir arada gidip ve için ve buna göre telaffuz edilir) kontrolün koşulsuz transferinin en temel şeklidir.

Her ne kadar kelime ya dile bağlı alt veya üst durumunda olabilir, genellikle olarak yazılır:

   goto label

Bir goto ifadesinin etkisi, yürütülecek sonraki ifadenin belirtilen etikette (veya hemen sonra) görünen ifade olmasını sağlamaktır.

Goto ifadeleri , başta Dijkstra olmak üzere birçok bilgisayar bilimcisi tarafından zararlı olarak kabul edilmiştir .

alt programlar

İçin terminoloji alt programlar değişir; alternatif olarak rutinler, prosedürler, işlevler (özellikle sonuç döndürüyorlarsa) veya yöntemler (özellikle sınıflara veya sınıflara aitlerse ) olarak bilinebilirler .

1950'lerde, bilgisayar bellekleri mevcut standartlara göre çok küçüktü, bu nedenle alt programlar esas olarak program boyutunu küçültmek için kullanıldı. Bir kod parçası bir kez yazıldı ve daha sonra bir programda çeşitli yerlerden birçok kez kullanıldı.

Bugün, alt rutinler daha sık, örneğin bazı algoritmaları izole ederek veya bazı veri erişim yöntemlerini gizleyerek bir programı daha yapılandırılmış hale getirmeye yardımcı olmak için kullanılmaktadır. Bir program üzerinde birçok programcı çalışıyorsa, altyordamlar işin bölünmesine yardımcı olabilecek bir tür modülerliktir .

Sıra

Yapılandırılmış programlamada, ardışık komutların sıralı sıralaması, yineleme, özyineleme ve seçimin yanı sıra programlar için bir yapı taşı olarak kullanılan temel kontrol yapılarından biri olarak kabul edilir.

Minimum yapılandırılmış kontrol akışı

Mayıs 1966'da Böhm ve Jacopini, Communications of the ACM'de goto s içeren herhangi bir programın yalnızca seçim (IF THEN ELSE) ve döngüler (WHILE koşulu DO xxx) içeren goto içermeyen bir forma dönüştürülebileceğini gösteren bir makale yayınladı. çoğaltılmış kod ve/veya Boole değişkenlerinin eklenmesiyle (doğru/yanlış bayrakları). Daha sonraki yazarlar, seçimin döngülerle (ve daha fazla Boole değişkeni) değiştirilebileceğini gösterdi.

Böyle bir minimalizmin mümkün olması, mutlaka arzu edilir olduğu anlamına gelmez; sonuçta, bilgisayarlar teorik olarak yalnızca bir makine talimatına ihtiyaç duyarlar (bir sayıyı diğerinden çıkarın ve sonuç negatifse dallandırın), ancak pratik bilgisayarlarda düzinelerce hatta yüzlerce makine talimatı vardır.

Böhm ve Jacopini'nin makalesinin gösterdiği şey, tüm programların ücretsiz olabileceğiydi. Diğer araştırmalar, bir giriş ve bir çıkışa sahip kontrol yapılarının anlaşılmasının diğer herhangi bir biçimden çok daha kolay olduğunu gösterdi, çünkü bunlar esas olarak kontrol akışını bozmadan herhangi bir yerde bir ifade olarak kullanılabilirler. Başka bir deyişle, birleştirilebilirlerdi . ( Sıkı olmayan programlama dilleri ve daha yakın zamanda birleştirilebilir yazılım işlemleri gibi sonraki gelişmeler, program bileşenlerini daha özgürce birleştirilebilir hale getirerek bu stratejiyi sürdürdü.)

Bazı akademisyenler Böhm-Jacopini sonucuna karşı saf bir yaklaşım benimsediler ve döngülerin ortasından breakve benzeri talimatların bile returnBöhm-Jacopini ispatında ihtiyaç duyulmadığından kötü uygulama olduğunu savundular ve böylece tüm döngülerin tek bir döngüye sahip olması gerektiğini savundular. çıkış noktası. Bu saf yaklaşım, 1990'ların ortalarına kadar akademide programlamaya giriş eğitimi için tercih edilen araç olan Pascal (1968–1969'da tasarlandı) dilinde somutlaştırıldı . Böhm-Jacopini teoreminin doğrudan uygulanması, yapılandırılmış çizelgeye ek yerel değişkenlerin eklenmesine ve ayrıca bazı kod tekrarlarına neden olabilir . Pascal bu problemlerin her ikisinden de etkilenir ve Eric S. Roberts tarafından alıntılanan ampirik çalışmalara göre , öğrenci programcılar bir dizideki bir elemanı aramak için bir fonksiyon yazmak da dahil olmak üzere birkaç basit problem için Pascal'da doğru çözümleri formüle etmekte zorlandılar. Roberts tarafından alıntılanan Henry Shapiro tarafından 1980'de yapılan bir araştırma, yalnızca Pascal tarafından sağlanan kontrol yapılarını kullanarak, deneklerin sadece %20'si tarafından doğru çözümün verildiğini, ancak hiçbir denek, testten bir dönüş yazmasına izin verilirse bu sorun için yanlış kod yazmadığını buldu. bir döngünün ortasında.

Uygulamada kontrol yapıları

Kontrol yapılarına sahip çoğu programlama dili, ilgili kontrol yapısının türünü belirten bir başlangıç ​​anahtar kelimesine sahiptir. Diller daha sonra kontrol yapılarının son bir anahtar kelimeye sahip olup olmadığına göre bölünür.

  • Son anahtar kelime yok: ALGOL 60 , C , C++ , Haskell , Java , Pascal , Perl , PHP , PL/I , Python , PowerShell . Bu tür diller, ifadeleri bir arada gruplandırmanın bir yolunu gerektirir:
    • ALGOL 60 ve Pascal: begin...end
    • C, C++, Java, Perl, PHP ve PowerShell: küme parantezleri { ...}
    • PL/I: DO...END
    • Python: girinti seviyesini kullanır (bkz. Off-side kuralı )
    • Haskell: girinti düzeyi veya küme parantezleri kullanılabilir ve bunlar serbestçe karıştırılabilir
    • Lua: kullanır do...end
  • Son anahtar kelime: Ada , ALGOL 68 , Modula-2 , Fortran 77 , Mythryl , Visual Basic . Nihai anahtar kelimenin biçimleri değişiklik gösterir:
    • Ada: son anahtar kelime end+ boşluk + ilk anahtar kelimedir, örneğin, if... end if, loop...end loop
    • ALGOL 68, Mythryl: ilk anahtar kelime tersten yazılmıştır örn., if... fi, case...esac
    • Fortran 77: son anahtar kelime END+ ilk anahtar kelimedir, örneğin, IF... ENDIF, DO...ENDDO
    • Modula-2: ENDher şey için aynı son anahtar kelime
    • Visual Basic: her kontrol yapısının kendi anahtar sözcüğü vardır. If... End If; For... Next; Do... Loop; While...Wend

Tercih

If-then-(else) ifadeleri

Koşullu ifadeler ve koşullu yapılar, programcı tarafından belirtilen bir boole koşulunun doğru veya yanlış olarak değerlendirilmesine bağlı olarak farklı hesaplamalar veya eylemler gerçekleştiren bir programlama dilinin özellikleridir .

  • IF..GOTO. Yapılandırılmamış dillerde bulunan, tipik bir makine kodu talimatını taklit eden bir form, koşul karşılandığında bir etikete veya satır numarasına (GOTO) atlayacaktır.
  • IF..THEN..(ENDIF). Herhangi bir basit ifade veya iç içe blok, bir sıçrama ile sınırlandırılmak yerine THEN anahtar anahtar sözcüğünü takip edebilir. Bu yapılandırılmış bir form.
  • IF..THEN..ELSE..(ENDIF). Yukarıdaki gibi, ancak koşul yanlışsa gerçekleştirilecek ikinci bir işlemle. Bu, birçok varyasyonu olan en yaygın biçimlerden biridir. Bazıları bir terminal gerektirir ENDIF, diğerleri gerektirmez . C ve ilgili diller, bir terminal anahtar sözcüğü veya 'then' gerektirmez, ancak koşulun etrafında parantez gerektirir.
  • Koşullu ifadeler, diğer koşullu ifadelerin içinde olabilir ve çoğu zaman iç içedir. Bazı diller izin ELSEve IFbirleştirilecek ELSEIFbir dizi olan ihtiyacı kaçınarak, ENDIFBileşik cümlenin sonunda veya diğer nihai ifadeleri.
Paskal : Ada : C : Kabuk komut dosyası : Python : Lisp :
if a > 0 then
  writeln("yes")
else
  writeln("no");
if a > 0 then
      Put_Line("yes");
else
      Put_Line("no");
end if;
if (a > 0) { 
    printf("yes");
}
else {
    printf("no");
}
if [ $a -gt 0 ]; then
      echo "yes"
else
      echo "no"
fi
if a > 0: 
    print("yes")
else:
    print("no")
(princ
  (if (plusp a)
      "yes"
      "no"))

Daha az yaygın varyasyonlar şunları içerir:

  • Fortran gibi bazı dillerde, sayısal bir değerin pozitif, negatif veya sıfır olup olmadığını test eden üç yönlü veya aritmetik if vardır .
  • Bazı diller , örneğin Lisp'in işlevsel bir ififade biçimine sahiptir . cond
  • Bazı dillerde, C'nin üçlü operatörü gibi bir ifadenin operatör biçimi vardır .if
  • Perl , C stilini ve ifile tamamlar .whenunless
  • Smalltalk , herhangi bir temel dil yapısından ziyade koşul şartlarını uygulamak için kullanır ifTrueve ifFalsemesajlar.

Case ve switch ifadeleri

Switch deyimleri (veya case deyimleri veya çok yollu dallar ) belirli bir değeri belirtilen sabitlerle karşılaştırır ve eşleştirilecek ilk sabite göre işlem yapar. Hiçbir eşleşme başarılı olmazsa, varsayılan bir işlem ("başka", "aksi takdirde") için genellikle bir hüküm vardır. Switch ifadeleri, arama tabloları gibi derleyici optimizasyonlarına izin verebilir . Gelen dinamik dillerin , olgular sabit ifadeler ile sınırlı olmayabilir ve uzatmak olabilir desen eşleştirme gibi kabuk komut dosyası , sağda, örneğin nerede *)uygular bir varsayılan durumda topak herhangi bir dize eşleşen. Vaka mantığı da olduğu gibi, fonksiyonel formda uygulanabilir SQL 'in decodeifadesi.

Paskal : Ada : C : Kabuk komut dosyası : Lisp :
case someChar of
  'a': actionOnA;
  'x': actionOnX;
  'y','z':actionOnYandZ;
  else actionOnNoMatch;
end;
case someChar is
  when 'a' => actionOnA;
  when 'x' => actionOnX;
  when 'y' | 'z' => actionOnYandZ;
  when others => actionOnNoMatch;
end;
switch (someChar) {
  case 'a': actionOnA; break;
  case 'x': actionOnX; break;
  case 'y':
  case 'z': actionOnYandZ; break;
  default: actionOnNoMatch;
}
case $someChar in 
   a)    actionOnA ;;
   x)    actionOnX ;;
   [yz]) actionOnYandZ ;;
   *)    actionOnNoMatch  ;;
esac
(case some-char
  ((#\a)     action-on-a)
  ((#\x)     action-on-x)
  ((#\y #\z) action-on-y-and-z)
  (else      action-on-no-match))

döngüler

Döngü, bir kez belirtilen ancak art arda birkaç kez gerçekleştirilebilen bir dizi ifadedir. Döngünün "içindeki" koda ( aşağıda xxx olarak gösterilen döngünün gövdesi ), belirli sayıda veya bir öğe koleksiyonu için bir kez veya bir koşul karşılanana kadar veya süresiz olarak uyulur .

Olarak işlevsel programlama gibi diller, Haskell'e ve Şema , döngüler kullanılarak eksprese edilebilir özyinelemeye veya sabit nokta iterasyon yerine açık döngüleri. Kuyruk özyineleme , yinelemeye kolayca dönüştürülebilen özel bir özyineleme durumudur.

Sayım kontrollü döngüler

Çoğu programlama dili, bir döngüyü belirli sayıda tekrarlamak için yapılara sahiptir. Çoğu durumda sayma yukarı yerine aşağı doğru gidebilir ve 1'den farklı adım boyutları kullanılabilir.

   FOR I = 1 TO N           | for I := 1 to N do begin
       xxx                  |     xxx
   NEXT I                   | end;
------------------------------------------------------------
   DO I = 1,N               | for ( I=1; I<=N; ++I ) {
       xxx                  |     xxx
   END DO                   | }

Bu örneklerde, eğer N < 1 ise, o zaman döngü gövdesi, programlama diline bağlı olarak bir kez (I değerine sahip I ile) yürütülebilir veya hiç yürütülmeyebilir.

Birçok programlama dilinde, sayım kontrollü bir döngüde yalnızca tamsayılar güvenilir bir şekilde kullanılabilir. Kayan nokta sayıları, donanım kısıtlamaları nedeniyle kesin olmayan bir şekilde temsil edilir, bu nedenle aşağıdaki gibi bir döngü

   for X := 0.1 step 0.1 to 1.0 do

yuvarlama hatalarına ve/veya donanıma ve/veya derleyici sürümüne bağlı olarak 9 veya 10 kez tekrarlanabilir. Ayrıca, X'in artışı tekrarlanan ekleme ile meydana gelirse, birikmiş yuvarlama hataları, her yinelemedeki X değerinin beklenen 0.1, 0.2, 0.3, ..., 1.0 dizisinden oldukça farklı olabileceği anlamına gelebilir.

Durum kontrollü döngüler

Çoğu programlama dili, bazı koşullar değişene kadar bir döngüyü tekrarlamak için yapılara sahiptir. Bazı varyasyonlar, durumu döngünün başlangıcında test eder; diğerleri sonunda test eder. Test başlangıçta ise, vücut tamamen atlanabilir; sonunda ise, gövde her zaman en az bir kez yürütülür.

   DO WHILE (test)          | repeat 
       xxx                  |     xxx 
   LOOP                     | until test;
----------------------------------------------
   while (test) {           | do
       xxx                  |     xxx
   }                        | while (test);

Bir kontrol kesintisi , değer grupları için işlemeyi tetiklemek için sıradan döngüler içinde kullanılan bir değer değişikliği algılama yöntemidir. Değerler döngü içinde izlenir ve bir değişiklik program akışını bunlarla ilişkili grup olayının işlenmesine yönlendirir.

   DO UNTIL (End-of-File)
      IF new-zipcode <> current-zipcode
         display_tally(current-zipcode, zipcount)
         
         current-zipcode = new-zipcode
         zipcount = 0
      ENDIF
      
      zipcount++
   LOOP

Toplama kontrollü döngüler

Birkaç programlama dili (örneğin, Ada , D , C++11 , Smalltalk , PHP , Perl , Object Pascal , Java , C# , MATLAB , Visual Basic , Ruby , Python , JavaScript , Fortran 95 ve üstü) örtük olarak izin veren özel yapılara sahiptir. bir dizinin tüm öğeleri veya bir kümenin veya koleksiyonun tüm üyeleri arasında döngü yapmak.

   someCollection do: [:eachElement |xxx].
   for Item in Collection do begin xxx end;

   foreach (item; myCollection) { xxx }

   foreach someArray { xxx }

   foreach ($someArray as $k => $v) { xxx }

   Collection<String> coll; for (String s : coll) {}

   foreach (string s in myStringCollection) { xxx }

   someCollection | ForEach-Object { $_ }
   forall ( index = first:last:step... )

Scala , toplama kontrollü döngüleri genelleştiren ve aynı zamanda eşzamansız programlama gibi diğer kullanımları destekleyen for-ifadelerine sahiptir . Haskell , birlikte Scala'daki ifadeler için benzer işlev sağlayan do ifadelerine ve anlamalara sahiptir.

Genel yineleme

Genel yineleme C'nin gibi yapıları fordeyimi ve Common Lisp 'ın doböyle paralel koleksiyonlarından bazı dizi üzerinde döngü yukarıdaki döngü türlü, ve diğerleri, herhangi ifade etmek için kullanılabilir formu. Daha spesifik bir döngü yapısının kullanılabileceği durumlarda, genellikle ifadenin amacını daha net hale getirdiği için genel yineleme yapısına göre tercih edilir.

sonsuz döngüler

Sonsuz döngüler , bir program bölümünün sonsuza kadar veya bir hata gibi istisnai bir durum ortaya çıkana kadar döngü yapmasını sağlamak için kullanılır. Örneğin, olaya dayalı bir program (bir sunucu gibi ) sonsuza kadar döngü yapmalı, olayları meydana geldikçe ele almalı, yalnızca işlem bir operatör tarafından sonlandırıldığında durmalıdır.

Sonsuz döngüler, diğer kontrol akışı yapıları kullanılarak uygulanabilir. En yaygın olarak, yapılandırılmamış programlamada bu geri atlamadır (goto), yapılandırılmış programlamada bu, koşul atlanarak veya açıkça true olarak ayarlanarak asla bitmeyecek şekilde ayarlanmış belirsiz bir döngüdür (while döngüsü) while (true) .... Bazı diller, genellikle belirsiz bir döngüden koşulu atlayarak, sonsuz döngüler için özel yapılara sahiptir. Örnekler arasında Ada ( loop ... end loop), Fortran ( DO ... END DO), Go ( for { ... }) ve Ruby ( loop do ... end) bulunur.

Genellikle, koşul kontrollü bir döngüde bir programlama hatası tarafından kasıtsız olarak sonsuz bir döngü oluşturulur, burada döngü koşulu, döngü içinde asla değişmeyen değişkenler kullanır.

Sonraki yineleme ile devam

Bazen bir döngünün gövdesi içinde, döngü gövdesinin geri kalanını atlamak ve döngünün bir sonraki yinelemesi ile devam etmek arzusu vardır. Bazı diller continue(çoğu dil) skip, veya next(Perl ve Ruby) gibi bunu yapacak bir ifade sağlar. Etki, en içteki döngü gövdesini zamanından önce sonlandırmak ve ardından bir sonraki yinelemeyle normal olarak devam etmektir. Yineleme döngüdeki sonuncuysa, bunun etkisi tüm döngüyü erken sonlandırmaktır.

Geçerli yinelemeyi yeniden yap

Perl ve Ruby gibi bazı dillerde, redogeçerli yinelemeyi baştan başlatan bir ifade vardır.

Döngüyü yeniden başlat

Ruby, retryilk yinelemeden tüm döngüyü yeniden başlatan bir ifadeye sahiptir .

Döngülerden erken çıkış

Bir tabloda arama yapmak için sayım kontrollü bir döngü kullanırken, gerekli öğe bulunur bulunmaz aramanın durdurulması istenebilir. Bazı programlama dilleri, break(çoğu dil), Exit(Visual Basic) veya last(Perl) gibi bir ifade sağlar; bu, geçerli döngüyü hemen sonlandırmak ve bu döngüden hemen sonra denetimi ifadeye aktarmaktır. Erken çıkış döngüleri için başka bir terim döngü ve bir buçuktur .

Aşağıdaki örnek, içinde yapılır Ada destekler döngüler erken bir çıkış ve ortasında test döngüler . Her iki özellik de çok benzerdir ve her iki kod parçacığını karşılaştırmak farkı gösterecektir: ortadaki bir koşul bağımsız bir yapıyken erken çıkış bir if ifadesiyle birleştirilmelidir .

with Ada.Text IO;
with Ada.Integer Text IO;

procedure Print_Squares is 
    X : Integer;
begin
    Read_Data : loop
        Ada.Integer Text IO.Get(X);
    exit Read_Data when X = 0;
        Ada.Text IO.Put (X * X);
        Ada.Text IO.New_Line;
    end loop Read_Data;
end Print_Squares;

Python , bir döngüden erken çıkılıp çıkılmadığına (bir breakifadeyle) veya döngüyle birlikte bir else-yan tümcesi kullanılarak yapılmamasına bağlı olarak koşullu kod yürütülmesini destekler . Örneğin,

for n in set_of_numbers:
    if isprime(n):
        print("Set contains a prime number")
        break
else:
    print("Set did not contain any prime numbers")

elseYukarıdaki örnekte maddesi ile bağlantılıdır foriç açıklamaya olup ifdeyimi. Hem Python en forve whiledöngüler döngünün erken çıkış vuku bulmadığı takdirde yürütülür böyle else sözcüğü, destekler.

Bazı diller iç içe döngülerden çıkmayı destekler; teori çevrelerinde bunlara çok seviyeli kırılmalar denir. Yaygın bir kullanım örneği, çok boyutlu bir tablo aramaktır. Bu, bash ve PHP'de olduğu gibi çok düzeyli kesmeler ( N düzeyinden ayrılma ) veya Java ve Perl'de olduğu gibi etiketli kesmeler (belirli etikette ayrılma ve devam etme) yoluyla yapılabilir. Çok seviyeli kesintilere alternatifler arasında, başka bir seviyeyi kırmak için test edilen bir durum değişkeni ile birlikte tekli kesintiler bulunur; kırıldığı düzeyde yakalanan istisnalar; iç içe döngüleri bir işleve yerleştirmek ve tüm iç içe döngünün sonlandırma etkisine dönüşünü kullanmak; veya bir etiket ve bir goto ifadesi kullanarak. C, çok düzeyli bir ara içermez ve genel alternatif, etiketli bir ara uygulamak için bir goto kullanmaktır. Python'un çok düzeyli bir kesintisi veya devamı yoktur - bu, PEP 3136'da önerildi ve eklenen karmaşıklığın nadir meşru kullanıma değmediği temelinde reddedildi.

Çok seviyeli kırılmalar kavramı teorik bilgisayar biliminde biraz ilgi çekicidir , çünkü bugün Kosaraju hiyerarşisi olarak adlandırılan şeye yol açar . 1973'te S. Rao Kosaraju , yapılandırılmış program teoremini , isteğe bağlı derinlikte, döngülerden çok düzeyli kesmelere izin verildiği sürece, yapılandırılmış programlamaya ek değişkenler eklemekten kaçınmanın mümkün olduğunu kanıtlayarak geliştirdi. Ayrıca, Kosaraju programlarının sıkı hiyerarşi var olduğunu kanıtladı: Her tamsayı için n , derinlik çok düzeyli mola içeren bir program vardır n daha az bir derinlik çok seviyeli sonları ile bir program olarak yeniden olamaz n katma sokulmasıyla olmadan değişkenler.

Ayrıca return, döngülü ifadeleri yürüten bir alt rutinden de çıkabilir , hem iç içe döngüden hem de alt rutinden ayrılabilir . Çoklu kesintiler için önerilen başka kontrol yapıları vardır , ancak bunlar genellikle bunun yerine istisnalar olarak uygulanır.

2004 ders kitabında David Watt , çok seviyeli kesintiler ve dönüş ifadeleri arasındaki benzerliği açıklamak için Tennent'in sıralayıcı kavramını kullanır . Watt , "metinsel olarak çevreleyen bir komut veya prosedürün yürütülmesini sonlandıran sıralayıcı" olarak tanımlanan, kaçış sıralayıcıları olarak bilinen bir sıralayıcı sınıfının , hem döngülerden kopmaları (çok seviyeli kesmeler dahil) hem de geri dönüş ifadelerini kapsadığını not eder. Bununla birlikte, yaygın olarak uygulandığı gibi, dönüş sıralayıcıları da bir (dönüş) değeri taşıyabilirken, çağdaş dillerde uygulandığı şekliyle ara sıralayıcı genellikle taşıyamaz.

Döngü çeşitleri ve değişmezler

Döngü varyantları ve döngü değişmezleri , döngülerin doğruluğunu ifade etmek için kullanılır.

Pratik açıdan, bir döngü varyantı, başlangıçta negatif olmayan bir değere sahip bir tamsayı ifadesidir. Değişkenin değeri her döngü yinelemesi sırasında azalmalı, ancak döngünün doğru yürütülmesi sırasında asla negatif olmamalıdır. Döngü çeşitleri, döngülerin sona ereceğini garanti etmek için kullanılır.

Döngü değişmezi, ilk döngü yinelemesinden önce doğru olması ve her yinelemeden sonra doğru kalması gereken bir iddiadır. Bu, bir döngü doğru bir şekilde sona erdiğinde, hem çıkış koşulunun hem de döngü değişmezinin karşılandığı anlamına gelir. Döngü değişmezleri, ardışık yinelemeler sırasında bir döngünün belirli özelliklerini izlemek için kullanılır.

Eiffel gibi bazı programlama dilleri, döngü değişkenleri ve değişmezler için yerel destek içerir. Diğer durumlarda, destek bir eklenti gibi olan Java Modelleme Dili 'la şartname döngü ifadeleri de Java .

Döngü alt dili

Bazı Lisp lehçeleri, Döngüleri tanımlamak için kapsamlı bir alt dil sağlar. Erken bir örnek, Interlisp'in Conversional Lisp'inde bulunabilir . Common Lisp , böyle bir alt dili uygulayan bir Döngü makrosu sağlar.

Döngü sistemi çapraz referans tablosu

Programlama dili koşullu döngü erken çıkış döngü devamı yeniden yapmak yeniden denemek doğruluk tesisleri
başlamak orta son saymak Toplamak Genel sonsuz varyant değişmez
Ada Evet Evet Evet Evet diziler Numara Evet derin iç içe Numara
APL Evet Numara Evet Evet Evet Evet Evet derin iç içe Evet Numara Numara
C Evet Numara Evet Numara Numara Evet Numara derin iç içe derin iç içe Numara
C++ Evet Numara Evet Numara Evet Evet Numara derin iç içe derin iç içe Numara
C# Evet Numara Evet Numara Evet Evet Numara derin iç içe derin iç içe
COBOL Evet Numara Evet Evet Numara Evet Numara derin iç içe derin iç içe Numara
Ortak Lisp Evet Evet Evet Evet yalnızca yerleşik Evet Evet derin iç içe Numara
NS Evet Numara Evet Evet Evet Evet Evet derin iç içe derin iç içe Numara
Eyfel Evet Numara Numara Evet Evet Evet Numara bir seviye Numara Numara Numara sadece tamsayı Evet
F# Evet Numara Numara Evet Evet Numara Numara Numara Numara Numara
77 Evet Numara Numara Evet Numara Numara Numara bir seviye Evet
90 Evet Numara Numara Evet Numara Numara Evet derin iç içe Evet
Fortran 95 ve sonrası Evet Numara Numara Evet diziler Numara Evet derin iç içe Evet
Haskell Numara Numara Numara Numara Evet Numara Evet Numara Numara Numara
Java Evet Numara Evet Numara Evet Evet Numara derin iç içe derin iç içe Numara yerli olmayan yerli olmayan
JavaScript Evet Numara Evet Numara Evet Evet Numara derin iç içe derin iç içe Numara
Doğal Evet Evet Evet Evet Numara Evet Evet Evet Evet Evet Numara
OCaml Evet Numara Numara Evet diziler, listeler Numara Numara Numara Numara Numara
PHP Evet Numara Evet Numara Evet Evet Numara derin iç içe derin iç içe Numara
Perl Evet Numara Evet Numara Evet Evet Numara derin iç içe derin iç içe Evet
piton Evet Numara Numara Numara Evet Numara Numara derin iç içe derin iç içe Numara
REBOL Numara Evet Evet Evet Evet Numara Evet bir seviye Numara Numara
yakut Evet Numara Evet Evet Evet Numara Evet derin iç içe derin iç içe Evet Evet
standart makine öğrenimi Evet Numara Numara Numara diziler, listeler Numara Numara Numara Numara Numara
Visual Basic .NET Evet Numara Evet Evet Evet Numara Evet döngü tipi başına bir seviye döngü tipi başına bir seviye
Güç kalkanı Evet Numara Evet Numara Evet Evet Numara ? Evet
  1. a while (true) , bu amaç için sonsuz bir döngü olarak sayılmaz, çünkü özel bir dil yapısı değildir.
  2. a b c d e f g h C'nindöngüsü, genellikle bunun için kullanılmasına rağmen, özel bir sayma değil, genel bir döngü yapısıdır.for (init; test; increment)
  3. a b c APL, C, C++ ve C#'da etiketler ve gotolar kullanılarak derin aralar gerçekleştirilebilir.
  4. Bir nesnelerin üzerine Yineleme edildieklendiPHP 5'de.
  5. a b c Artan bir liste veya oluşturucu üzerinde yineleme yapılarak bir sayma döngüsü simüle edilebilir, örneğin Python'srange().
  6. a b c d e Özel durum işleme kullanılarak derin kesintiler gerçekleştirilebilir.
  7. a Özel bir yapı yoktur, çünküwhileişlev bunun için kullanılabilir.
  8. a Özel bir yapı yoktur, ancak kullanıcılar genel döngü işlevlerini tanımlayabilir.
  9. Bir C ++ 11standart kişiyeiçin aralık tabanlı. OlarakSTL, bir olduğustd::for_each şablonSTL yineleme işlevkaplarve bir çağrıtekli fonksiyonuher bir eleman için. İşlev, bu kaplar üzerindemakroolarak da oluşturulabilir.
  10. a Sayım kontrollü döngü, bir tamsayı aralığında yineleme ile gerçekleştirilir; çıkış için ek bir koşul dahil ederek erken çıkış.
  11. a Eiffel, ayrılmış bir Word'ü desteklerretry, ancakdöngü kontrolünde değil,istisna işlemedekullanılır.
  12. Bir gerektirirJava Modelleme Dili(JML) davranışsal arayüz şartname dilini.
  13. a Döngü değişkenlerinin tamsayı olmasını gerektirir; transfinite varyantları desteklenmez. [1]
  14. a D, sonsuz koleksiyonları ve bu koleksiyonlar üzerinde yineleme yeteneğini destekler. Bu, herhangi bir özel yapı gerektirmez.
  15. a Derin aralarGO TOve prosedürlerikullanılarak elde edilebilir.
  16. Bir Common Lisp jenerik toplama tip kavramını öncedir.

Yapılandırılmış yerel olmayan kontrol akışı

Birçok programlama dili, özellikle daha dinamik programlama stillerini tercih edenler, yerel olmayan kontrol akışı için yapılar sunar . Bunlar, yürütme akışının belirli bir bağlamdan çıkmasına ve önceden bildirilen bir noktada yeniden başlamasına neden olur. Koşullar , istisnalar ve devamlar , üç yaygın yerel olmayan kontrol yapısı türüdür; jeneratörler , eşyordamlar ve async anahtar sözcüğü gibi daha egzotik olanlar da mevcuttur .

Koşullar

PL/I , yükseltilebilen ve engellenebilen 22 standart koşula sahiptir (örneğin, ZERODIVIDE SUBSCRIPTRANGE ENDFILE): ON koşulu eylemi; Programcılar ayrıca kendi adlandırılmış koşullarını tanımlayabilir ve kullanabilir.

Gibi yapılandırılmamış eğer yalnızca bir deyim çoğu durumda bu nedenle belirtilebilir bir GOTO kontrol akışı tekrar başlayacaktır karar vermeye ihtiyaç vardır.

Ne yazık ki, bazı uygulamaların hem uzayda hem de zamanda (özellikle SUBSCRIPTRANGE) önemli bir ek yükü vardı, bu yüzden birçok programcı koşulları kullanmaktan kaçınmaya çalıştı.

Ortak Sözdizimi örnekleri:

 ON condition GOTO label

istisnalar

Modern diller, istisna işleme için GOTOveya (çok düzeyli) kesintiler veya geri dönüşlere dayanmayan özel bir yapılandırılmış yapıya sahiptir . Örneğin, C++'da şunlar yazılabilir:

try {
    xxx1                                  // Somewhere in here
    xxx2                                  //     use: '''throw''' someValue;
    xxx3
} catch (someClass& someId) {             // catch value of someClass
    actionForSomeClass 
} catch (someType& anotherId) {           // catch value of someType
    actionForSomeType
} catch (...) {                           // catch anything not already caught
    actionForAnythingElse
}

catchYukarıda herhangi bir sayıda ve çeşitte tümce kullanılabilir. Belirli catchbir eşleşme yoksa throw, kontrol bir eşleşme catchbulunana kadar veya ana programın sonuna ulaşılana kadar alt program çağrıları ve/veya iç içe bloklar aracılığıyla geri süzülür , bu noktada program uygun bir hata mesajıyla zorla durdurulur.

C++'ın etkisiyle, catchJava veya C# gibi günümüzde popüler olan diğer dillerde kalıp eşleştirme özel durum işleyicisi bildirmek için ayrılmış anahtar kelimedir. Ada gibi diğer bazı diller, exceptionbir istisna işleyicisi tanıtmak için anahtar kelimeyi kullanır ve daha sonra when, kalıp eşleştirme için farklı bir anahtar kelime ( Ada'da) bile kullanabilir . AppleScript gibi birkaç dil , istisna oluştuğunda birkaç bilgiyi otomatik olarak çıkarmak için istisna işleyici sözdiziminde yer tutucular içerir. Bu yaklaşım, aşağıda on errorAppleScript'teki yapı ile örneklenmiştir :

try
    set myNumber to myNumber / 0
on error e  number n  from f  to t  partial result pr
    if ( e = "Can't divide by zero" ) then display dialog "You must not do that"
end try

David Watt'ın 2004 ders kitabı ayrıca sıralayıcılar çerçevesinde istisna işlemeyi de analiz eder (bu makalede döngülerden erken çıkışlar bölümünde tanıtılmıştır). Watt, genellikle aritmetik taşmalar veya dosya bulunamadı gibi giriş/çıkış hatalarıyla örneklenen anormal bir durumun, "bazı düşük seviyeli program birimlerinde algılanan, ancak [bunun için] bir işleyicinin daha doğal olarak konumlandırıldığı bir tür hata olduğunu belirtir. üst düzey bir program biriminde". Örneğin, bir program, dosyaları okumak için birkaç çağrı içerebilir, ancak bir dosya bulunmadığında gerçekleştirilecek eylem, söz konusu dosyanın programa göre anlamına (amacı) bağlıdır ve bu nedenle, bu anormal durum için bir işleme rutini olamaz. düşük seviyeli sistem kodunda bulunur. Watts ayrıca, tek çıkışlı yapılandırılmış programlama veya hatta (çok çıkışlı) dönüş sıralayıcılarının gerektireceği gibi, arayan kişiye durum bayrakları testinin getirilmesinin, "uygulama kodunun durum bayraklarının testleri tarafından karmaşık hale gelme eğiliminde olduğu" bir duruma yol açtığını ve "programcı bir durum bayrağını test etmeyi unutabilir veya tembelce ihmal edebilir. Aslında, durum bayraklarıyla temsil edilen anormal durumlar varsayılan olarak yok sayılır!" Watt, durum bayrakları testinin aksine, istisnaların zıt varsayılan davranışa sahip olduğunu ve programcı istisna ile bir şekilde açıkça ilgilenmediği sürece, muhtemelen onu yok saymak için açık kod ekleyerek programın sonlandırılmasına neden olduğunu not eder. Bu argümanlara dayanarak Watt, atlama sıralayıcılarının veya kaçış sıralayıcılarının, yukarıda tartışılan anlambilim ile özel bir istisna sıralayıcı kadar uygun olmadığı sonucuna varır.

Object Pascal, D, Java, C# ve Python'da yapıya bir finallyyan tümce eklenebilir try. Cümlenin tryiçindeki kodu kontrol ne kadar bırakırsa finallybıraksın yürütülmesi garanti edilir. Bu, işleme bittiğinde pahalı bir kaynaktan (açık bir dosya veya veritabanı bağlantısı gibi) vazgeçmesi gereken kod yazarken kullanışlıdır:

FileStream stm = null;                    // C# example
try
{
    stm = new FileStream("logfile.txt", FileMode.Create);
    return ProcessStuff(stm);             // may throw an exception
} 
finally
{
    if (stm != null)
        stm.Close();
}

Bu model oldukça yaygın olduğundan, C#'ın özel bir sözdizimi vardır:

using (var stm = new FileStream("logfile.txt", FileMode.Create))
{
    return ProcessStuff(stm); // may throw an exception
}

using-Bloğundan ayrıldıktan sonra , derleyici stmnesnenin serbest bırakılmasını garanti eder, dosyayı başlatmanın ve serbest bırakmanın yan etkilerinden soyutlarken değişkeni dosya akışına etkin bir şekilde bağlar . Python'un withifadesi ve Ruby'nin blok argümanı File.openbenzer etki için kullanılır.

Yukarıda bahsedilen tüm diller, standart istisnaları ve bunların atıldığı koşulları tanımlar. Kullanıcılar kendi istisnalarını atabilir; aslında C++, kullanıcıların gibi temel türler de dahil olmak üzere hemen hemen her türü fırlatıp yakalamasına izin intverirken, Java gibi diğer diller bu kadar serbest değildir.

Devamı

zaman uyumsuz

C# 5.0, "doğrudan stilde" asenkron G/Ç'yi desteklemek için async anahtar sözcüğünü tanıttı .

jeneratörler

Jeneratörler da semicoroutines olarak bilinen, tipik olarak bir kullanarak, kontrol geçici bir tüketici yöntemle elde izin yieldanahtar ( verim açıklama ). async anahtar sözcüğü gibi, bu da "doğrudan stilde" programlamayı destekler.

eşyordamlar

Eşyordamlar , birbirlerine kontrol sağlayabilen işlevlerdir - parçacığı olmadan işbirlikçi çoklu görev biçimi .

Programlama dili ya devamlar ya da oluşturucular sağlıyorsa eşyordamlar bir kitaplık olarak uygulanabilir - bu nedenle eşyordamlar ve oluşturucular arasındaki ayrım pratikte teknik bir ayrıntıdır.

Yerel olmayan kontrol akışı çapraz referansı

Programlama dili koşullar istisnalar jeneratörler / eşyordamlar zaman uyumsuz
Ada Numara Evet ? ?
C Numara Numara Numara Numara
C++ Numara Evet evet, BOOST kullanarak ?
C# Numara Evet Evet Evet
COBOL Evet Evet Numara Numara
Ortak Lisp Evet Numara ? ?
NS Numara Evet Evet ?
Eyfel Numara Evet ? ?
Erlang Numara Evet Evet ?
F# Numara Evet Evet Evet
Gitmek Numara Evet Evet ?
Haskell Numara Evet Evet Numara
Java Numara Evet Numara Numara
JavaScript ? Evet Evet Evet
Amaç-C Numara Evet Numara ?
PHP Numara Evet Evet ?
PL/I Evet Numara Numara Numara
piton Numara Evet Evet Evet
REBOL Evet Evet Numara ?
yakut Numara Evet Evet ?
Pas Numara Evet deneysel Evet
Skala Numara Evet deneysel uzatma yoluyla deneysel uzatma yoluyla
Tcl izler aracılığıyla Evet Evet olay döngüsü aracılığıyla
Visual Basic .NET Evet Evet Numara ?
Güç kalkanı Numara Evet Numara ?

Önerilen kontrol yapıları

1973'teki sahte bir Datamation makalesinde, R. Lawrence Clark GOTO ifadesinin COMEFROM ifadesi ile değiştirilebileceğini öne sürdü ve bazı eğlenceli örnekler verdi. COMEFROM, INTERCAL adlı bir ezoterik programlama dilinde uygulandı .

Donald Knuth'un 1974 tarihli "Go to Statements ile Yapılandırılmış Programlama" makalesi, yukarıda listelenen kontrol yapılarının kapsamadığı iki durumu tanımlar ve bu durumları idare edebilecek kontrol yapılarına örnekler verir. Faydalarına rağmen, bu yapılar henüz ana akım programlama dillerine girmemiştir.

Ortada test bulunan döngü

Dahl tarafından 1972'de aşağıdakiler önerildi :

   loop                           loop
       xxx1                           read(char);
   while test;                    while not atEndOfFile;
       xxx2                           write(char);
   repeat;                        repeat;

Eğer xxx1 atlanırsa, biz üstünde testi (geleneksel bir döngü elde ederken döngü). Eğer XXX2 atlanırsa, bir eşdeğer altındaki testi ile bir döngü elde ederken do döngüsü birçok dilde. Eğer süre atlanırsa, biz sonsuz döngü olsun. Buradaki yapı , ortada while kontrolü olan bir do döngüsü olarak düşünülebilir . Bu nedenle bu tek yapı, çoğu programlama dilinde birkaç yapının yerini alabilir.

Bu yapıya sahip olmayan diller, genellikle eşdeğer bir sonsuz döngülü kesintili deyim kullanarak öykünür:

while (true) {
    xxx1
    if (not test)
        break
    xxx2
}

Olası bir değişken, test sırasında birden fazlasına izin vermektir ; döngü içinde, ancak çıkış zamanı (sonraki bölüme bakın) kullanımı bu durumu daha iyi kapsıyor gibi görünüyor.

Gelen Ada , yukarıdaki döngü yapı ( döngü - iken - tekrar ) (standart sonsuz döngü kullanılarak temsil edilebilir döngü - uç halka bir sahiptir) çıkış maddesi orta ile (karıştırılmamalıdır exitwhen aşağıdaki bölümde deyimi ).

with Ada.Text_IO;
with Ada.Integer_Text_IO;

procedure Print_Squares is 
    X : Integer;
begin
    Read_Data : loop
        Ada.Integer_Text_IO.Get(X);
    exit Read_Data when X = 0;
        Ada.Text IO.Put (X * X);
        Ada.Text IO.New_Line;
    end loop Read_Data;
end Print_Squares;

Bir döngüyü adlandırmak ( bu örnekteki Read_Data gibi ) isteğe bağlıdır, ancak iç içe geçmiş birkaç döngünün dış döngüsünün bırakılmasına izin verir.

Yuvalanmış döngülerden çoklu erken çıkış/çıkış

Bu, 1974'te Zahn tarafından önerildi . Burada değiştirilmiş bir versiyon sunulmaktadır.

   exitwhen EventA or EventB or EventC;
       xxx
   exits
       EventA: actionA
       EventB: actionB
       EventC: actionC
   endexit;

xxx içinde meydana gelebilecek olayları belirtmek için exitwhile kullanıldığında , olayın adı bir ifade olarak kullanılarak bunların meydana geldiği belirtilir. Bir olay meydana geldiğinde, ilgili eylem gerçekleştirilir ve ardından kontrol, endexit'ten hemen sonra geçer . Bu yapı, bazı durumların geçerli olduğunu belirlemek ile bu durum için yapılacak eylem arasında çok net bir ayrım sağlar.

exitWhen , kavramsal olarak istisna işlemeye benzer ve birçok dilde istisnalar veya benzer yapılar bu amaçla kullanılır.

Aşağıdaki basit örnek, belirli bir öğe için iki boyutlu bir tablo aramayı içerir.

   exitwhen found or missing;
       for I := 1 to N do
           for J := 1 to M do
               if table[I,J] = target then found;
       missing;
   exits
       found:   print ("item is in table");
       missing: print ("item is not in table");
   endexit;

Güvenlik

Bir yazılım parçasına saldırmanın bir yolu, bir programın yürütme akışını yeniden yönlendirmektir. Bu saldırılara karşı savunmak için yığın kanaryaları , arabellek taşması koruması , gölge yığınları ve vtable işaretçi doğrulaması dahil olmak üzere çeşitli denetim akışı bütünlüğü teknikleri kullanılır.

Ayrıca bakınız

Referanslar

daha fazla okuma

  • Hoare, ARAÇ "Bölüm: Algoritma 63", "Hızlı Sıralama: Algoritma 64" ve "Bul: Algoritma 65." İletişim ACM 4, 321-322, 1961.

Dış bağlantılar