Menu
Coddy logo textTech

Jenerik Yer Değiştirme

Coddy'nin C Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 51 / 61.

Programlamada yaygın bir işlem, iki değerin yerini değiştirmektir. Normalde, her tür için ayrı bir takas fonksiyonu yazarsınız — biri int için, diğeri double için vb. Ancak void* ve memcpy ile, herhangi iki değişkeni takas eden tek bir fonksiyon yazabiliriz.

Temel içgörü, takas işleminin (swapping) sadece baytları yer değiştirmekten ibaret olduğudur. Verinin boyutunu biliyorsanız, gerçek türü bilmenize gerek kalmadan baytları kopyalayabilirsiniz. Fonksiyon imzası şu şekildedir:

void generic_swap(void* a, void* b, size_t size);

size parametresi fonksiyona kaç bayt taşınacağını söyler. İçeride, baytları yer değiştirmek için geçici bir tampon ve <string.h> kütüphanesinden memcpy kullanıyoruz:

void generic_swap(void* a, void* b, size_t size) {
    char temp[size];      // geçici tampon
    memcpy(temp, a, size);  // temp = a
    memcpy(a, b, size);     // a = b
    memcpy(b, temp, size);  // b = temp
}

Artık bu tek fonksiyon her tür için çalışıyor:

int x = 5, y = 10;
generic_swap(&x, &y, sizeof(int));
// x artık 10, y artık 5
double p = 3.14, q = 2.71;
generic_swap(&p, &q, sizeof(double));
// p artık 2.71, q artık 3.14

Bu desen — void* ile size_t kullanımı — C'nin standart kütüphanesinin qsort ve bsearch gibi genel fonksiyonları nasıl uyguladığıdır.

challenge icon

Görev

Kolay

void* işaretçilerinin ve memcpy fonksiyonunun gücünü kullanarak, türleri ne olursa olsun herhangi iki değişkenin değerlerini değiştirebilen genel bir takas (swap) aracı oluşturalım.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • swap.h: İki adet void* işaretçisi ve takas edilecek verinin boyutunu belirten bir size_t parametresi alan generic_swap fonksiyonunuzu bildirin. Include guard (ekleme korumaları) kullanmayı unutmayın!
  • swap.c: generic_swap fonksiyonunu uygulayın. İki bellek konumu arasında baytları taşımak için geçici bir tampon (buffer) ve memcpy kullanın. Üç adımlı takas modelini hatırlayın: ilk değeri geçiciye kopyala, ikinciyi ilke kopyala, geçiciyi ikinciye kopyala.
  • main.c: Genel takas işleminizin farklı veri türleriyle çalıştığını gösterin. Bir tür göstergesi (tam sayılar için i, double değerler için d) ve ardından iki değer okuyun. Uygun türde iki değişken oluşturun, bunları generic_swap fonksiyonunuzu kullanarak takas edin ve takas işleminden sonra her iki değeri de yazdırın.

Programınız üç girdi alacaktır:

  1. Bir tür göstergesi: tam sayı için i veya double için d
  2. İlk değer
  3. İkinci değer

Takas işleminden sonra, her iki değeri de ayrı satırlara yazdırın. Double değerler için 2 ondalık basamak kullanın.

Girdiler i, 5 ve 10 olduğunda örnek çıktı:

10
5

Girdiler d, 3.14 ve 2.71 olduğunda örnek çıktı:

2.71
3.14

Girdiler i, -7 ve 42 olduğunda örnek çıktı:

42
-7

Girdiler d, 99.99 ve 0.01 olduğunda örnek çıktı:

0.01
99.99

Bu yaklaşımın güzelliği, generic_swap fonksiyonunuzun hangi türleri takas ettiğine dair hiçbir fikrinin olmamasıdır; o sadece baytları taşır. Aynı fonksiyon tam sayılar, double değerler, struct'lar veya diğer herhangi bir veri türü için çalışır. memcpy için <string.h> ve size_t için <stddef.h> veya <stdlib.h> kütüphanelerini eklemeniz gerekecektir.

Kopya kağıdı

Genel bir takas (swap) fonksiyonu, gerçek türü bilmeden baytları taşıyarak herhangi bir türdeki değerleri takas etmek için void* işaretçilerini ve memcpy fonksiyonunu kullanır.

Fonksiyon imzası:

void generic_swap(void* a, void* b, size_t size);

Geçici bir tampon (buffer) ve memcpy kullanarak uygulama:

void generic_swap(void* a, void* b, size_t size) {
    char temp[size];      // geçici tampon
    memcpy(temp, a, size);  // temp = a
    memcpy(a, b, size);     // a = b
    memcpy(b, temp, size);  // b = temp
}

Farklı türlerle kullanım:

int x = 5, y = 10;
generic_swap(&x, &y, sizeof(int));
// x artık 10, y artık 5

double p = 3.14, q = 2.71;
generic_swap(&p, &q, sizeof(double));
// p artık 2.71, q artık 3.14

Gerekli başlık dosyaları: memcpy için <string.h> ve size_t için <stddef.h> veya <stdlib.h>.

Kendin dene

#include <stdio.h>
#include "swap.h"

int main() {
    char type;
    scanf("%c", &type);
    
    if (type == 'i') {
        int a, b;
        scanf("%d", &a);
        scanf("%d", &b);
        
        // TODO: a ve b değerlerini takas etmek için generic_swap fonksiyonunu çağırın
        // Hint: &a, &b ve sizeof(int) kullanın
        
        printf("%d\n", a);
        printf("%d\n", b);
    } else if (type == 'd') {
        double a, b;
        scanf("%lf", &a);
        scanf("%lf", &b);
        
        // TODO: a ve b değerlerini takas etmek için generic_swap fonksiyonunu çağırın
        // Hint: &a, &b ve sizeof(double) kullanın
        
        printf("%.2f\n", a);
        printf("%.2f\n", b);
    }
    
    return 0;
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Object Oriented Programming bölümündeki tüm dersler