Langsung ke konten
Belajar C

C++: Program Penjualan Susu Kaleng — Panduan Lengkap dari Dasar hingga OOP

Foto TaufiqOleh Taufiq
C++: Program Penjualan Susu Kaleng

Program penjualan susu kaleng adalah latihan klasik dalam pembelajaran pemrograman C++ yang menguji pemahaman tentang input/output, percabangan logika (switch-case), manipulasi data dengan struct atau class, serta formatting output. Pada tutorial ini, kita akan membangun program tersebut secara bertahap — mulai dari analisis kebutuhan hingga implementasi berbasis Object-Oriented Programming (OOP).

Analisis Kebutuhan Program

Sebelum menulis kode, kita harus memahami persyaratan bisnis program ini secara detail.

Data Input

  • Kode Jenis Susu — input karakter (A, B, atau C) yang merepresentasikan merek susu:
    • Kode A = Dancow
    • Kode B = Bendera
    • Kode C = SGM
  • Kode Ukuran Kaleng — input integer (1, 2, atau 3) yang merepresentasikan ukuran:
    • Kode 1 = Kecil
    • Kode 2 = Sedang
    • Kode 3 = Besar
  • Jumlah Beli — input integer yang merepresentasikan jumlah kaleng yang dibeli.

Tabel Harga (Harga Per Kaleng)

Jenis SusuKecil (1)Sedang (2)Besar (3)
Dancow (A)Rp 25.000Rp 20.000Rp 15.000
Bendera (B)Rp 20.000Rp 17.500Rp 13.500
SGM (C)Rp 22.000Rp 18.500Rp 15.000

Rumus Perhitungan

Total Pembayaran = Harga Satuan × Jumlah Beli. Harga satuan ditentukan berdasarkan kombinasi kode jenis susu dan kode ukuran kaleng.

Implementasi Dasar dengan switch-case

Mari kita mulai dengan implementasi prosedural yang paling sederhana:

CSS Snippet CSS
#include <iostream>
#include <iomanip>
using namespace std;

int main() {
 // === Deklarasi Variabel ===
 char kodeJenis; // Kode jenis susu: A, B, atau C
 char kodeUkuran; // Kode ukuran kaleng: 1, 2, atau 3
 int jumlahBeli; // Jumlah kaleng yang dibeli
 int hargaSatuan; // Harga per kaleng berdasarkan jenis & ukuran
 int totalBayar; // Total pembayaran
 string namaJenis; // Nama jenis susu untuk tampilan
 string namaUkuran; // Nama ukuran kaleng untuk tampilan

 // === Input Data ===
 cout << "========================================" << endl;
 cout << " PROGRAM PENJUALAN SUSU KALENG" << endl;
 cout << "========================================" << endl;
 cout << endl;

 // Tampilkan menu jenis susu
 cout << "Kode Jenis Susu:" << endl;
 cout << " A = Dancow" << endl;
 cout << " B = Bendera" << endl;
 cout << " C = SGM" << endl;
 cout << "Masukkan kode jenis susu (A/B/C): ";
 cin >> kodeJenis;

 // Konversi ke huruf besar untuk fleksibilitas input
 kodeJenis = toupper(kodeJenis);

 // Tampilkan menu ukuran kaleng
 cout << endl;
 cout << "Kode Ukuran Kaleng:" << endl;
 cout << " 1 = Kecil" << endl;
 cout << " 2 = Sedang" << endl;
 cout << " 3 = Besar" << endl;
 cout << "Masukkan kode ukuran (1/2/3): ";
 cin >> kodeUkuran;

 // Input jumlah beli
 cout << "Masukkan jumlah beli: ";
 cin >> jumlahBeli;

 // === Validasi Input ===
 if (jumlahBeli <= 0) {
 cout << "\nError: Jumlah beli harus lebih dari 0!" << endl;
 return 1;
 }

 // === Menentukan Harga Satuan ===
 bool inputValid = true;

 switch (kodeJenis) {
 case 'A': // Dancow
 namaJenis = "Dancow";
 switch (kodeUkuran) {
 case '1': hargaSatuan = 25000; namaUkuran = "Kecil"; break;
 case '2': hargaSatuan = 20000; namaUkuran = "Sedang"; break;
 case '3': hargaSatuan = 15000; namaUkuran = "Besar"; break;
 default: inputValid = false; break;
 }
 break;
 case 'B': // Bendera
 namaJenis = "Bendera";
 switch (kodeUkuran) {
 case '1': hargaSatuan = 20000; namaUkuran = "Kecil"; break;
 case '2': hargaSatuan = 17500; namaUkuran = "Sedang"; break;
 case '3': hargaSatuan = 13500; namaUkuran = "Besar"; break;
 default: inputValid = false; break;
 }
 break;
 case 'C': // SGM
 namaJenis = "SGM";
 switch (kodeUkuran) {
 case '1': hargaSatuan = 22000; namaUkuran = "Kecil"; break;
 case '2': hargaSatuan = 18500; namaUkuran = "Sedang"; break;
 case '3': hargaSatuan = 15000; namaUkuran = "Besar"; break;
 default: inputValid = false; break;
 }
 break;
 default:
 inputValid = false;
 break;
 }

 // Cek validitas input
 if (!inputValid) {
 cout << "\nError: Kode jenis susu atau ukuran tidak valid!" << endl;
 return 1;
 }

 // === Hitung Total ===
 totalBayar = hargaSatuan * jumlahBeli;

 // === Tampilkan Hasil ===
 cout << endl;
 cout << "========================================" << endl;
 cout << " STRUK PEMBELIAN" << endl;
 cout << "========================================" << endl;
 cout << left << setw(20) << "Jenis Susu" << ": " << namaJenis << endl;
 cout << left << setw(20) << "Ukuran Kaleng" << ": " << namaUkuran << endl;
 cout << left << setw(20) << "Harga Satuan" << ": Rp "
 << right << setfill('.') << setw(10) << setprecision(0)
 << fixed << hargaSatuan << setfill(' ') << endl;
 cout << left << setw(20) << "Jumlah Beli" << ": "
 << jumlahBeli << " kaleng" << endl;
 cout << "----------------------------------------" << endl;
 cout << left << setw(20) << "TOTAL BAYAR" << ": Rp "
 << right << setfill('.') << setw(10) << setprecision(0)
 << fixed << totalBayar << setfill(' ') << endl;
 cout << "========================================" << endl;

 return 0;
}

