Klasik Bir Örnek: Swap
Coddy'nin C Journey'sinin Logic & Flow bölümünün bir parçası — ders 28 / 63.
swap fonksiyonu, C programlamada işaretçilerin neden vazgeçilmez olduğunu gösteren en ünlü örneklerden biridir. Hedef basittir: iki değişkenin değerlerini birbiriyle değiştiren bir fonksiyon yazmak. Ancak, görünüşte basit olan bu görev, değerle çağırmanın (pass-by-value) temel bir kısıtlamasını ortaya çıkarır.
Normal değerle çağırma (pass-by-value) kullanarak iki değişkenin yerini değiştirmeye çalıştığınızda ne olacağını düşünün:
void badSwap(int a, int b) {
int temp = a;
a = b;
b = temp;
// Bu sadece kopyaların yerini değiştirir, orijinal değişkenleri değil!
}Bu yaklaşım başarısız olur çünkü fonksiyon değerlerin yalnızca kopyalarını alır. Çağıran fonksiyondaki orijinal değişkenler değişmeden kalır.
Çözüm, bunun yerine değişkenlere işaretçiler geçirmeyi gerektirir:
void swap(int *a, int *b) {
int temp = *a; // a adresindeki değeri sakla
*a = *b; // b adresindeki değeri a adresine koy
*b = temp; // Saklanan değeri b adresine koy
}Değişkenlerin adreslerini geçirerek ve dereference (başvuru giderme) operatörünü kullanarak, fonksiyon orijinal değişkenlerin değerlerini doğrudan değiştirebilir. Bu, swap fonksiyonunu, değerle geçme (pass-by-value) yönteminin tek başına halledemeyeceği görevleri yerine getirmek için ne zaman ve neden işaretçilere (pointers) ihtiyaç duyduğunuzun mükemmel bir gösterimi haline getirir.
Görev
Kolayİşaretçileri (pointers) kullanarak klasik swap (yer değiştirme) fonksiyonunu uygulayan ve gösteren bir C programı yazın. Programınız şunları yapmalıdır:
- Parametre olarak tam sayılara yönelik iki işaretçi alan
swapadında bir fonksiyon oluşturun swapfonksiyonunun içinde, geçici bir değişken kullanarak iki işaretçinin gösterdiği bellek adreslerindeki değerleri birbiriyle değiştirinmainfonksiyonunda, kullanıcı girişinden iki tam sayı okuyun- Orijinal değerleri şu formatta yazdırın:
Before swap: a = [value], b = [value] swapfonksiyonunu çağırın ve adres operatörünü kullanarak her iki değişkenin adresini geçirin- Fonksiyon çağrısından sonra, yer değiştirmiş değerleri şu formatta yazdırın:
After swap: a = [value], b = [value]
Çıktınız, fonksiyonun orijinal değişkenlerin değerlerini başarıyla değiştirdiğini göstermelidir:
Before swap: a = [first_input], b = [second_input]
After swap: a = [second_input], b = [first_input]Bu meydan okuma, swap işlemi için işaretçilerin neden gerekli olduğunu gösterir - fonksiyonun, değerleri kalıcı olarak değiştirmek için orijinal değişkenlerin bellek konumlarına erişmesi gerekir; bu, değerle çağırma (pass-by-value) ile imkansızdır.
Kopya kağıdı
swap fonksiyonu, pointer'ların (işaretçilerin) C'de neden temel olduğunu gösterir. Değerle çağırma (pass-by-value), fonksiyonlar yalnızca kopyaları aldığı için orijinal değişkenleri takas edemez:
void badSwap(int a, int b) {
int temp = a;
a = b;
b = temp;
// Bu sadece kopyaları takas eder, orijinal değişkenleri değil!
}Doğru yaklaşım, orijinal değişkenlere erişmek ve onları değiştirmek için pointer'ları kullanır:
void swap(int *a, int *b) {
int temp = *a; // a adresindeki değeri sakla
*a = *b; // b adresindeki değeri a adresine koy
*b = temp; // Saklanan değeri b adresine koy
}Adresleri geçirerek ve dereference (içerik) operatörünü (*) kullanarak, fonksiyon orijinal değişkenlerin değerlerini doğrudan değiştirebilir.
Kendin dene
#include <stdio.h>
// YAPILACAK: Takas (swap) fonksiyonunuzu buraya yazın
int main() {
int a, b;
// Girdiyi oku
scanf("%d", &a);
scanf("%d", &b);
// Orijinal değerleri yazdır
printf("Before swap: a = %d, b = %d\n", a, b);
// YAPILACAK: Takas (swap) fonksiyonunuzu burada çağırın
// Takas edilmiş değerleri yazdır
printf("After swap: a = %d, b = %d\n", a, b);
return 0;
}Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Logic & Flow bölümündeki tüm dersler
1Pointer Temelleri
Pointer Nedir?Pointer TanımlamaAdres Operatörü (&)Dereference Operatörü (*)NULL Pointer'larÖzet: Pointer Temelleri4Proje: Basit Metin Aracı
Projeye Genel BakışKarakter Sayma2İşaretçiler ve Diziler
İşaretçi Olarak Dizi İsimleriDizi Elemanları - İşaretçilerİşaretçi Aritmetiğiİşaretçilerin KarşılaştırılmasıÖzet: İşaretçi ile Dizi Gezinme5İşaretçiler ve Fonksiyonlar
Değer ile GeçmeFonksiyonlara İşaretçi Göndermeİşaretçiler ile Değişkenleri DeğiştirmeKlasik Bir Örnek: SwapFonksiyonlara Dizi GöndermeÖzet: Fonksiyon İşaretçi Argümanları8Yapılar ve İşaretçiler
Yapılara İşaretçilerOk Operatörü (->)Yapıları Değer ile AktarmaYapı İşaretçilerini AktarmaYapıların Dinamik TahsisiÖzet: Yapıyı Değiştirme - Ptr11Son Tekrar Görevleri
Tekrar: Dinamik String BirleştirmeTekrar: Struct DizisiTekrar: Kelime Frekans Sayacı3Karakter Dizileri ve Stringler
char Dizisi Olarak StringlerNull Sonlandırıcıscanf ile String Girişistrlen() Kullanımıstrcpy() Kullanımıstrcat() Kullanımıstrcmp() KullanımıÖzet: Temel String Fonksiyonları