Programlama Temelleri

8 - Diziler - Bölüm 2: Karakter Dizileri

Emre Can Yılmaz

Ondokuz Mayıs Üniversitesi

2024

Karakter Dizileri (Dize - String)

  • Karakter dizileri, karakterlerin ardışık olarak saklandığı ve işlendiği veri yapılarıdır.
  • Bir karakter dizisi, char veri tipinde bir dizi olarak tanımlanabilir.
  • C programlama dilinde bir karakter dizesi, null karakter \0 ile sonlandırılır. Derleyici, çift tırnak işareti içine alınmış bir karakter dizisiyle karşılaştığında, varsayılan olarak sonuna bir null karakteri, yani \0, ekler.
char c[] = "c string";

Karakter Dizisi Tanımlama ve Başlatma

char dizi_adı[dizi_boyutu];
  • dizi_boyutu, saklanacak metnin maksimum uzunluğundan bir fazla olmalıdır (null karakteri için).

Örnekler: Karakter Dizisi İlklendirme

Dizeleri çeşitli şekillerde ilklendirebilirsiniz.

char c[] = "abcd";

char c[50] = "abcd";

char c[] = {'a', 'b', 'c', 'd', '\0'};

char c[5] = {'a', 'b', 'c', 'd', '\0'};

char c[5] = "abcde";
// HATA! 5 karakterlik bir diziye 6 karakter atanmaz.
// (null karakteri unutmayın)

Karakter Dizilere Değer Atama

  • Diziler C’de ikinci sınıf vatandaşlardır; diziler bir kez tanımlandıktan sonra, atama işlecini desteklemezler. strcpy fonksiyonu ile kopyalama yapılabilir.
char c[100];
c = "C programming";  // Error! array type is not assignable.

Dize Elemanlarına Erişim

  • Karakter dizilerinde her bir karakter, dizi içerisinde bir indeks numarası ile temsil edilir. Örneğin, isim[0], isim[1], isim[2], vb. şeklinde her bir indeks bir karakteri gösterir.
char isim[20] = "Ahmet";

printf("%c\n", isim[0]); // Çıktı: A
printf("%c\n", isim[1]); // Çıktı: h

isim[0] = 'M'; // İlk karakteri değiştirme
printf("%s\n", isim); // Çıktı: Mehmet

Kullanıcıdan Karakter Dizisi Okuma

  • Bir string’i okumak için scanf() işlevini kullanabilirsiniz. scanf() işlevi, “whitespace” (beyaz boşluk) ile (boşluk, yeni satır, sekme vb.) karşılaşıncaya kadar karakter dizisini okur.

Örnek 1: scanf() ile string okuma

#include <stdio.h>

int main() {
    char name[20];
    printf("Adinizi Girin: ");
    scanf("%s", name);
    printf("Adiniz %s.", name);
    return 0;
}

Çıktı:

Adinizi Girin: Emre Can
Adiniz Emre.
  • Bu örnekte kodda “Emre Can” girilmiş olmasına rağmen, “name” dizesinde yalnızca “Emre” saklanmıştır.

  • Bunun nedeni, scanf fonksiyonunun boşluk karakterini string’in sonu olarak kabul etmesidir.

  • Ayrıca scanf() ile &name yerine name kullandığımıza dikkat edin!

scanf("%s", name);

Bunun nedeni, name’in bir char dizisi olması ve dizi adlarının C’de bellek adresini göstermesindendir. Yani name, dizinin başlangıç adresini gösteriyor, bu nedenle & kullanmamıza gerek yoktur.

Bir Metin Satırı Nasıl Okunur?

  • Kullanıcıdan boşluk içeren bir metin satırı okumak için fgets() fonksiyonunu kullanırız.

Örnek 2: fgets() ile string okuma

#include <stdio.h>

int main() {
    char name[30];
    printf("Adinizi Girin: ");
    fgets(name, sizeof(name), stdin);  // read string
    printf("Ad: ");
    puts(name);    // display string
    return 0;
}

Çıktı:

Adinizi Girin: emre can
Ad: emre can
  • Burada, kullanıcıdan bir dizi okumak için fgets() fonksiyonunu kullandık. fgets() fonksiyonu 3 parametre alır:
    1. name: Kullanıcıdan alınan veriyi hangi değişkene yazacağınız değişken adı.
    2. sizeof(name): Değişkenin boyutu. Bu, fgets fonksiyonunun arabellek taşmasını önlemek için önemlidir.
    3. stdin: Kullanıcının klavyeden bir metin gireceğini belirtir.
  • Diziyi yazdırmak için puts(name); kullandık.