Penjelasan Kode Baris per Baris

1. Header dan Namespace

Block Code Snippet Code
#include <iostream> // Untuk cin dan cout (input/output stream)
#include <iomanip> // Untuk setw, setprecision, setfill, left, right, fixed
using namespace std; // Agar tidak perlu menulis std:: di depan cin/cout

<iostream> menyediakan objek cin untuk input dan cout untuk output. <iomanip> (iomanipulation) menyediakan manipulator untuk formatting output seperti setw (set width), setprecision (presisi angka), dan setfill (character pengisi).

2. Deklarasi Variabel

Block Code Snippet Code
char kodeJenis; // char because input is a single character (A/B/C)
char kodeUkuran; // char because input is '1', '2', or '3' as character
int jumlahBeli; // int because quantity is always a whole number
int hargaSatuan; // int to store the price per can
int totalBayar; // int for the final total
string namaJenis; // string for display name of milk brand
string namaUkuran; // string for display name of can size

Penggunaan char untuk kode jenis dan ukuran karena kita menerima satu karakter dari keyboard. string digunakan untuk menyimpan nama yang akan ditampilkan di struk.

3. Konversi Input dengan toupper()

Block Code Snippet Code
kodeJenis = toupper(kodeJenis);

Fungsi toupper() dari header <cctype> mengkonversi karakter lowercase ke uppercase. Ini memungkinkan pengguna memasukkan ‘a’, ‘b’, atau ‘c’ (huruf kecil) dan tetap diterima sebagai kode yang valid. Tanpa konversi ini, input ‘a’ akan ditolak karena switch-case hanya menangani ‘A’, ‘B’, dan ‘C’.

4. Nested switch-case

Struktur switch bersarang (nested) digunakan untuk menentukan harga berdasarkan dua parameter: kode jenis dan kode ukuran. Switch luar menangani jenis susu, switch inner menangani ukuran kaleng. Pendekatan ini jelas dan mudah dipahami, meskipun untuk tabel harga yang lebih besar, pendekatan 2D array akan lebih efisien.

5. Formatting Output dengan iomanip

Block Code Snippet Code
cout << left << setw(20) << "Jenis Susu" << ": " << namaJenis;
// setw(20) = set field width to 20 characters
// left = align text to the left within the 20-char field
// hasil = "Jenis Susu : Dancow"

Manipulator setw menentukan lebar minimum field. left membuat teks rata kiri dalam field tersebut. Kombinasi ini menghasilkan tampilan struk yang rapi dan profesional.

Implementasi Lanjutan dengan Array 2D

Menggunakan nested switch-case untuk tabel harga bisa menjadi verbose. Alternatif yang lebih elegan adalah menggunakan array 2D:

CSS Snippet CSS
#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>
using namespace std;

int main() {
 // Array 2D untuk harga: [jenis][ukuran]
 // Index 0=Dancow, 1=Bendera, 2=SGM
 // Index 0=Kecil, 1=Sedang, 2=Besar
 int harga[3][3] = {
 {25000, 20000, 15000}, // Dancow
 {20000, 17500, 13500}, // Bendera
 {22000, 18500, 15000} // SGM
 };
 string namaJenis[] = {"Dancow", "Bendera", "SGM"};
 string namaUkuran[] = {"Kecil", "Sedang", "Besar"};

 char kodeJenis, kodeUkuran;
 int jumlahBeli;

 //... (bagian input sama seperti implementasi sebelumnya)

 // Mapping kode ke index array
 int idxJenis = -1;
 switch (toupper(kodeJenis)) {
 case 'A': idxJenis = 0; break;
 case 'B': idxJenis = 1; break;
 case 'C': idxJenis = 2; break;
 default: break;
 }

 int idxUkuran = -1;
 switch (kodeUkuran) {
 case '1': idxUkuran = 0; break;
 case '2': idxUkuran = 1; break;
 case '3': idxUkuran = 2; break;
 default: break;
 }

 // Validasi
 if (idxJenis == -1 || idxUkuran == -1 || jumlahBeli <= 0) {
 cout << "Error: Input tidak valid!" << endl;
 return 1;
 }

 // Akses harga dari array — jauh lebih bersih!
 int hargaSatuan = harga[idxJenis][idxUkuran];
 int totalBayar = hargaSatuan * jumlahBeli;

 // Tampilkan hasil...
 return 0;
}

Pendekatan array 2D jauh lebih bersih dan mudah dimaintain. Jika harga berubah, Anda hanya perlu memodifikasi satu baris array — bukan mengubah seluruh nested switch-case. Ini juga memudahkan penambahan jenis susu atau ukuran baru di masa depan.

Implementasi Berbasis OOP (Class)

Untuk proyek yang lebih besar dan real-world, pendekatan Object-Oriented Programming (OOP) memberikan struktur yang lebih baik:

CSS Snippet CSS
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <cctype>
using namespace std;

// === Class Produk Susu ===
// Mengenkapsulasi data produk: nama, ukuran, dan harga
class ProdukSusu {
private:
 string nama;
 string ukuran;
 int harga;

public:
 // Constructor — dipanggil saat objek dibuat
 ProdukSusu(string n, string u, int h)
 : nama(n), ukuran(u), harga(h) {}

 // Getter methods — mengakses data privat
 string getNama() const { return nama; }
 string getUkuran() const { return ukuran; }
 int getHarga() const { return harga; }
};

// === Class Transaksi ===
// Mengelola satu transaksi pembelian
class Transaksi {
private:
 ProdukSusu produk;
 int jumlah;

public:
 Transaksi(const ProdukSusu& p, int j)
 : produk(p), jumlah(j) {}

 // Menghitung total pembayaran
 int hitungTotal() const {
 return produk.getHarga() * jumlah;
 }

 // Menampilkan struk pembelian
 void tampilkanStruk() const {
 cout << fixed << setprecision(0);
 cout << "========================================" << endl;
 cout << " STRUK PEMBELIAN" << endl;
 cout << "========================================" << endl;
 cout << left << setw(22) << " Jenis Susu"
 << ": " << produk.getNama() << endl;
 cout << left << setw(22) << " Ukuran Kaleng"
 << ": " << produk.getUkuran() << endl;
 cout << left << setw(22) << " Harga Satuan"
 << ": Rp " << right << setw(10)
 << produk.getHarga() << endl;
 cout << left << setw(22) << " Jumlah Beli"
 << ": " << jumlah << " kaleng" << endl;
 cout << " ----------------------------------------" << endl;
 cout << left << setw(22) << " TOTAL BAYAR"
 << ": Rp " << right << setw(10)
 << hitungTotal() << endl;
 cout << "========================================" << endl;
 }
};

