Yazan: Şadi Evren ŞEKER

Bir dilde bulunan ve o dilin tanımlı olan alfabesi içerisindeki sembollerin çeşitli sayılarda ve çeşitli sırada dizilmesi ile elde edilen yazılardır.

Örneğin bir dildeki alfabe aşağıdaki şekilde tanımlı olsun:

1 = {0,1}

Buna göre dilimizde sadece “0” ve “1” sembolleri tanımlı demektir. Bu dilde örneğin w1=0 veya w2=10101011010 gibi bir dizgi elde etmek mümkündür.

Bir dizginin belirli bir kımını içeren dizgiye ise alt dizgi adı verilir. Örneğin w3=1011 dizgisi w2 dizgisinin bir altdizgisidir.

Ayrıca iki dizginin arka arkaya eklenmesine de üleştirme(concatenation) denilir.Örneğin w1 ile w3 dizgilerinin üleştirilmiş hali w4=01011 olur.

Dizgiler ile ilgili diğer yazılar:

Dizgi Karşılaştırma/Arama/Mesafe algoritmaları:

Dizgi Parçalama (Parsing) algoritmaları:

 

C ile dizgi okuma

C dilinde klavyeden dizgi (String) okumak için kullanılan en basit fonksiyon scanf fonksiyonudur. Bu fonksiyonu basit bir uygulamada aşağıdaki şekilde kullanabiliriz:

Yukarıdaki kodda, 5. satırda tanımlalan karakter dizisi (string) içerisine 7. satırda %s parametresi ile scanf fonksiyonu kullanılarak bir dizgi okunmuştur. Bu dizginin içeriği kodun 8. satırında ekrana basılmıştır.

Örneğin yukarıdaki kod aşağıdaki şekilde çalıştırılabilir:

Görüldüğü üzere, kullanıcı isim olarak “ali” girmiş ve ekranda, girdiği bu dizgiyi görmüştür. Ancak aynı kodu çalıştırarak aşağıdaki şekilde bir dizgi girilirse problem yaşanır:

Yukarıdaki girdide “ali baba ve kirk haramiler” şeklinde 5 kelimeden oluşan bir dizgi girilirken, bu dizginin sadece ilk kelimesi scanf tarafından okunmuştur. Aslında burada bir hata yoktur çünkü scanf fonksiyonu, boşluk karakteri veya  satır sonu gibi karakterlere kadar olan dizgileri okur. Yukarıdaki gibi birden fazla kelimeden oluşan dizgiler okunmak istendiğinde, aşağıdaki kodda da gösterilen gets fonksiyonu kullanılabilir:

Yukarıdaki kodda bir önceki koda göre sadece 7. satırda bulunan scanf fonksiyonu, gets fonksiyonu ile değiştirilmiştir. Kodumuzun yeni halini çalıştırdığımızda, aşağıdaki şekilde birden fazla kelime okuyabildiğimizi görürüz:

Dizgilerin Eşitliği

İki farklı değişkende bulunan dizginin eşit olup olmadığı, programlama dillerinde bulunan klasik operatörler ile yapılamaz.

Örneğin aşağıdaki kodlama C dili açısından doğru olsa bile mantıksal olarak hatalıdır (logic error):

char a[100] = “bilgisayarkavramlari.com”;

char b[100]= “bilgisayarkavramlari.com”;

if(a==b)

Yukarıdaki kodun, son satırında bulunan eşitlik kontrolü, C dili açısından ne derleme (compile) ne de çalışma (run-time) hatası döndürmez. Ancak buradaki karşılaştırma aslında iki dizinin (array) hafızada (RAM) aynı yeri gösterip göstermediğini sorgulamaktadır.

