Categories: C

C Programlama Dersi – 7

Selam,

Bugün diziler konusuna devam ediyorum. Bu sefer “karakter dizisi“ni öğrenmeye çalışacağım. Dizgi, katar ya da string olarakta adlanırılabiliyor.  Aslında string modern programlama dillerine ait bir terim. Metinsel verileri saklamak için kullanılan değişken türünü ifade ediyor ama C dilinde string veri tipi yok. Bunun yerine karakterleri (char) bir araya getirerek bir dizi oluşturuyoruz. Yine de ben karakter dizisi yerine string terimini kullanacağım.

Stringlere İlk Bakış

Önce basitçe bir karakter dizisi tanımlamakla başlıyorum. Dizilerde geçerli olan kurallar stringler içinde geçerli.

char karakterDizisi[] = {'S','E','L','A','M'};

Bir dizi tanımlandığı zaman bellekte ardışık olarak yer ayrılıyordu. karakterDizisinin indislerine göre adreslerini yazdıralım:

int i;
    for(i=0;i<5;i++) {
        printf("%u ", &karakterDizisi[i]);
    }

Çıktı:

2337488 2337489 2337490 2337491 2337492

Görüldüğü üzere adresler birer birer artıyor. İlk derslerde öğrendiğim hangi veri tipinin bellekte ne kadar yer kapladığı meselesi şimdi daha da netleşti.

String tanımlamanın başka bir yolu ise  çift tırnakları (” “) kullanmak. Bu şekilde metni bir bütün olarak yazabiliriz.

char baskaKarakterDizisi[] = "Hırs, hasaret ve muvaffakiyetsizliğin sebebidir.";

Çift tırnaklar içinde bazı özel karakterleri kullanmak istediğimde, kaçış karakterini kullanmam gerektiğini de öğrenmiştim. Yani karakterini.

char string[] = "\"İslamiyetin menşei, ilim; esası, akıldır.\"";

Stringler konusunda önemli bir nokta ise, her zaman “null” karakteri ile sonlandıkları. Yani “\0” karakteri ile. \0 ASCII tablosundaki değeri 0 dır.

Stringler de bir dizi olduğuna göre tek tek elemanlarına erişebiliriz demektir.

char film[10] = "Matrix";

Yukarıdaki dizi için,

film[0]: M 
film[1]: a 
film[2]: t 
film[3]: r 
film[4]: i 
film[5]: x 
film[6]: '\0'

demektir. Şimdi bunu bir do-while döngüsüyle görelim. Döngü ‘\0‘ karakterini görene kadar devam etsin. Bakalım ne kadar dönecek?

int i=0;
    do {
        printf("film[%d]: %c \n", i, film[i]);
        i++;
    }while(film[i] != '\0');

Çıktı:

film[0]: M 
film[1]: a 
film[2]: t 
film[3]: r 
film[4]: i 
film[5]: x 

Bir stringin boyutunu gereğinden az verirsek C bize hata vermez ama fazla olan veriler saklanmaz.

char film[3] = "Matrix";

Bu stringi ekrana yazdırıyorum. Bu arada puts() diğer kullanım şeklini de öğrenmiş oluyorum.

puts(film);

Çıktı:

Mat

Stringlere İlk Değer Ataması

Buraya kadar olan kısımda zaten bunları yaptım ama hızlıca tekrar değineceğim. Karakter dizilerine şu şekillerde ilk atamlar yapılabilir:

  1. Dizinin boyutunu belirtmeden karakterleri yazarak
  2. Metinsel ifadeyi direkt yazarak
  3. Pointer kullanarak (pointer kavramını henüz öğrenmedim)

1-Boyut Belirtilmemiş Diziler ve Karakterler

