sayfa başı

26 Şubat 2019 Salı

C Çalışma Soruları – 21 (göstericiler)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.


Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?

#include <stdio.h>
 
int main()
{
    int a[4] = { 2, 0, 3, 1};
    int i;
    
    ++2[a][a][a][a];
    
    for (i = 0; i < 4; ++i)
        printf("%d ", a[i]);
 
    return 0;
}

Yanıt:
++2[a][a][a][a]; satırı her ne kadar göze karışık ve zor görünsede aslında göstericilerde içeriğe ulaşma kurallarını göz önüne alınca oldukça basitleşiyor. Çözümü anlamak için aşağıdaki kod parçasına bakalım.
int a[4] = { 2, 0, 3, 1};
printf(" %d  %d %d \n\n", 1[a], *(a+1), a[1]);  //çıktısı 0 0 0
printf(" %d  %d %d \n\n", 2[a], *(a+2), a[2]);  //çıktısı 3 3 3

Gördüğünüz gibi 1[a] ile a[1] aynı sonuçları gösteriyor. Kısaca a dizisinin 1. Indeksli elemanına ulaşltık.
++2[a][a][a][a]; satırını yukarıdaki bilgiler ile soldan sağa doğru çözümleyelim. ++a[2][a][a][a]; şeklinde gösterebiliriz. a[2] değeri 3 olur ve ++3[a][a][a]; şekline dönüşür. ++a[3][a][a]; şeklinde tekrar dönüştürebiliriz ve a[3] değeri 1 olur. ++1[a][a]; bir sonraki dönüşümü ++0[a]; olur son adımda ++a[0]; ulaşmış oluruz ve bu da a nın 0. Indeksteki elemanının değerini bir arttırır. Sonuç olarak a dizisinin son hali { 3, 0, 3, 1} olur ve bu da programın çıktısıdır.

C Çalışma Soruları – 20 (göstericiler)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.

Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?

#include <stdio.h>
 
int main()
{
    int a[5] = { -1, 3, 2, -2, 0};
    int *p = a + 3;
    int i;
    
    a[p[*p]]++;
    a[p[*p]]++;

    for (i = 0; i < 5; ++i)
        printf("%d ", a[i]);
        
    return 0;
}

Yanıt:
Sorunun yanıtına geçmeden önce *p ile p[0] aynı sonuçlar ürettiğini bilmek gerekir. Yani bu iki yöntemle pointer içeriğine ulaşabiliriz. Aşağıdaki iki satır koşulur ise aynı çıktıyı ürettiğini göreceksiniz.
   printf(" %d \n", p[0]);
   printf(" %d \n", *p);
Yukarıdaki temel bilgiler ile p[2] nin ne anlama geldiğini görebiliriz. p taşıdığı adresten, taşıdığı tür adresi biçiminde 2 adres ilerle ve içeriğini al manasına gelir.(p nin adresi değişmez.) Sorunun çözümüne geçelim.
a[p[*p]]++; ilk satırda *p, -2 değerini üretir. a[p[-2]]++; şekline döner. p[-2] demek p nin taşıdığı adresten 2 adres geri gel ve içeriğini al demektir. p nin taşıdığı adres a+3 olduğu için 2 gerisi a+1 olur ve içeriği de 3 olur. Bu durumda a[3]++;  şekline döner. Bu işlem sonucunda a nın 3. endeksli elemanı olan -2 ulaşıp değerini bir arttırmış oluruz ve -1 olur. Dizinin yeni hali aşağıdaki gibi olur.
{ -1, 3, 2, -1, 0}
Kodun geri kalanındaki a[p[*p]]++; kısmını da yukarıdaki açıklamalar doğrultusunda işlersek dizinin son hali { -1, 3, 3, -1, 0} olur ve çıktı olarak bu dizi elemanlarını alırız.

C Çalışma Soruları – 18 (işleçler)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.

Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?
#include <stdio.h>
 
int main()
{
    int a = 11;

    if (10 < --a < 20)
       printf("%d", --a);
    else
        printf("%d", ++a);

    return 0;
}

Yanıt:
< operatöründe işlem soldan sağa doğrudur. Bu bilgi ile if koşulunu daha anlaşılır hale getirebiliriz.
if ((10 < --a) < 20) dönüşümünden sonra çözüme geçebiliriz.  (10 < --a) sonucu 0 olur.(a’nın değeri 10 oldu.) Bu adımdan sonra  if (0 < 20) koşuluna dönüşür ve sonuç 1 olacağından if bloğu çalışır. If bloğunda bulunan printf içinde de --a işlemi ile a’nın değeri 1 azaltılır ve çıktı olarak 9 değerini görürüz.

25 Şubat 2019 Pazartesi

C Çalışma Soruları – 17 (döngü deyimleri)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.

Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?
#include <stdio.h>
 
int main()
{
    int x = 1;
    
    while (x-- >= 1)
        while (x-- >= 0);
            printf("%d", x);
            
    return 0;
}

Yanıt:
Soruda ikinci while satırı sonunda noktalı virgül olduğunu görmek gerekir. Bu durumda printf fonksiyonu while döngülerinin dışındadır. While döngüleri bittikten sonra printf fonksiyonu çağrılır.
sağ taraf -- operatörü kullanıldığı için koşul içinde o anki x’in deri kullanılır ve daha sonra bir azaltılır. Ayrıca döngü koşulu sınanması için ilk olarak -- işleminin gerçekleşmesi gerekir. Koşul bu işlemden sonra sınanır. Her while döngüsünde -- işlemi iki defa gerçekleşir ve sonuç -3 olur.
Daha iyi anlamak için aşağıdaki kod parçası koşulabilir. While koşulu x in ilk değeri için bile sa
ğlamazken koşul şartına gelmeden önce -- işlemi gerçekleşir ve sonuç 0 olur.

   int x = 1;    
   while (x-- >= 100);
        printf("%d", x) ;

C Çalışma Soruları – 16 (işleçler)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.

Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?

#include <stdio.h>
 
int main()
{
    int x = 1;
 
    if (++x > 2,5)
       printf("%d", ++x);
    else
        printf("%d", x++);
    
    return 0;
}


Yanıt:
if (++x > 2,5) satırında 2 ile 5 arasında virgül olduğuna dikkat edilmelidir. C dilinde ondalık sayılar nokta ile oluşturulur. Bu durumda if (++x > 2,   5) şeklinde ele almamız gerekir. Virgül operatörü geri dönüş olarak sağ taraf değerini döner yani 5 değerini döner. If koşulu için virgülün sol tarafı bir anlam ifade etmez fakat x değeri ++ operatör yüzünden bir artar.
if (5) koşulu doğru olarak sonuç üretir ve if bloğu çalışır.(else bloğu çalışmaz.) if bloğunda da x değeri bir arttırıldığı için sonuç 3 olur.

C Çalışma Soruları – 15 (işleçler)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.

Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?


#include <stdio.h>
 
void func(int x)
{
    ++x;
    printf("%d", x);
}
 
int main()
{
    int x = 10;
    
    func(++x);
    func(x++);

    printf("%d", x);

    return 0;
}

Yanıt:
++x ve x++ çalışma farklılığına deyinerek soruyu çözebiliriz. ++x işleminde x in değeri bulunduğu satırda arttırılarak işleme katılır. X++ işleminde ise x değişkeni kendi değerinde bulunduğu satırda işlenir fakat bir sonraki işlendiği satırda değeri bir artmış olarak işlenir.
   int x = 10;    
   func(++x); → x 11 olarak değer alır ve fonksiyona 11 değeri gönderilir.
   func(x++); → x değeri bu satırsa 11 dir. Fakat bir sonraki işlemde x değeri bir artmış olarak karşımıza çıkacaktır. Sonuç olarak fonksiyona 11 değeri gönderilir.


   printf("%d", x); → x++ işlemi sonrasında x değeri burada 12 olarak işlenir.

Sonuç 121212 olur.


C Çalışma Soruları – 13 (döngüler)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.

Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?


#include<stdio.h>
 
int main()
{
    int i, k;

    for (i = 1, k = 1; k; printf("%d%d", i, k))
        k = i++ <= 3;

        return 0;
}

Yanıt:

Sorunun yanıtına geçmeden önce for döngüsünün nasıl çalıştığına bakmak lazım. İlk olarak aşağıdaki resim for döngüsünün akış diyagramını incelemek gerekir.
Yukarıdaki bilgiler ile adım adım aşağıdaki kodu koşalım ve her bir adımda çıktıları yazalım. i++ dikkat etmeyi unutmayalım. Çünkü bu satırda i değeri değişmezken i++ etkisi ile i nin kullanıldığı bir sonraki işlemde i değeri bir artmış olacak.
  for (i = 1, k = 1; k; printf("%d%d", i, k))
       k = i++ <= 3;

i=1: → k = 1 → printf çıktısı: 21 (i++ etkisi ile i=2 olarak işlendi)
i=2: → k = 1 → printf çıktısı: 31 (i++ etkisi ile i=3 olarak işlendi)
i=3: → k = 1 → printf çıktısı: 41 (i++ etkisi ile i=4 olarak işlendi)
i=4: → k = 0;→ printf çıktısı: 50 (i++ etkisi ile i=5 olarak işlendi)

k=0 olduğu için döngü akışı biter. Sonuç olarak çıktı 21314150 olur.





22 Şubat 2019 Cuma

C Çalışma Soruları – 11 (işleçler)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.

Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?

#include<stdio.h>
 
int main()
{
    int num = 30;
    int ival = (num > 5 ? num <= 10 ? 10 : 20 : 50);

    printf("%d\n", ival);

    return 0;
}

Yanıt: 



?: operatöründe öncelik sağdan sola olduğu görülüyor. Yani ilk olarak en sağdaki ?: işlem çözülür.

Bu bilgi ile ile ilk olarak num <= 10 ? 10 : 20 işleminin ele alınacağını görebiliriz. Koşulun doğru olmamasından dolayı buradan sonuç olarak 20 değerini alırız. En sağdaki ?: işlemi sonucunda durum num > 5 ? 20 : 50 şekline döner. Buradan da sonuç 20 elde edilir.

C Çalışma Soruları – 10 (göstericiler)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.

Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?

#include <stdio.h>
 
int main()
{
    char *a[] = { "necati", "kagan", "oguz", "gurbuz" };
    char **ptr[] = { a + 3, a + 2, a + 1, a }, ***p;
    p = ptr;
    ++p;
    printf("%s", **p + 1);

    return 0;
}

Yanıt:
Ilk olarak a ile ptr ve p göstericilerinin farklı türden olduğunu bilmek gerekir. a pointeri bir değişkenin adresini taşımaktadır. Yani a pointerinin içeriği bir değerdir. 
ptr ve p göstergeleri ise a pointeri gibi bir pointerin adresini tutan pointerdır. ptr ve p göstergeleri başka bir göstergenin adresini taşır ve dolayısı ile ptr ve p pointer içeriği de taşıdıkları pointer adresinin taşıdığı adrestir.


Yukarıdaki şekil üzerinde değişkenleri yerine koyalım. V değer taşıyan bir değişken ve taşıdığı değer 5. Ayrıca bu değişkenin adresi 0x35 adresinde. ad bir pointer olup v değişkeninin adresini taşıyor. Dolayısı ile ad pointerinin içeriği v değişkenin değeridir ve bu değer 5 dir. Ayrıca ad pointerinin kendi adresi 0x66 dır. Add ise ad pointerinin adresini taşıyan bir pointerdır. ad adresi 0x66 olduğu için add pointeri 0x66 adres değerini taşır. add pointerini içeriği ise add taşıdığı adres durumundadır.

Int V; int *ad; int **add; → Tanımlamalar bu şekilde yapılır.

V = 5;
ad = &V; → ad pointerine V adresi atandı.
add = &ad; → add pointerine ad pointerinin kendi adresi atandı.

Aşağıdaki örnek uygulamayı çalıştırarak daha net anlayabilirsiniz.


#include <stdio.h>
 
int main()
{
    int v;         int *ad;         int **add;    
    
    v = 5;
    ad = &v;
    
    add = &ad;

    printf("v adresi %p \n", &v);  // bu iki satırın çıktıları aynı olacaktır.
    printf("ad tasidigi adres %p \n\n", ad);
    
    printf("ad kendi adresi %p \n", &ad);    // bu iki satırın çıktıları aynı olacaktır.
    printf("add tasidigi adres %p \n\n", add);
    
    printf("add kendi adresi %p \n\n", &add);
    
    
    printf(" v degeri: %d \n", v); // bu iki satırın çıktıları aynı olacaktır.
    printf("ad tasidigi adresin degeri %d \n\n", *ad);
    
    printf("add tasidigi adresin icerigi %p \n", *add); // ad adresini verecektir
    printf("add tasidigi adresin iceriginin icerigi %d \n", **add); // ad adresine ulaşır ve onun taşıdığı adrese de gider
    

    return 0;
}

char *a[] = { "necati", "kagan", "oguz", "gurbuz" };
char **ptr[] = { a + 3, a + 2, a + 1, a }, ***p;
p = ptr;
++p;
printf("%s", **p + 1);

Bu bilgiler ile soruyu ele alalım. ilk olarak a pointeri char *a; şeklinde bir pointerdır. a nın taşıdığı değer ilk olarak “necati” dizisini başlangıç değeridir. 

ptr pointerinin ilk taşıdığı değer a+3 adresidir. 

p = ptr; bu atama sonrasında p pointeri de a+3 adresini taşıyor.++p; ile p nin taşıdığı adres bir arttırıldı. Yukarıdaki işlemde p pointerine ptr taşıdığı adres atanmıştı. ++p işlemi ptr dizisinde bir eleman ilerlemeye neden olur. Dolayısı ile ptr dizisinde bulunan a+2 adresine ulaşmış olduk. p pointeri a+2 adresini taşıyor. a+2 demek a pointerin taşıdığı adrese 2 eklemek demektir. Yani adres değiştirmektir. a pointeri “necati” adresini tutarken a+2 ise “oguz” stringinin başlangıç adresini tutar. p pointeri şu an a+2 adresini taşıdığını anladığımıza göre **p + 1 işlemine bakabiliriz. **p işlemi ile içeriğe ulaşılır. Bu içerik “oguz” stringinin başlangıç adresidir. Daha sonra +1 işlemi ile bu stringin başlangıç adresinden bir sonraki adrese gidiyoruz. Yani “oguz” stringinin 2. Üyesine ulaşmış oluruz. Sonuç olarak çıktı “guz” olur.