c programlama etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
c programlama etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

Stack(Yığın)

Stack(yığın), aynı türden verilerin bulunduğu lineer(doğrusal) bir veri yapısıdır. Stack, Son Giren İlk Çıkar (Last In First Out - LIFO) şekilinde çalışır yani stack'a eklenen son ögenin ilk kaldırıldığı anlamına gelir. 



Last In First Out (LIFO):

Bu strateji, son eklenen ögenin ilk çıkarılacağını belirtir. Gerçek hayattan bir örnek olarak üst üste yerleştirilmiş tabak yığını düşünülebilir. En son koyduğumuz tabak en üsttedir ve en üstteki tabağı çıkardığımızda, en son konan tabak ilk çıkar diyebiliriz.


Eğer en alttaki tabağı istiorsak, önce üstteki tüm tabakları çıkartmamız gerekir. Stack(yığın) veri yapısı tam olark böyle çalışır.

Stack LIFO Prensibi

Programlama terimlerinde, bir öğeyi stack'ın üstüne koymaya push, bir öğeyi kaldırmaya ise pop denir.


Görselde, 3. öğe en sonda kalmasına rağmen, ilk olarak kaldırılmıştır.

Stack'ın Temel İşlemleri

Bir stack üzerinde farklı eylemler gerçekleştirmemizi sağlayan bazı temel işlemler vardır.

push: Bir stack'ın üstüne bir eğe ekler
pop: Bir stack'ın tepesinden bir öğeyi kaldırma
IsEmpty: Stack'ın boş olup olmadığını kontrol eder
IsFull: Stack'ın dolu olup olmadığını kontrol eder
peek: Üst öğenin değerini kaldırmadan alma

Stack Türleri

Register Stack(Kayıt Yığını)

Bu tür bir stack aynı zamanda bellek biriminde bulunan bir bellek öğesidir ve yalnızca az miktarda veriyi işleyebilir. Register stack'nın boyutu belleğe kıyasla çok küçük olduğundan, register stack'nın yüksekliği her zaman sınırlıdır. 

Memory Stack(Bellek Yığını)

Bu tür bir stack, büyük miktarda bellek verisini işleyebilir. Memort stack'nın yüksekliği, büyük miktarda bellek verisi kapşadığından esnektir.

Stack Uygulaması

1. Dizi Kullanarak

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

// stack'ı temsil edecek bir struct
struct Stack{
int top;
unsigned capacity;
int* array;
};

// verilen kapasitede bir stack oluşturma. Stack boyutu 0 olarak başlatılır
struct Stack* createStack(unsigned capacity){
struct Stack* stack = (struct Stack*) malloc(sizeof(struct Stack));
stack->capacity = capacity;
stack->top = -1;
stack->array = (int*) malloc(stack->capacity*sizeof(int));
return stack;
}

// top son indekse eşit olduğında stack dolu
int isFull(struct Stack* stack){
return stack->top == stack->capacity - 1;
}

// top -1'e eşit olduğunda stack boştur
int isEmpty(struct Stack* stack){
return stack->top == -1;
}

// Stack'a bir öğe ekleme, top'u 1 artırır
void push(struct Stack* stack,int item){
if(isFull(stack)) return;
stack->array[++stack->top] = item;
printf("%d stack'a eklendi\n",item);
}

// Stack'tan bir öğe kaldırma, top 1 azaltılır.
int pop(struct Stack* stack){
if (isEmpty(stack)) return INT_MIN;
return stack->array[stack->top--];
}

// üst kısmı çıkarmadan stack'ı döndürme
int peek(struct Stack* stack){
if(isEmpty(stack)) return INT_MIN;
return stack->array[stack->top];
}

int main(){
struct Stack* stack = createStack(5);
push(stack,10);
push(stack,40);
push(stack,20);
push(stack,50);

printf("%d stack'tan kaldirildi\n",pop(stack));
return 0;
}
Çıktı:


Dizi Kullanmanın Avantajları:

  • Uygulaması kolay.