// === Class KatalogSusu ===
// Mengelola daftar produk yang tersedia
class KatalogSusu {
private:
 vector<ProdukSusu> daftarProduk;

public:
 void tambahProduk(const ProdukSusu& produk) {
 daftarProduk.push_back(produk);
 }

 const ProdukSusu* cariProduk(char kodeJenis, char kodeUkuran) const {
 string targetJenis;
 switch (toupper(kodeJenis)) {
 case 'A': targetJenis = "Dancow"; break;
 case 'B': targetJenis = "Bendera"; break;
 case 'C': targetJenis = "SGM"; break;
 default: return nullptr;
 }

 string targetUkuran;
 switch (kodeUkuran) {
 case '1': targetUkuran = "Kecil"; break;
 case '2': targetUkuran = "Sedang"; break;
 case '3': targetUkuran = "Besar"; break;
 default: return nullptr;
 }

 for (const auto& produk : daftarProduk) {
 if (produk.getNama() == targetJenis &&
 produk.getUkuran() == targetUkuran) {
 return &produk;
 }
 }
 return nullptr;
 }
};

int main() {
 // Inisialisasi Katalog
 KatalogSusu katalog;
 katalog.tambahProduk(ProdukSusu("Dancow", "Kecil", 25000));
 katalog.tambahProduk(ProdukSusu("Dancow", "Sedang", 20000));
 katalog.tambahProduk(ProdukSusu("Dancow", "Besar", 15000));
 katalog.tambahProduk(ProdukSusu("Bendera", "Kecil", 20000));
 katalog.tambahProduk(ProdukSusu("Bendera", "Sedang", 17500));
 katalog.tambahProduk(ProdukSusu("Bendera", "Besar", 13500));
 katalog.tambahProduk(ProdukSusu("SGM", "Kecil", 22000));
 katalog.tambahProduk(ProdukSusu("SGM", "Sedang", 18500));
 katalog.tambahProduk(ProdukSusu("SGM", "Besar", 15000));

 // Input dari User
 char kodeJenis, kodeUkuran;
 int jumlahBeli;

 cout << "========================================" << endl;
 cout << " PROGRAM PENJUALAN SUSU KALENG" << endl;
 cout << "========================================" << endl;

 cout << "\nKode Jenis Susu: A=Dancow, B=Bendera, C=SGM" << endl;
 cout << "Masukkan kode jenis susu: ";
 cin >> kodeJenis;

 cout << "\nKode Ukuran: 1=Kecil, 2=Sedang, 3=Besar" << endl;
 cout << "Masukkan kode ukuran: ";
 cin >> kodeUkuran;

 cout << "Masukkan jumlah beli: ";
 cin >> jumlahBeli;

 // Validasi
 if (jumlahBeli <= 0) {
 cout << "Error: Jumlah beli harus lebih dari 0!" << endl;
 return 1;
 }

 // Cari Produk dan Buat Transaksi
 const ProdukSusu* produk = katalog.cariProduk(kodeJenis, kodeUkuran);
 if (produk == nullptr) {
 cout << "Error: Kode jenis atau ukuran tidak valid!" << endl;
 return 1;
 }

 Transaksi transaksi(*produk, jumlahBeli);
 transaksi.tampilkanStruk();

 return 0;
}

Keunggulan Pendekatan OOP

  • Enkapsulasi — data produk tersembunyi di dalam class (private), hanya dapat diakses melalui getter methods. Ini melindungi integritas data.
  • Modularity — setiap class memiliki tanggung jawab masing-masing: ProdukSusu untuk data produk, Transaksi untuk logika transaksi, KatalogSusu untuk pencarian produk.
  • Reusability — class-class ini dapat digunakan kembali dalam proyek lain, misalnya sistem POS toko kelontong.
  • Maintainability — menambah produk baru cukup memanggil tambahProduk(), tanpa mengubah logika pencarian atau transaksi.

Membandingkan Procedural vs OOP

AspekProcedural (switch-case)OOP (class)
Kerumitan KodeSederhana, langsungLebih banyak class & method
MaintainabilitySulit jika harga berubahMudah — ubah di satu tempat
EkstensibilitasPerlu tambah case baruCukup tambah objek ProdukSusu
EnkapsulasiTidak adaData terproteksi dalam class
Ukuran ProgramLebih kecilLebih besar tapi terstruktur
Cocok untukProgram kecil & tugas kuliahProyek nyata & skala besar

Panduan Kompilasi

Simpan kode dalam file berekstensi .cpp (misalnya susu.cpp), kemudian kompilasi menggunakan compiler C++.

Menggunakan g++ (GCC)

Block Code Snippet Code
# Kompilasi dasar
g++ -o program_susu susu.cpp

# Kompilasi dengan standar C++17
g++ -std=c++17 -o program_susu susu.cpp

# Kompilasi dengan warning level tinggi (sangat direkomendasikan!)
g++ -Wall -Wextra -std=c++17 -o program_susu susu.cpp

# Jalankan program./program_susu

-Wall -Wextra mengaktifkan semua peringatan compiler, yang sangat membantu dalam mendeteksi potensi bug. Referensi: cppreference.com — Compilation and execution.

Menggunakan clang++

Block Code Snippet Code
# Kompilasi dengan clang++
clang++ -std=c++17 -o program_susu susu.cpp

# Jalankan./program_susu

clang++ sering menghasilkan pesan error yang lebih informatif dibandingkan g++, sehingga sangat membantu saat debugging. Keduanya menghasilkan binary yang setara secara fungsional.

Tips Tambahan dan Best Practices

  • Validasi input selalu dilakukan — jangan asumsikan user selalu memasukkan data yang benar. Periksa apakah kode jenis dan ukuran valid sebelum diproses.
  • Gunakan konstanta untuk harga — dalam proyek nyata, harga seharusnya tidak hard-coded di dalam switch-case. Pertimbangkan menggunakan array atau database.
  • Gunakan enum untuk kode — enum class lebih type-safe dibandingkan char atau int untuk kode jenis/ukuran.
  • Format output dengan iomanip — gunakan setw, left, right, dan fixed untuk membuat struk yang rapi dan profesional.
  • Pisahkan logika dari presentasi — hitung total di fungsi terpisah, tampilkan struk di fungsi terpisah. Ini memudahkan testing dan modifikasi.

Kesimpulan

Program penjualan susu kaleng adalah latihan yang excellent untuk memahami konsep dasar C++: input/output, switch-case, array, string, dan formatting. Untuk implementasi yang lebih scalable dan maintainable, gunakan pendekatan OOP dengan class yang terstruktur. Kunci utama adalah memvalidasi input pengguna, mengorganisasi data secara efisien, dan menampilkan output yang rapi dengan <iomanip>.

Untuk referensi lebih lanjut tentang fitur-fitur C++ yang digunakan dalam tutorial ini, kunjungi cppreference.com — sumber referensi C++ paling lengkap dan terpercaya.

Hal yang sering ditanyakan seputar C++: Program Penjualan Susu Kaleng — Panduan Lengkap dari Dasar hingga OOP

Apa itu program penjualan susu kaleng dalam C++?

Program ini adalah latihan dasar untuk memahami input/output, percabangan logika, dan manipulasi data dalam C++. Program menghitung total pembayaran berdasarkan jenis susu, ukuran kaleng, dan jumlah beli yang diinput pengguna.

Bagaimana cara menentukan harga satuan dalam program penjualan susu kaleng?

Harga satuan ditentukan oleh kombinasi kode jenis susu (A, B, atau C) dan kode ukuran kaleng (1, 2, atau 3) sesuai tabel harga yang diberikan. Program menggunakan switch-case atau struktur OOP untuk mengambil harga yang sesuai.

Apa keuntungan menggunakan OOP dibandingkan switch-case dalam program ini?

OOP memungkinkan pengorganisasian kode ke dalam kelas dan objek, sehingga program lebih modular dan mudah dipelihara. Dalam konteks ini, OOP dapat mengelola data produk dan perhitungan dengan cara yang lebih terstruktur dan ekstensible.

Bagaimana cara menghitung total pembayaran dalam program?

Total pembayaran dihitung dengan mengalikan harga satuan dengan jumlah beli. Harga satuan diperoleh berdasarkan jenis dan ukuran susu dari tabel harga yang telah ditetapkan.

Komentar

Memuat komentar…

Tinggalkan Komentar

Alamat email Anda tidak akan dipublikasikan.