Sık Kullanılan Dize Fonksiyonları

  • Karakter dizilerinde iki değişkenin birbirine atanması ya da karşılaştırılması işlemleri standart operatörler kullanılırsa (=, == gibi) beklenmedik sonuçlar doğurabilir. Bunun yerine, string kütüphanesindeki (<string.h>) fonksiyonları kullanılmalıdır.

strlen() - Dize Uzunluğunu Hesaplar

  • strlen() işlevi bir dizeyi argüman olarak alır ve uzunluğunu döndürür. Döndürülen değer, size_t türündedir (işaretsiz bir tamsayı türü).

Örnek: strlen() Fonksiyonu

#include <stdio.h>
#include <string.h>

int main() {
    char a[20] = "Program";
    char b[20] = {'P','r','o','g','r','a','m','\0'};

    // size_t'yi yazdırmak için %zu format belirticisini kullan
    printf("Length of string a = %zu \n", strlen(a));
    printf("Length of string b = %zu \n", strlen(b));

    return 0;
}

Çıktı:

Length of string a = 7
Length of string b = 7

Not

strlen() fonksiyonunun uzunluğu hesaplarken \0 null karakteri saymadığını unutmayın!

strcpy() - Bir Dizeyi Başka Bir Dizeye Kopyalar

  • strcpy() fonksiyonu, kaynağın işaret ettiği dizeyi (null karakter dahil) hedefe kopyalar.

Örnek: strcpy() Fonksiyonu

#include <stdio.h>
#include <string.h>

int main() {
  char str1[20] = "C programming";
  char str2[20];

  // str1'i str2'ye kopyalar
  strcpy(str2, str1);

  puts(str2); // C programming

  return 0;
}

Çıktı:

C programming

strcpy() Fonksiyonu ve Arabellek Taşması

Not: strcpy() işlevini kullandığınızda, hedef dizenin boyutu, kopyalanan dizeyi depolayacak kadar büyük olmalıdır. Aksi halde, arabellek taşması (buffer overflow) meydana gelebilir ve programınız çökebilir veya beklenmedik davranışlar gösterebilir.

strcmp() - İki Dizeyi Karşılaştırır

  • strcmp() işlevi iki dizeyi karakter karakter karşılaştırır. Parametre olarak iki dize alır.

Dönüş Değerleri

Dönüş Değeri Anlamı
0 Dizeler eşit.
> 0 str1’deki eşleşmeyen ilk karakterin str2’ninkinden büyükse (ASCII’ye göre).
< 0 str1’deki eşleşmeyen ilk karakter str2’dekinden daha küçükse (ASCII’ye göre).

Örnek: strcmp() Fonksiyonu

#include <stdio.h>
#include <string.h>

int main() {
  char str1[] = "abcd", str2[] = "abCd", str3[] = "abcd";
  int result;

  // str1 ve str2 dizelerini karşılaştırıyoruz
  result = strcmp(str1, str2);
  printf("strcmp(str1, str2) = %d\n", result);

  // str1 ve str3 dizelerini karşılaştırıyoruz
  result = strcmp(str1, str3);
  printf("strcmp(str1, str3) = %d\n", result);

  return 0;
}

Çıktı:

strcmp(str1, str2) = 32
strcmp(str1, str3) = 0

Programda;

  • str1 ve str2 dizeleri eşit değildir. Dolayısıyla sonuç sıfır olmayan bir tam sayıdır.
  • str1 ve str3 dizeleri eşittir. Dolayısıyla sonuç 0’dır.

strcat() - İki Dizeyi Birleştirir

  • strcat() iki argüman alır;
    • destination: Hedef dize.
    • source: Kaynak dize.
  • strcat() işlevi, hedef dizeyi ve kaynak dizeyi birleştirir ve sonuç, hedef dizede saklanır.

Örnek: strcat() Fonksiyonu

#include <stdio.h>
#include <string.h>

int main() {
   char str1[100] = "Programlamayi ";
   char str2[] = "seviyoruz!";

   // str1 ve str2'yi birlestir sonucu str1'e kaydet
   strcat(str1, str2);

   puts(str1);
   puts(str2);

   return 0;
}

Çıktı:

Programlamayi seviyoruz!
seviyoruz!

strcat() Fonksiyonu ve Arabellek Taşması

Uyarı

strcat()’i kullandığınızda, hedef dizenin boyutu, elde edilen dizeyi depolayacak kadar büyük olmalıdır. Aksi halde segmentasyon hatası (segmentation fault) alırız.

Problem 1: Metnin Son Karakterini Bulma

Kullanıcıdan bir metin girmesini isteyin ve girilen metnin son karakterini ekrana yazdırın.

Problem 2: Metni Ters Çevirme

Kullanıcıdan alınan metni ters çevirip, önce bir değişkene atayıp ardından bu değişkeni ekrana yazdıran kodu yazın.

Gelecek Hafta

  • İşaretçiler (Pointers)