Kontrol akışı - Control flow
Döngü yapıları |
---|
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
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 break
ve benzeri talimatların bile return
Bö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
- ALGOL 60 ve Pascal:
- 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:
END
her ş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
- Ada: son anahtar kelime
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 gerektirirENDIF
, 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
ELSE
veIF
birleştirilecekELSEIF
bir dizi olan ihtiyacı kaçınarak,ENDIF
Bileş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
if
ifade 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
if
ile tamamlar .when
unless
-
Smalltalk , herhangi bir temel dil yapısından ziyade koşul şartlarını uygulamak için kullanır
ifTrue
veifFalse
mesajlar.
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 decode
ifadesi.
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ı for
deyimi ve Common Lisp 'ın do
bö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, redo
geçerli yinelemeyi baştan başlatan bir ifade vardır.
Döngüyü yeniden başlat
Ruby, retry
ilk 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 break
ifadeyle) 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")
else
Yukarıdaki örnekte maddesi ile bağlantılıdır for
iç açıklamaya olup if
deyimi. Hem Python en for
ve while
dö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 |
-
a
while (true)
, bu amaç için sonsuz bir döngü olarak sayılmaz, çünkü özel bir dil yapısı değildir. -
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)
- a b c APL, C, C++ ve C#'da etiketler ve gotolar kullanılarak derin aralar gerçekleştirilebilir.
- Bir nesnelerin üzerine Yineleme edildieklendiPHP 5'de.
-
a b c Artan bir liste veya oluşturucu üzerinde yineleme yapılarak bir sayma döngüsü simüle edilebilir, örneğin Python's
range()
. - a b c d e Özel durum işleme kullanılarak derin kesintiler gerçekleştirilebilir.
-
a Özel bir yapı yoktur, çünkü
while
işlev bunun için kullanılabilir. - a Özel bir yapı yoktur, ancak kullanıcılar genel döngü işlevlerini tanımlayabilir.
-
Bir C ++ 11standart kişiyeiçin aralık tabanlı. OlarakSTL, bir olduğu
std::for_each
şablonSTL yineleme işlevkaplarve bir çağrıtekli fonksiyonuher bir eleman için. İşlev, bu kaplar üzerindemakroolarak da oluşturulabilir. - 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ış.
-
a Eiffel, ayrılmış bir Word'ü destekler
retry
, ancakdöngü kontrolünde değil,istisna işlemedekullanılır. - Bir gerektirirJava Modelleme Dili(JML) davranışsal arayüz şartname dilini.
- a Döngü değişkenlerinin tamsayı olmasını gerektirir; transfinite varyantları desteklenmez. [1]
- a D, sonsuz koleksiyonları ve bu koleksiyonlar üzerinde yineleme yeteneğini destekler. Bu, herhangi bir özel yapı gerektirmez.
-
a Derin aralar
GO TO
ve prosedürlerikullanılarak elde edilebilir. - 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 GOTO
veya (ç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
}
catch
Yukarıda herhangi bir sayıda ve çeşitte tümce kullanılabilir. Belirli catch
bir eşleşme yoksa throw
, kontrol bir eşleşme catch
bulunana 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, catch
Java 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, exception
bir 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 error
AppleScript'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 finally
yan tümce eklenebilir try
. Cümlenin try
içindeki kodu kontrol ne kadar bırakırsa finally
bı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 stm
nesnenin 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 with
ifadesi ve Ruby'nin blok argümanı File.open
benzer 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 int
verirken, 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 yield
anahtar ( 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 - iş 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
- Şube (bilgisayar bilimi)
- Kontrol akışı analizi
- Kontrol akış şeması
- Kontrol akış grafiği
- Kontrol tablosu
- eşyordam
- Cyclomatic karmaşıklık
- Drakon-grafiği
- Akış çizelgesi
- GOTO
- Jeroo , kontrol yapılarının öğrenilmesine yardımcı olur
- Ana döngü
- özyineleme
- Zamanlama (hesaplama)
- spagetti kodu
- Yapılandırılmış programlama
- alt program
- Anahtar deyimi , kontrol akışını koşullu olarak değiştirir
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
- İlgili Medya Kontrol akış Wikimedia Commons
- Zararlı Kabul Edilen Açıklamaya Git
- GOTO'suz Programlamanın Dilbilimsel Katkısı
- "Git İfadeleriyle Yapılandırılmış Programlama" (PDF) . Orijinalinden (PDF) 2009-08-24 tarihinde arşivlendi . (2,88 MB)
- "IBM 704 Kılavuzu" (PDF) . (31.4 MB)