Bir diziye boyutunu belirlemeden elemanları girdiğim zaman benim için elemanları sayıp boyutunu otomatik hesaplıyordu. Aynı durum karakter dizileri için de geçerli. Elemanları yine { } içine yazıyorum ama bu kez her bir elemanı ‘ ‘ içinde belirtiyorum. Ve dizinin sonuna ulaştığımı bildirmek için null karakterini yani '\0' eklemeyi unutmamak gerek.

char name [] = {'Y', 'U', 'S', 'U', 'F', '\0'};

 2-Metinsel İfadeyi  Direkt Girerek

En pratik ilk değer ataması bu şekilde oluyor. ” ” arasına metinsel ifadeyi giriyoruz. Üstelik bu yöntemle sonlandırı karakteri yani ‘\0‘ elle girmeme gerek kalmıyor çünkü benim için derleyici bunu yapıyor.

3-Pointer Kullanarak

Pointer kavramını henüz öğrenmediğim için bunu şimdi atlıyorum ama isteyenler olursa buraya linki bırakıyorum.

Stringler için Giriş İşlemleri

3 tane fonksiyon kullanabiliriz

  • getchar()
  • gets()
  • scanf()

getchar()

getchar() fonksiyonu enter girilene kadar klavyeden veri almaya devam eder ama sadece ilk girilen karakteri saklar. Eğer bir string saklamak istersek şu şekilde kullanabiliriz.

int i = 0;
    char name[20]; 

    puts("Lütfen isminizi girin:"); 

    while((name[i] = getchar())!='\n')
            i++ ;
    
    puts(name);

Yukarıdaki kod enter girilene kadar girilen karakterleri name içine atıyor. Bu sırada her karakter girişinde değeri 1 artarak dizinin indisi ilerletiliyor. Son olarak entera basıldıktan sonra ekrana girilen değeri yazdırıyor.

gets()

gets() fonksiyonu da enter girilene kadar boşluklar da dahil olmak üzere girilen karakterleri saklar ve dizinin sonuna otomatik olarak ‘\0‘ karakterini de ekler.

Aşağıda gets() fonksiyonun kullanım şeklini görüyoruz:

char name[20];

puts("Lütfen isminizi girin:");
gets(name);

 gets() ile stringleri almak pratik gözükse de kötü bir yanı var. Yukarıda name[20] için 20 karakterlik bir alan belirlenmiş olsa da gets() bunu dikkate almaz. 30 karakter girilse de bunu saklamaya çalışır. Bu durumda “overflow” yaşanabilir ve program çökebilir.

scanf()

Bu fonksiyonu daha önce birçok kez kullanmıştım zaten. Şimdi de string ifadeler için kullanım şekline bakalım:

char name[20]; 

    puts("Lütfen isminizi girin:"); 

    scanf("%s",name);

İlk dikkat ettiğim nokta stringler için placeholer %s. Diğer nokta ise & operatörü kullanılmamış.

scanf(), gets() ve getchar() dan farklı olarak, entera kadar olan tüm karakterleri değil boşluğa kadar olan karakterleri kabul ediyor. Yani yukarıdaki kod için name değişkenine “Yusuf Karaçin” yazarsam sadece “Yusuf” saklanır.

scanf() fonksiyonu ile boşlukları da saklamak istersek şu kodu kullanabiliriz:

scanf("%[^\n]s",name);

Yalnız scanf() fonksiyonu da overflow a açıktır. Overflowlarla baş etmeyi ilerledikçe öğrenmeyi umut ediyorum. Ayrıca stringleri alırken neden & kullanmadığımıza gelirsek bu da pointerlarla alakalı bir konu olduğu için şimdilik atlıyorum.

Stringleri Yazdırma

Yukarıda örnekleri gördüm ama yine hızlıca değinmek istiyorum:

  1. putchar()
  2. puts()
  3. printf()

putchar()

Adından anlaşıldığı üzere tek bir karakter yazdırmak için kullanılıyor. 3 farklı şekilde kullanabiliriz:

