Jenerik Sarmalayıcı
Coddy'nin C Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 50 / 61.
Tek başına bir void* herhangi bir veriyi saklayabilir, ancak kritik bir kusuru vardır: hangi türü tuttuğunu takip edemezsiniz. Gerçekten kullanışlı genel amaçlı kapsayıcılar oluşturmak için veri işaretçisini tür bilgileriyle eşleştirmemiz gerekir. İşte Genel Kapsayıcı deseni burada devreye girer.
Fikir basit: bir void* ile depolanan türü tanımlayan bir enum'u bir araya getiren bir struct oluşturun. Bu şekilde sarmalayıcı, içeriğini nasıl yorumlayacağını her zaman bilir.
typedef enum {
TYPE_INT,
TYPE_STRING
} DataType;
typedef struct {
void* data;
DataType type;
} Wrapper;Verileri depolarken gerçek değer için bellek ayırır ve türünü kaydedersiniz. Geri alırken dönüştürmeden önce türü kontrol edersiniz:
Wrapper wrap_int(int value) {
int* p = malloc(sizeof(int));
*p = value;
return (Wrapper){ .data = p, .type = TYPE_INT };
}
void print_wrapper(Wrapper* w) {
if (w->type == TYPE_INT) {
printf("%d\n", *(int*)w->data);
} else if (w->type == TYPE_STRING) {
printf("%s\n", (char*)w->data);
}
}Bu kalıp, C dilinde tür güvenli genel kapsayıcılar oluşturmanın temelini oluşturur. enum, çalışma zamanında tür etiketi görevi görerek kodunuzun depolanan verilerin nasıl işleneceği konusunda güvenli kararlar almasını sağlar.
Görev
KolayDaha sonra verileri güvenli bir şekilde alıp yazdırabilmek için, bir tamsayıyı veya bir dizeyi depolayabilen ve hangi türü tuttuğunu izleyen, tür güvenli bir genel sarmalayıcı sistemi oluşturalım.
kodunuzu üç dosya arasında düzenleyeceksiniz:
wrapper.h:DataTypeveTYPE_INTdeğerlerine sahip birTYPE_STRINGenum'u tanımlayın. Ardından birWrapperveri işaretçisini ve birvoid*alanını bir araya getiren birDataTypestruct'ı tanımlayın. Sarmalayıcıları oluşturmak ve içeriklerini yazdırmak için işlev prototiplerini bildirin.wrapper.c: Sarmalayıcı işlevselliğini uygulayın:wrap_int: bir tamsayı alır, bunun için bellek ayırır, değeri depolar ve uygun tür etiketiyle bir Wrapper döndürürwrap_string: bir dize (char*) alır, bellek ayırır ve dizeyi kopyalar, ardından dize türü etiketiyle bir Wrapper döndürürprint_wrapper: tür etiketini kontrol eder ve verileri uygun şekilde yazdırır (tamsayı olduğu gibi, dize olduğu gibi)free_wrapper: sarmalayıcının içindeki dinamik olarak ayrılmış veriyi serbest bırakır
main.c: Hepsini bir araya getirin. Bir değerin ardından bir tür göstergesi (itamsayı için,sdize için) okuyun. Uygun sarmalayıcıyı oluşturun, içeriğini yazdırın ve belleği serbest bırakın.
Programınız iki girdi alacaktır:
- Bir tür göstergesi: tamsayı için
iveya dize içins - Sarmalanacak değer
Girdiler i ve 42 olduğunda örnek çıktı:
42Girdiler s ve Hello olduğunda örnek çıktı:
HelloGirdiler i ve -100 olduğunda örnek çıktı:
-100Girdiler s ve Generic Programming olduğunda örnek çıktı:
Generic ProgrammingBaşlık dosyanızda include guard'ları kullanmayı unutmayın. Dize kopyalama işlemi için strlen ve strcpy kullanarak dize ve null sonlandırıcı için yeterli alan ayırın.
Kendin dene
#include <stdio.h>
#include <string.h>
#include "wrapper.h"
int main() {
char type;
scanf("%c", &type);
getchar(); // yeni satırı tüket
Wrapper w;
if (type == 'i') {
int value;
scanf("%d", &value);
// TODO: wrap_int kullanarak bir tamsayı sarmalayıcı oluştur
} else if (type == 's') {
char str[256];
fgets(str, sizeof(str), stdin);
// Varsa sondaki yeni satırı kaldır
str[strcspn(str, "\n")] = '\0';
// TODO: wrap_string kullanarak bir dize sarmalayıcı oluştur
}
// TODO: print_wrapper kullanarak sarmalayıcı içeriğini yazdır
// TODO: free_wrapper kullanarak sarmalayıcı belleğini serbest bırak
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