Dizi Kullanmanın Dezavantajları:

  • Dinamik değildir, yani çalışma zamanında ihtiyaca göre büyüyüp küçülmez.
  • Stack'ın toplam boyutu önceden tanımlanır.

2. Linked List Kullanarak

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

// stack'ı temsil edecek bir struct
struct StackNode{
int data;
struct StackNode* next;
};

struct StackNode* newNode(int data){
struct StackNode* stackNode = (struct StackNode*) malloc(sizeof(struct StackNode));
stackNode->data = data;
stackNode->next = NULL;
return stackNode;
}

int isEmpty(struct StackNode* root){
return !root;
}

void push(struct StackNode** root, int data){
struct StackNode* stackNode = newNode(data);
stackNode->next = *root;
*root = stackNode;
printf("%d stack'a eklendi\n",data);
}

int pop(struct StackNode** root){
if(isEmpty(*root)) return INT_MIN;
struct StackNode* temp = *root;
*root = (*root)->next;
int popped = temp->data;
free(temp);

return popped;
}

int peek(struct StackNode* root){
if(isEmpty(root)) return INT_MIN;
return root->data;
}

int main(){
struct StackNode* root = NULL;

push(&root,10);
push(&root,40);
push(&root,20);
push(&root,50);

printf("%d stack'tan kaldirildi\n",pop(&root));
printf("En ustteki eleman %d\n", peek(root));

return 0;
}
Çıktı:



Linked List Kullanmanın Avantajları:

  • Dinamiktir, yani çalışma zamanındaki ihtiyaçlara göre büyüyebilir ve küçülebilir.


Linked List Kullanmanın Dezavantajları:

  • Pointer'ların dahil olması nedeniyle ekstra bellek gerektirir.
  • Stack içinde rastgele erişim mümkün değildir.


Kaynaklar:
https://www.geeksforgeeks.org/introduction-to-stack-data-structure-and-algorithm-tutorials/
https://www.digitalocean.com/community/tutorials/stack-in-c
https://www.programiz.com/dsa/stack
https://www.tutorialspoint.com/data_structures_algorithms/stack_program_in_c.htm
 Bu örnekte C programlama dilinde, kullanıcıdan alınan sayının tek sayımı yoksa çift sayı mı olduğunu bulan programı yazdık:




#include <stdio.h>

void tekcift(int x){
    if(x%2==0){
        printf("Cift");
    }
    else
        printf("Tek");
}

int main() {
    int sayi;
    printf("Sayi giriniz: ");
    scanf("%d",&sayi);

    tekcift(sayi);

    return 0;
}

---------

#include <stdio.h>

int main() {
    int sayi;
    printf("Sayi giriniz: ");
    scanf("%d",&sayi);

    if(sayi%2==0){
        printf("Cift");
    }
    else
        printf("Tek");
    return 0;
}


 

Bu yazımızda, C programlamanın en önemli elemanlarında bir olan yapılar (struct) konusuna değineceğiz. 



Yapı (Struct) Nedir ?

Yapılar -bazen topluluklar diye anılır- tek bir isim altında onunla ilgili değişkenlerin olduğu koleksiyonlardır. Yapılar, sadece aynı veri türünde öğeleri içeren dizilerin aksine farklı veri türünde değişkenler içerebilir. Yapılar, diziler gibi belleğe sürekli biçimde yerleşen nesnelerdir. Dizilerde olduğu gibi başlangıç adresleri içerilerek fonksiyonlara kolaylıkla aktarılabilirler. 

Yapıların Bildirimi

Yapılar türetilmiş veri türleridir. Yapılar diğer türdeki nesneleri kullanarak inşa edilirler. Yapı bildiriminin genel biçimi:

struct [yapı_ismi] {
    <tür> <yapı_elemanı>;
    <tür> <yapı_elemanı>;
    <tür> <yapı_elemanı>;
    ...
};


Yukarıdaki genel biçimde:

struct :             Bildirim için gerekli anahtar sözcüktür.
yapı_ismi :      Yapıyı anlatan isimlendirme kurallarına uygun herhangi bir isim olabilir. / yapı                                         etiketidir.
yapı_elemanı : Yapıyı oluşturan değişken isimleridir; isimlendirme kurallarına uygun herhangi bir isim                           olabilir.

!! Bildirimin küme parantezinden sonra noktalı virgül ile sonlandırıldığına dikkat ediniz.!!

Örneğin, düzlemde bir nokta x ve y bileşenlerinden oluştuğuna göre, bu aynı elemanlar yerine bir yapı biçiminde de bildirebiliriz:

struct NOKTA {
    int x;
    int y;
};
...


Benzer biçimde, tarih bilgileri de hiçbiri int türünden üç ayrı değişken yerine, yapı kullanılarak mantıksal bir bütünlük içinde ifade edilebilir:

struct DATE {
    int day;
    int month;
    int year;
};

Yukarıdaki bildirimde DATE yapının ismi; day, month ve year ise int türünden yapı elemanlarıdır.

Yapı bildirimiyle derleyici yalnızca yapılar hakkında bilgi edinir; bellekte onlar için herhangi bir yer ayrılmaz. Yapı bildirimlerini bir çeşit şablon tanımlaması gibi düşünebilirsiniz. Tıpkı fonksiyon prototiplerinde olduğu gibi yapı bildirimleri de yalnızca derleyiciyi bilgilendirmek amacıyla kullanılmaktadır.

Yapı Değişkenlerinin Tanımlanması

Bellekte yer ayırma işlemi yapı değişkenlerinin tanımlanmasıyla oluşur. Yapı değişkenlerinin tanımlanması aşağıdaki iki biçimde yapılır:

struct <yapı_ismi> <yapı_değişkeninin_ismi>;

veya

struct [yapı_ismi] {
    ...
} [değişken_listesi];

Yağı değişkenlerinin yapı bildiriminde sonra tanımlanması zorunludur. 

Örneğin:

struct NOKTA {
    int x;
    int y;
};
...

struct NOKTA a;

veya

struct NOKTA {
    int x;
    int y;
}a;
...


benzer biçimde DATE yapısı türünden bir d değişkeni:

struct DATE {
    int day;
    int month;
    int year;
};
...
struct DATE d;

veya

struct DATE {
    int day;
    int month;
    int year;
}d;
...

Yapı Değişkenlerine İlk Değerin Verilmesi

Yapı değişkenlerine dizilerde olduğu gibi küme parantezleri içerisinde ilk değer verilir. 

Örneğin:

struct date {
    int day;
    int month;
    int year;
};
...
struct date d = {1,4,1995};


Derleyici ilk değerleri yapı elemanlarına sırasıyla yerleştirir. Yani yukarıdaki örnekte yapı elemanlarının alacağı değerler şöyledir:

d.day => 1
d.month => 4
d.year => 1995


Yapı Üyelerine Erişim

Yapı üyelerine erişmek için iki operatör kullanılır: Yapı üyesi operatörü (.) (aynı
zamanda nokta operatörü olarak da bilinir) ve yapı işaretçisi operatörü ( ->) (aynı zamanda ok
operatörü olarak da adlandırılır). Yapı üyesi operatörü yapının değişken ismiyle yapı üyesine erişir. 

Örneğin:

printf("%d",d.day);

Yapı işaretçisi operatörü -aralarında herhangi bir boşluk olmayan eksi (-) işareti ve büyüktür (>) işaretinden oluşan - yapıda bir işaretçi üzerinden bir yapı üyesine erişir.

struct data *x;
printf("%d", x-> year);

Örnek:

#include <stdio.h>

struct card {
char *face;
char *suit;
};

int main( )
{
struct card aCard;
struct card *cardPtr;

aCard.face = "Ace";
aCard.suit = "Spades";

cardPtr = &aCard;

printf( "%s%s%s\n%s%s%s\n%s%s%s\n", aCard.face," of ", aCard.suit,
cardPtr->face," of ",cardPtr->suit,
(*cardPtr).face," of ",(*cardPtr).suit);
return 0;
}
Ekran Çıktısı:

Ace of Spades
Ace of Spades
Ace of Spades

İç İçe Yapılar

Bir yapının içende başka bir yapı nesnesi tanımlanabilir. İç içe yapıların tanımlanması C'de iki biçimde yapılmaktadır:

1) İçerideki yapının bildirimini daha yukarıda yaparak. Bu durumda derleyici doğal akış yönünde ilerlerken bildirilen yapıyı tanıyabilir.

struct date{
    int day, month, year;
};
...
struct person {
    char name[30];
    struct date bday;
};

2) İçerideli yapının dışındaki yapının içerisinde bildirilmesiyle. Bu durumda değişken tanımlanması da yapılmalıdır:

struct person {
    char name[30];
    struct date{
        int day, month, year;
    }bday;
};

Yapıların Fonksiyonlara Parametre Olarak Geçirilmesi

C'de parametrelerin kopyalanarak fonksiyonlara geçirildiğini hatırlayalım. Yapı değişkenleri de fonksiyonlara kopyalanarak parametre olarak geçirilebilirler. 

Örnek:

#include <stdio.h>

struct date{
int day,month,year;
};

void dispDate(struct date x){
printf("Year: %d\n",x.year);
printf("Month: %d\n",x.month);
printf("Dat: %d\n",x.day);
}

int main() {
// Write C code here
struct date n;

n.day = 4;
n.month = 5;
n.year = 1995;
dispDate(n);

}
Ekran Çıktısı:

Year: 1995
Month: 5
Dat: 4




C programlama ile ilgili olan diğer konulara aşağıdaki linkten ulaşabilirsiniz:




Bu yazıda, C programlama dilinin en güçlü özelliklerinden biri olan göstericilere değineceğiz. Göstericiler, C'nin yönetilmesi en zor yeteneklerinden biridir. Göstericiler, programların referansa göre çağırma yapmasını ve bağlı listeler, sıralar, yığınlar ve ağaçlar gibi büyüyüp küçülebilen dinamik veri yapılarının oluşturulmasıyla, yönetilmesini sağlar. Bu yazıda, temel gösterici kavramlarına değineceğiz. Hadi başlayalım :)



Gösterici Değişkenlerini Bildirmek 

Göstericiler, adres bilgilerini saklamak ve adreslerle ilgili işlemler yapmak için kullanılan nesnelerdir. Normalde bir değişken doğrudan kesin bir değer içerir. Göstericiler ise kesin bir değer tutan değişkenlerin adresini içerir. Bu durumda, bir değişken ismi bir değeri doğrudan belirtirken, göstericiler değerleri dolaylı yoldan belirtir.

Gösterici bildirimlerinin genel biçimi şöyledir:

<tür> * <gösterici_ismi>;

<tür> göstericinin (içerisindeki adresin) türüdür. char, floan, int ... gibi herhangi bir türdür.
Burada * göstericiyi ya da adresi temsil etmektedir.

int *sayiciPtr, sayici;
Biçiminde bir bildirim, sayiciPtr değişkenini int * (bir tamsayıyı gösteren gösterici) tipinde bildirir. Bu bildirim "sayiciPtr bir int göstericisidir" ya da "sayiciPtr, tamsayı tipinde bir nesneyi gösterir" biçiminde okunur. Ayrıca, sayici değişkeni de bir tamsayı olarak bildirilmiştir. Bildirim içindeki * yalnızca sayiciPtr'ye uygulanır

Örnek gösterici bildirimleri:

float *f;
char *s;
int *dizi;
...

Gösterici Operatörleri

& ya da adres operatörü, operandının adresini döndüren bir tekli operatördür. Örneğin;

int y = 5;
int *yPtr;

bildirimlerini ele aldığımızda

yPtr = &y;

ifadesi, y değişkeninin adresini yPtr gösterici değişkenine atar. Buna, yPtr değişkeni y'yi göstermektedir denir.

Örnek:

#include <stdio.h> // Ekran girdi ve çıktılarını sağlamak için fonksiyon kütüphanemizi çağırıyoruz


    int main(){//ana fonksiyonumuzu başlatıyoruz.
        char degisken='a';
        char *gosterici=&degisken;

        printf("Ilk gosterici degeri : %X\n",gosterici);
        gosterici++;

        printf("Bir sonraki gosterici degeri : %X\n",gosterici);
        gosterici+=5;

        printf("Alti sonraki gosterici degeri : %X\n",gosterici);
        
        /*
        Ekran Çıktısı :
        Ilk gosterici degeri : 62FE17
        Bir sonraki gosterici degeri : 62FE18
        Alti sonraki gosterici degeri : 62FE1D
        */

        return 0; // programın sorusuz çalıştığını işletim sistemine bildiriyoruz.
    }

Fonksiyonları Referansa Göre Çağırmak

Bir fonksiyona argüman geçirmenin iki yolu vardır: değere göre ve referansa göre çağırma. Bir çok fonksiyon, çağırıcıdaki bir ya da birden çok değişkeni değiştirebilme yeteneğine veya değere göre çağırmanın yükünden (bu nesnenin bir kopyasının oluşturulmasını gerektirir) kurtulmak için büyük bir veri nesnesini gösteren göstericiyi geçirmeye ihtiyaç duyarlar. Bu amaçlar için C, referansa göre çağırma yeteneklerini sunar.

Örnek:

#include <stdio.h>
int degereGoreKup ( int ); /* prototip */

int main( ){

    int sayi = 5;

    printf( "Sayının esas değeri %d", sayi);
    sayi = degereGoreKup ( sayi );
    printf( "\nSayının yeni değeri %d\n", sayi);

    return 0;
}
int degereGoreKup( int n )
{
    return n * n * n; /* yerel değişken n’in küpünü al*/
}

Çıktı:

Sayının esas değeri 5
Sayının yeni değeri 125


Göstericilerin Artırılması ve Eksiltilmesi

Göstericiler *,/,%,... gibi aritmetik operatörlerle ve bit operatörleriyle kullanılmazlar. Fakat, bir gösterici tamsayılı artırılabilir ya da eksiltilebilir. Örneğin p bir gösterici olmak üzere aşağıdaki ifadelerin hepsi geçerlidir.

++p;
p = p - 2;
p += 4;
p -= 10;
--p;
...

Göstericiler yalnızca tamsayılı sabitleri ile değil tamsayı değişkenleriyle de artırılıp azaltılabilir.

char *p;
int a;
...
p = p + a;
p = p - 2;
p += a;
p = p + a + 10;

Göstericiler ve Diziler Arasındaki İlişki   

Diziler ve göstericiler, C‘de özel bir biçimde ilişkilidirler ve birbirleri yerine hemen hemen
her yerde kullanılabilirler. Bir dizi ismi, sabit bir gösterici olarak düşünülebilir. Göstericiler,
dizilerin belirteçlerle gösterimi de dahil olmak üzere her işlemde kullanılabilir.

b[5] tamsayı dizisinin ve bPtr tamsayı göstericisinin bildirildiğini varsayalım. Bir belirteç
kullanmayan dizi isminin, dizinin ilk elemanını gösteren bir gösterici olduğunu bildiğimize
göre, bPtr ‘yi b dizisinin ilk elemanına aşağıdaki ifade ile eşitleyebiliriz.

bPtr =b;

Bu ifade, dizinin ilk elemanının adresini aşağıdaki biçimde almakla eşdeğerdir.

bPtr = &b[0];

b[3] dizi elemanı, alternatif bir biçimde;

*(bPtr+3)

gösterici deyimi ile belirtilebilir.

Yukarıdaki deyimde 3, göstericinin offsetidir. Gösterici, dizinin başlangıç adresini
gösterirken, offset dizinin hangi elemanının kullanılacağını belirtir ve offset değeri dizi
belirteciyle eştir. Az önceki gösterime gösterici/offset gösterimi denir. Parantezler gereklidir
çünkü * operatörünün önceliği + operatörünün önceliğinden yüksektir. Parantezler olmadan
yukarıdaki ifade, *bPtr‘ye 3 eklerdi. (yani, bPtr‘nin dizinin başlangıcını gösterdiği
düşünülürse, b[0] 'a 3 eklenirdi.) Dizi elemanlarının, gösterici deyimleri ile belirtilebilmesi
gibi

&b[3]
adresi de

bPtr+3

biçimindeki gösterici deyimi ile belirtilebilir.
Dizinin kendisine de bir gösterici olarak davranılabilir ve göstericiği aritmetiğinde
kullanılabilir. Örneğin,

*(b+3)

deyimi de b[3] dizi elemanını belirtir. Genelde belirteç kullanan tüm dizi deyimleri, gösterici
ve offset ile yazılabilir. Bu durumda, gösterici/offset gösterimi, dizinin ismini gösterici olarak
kullanır. Az önceki ifadenin, dizinin ismini değiştirmediğine dikkat ediniz. b, hala dizinin ilk
elemanını göstermektedir.
Göstericiler de diziler gibi belirteçlerle kullanılabilir. Örneğin,

bPtr[1]

deyimi, b[1] dizi elemanını belirtir. Buna, gösterici/belirteç gösterimi denir.

Dizi isminin, her zaman dizinin başlangıcını gösteren sabit bir gösterici olduğunu hatırlayınız.
Bu sebepten,

b+=3

deyimi geçersizdir çünkü dizi isminin değerini, gösterici aritmetiği kullanarak değiştirmeye
çalışmaktadır.

Örnek:

#include <stdio.h>

int main( )
{
int b[ ] = { 10, 20, 30, 40 };
int *bPtr = b; /* bPtr b dizisini göstersin */
int i, offset;
printf( "b dizisi asağıdaki metodla yazılmıstır:\n"
"Dizi belirteçleri yöntemi\n" );
for ( i = 0; i < 4; i++ )
printf( "b[ %d ] = %d\n", i, b[ i ] );

printf( "\nGösterici/offset yöntemi,\n"
"gösterici dizinin ismidir\n" );

for ( offset = 0; offset < 4; offset++ )
printf( "*( b + %d ) = %d\n", offset, *( b + offset ) );

printf( "\nGösterici belirteç yöntemi\n" );

for ( i = 0; i < 4; i++ )
printf( " bPtr[ %d ] = %d\n", i, bPtr[ i ] );
printf( "\nGösterici/offset yöntemi\n" );

for ( offset = 0; offset < 4; offset++ )
printf( "*( bPtr + %d ) = %d\n", offset, *( bPtr + offset ) );
return 0;
}

Çıktı:

b dizisi aĢağıdaki metodla yazılmıĢtır:
Dizi belirteçleri yöntemi
b[0] = 10
b[1] = 20
b[2] = 30
b[3] = 40
Gösterici/offset yöntemi
gösterici dizinin ismidir
*(b + 0) = 10
*(b + 1) = 20
*(b + 2) = 30
*(b + 3) = 40
Gösterici belirteç yöntemi
bPtr[0] = 10
bPtr[0] = 20
bPtr[0] = 30
bPtr[0] = 40
Gösterici/offset yöntemi
*(bPtr + 0) = 10
*(bPtr + 1) = 20
*(bPtr + 1) = 30
*(bPtr + 1) = 40


C programlama ile ilgili olan diğer konulara aşağıdaki linkten ulaşabilirsiniz:

Kaynaklar:
A'dan Z'ye C Kılavuzu 
Deitel C/C++
  Bu yazımızda do...while döngülerine, break ve continue ifadeleri ile ilgili bilgi vereceğiz ve örneklerle bu ifadeleri pekiştireceğiz. Hadi başlayalım.

do...while Tekrarlama İfadesi

do...while tekrarlama ifadesi while ifadesine benzerdir. while ifadesinde, döngü devam koşulu, döngü gövdesi icra edilmeden önce döngü başında kontrol edilir. do...while ifadesi döngü devam koşulunu döngü gövdesi yapıldıktan sonra kontrol eder. Yani do...while döngülerinde kontrol sonda olduğu için döngü içindeki deyimler en az bir kere işlem görür. Genel biçimi aşağıda verilmiştir.

do
    deyim
while(koşul);
...

do döngünün başını gösteren bir anahtar sözcüktür. Döngünün iç bölgesi do anahtar sözcüğünden while anahtar sözcüğüne kadar olan bölgedir. Diğerlerinde olduğu gibi, tek bir deyim için bloklamaya gerek yoktur, fakat birden fazla deyim için bloklama yapılır. Örneğin:

do{
    deyim1
    deyim2
    ...
}while(koşul);
...



do...while döngüsünün gövdesi bir kez yürütülür.
 Test Expression doğruysa döngünün gövdesi yeniden yürütülür ve Test Expression bir kez daha değerlendirilir. Bu işlem Test Expression yanlış olana kadar devam eder. Test Expression yanlış ise döngü sona erer.





Aşağıdaki örneği inceleyelim:

do{
    printf("(E)vet ya da (H)ayır\n");
    ch = getch();
}while((ch = toupper(ch)) != 'E' && ch != 'H');

Bu örnekte kullanıcı E,e,h,H harflerinden birini girmeye zorlanmaktadır. Bu harflerden biri girilmediği sürece döngü devam edecektir. Bir örnek daha yapalım.

#include <stdio.h>
int main(void){
    unsigned int counter = 1;
    do{
        printf(" %u ",counter);
    }while(++counter <=10);
}

Ekran çıktısı:

1 2 3 4 5 6 7 8 9 10

break ve continue İfadeleri

break ve continue ifadeleri kontrol akışını değiştirmek için kullanılır.

break İfadesi

break anahtar sözcüğü döngüleri sonlandırarak program akışını döngünün dışındaki ilk deyime taşır. Örneğin:

for(;;){
    ...   
    ch = getchar();
    if(ch =='q')
        break;
}
...

Burada klavyeden girilen karakter 'q' olduğunda break anahtar sözcüğü ile döngü kırılmaktadır. for(;;) sonsuz bir döngü olduğundan çıkış da ancak break ile mümkün olabilir.

...
while(k<100){
    ...   
    if(sample()<0) break;
    ...
}
...

Bu örnekte ise sample() fonksiyonunun geri dönüş değeri sıfırdan küçük ise döngü kırılmaktadır. Aşağıdaki örnekte de 0'dan 100'e kadar olan tamsayıları ekrana yazdırılıyor.

k=0;
for(;;){
    if(k>=100) break;
    printf("%d\n",++k);
}


continue İfadesi

continue anahtar sözcüğü o anda içinde bulunan yinelemeyi keserek bir sonraki yinelemeye geçilmesine neden olur. Aşağıdaki örneği inceleyelim.

do{
    ch = getchar();
    if(isupper(ch))
        continue;
    ...
}while(ch!='q');

Bu örnekte girilen harf, büyük harf ise işlem yapma, büyük harf değilse işlemleri gerçekleştir. Girilen harf 'q' ise döngüden çıkar.


Örnekler

1) Girilen sayıların toplamını bulan ve 0 girildiğinde döngüden çıkan program

