Pembungkus Generik
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan C di Coddy. Pelajaran 50 dari 61.
void* saja dapat menyimpan data apa pun, tetapi memiliki kekurangan kritis: kamu kehilangan jejak tipe data yang disimpannya. Untuk membuat container generik yang benar-benar berguna, kita perlu memasangkan pointer data dengan informasi tipe. Di sinilah pola Generic Wrapper berperan.
Idenya sederhana: buat struct yang menggabungkan void* dengan enum yang mengidentifikasi tipe yang disimpan. Dengan cara ini, wrapper selalu tahu cara menafsirkan isinya.
typedef enum {
TYPE_INT,
TYPE_STRING
} DataType;
typedef struct {
void* data;
DataType type;
} Wrapper;Saat menyimpan data, kamu mengalokasikan memori untuk nilai sebenarnya dan mencatat tipenya. Saat mengambilnya, kamu memeriksa tipe sebelum melakukan casting:
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);
}
}Pola ini menjadi dasar untuk membangun container generik yang aman terhadap tipe di C. Enum berfungsi sebagai penanda tipe saat runtime, sehingga kodemu dapat menentukan cara menangani data yang disimpan dengan aman.
Tantangan
MudahMari buat sistem wrapper generik yang aman terhadap tipe dan dapat menyimpan integer atau string, sambil melacak tipe yang disimpan agar kita dapat mengambil dan mencetak data dengan aman nanti.
Kamu akan mengatur kodemu dalam tiga file:
wrapper.h: Definisikan enumDataTypedengan nilaiTYPE_INTdanTYPE_STRING. Lalu, definisikan structWrapperyang menggabungkan pointer datavoid*dengan fieldDataType. Deklarasikan prototipe fungsi untuk membuat wrapper dan mencetak isinya.wrapper.c: Implementasikan fungsionalitas wrapper:wrap_int: menerima integer, mengalokasikan memori untuknya, menyimpan nilainya, dan mengembalikan Wrapper dengan penanda tipe yang sesuaiwrap_string: menerima string (char*), mengalokasikan memori dan menyalin string tersebut, lalu mengembalikan Wrapper dengan penanda tipe stringprint_wrapper: memeriksa penanda tipe dan mencetak data yang sesuai (integer apa adanya, string apa adanya)free_wrapper: membebaskan data yang dialokasikan secara dinamis di dalam wrapper
main.c: Gabungkan semuanya. Baca indikator tipe (iuntuk integer,suntuk string), lalu nilainya. Buat wrapper yang sesuai, cetak isinya, dan bebaskan memorinya.
Programmu akan menerima dua input:
- Indikator tipe:
iuntuk integer atausuntuk string - Nilai yang akan dibungkus
Contoh output saat inputnya adalah i dan 42:
42Contoh output saat inputnya adalah s dan Hello:
HelloContoh output saat inputnya adalah i dan -100:
-100Contoh output saat inputnya adalah s dan Generic Programming:
Generic ProgrammingIngat untuk menggunakan include guard di file header-mu. Untuk menyalin string, alokasikan ruang yang cukup untuk string beserta terminator null menggunakan strlen dan strcpy.
Coba sendiri
#include <stdio.h>
#include <string.h>
#include "wrapper.h"
int main() {
char type;
scanf("%c", &type);
getchar(); // konsumsi karakter baris baru
Wrapper w;
if (type == 'i') {
int value;
scanf("%d", &value);
// TODO: Buat pembungkus bilangan bulat menggunakan wrap_int
} else if (type == 's') {
char str[256];
fgets(str, sizeof(str), stdin);
// Hapus karakter baris baru di akhir jika ada
str[strcspn(str, "\n")] = '\0';
// TODO: Buat pembungkus string menggunakan wrap_string
}
// TODO: Cetak isi pembungkus menggunakan print_wrapper
// TODO: Bebaskan memori pembungkus menggunakan free_wrapper
return 0;
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar Pemrograman Modular
file headerProteksi includefile sumberFungsi StatisRingkasan: Kalkulator Modular4Enkapsulasi
Konsep Opaque PointerMendefinisikan Opaque StructGetter dan SetterValidasi pada SetterUlasan: Kotak Rahasia7Pointer Fungsi
Mendeklarasikan Pointer FungsiMemanggil Pointer FungsiTypedef untuk Pointer FungsiMengirim Fungsi sebagai ArgumenRangkuman: Dispatch Kalkulator10Wadah Generik
Tinjauan Ulang Pointer VoidPembungkus GenerikPertukaran GenerikPerbandingan GenerikTinjauan Ulang: Generic array2Object dan method
Struct sebagai objectPointer 'self'Konsistensi constPointer vs nilaiMethod pembantuRangkuman: Pengelola Point5Proyek: Akun Bank Sederhana
Penyiapan ProyekImplementasi Akun3Siklus Hidup object
Pola KonstruktorPola DestruktorInisialisasi StackSalinan MendalamRangkuman: Pembungkus string6Pewarisan melalui Komposisi
Penyematan StructAturan Anggota PertamaMengakses Anggota ParentUpcastingRekap: Hierarki Bentuk9Proyek: Penggambar Bentuk
Ringkasan ProyekImplementasi LingkaranImplementasi Persegi PanjangPenggunaan PolimorfismeWadah BentukLatihan sendiri: Compiler C online