char a = 'Y';
    char isim[] = "Yusuf";
    putchar('a');  // a yazar
    putchar(a); // a değişkeni içindeki değeri yazar. Yani Y
    putchar(isim[1]); //isim dizisinin 1. indisini yazar. Yani u

 puts()

Kullanıcıya bildirmek vermek istediğim zaman sıklıkla tercih ettiğim fonksiyon. Kullanım şekillerini hızlıca hatırlayalım:

char isim[] = "Yusuf";
    puts(isim); //isim değişkenini, yani Yusuf yazar
    puts("Hoşgeldiniz!"); // hoşgeldiniz! yazar

 printf()

İlk konularda uzunca incelemiştim. Şimdi de stringler için kısaca göz atıyorum:

char isim[] = "Yusuf";
    char x = 'a';

    printf("Merhaba, %s", isim); //Merhaba, Yusuf yazar
    printf("\n Hoşgeldiniz!"); // bir sayır aşağıya iner ve hoşgeldiniz! yazar
    printf("%d",x); // 97 yazar

Stringler için placeholderın %s olduğunu bir kez daha görmüş oldum.

Stringleri Integer a Çevirme (atoi)

Bazen metinsel bir ifade aslında sayısal bir değer taşıyor olabilir. Mesela kullanıcıdan string olarak “17” değerini aldık. Bunun üzerinde matematiksel işlemler yapmak istersek öncelikle sayısal veri tipine çevirmemiz gerekir. Bunun için de atoi() fonksiyonunu kullanıyoruz.

atoi = A to I =Alphabet to Integer

int num;
    num = atoi("98");
    printf("\nNum: %d",num);

ya da

int num;
    char marks[3] = "98";
    num = atoi(marks);
    printf("\nNum : %d",num);

şeklinde kullanabiliriz.

Özet

  • Modern dillerideki string C dilinde karakter dizisidir.
  • Diziler için geçerli olan kurallar, karakter dizileri için de geçerli.
  • Karakter dizilerinin sonunda, bitirici karakter ‘\0’ olmalı.
  • İlk değer atamaları çift tırnak içinde direkt metinsel ifade şeklinde ya da tek tek karakter şeklinde olabilir.
  • Tek tek karakter girilirse, bitirici karakter olarak ‘\0’ eklenmeli.
  • putchar() tek bir karakter yazdırır, getchar() tek bir karakter alır.
  • Stringi sayısal ifadeye çevirmek için atoi() fonksiyonu kullanılabilir.

Recent Posts

Celery Checklist [Python]

Celery ile alakalı "best practice"leri ve faydalı araçları bir araya getiren güzel bir checklist'e denk…

5 yıl ago

JavaScript Dizileri için 13 İpucu

Diziler en temel ve sık kullandığımız araçlardan... Kod yazarken işimizi kolaylaştıracak, daha temiz kod yazmamızı…

5 yıl ago

List & Tuple Mini Test (Python)

listve tuple bilginizi test etmek ister misiniz? realpython.com da keşfettiğim ve Türkçe'ye çevirdiğim mini teste…

5 yıl ago

Bilmeniz Gereken 11 Python Mülakat Sorusu

Rehberlik sağlaması ve bilgi tazelemesi açısından faydalı olduğunu düşündüğüm bir Toptal blog paylaşımınıTürkçe'ye çevirdim.Devamını okuyunBilmeniz…

5 yıl ago

Angular Componentlere Konsol Üzerinden Hızlı Erişim

Angular componentlerine console üzerinden hızlıca erişmek için kullanılan bir teknik. Unutmamak için kendime not düşüyorum.Devamını…

5 yıl ago

Birkaç Güzel JavaScript Sorusu İster Miydiniz?

Geçtiğimiz günlerde keşfettiğim ve oldukça da hoşuma giden repoyu paylaşmak istiyorum: lydiahallie/javascript-questions Genel olarak temel…

5 yıl ago