// Program to add numbers until the user enters zero

#include <stdio.h>
int main() {
  double number, sum = 0;

  // the body of the loop is executed at least once
  do {
    printf("Enter a number: ");
    scanf("%lf", &number);
    sum += number;
  }
  while(number != 0.0);

  printf("Sum = %.2lf",sum);

  return 0;
}

Ekran Çıktısı:

Enter a number: 1.5
Enter a number: 2.4
Enter a number: -3.4
Enter a number: 4.2
Enter a number: 0
Sum = 4.70


2)  

#include<stdio.h>  
#include<stdlib.h>  
void main ()  
{  
    char c;  
    int choice,dummy;    
    do{  
    printf("\n1. Print Hello\n2. Print Javatpoint\n3. Exit\n");  
    scanf("%d",&choice);  
    switch(choice)  
    {  
        case 1 :   
        printf("Hello\n");   
        break;  
        case 2:    
        printf("Javatpoint\n");  
        break;  
        case 3:  
        exit(0);   
        break;  
        default:   
        printf("please enter valid choice\n");      
    }  
    printf("do you want to enter more?\n");   
    scanf("%d",&dummy);  
    scanf("%c",&c);  
    }while(c=='y');  
}    


Ekran Çıktısı

1. Print Hello
2. Print Javatpoint
3. Exit
1
Hello
do you want to enter more?
y