Yukarıdaki kod, her zaman için yanlış (false) döner ve if kontrolüne hiçbir zaman girilemez. Bunun yerine dizgilerin içeriklerinin karakter karakter kontrol edilmesi ve dizgilerin boyutlarının eşit olup olmadığının sorgulanması gerekir.. Bizim iki dizginin eşitliğinden anladığımız genelde budur. Bu kontrole literatürde derin karşılaştırma (deep compare) ismi verilmektedir.. Klasik olarak yapılan a==b kontrolü ise sığ karşılaştırma (shallow compare) olarak geçmektedir.

Derin karşılaştırma için kendimiz bir fonksiyon yazabileceğimiz gibi, C dilinde var olan string.h kütüphanesindeki strcmp fonksiyonunu kullanabiliriz. Bu fonksiyon iki dizgiyi (string) sözlük sıralamasına göre karşılaştırır (lexiconically) ve şayet eşitlerse 0 değerini döndürür.

C dilinde 0 değeri mantıksal olarak yanlış (false) olduğu için eşit olmaları durumunda bir if bloğunun çalışmasını istiyorsak, aşağıdaki şekilde yazabiliriz:

if(!strcmp(a,b))

yukarıdaki kontrol, a ve b dizgilerinin eşitliği durumunda geçer.

Aynı kontrol JAVA veya C# gibi dillerde, String sınıfının bulunması sayesinde, ilave bir kütüphane ve fonksiyona gerek kalmadan çözülebilir.

Örneğin JAVA dili için:

String a= “www.bilgisayarkavramlari.com”;

String b= “www.bilgisayarkavramlari.com”;

if(a.equals(b))

kontrolü yapılması yeterlidir. Java dilinde, bulunan ve dizgileri karşılaştırmak için kullanılan equals fonksiyonu C# dilinde ilk harfi büyük olarak Equals şeklinde yazılarak çalıştırılabilir (burada bir kere daha JAVA’yı taklit ederken, java kodlarının çalışmaması için özel gayret sarf eden microsoft geliştiricilerini selamlıyoruz.)

Dizgilerin birbirine eklenmesi (concatenate, üleştirme) için C ve C++ gibi dillerde strcat fonksiyonu kullanılabilir.

Örneğin:

char a[100]= “www.”;

char b[100] = “bilgisayarkavramlari.com”;

strcat(a,b);

printf(“%s”,a);

şeklindeki bir kod, ekrana “www.bilgisayarkavramlari.com” sonucunu basacaktır.

Aynı üleştirme işlemi, JAVA veya C# için basit bir toplama (+) işlemi ile yapılabilir.

String a=”www.”;

String b=”bilgisayarkavramlari.com”;

System.out.println(a+b);

yukarıdaki kod, ekrana “www.bilgisayarkavramlari.com” sonucunu basarken aynı kodu C# dilinde sadece son satırını Console.write(a+b) olarak değiştirerek deneyebilirsiniz.

