Jenerik Yer Değiştirme
Coddy'nin C Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 51 / 61.
Programlamada yaygın bir işlem, iki değeri takas etmektir. Normalde her tür için ayrı bir takas işlevi yazarsın: int için bir tane, double için başka bir tane ve bu şekilde devam eder. Ancak void* ve memcpy sayesinde, herhangi iki değişkeni takas eden tek bir işlev yazabiliriz.
Temel fikir, takas işleminin yalnızca baytları taşımaktan ibaret olmasıdır. Verilerin boyutunu biliyorsanız, gerçek türü bilmeden baytları kopyalayabilirsiniz. İşlev imzası şu şekilde görünür:
void generic_swap(void* a, void* b, size_t size);size parametresi, fonksiyona kaç byte taşınacağını söyler. İçeride, byte'ları yer değiştirmek için geçici bir arabellek ve <string.h> içindeki memcpy işlevini kullanırız:
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 işlev herhangi bir tür için çalışır:
int x = 5, y = 10;
generic_swap(&x, &y, sizeof(int));
// x artık 10, y artık 5double p = 3.14, q = 2.71;
generic_swap(&p, &q, sizeof(double));
// p artık 2.71, q artık 3.14void* ile size_t kullanan bu yaklaşım, C'nin standart kütüphanesinin qsort ve bsearch gibi genel amaçlı işlevleri uygulama biçimidir.
Görev
KolayTürleri ne olursa olsun herhangi iki değişkenin değerlerini değiştirebilen genel bir takas yardımcı programı oluşturalım: void* işaretçilerinin ve memcpy işlevinin gücünü kullanarak.
Kodunuzu üç dosyaya ayıracaksınız:
swap.h: İkigeneric_swapişaretçisi ve takas edilecek verinin boyutunu belirten birvoid*parametresi alansize_tişlevinizi bildirin. Include guard'ları eklemeyi unutmayın!swap.c:generic_swapişlevini uygulayın. İki bellek konumu arasında baytları taşımak için geçici bir arabellek vememcpykullanın. Üç adımlı takas örüntüsünü hatırlayın: ilk değeri geçici alana kopyalayın, ikinci değeri ilk konuma kopyalayın, geçici değeri ikinci konuma kopyalayın.main.c: Farklı veri türleriyle çalışan genel takasınızı gösterin. İki değerin ardından bir tür belirteci (itamsayılar için,ddouble değerler için) okuyun. Uygun türde iki değişken oluşturun, bunlarıgeneric_swapişlevinizi kullanarak takas edin, ardından takastan sonraki iki değeri yazdırın.
Programınız üç girdi alacaktır:
- Bir tür belirteci: tamsayı için
iveya double içind - İlk değer
- İkinci değer
Takas işleminden sonra her iki değeri ayrı satırlarda yazdırın. Double değerler için 2 ondalık basamak kullanın.
Girdilerin i, 5 ve 10 olduğu durumdaki örnek çıktı:
10
5Girdilerin d, 3.14 ve 2.71 olduğu durumdaki örnek çıktı:
2.71
3.14Girdilerin i, -7 ve 42 olduğu durumdaki örnek çıktı:
42
-7Girdilerin d, 99.99 ve 0.01 olduğu durumdaki örnek çıktı:
0.01
99.99Bu yaklaşımın güzelliği, generic_swap işlevinizin hangi türleri takas ettiğini bilmemesidir. Yalnızca baytları taşır. Aynı işlev tamsayılar, double değerler, yapılar veya başka herhangi bir veri türüyle çalışır. <string.h> için memcpy ve <stddef.h> için <stdlib.h> veya size_t eklemeniz gerekir.
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'yi takas etmek için generic_swap'ı çağır
// İpucu: &a, &b ve sizeof(int) kullan
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'yi takas etmek için generic_swap'ı çağır
// İpucu: &a, &b ve sizeof(double) kullan
printf("%.2f\n", a);
printf("%.2f\n", b);
}
return 0;
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1Modüler Programlama Temelleri
Başlık DosyalarıInclude Guard'larKaynak DosyalarıStatik FonksiyonlarÖzet: Modüler Hesap Makinesi4Kapsülleme
Opaque Pointer KavramıOpaque Struct TanımlamaGetter ve Setter MetotlarıSetter Metotlarında DoğrulamaÖzet: Gizli Kutu7Fonksiyon İşaretçileri
Fonksiyon İşaretçilerini TanımlamaFonksiyon İşaretçilerini ÇağırmaFonksiyon İşaretçileri için TypedefFonksiyonları Argüman Olarak GeçirmeÖzet: Hesap Makinesi Yönlendirme10Jenerik Kapsayıcılar
Void İşaretçiler ÖzetiJenerik SarmalayıcıJenerik Yer DeğiştirmeJenerik KarşılaştırmaÖzet: Jenerik Dizi2Nesneler ve Metotlar
Nesne Olarak Struct'lar'Self' İşaretçisiConst Doğruluğuİşaretçi vs DeğerYardımcı MetotlarÖzet: Point Manager5Proje: Basit Banka Hesabı
Proje KurulumuHesabın Oluşturulması3Nesne Yaşam Döngüsü
Constructor DeseniDestructor DeseniStack İlklendirmeDerin KopyalamaÖzet: String Wrapper6Kompozisyon Yoluyla Kalıtım
Struct Gömmeİlk Üye KuralıÜst Üyelere ErişimUpcastingÖzet: Şekil HiyerarşisiKendi başına pratik yap: Online C derleyicisi