1. Print Hello
2. Print Javatpoint
3. Exit
2
Javatpoint
do you want to enter more?
n

3) 1'den 10'a kadar sayıları yazan program

#include<stdio.h>  
int main(){    
    int i=1;      
    do{    
        printf("%d \n",i);    
        i++;    
    }while(i<=10);   
    return 0;  
   

Ekran Çıktısı

1
2
3
4
5
6
7
8
9
10


4)  Girilen sayının çarpım tablosundaki değerleri yazan program

#include<stdio.h>  
    int main(){    
    int i=1,number=0;    
    printf("Enter a number: ");    
    scanf("%d",&number);    
    do{    
        printf("%d \n",(number*i));    
        i++;    
    }while(i<=10);    
    return 0;  
}    

Ekran Çıktısı


Enter a number: 5
5
10
15
20
25
30
35
40
45
50

5) Max 10 sayı alan ve bunları toplayan program. Kullanıcı negatif sayı girdiğinde döngüden çıkan program.


// Program to calculate the sum of numbers (10 numbers max)
// If the user enters a negative number, the loop terminates

#include <stdio.h>

int main() {
   int i;
   double number, sum = 0.0;

   for (i = 1; i <= 10; ++i) {
      printf("Enter n%d: ", i);
      scanf("%lf", &number);

      // if the user enters a negative number, break the loop
      if (number < 0.0) {
         break;
      }

      sum += number; // sum = sum + number;
   }

   printf("Sum = %.2lf", sum);

   return 0;
}

Ekran Çıktısı

Enter n1: 2.4
Enter n2: 4.5
Enter n3: 3.4
Enter n4: -3
Sum = 10.30


6) Max 10 sayı alan ve bunları toplayan program. Kullanıcı negatif sayı girdiğinde toplamaya eklemeyen program.

// Program to calculate the sum of numbers (10 numbers max)
// If the user enters a negative number, it's not added to the result

#include <stdio.h>
int main() {
   int i;
   double number, sum = 0.0;

   for (i = 1; i <= 10; ++i) {
      printf("Enter a n%d: ", i);
      scanf("%lf", &number);

      if (number < 0.0) {
         continue;
      }

      sum += number; // sum = sum + number;
   }

   printf("Sum = %.2lf", sum);

   return 0;
}

Ekran Çıktısı

Enter n1: 1.1
Enter n2: 2.2
Enter n3: 5.5
Enter n4: 4.4
Enter n5: -3.4
Enter n6: -45.5
Enter n7: 34.5
Enter n8: -4.2
Enter n9: -1000
Enter n10: 12
Sum = 59.70





Bir sonraki derse ulaşmak için: C'de Fonksiyonlar #C4
Bir önceki derse ulaşmak için: C'de Program Kontrolü - switch-case #C3.2


Kaynaklar:

A'dan Z'ye C programlama
Deitel Deitel C ile programlama
https://www.programiz.com/c-programming/c-do-while-loops
javatpoint.com/do-while-loop-in-c
https://www.programiz.com/c-programming/c-break-continue-statement