Yorumlar

  1. Muzaffer Boran

    hocam örnegin scanf(“%s”,isim) yazdıgımda program uzun giris yaptıgımda
    sapıtıyor gets(isim) yazdıgımda ise o bolümü atlıyor gets’i nasıl
    kullanacagımı gösterirmisiniz?

  2. Şadi Evren ŞEKER Article Author

    sorunuza cevap olması açısından yukarıdaki yazının içerisine hem scanf hem de gets kullanan basit birer örnek ekliyorum, farkları zaten bu örnekten anlaşılır.

    umarım yardımcı olur

    başarılar

  3. Ozan

    hocam tekrar merhabalar:
    dun hatırlasanız bır soru sormustum dizgilerle ilgili orneğin işte 5 tane isim girilecek ve baş harfi ‘B’ ile başlayanlar ekrana basılacak:sizin kodunuzu denedım soyle gostereyım hatta bir kac defa denedım ama hata verdi

    #include 
    #include 
    int main(){
       char *a[5];
       for(int i=0;i<5;i++){
       scanf("%s",a[5]);
       for(int i=0;i<5;i++){
          if(a[i][0]=='B'){
             printf("%s",a[i]);
          }
       }
       getch();
       return 0;
    }
    

    bu kod calısmadı hocam nedeni sizce ne olabilir.

  4. Ozan

    hocam orda includeların yanında stdio.h ve oburunde conio.h vardı cıkmamıs belirteyim dedım ayrıca scanf(“%s”,a[i]) olarak da denedım gene hata verdi.

  5. Ozan

    hocam bir de dizgilerde anlayadığım ikinci nokta orneğin bir metin girin diyor ve mesela
    ozannasılsıniyimsin gibi ve diyoki bu metnin örneğin 3 defa ötelenmiş şeklini ekrana yazınız .bunu nasıl yapmam gerejiyor.yani bu oteleme işlemiyle ilgili bir sıkıntım var .acıklayabilirseniz cok sevinirim.

  6. Şadi Evren ŞEKER Article Author

    Bakın sizin için kodu yazdım derledim ve çalıştırdım.
    Kodun tamamı aşağıdaki şekilde yazılabilir:

    #include 
    #include 
    int main(){
       char *a[5];
       for(int i=0;i<5;i++){
            a[i] = (char *)malloc(sizeof(char)*10);
       	scanf("%s",a[i]);
       }
       printf("n B ile baslayanlar : n");
       for(int i=0;i<5;i++){
          if(a[i][0]=='B'){
             printf("%sn",a[i]);
          }
       }
       return 0;
    }
    

    Çalışması ve ekran görütüsü ise aşağıdaki şekildedir:

  7. Şadi Evren ŞEKER Article Author

    Öteleme ile ilgili neyin kast edildiğini ben de anlayamadım, şayet ekrana soldan 3 karakter daha içerde çıkması isteniyorsa, 3 kere boşluk karakteri (white space) yani ” ” karakteri konulabilir. Bu sayı parametrik de yapılabilir.

    Örneğin aşağıdaki gibi bir dizgi bir de sayı alıp verilen sayı kadar öteleyelim:

    #include 
    int main(){
    	printf("bir dizgi giriniz");
    	char s[100];
    	scanf("%s",s);
    	printf("bir sayi giriniz");
    	int sayi ;
    	scanf("%d",&sayi);
    	for(int i = 0;i
    

    Kodun çalışması aşağıda verilmiştir:

  8. Ozan

    hocam aslında soru su bu oteleme ile ilgili diyoki mesela:
    klavyeden nokta yazılıncaya kadar girilen cumleyi sifreleyerek ekrana yazınız.bu soruda eski şifre metotlarından her harfin belli miktar ötelenmesi esas alınmıs.yani orneğin oteleme miktarı 3 seçildiğinde A lar D K lar da N oluyor gibi.Ötelendiğinde son harfi geçen harfler başa dondurulerek oradan devam edilir diyor hocam.yanı bu nasıl yapıcam uraşıyorum ama bir turlu bulamadım.

  9. Ozan

    hocam merhabalar şimdi örneğin bir metindeki “ak” ikilisinin hangi indexlerde olduğunu gosterebiliyorum ancak burada kac ak boyle ak olduğunu nasıl ekrana yazdırcam onu yapamadım.yazdıım kod soyle:
    #include
    #include
    #include
    int main(){
    char dizgi[]=”Korkma sönmez bu şafaklarda yuzen alsancak sonmeden yurdumun üstünde tüten en son ocakO benim milletimin yildizidir parlayacak”;
    char*s2;
    s2=strstr(dizgi,”ak”);
    while(s2!=NULL){
    printf(“n%d”,s2-dizgi);
    s2=strstr(s2+1,”ak”);
    }

    getch();
    return 0;
    }

    hocam burada toplamda 4 tane ak var indexlerini yazdırdım ama iste 4 tane ak var nasıl demem gerekir

  10. Ozan

    hocam merhabalar bı soruda takıldım da sımdı metindeki sadece sesli harfleri yazdırmak istiyorum ama sistem hata veriyo.yazdıım bu koddaki hata nedir sizce?

    #include 
    #include 
    
    int main(){
        char metin[100];
        int c=0;
        printf("Metni giriniz:");
        gets(metin);
        char ozan;
        while(metin[c]!=''){
                            if(metin[c]=='a' || metin[c]=='e' || metin[c]=='o' || metin[c]=='i' || metin[c]=='u'){
                                           ozan=metin[c];     
                            }
                            c++;  
        }
        for(int i=0;i
    

  11. Şadi Evren ŞEKER Article Author

    Öncelikle sistem hata vermez, bilgisayarlar hep doğru çalışır 🙂

    Sorunuza gelince, bir iki genel hata var, dizgiyi gets ile okumuşsunuz, bu durumda sonuna geldiğinizi n karakterini kontrol ederek anlayabilirsiniz. Ayrıca bulduğunuz sesli harflerden sadece birsini char değişkeninde tutmuşsunuz bu durumda birden fazla sesli harf varsa üzerine yazıyor, bunun yerine bir dizi tutmak daha işlevsel olabilir.
    Aşağıda kodunuzu değiştirmeye çalıştım:

    #include 
    #include 
     
    int main(){
        char metin[100];
        char sonuc[100];
        int c=0,d=0;
        printf("Metni giriniz:");
        gets(metin);
        while(metin[c]!='n'){
                            if(metin[c]=='a' || metin[c]=='e' || metin[c]=='o' || metin[c]=='i' || metin[c]=='u'){
                                           sonuc[d++]=metin[c];     
                            }
                            c++;
        }
        for(int i=0;i
    

  12. Ozan

    evet hocam sistem hata vermiyor:D:d.zaten koddaki hatayı sormustum sayenizde bu soruyla genis bir perspektife kazandım gercekten cunku dızgılerde hep karıstırdııım noktalardan biriydi sayenizde o da artık tarıh oldu:….saolun varolun:…

  13. Ozan

    hocam merhabalar sımdı dizgi icinde bir kelimeyle disardan girdiiim bir kelimeyle yer değiştirmek istiyorum kodu yazdım ama galıba bır yerlerde yanlıs yapıyorum kod soyle:yanlısım nerede gosterırsenız cok sevinirim:

    #include 
    #include 
    #include 
    #include 
    int main(){
        char metin[100];
        char aranan[50];
        char yerine[50];
          char yedek[100];
          int c=0;
        
        printf("Metni giriniz:");
        gets(metin);
        printf("Aranan kelimeyi giriniz:");
        scanf("%s",aranan);
        printf("Yerine konulacak kelime:");
        scanf("%s",yerine);
        char*ara=strstr(metin,aranan);
        if((strcmp(ara,aranan)==0)){
                                  
                strcpy(yedek,ara);
                strcpy(ara,yerine);
                strcpy(yerine,yedek);
       }
       printf("nDegismis hali:");
       printf("%s",metin);
       getch();
       return 0;
    }
    
  14. Şadi Evren ŞEKER Article Author

    Öncelikle bulundu kontrolünüz hatalı. Yani ara göstericisi (pointer) konum olarak metnin içindeki aranan kelimenin geçtiği yeri döndürür (aslında strstr fonksiyonu bunu ara değişkenine döndürür). Ancak strcmp ile yapılan kontrolde ara ile aranan karşılaştırılması yapılmış ki bu yanlış.

    Örnek üzerinden anlayalım:

    metin =”ali baba ve kirk haramiler”
    aranan = “baba”
    yerine = “anne”

    olarak girilmiş olsun, bu durumda ara değişkeni bize aşağıdaki şekilde dönecek:

    ara = “baba ve kirk haramiler”

    çünkü baba kelimesinin ilk geçtiği yeri gösteren bir göstericimiz var. Ve dolayısıyla strcmp iki dizgiyi, yani “baba ve kirk haramiler” ile “baba” dizgilerini karşılaştıracak ve doğal olarak eşit olmadığı için if kontrolüne girilmeyecek.

    Çözüm olarak illaki böyle bir karşılaştırma isteniyorsa, strncmp kullanılabilir. Bu fonksiyon sonda verilen sayı kadar karakteri karşılatırır. Doğru kullanımı aşağıdaki şekilde olacaktır:

    if((strncmp(ara,aranan,strlen(aranan))==0)){
    

    Dolayısıyla sadece aranan dizgi kadar karaktere bakılacak ve eşitlik kontrolü sağlanacaktır. Ancak bu if kontrolü çok gerekli değil, aslında bu if kontrolü strstr fonksiyonunun doğru çalışıp çalışmaıdğını kontrol ediyor ki çok anlamlı bir kontrol değil.

    Gelelim diğer hatalara. kodun 22. ve 23. satırlarında üst üste dizgileri kopyalamışsınız. Oysaki yaklaşım şu şekilde olmalı

    aranan kısma kadar olan dizgi ile yerine konulacak dizginin birleşimi ile aranan dizgiden sonraki dizginin birleşimi

    Bu durumda benim izleyeceğim yol, indis değerlerini kullanmak olurdu. Yani öncelikle aradığımız dizginin kaçıncı karakter olduğunu bulalalım:
    Basit bir pointer (gösterici) matematiği ile:
    ara – metin
    bize bu değeri verir.
    şimdi bu bilgiyi kullanarak işlemi tamamlayalım:

                    strncpy(yedek,metin,ara-metin);
                    strcat(yedek,yerine);
                    strcat(yedek,ara+strlen(aranan));
    

    Yukarıda, dikkat edilirse öncelikle ara-metin kadar karakteri, yani aranan kelimenin bulunduğu yere kadar olan karakteri yedek dizgisine kopyaladık.
    Ardından bu dizgiye, yerine konulacak olan kelimeyi üleştirdik (ekledik)
    son olarak aradığımız kelimeden sonraki karakterleri yedek dizgisine üleştirdik. Burada aradığımız kelime kadar karakter atlayarak kalanları almak için ara + strlen(aranan) formülü kullanılmış, bu sayede kelimenin bulunduğu noktadan, kelime kadar ileri gidilmiştir.

    Anlaşılması için örneğe geri dönelim:
    metin =”ali baba ve kirk haramiler”
    aranan = “baba”
    yerine = “anne”

    Yukarıdaki örnek girdiler için değerler aşağıdaki şekildedir:
    ara – metin = 4 (çünkü baba kelimesinin ilk b harfi dizideki 4. elemandır)
    strlen(aranan) = 4 (çünkü baba kelimesinin boyu 4 karakter)
    ara + strlen(aranan) = 8

    strncpy(yedek,metin,ara-metin);
    işleminden sonra yedek dizgisinde = “ali ”
    strcat(yedek,yerine);
    işleminden sonra yedek dizgisinde = “ali anne”
    strcat(yedek,ara+strlen(aranan));
    işleminden sonra yedek dizgisinde = “ali anne ve kirk haramiler”

    şeklinde dizgi bulunmaktadır.

    kodun tamamını aşağıda ayrıca veriyorum:

    #include 
    #include 
    #include 
    int main(){
        char metin[100];
        char aranan[50];
        char yerine[50];
        char yedek[100];
        int c=0;
    
        printf("Metni giriniz:");
        gets(metin);
        printf("Aranan kelimeyi giriniz:");
        scanf("%s",aranan);
        printf("Yerine konulacak kelime:");
        scanf("%s",yerine);
        char *ara=strstr(metin,aranan);
        if((strncmp(ara,aranan,strlen(aranan))==0)){
                    strncpy(yedek,metin,ara-metin);
                    strcat(yedek,yerine);
                    strcat(yedek,ara+strlen(aranan));
       }
       printf("nDegismis hali:");
       printf("%s",yedek);
       return 0;
    }
    

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir