
- 1Analisis Kebutuhan Program
- 1.1Data Input
- 1.2Tabel Harga (Harga Per Kaleng)
- 1.3Rumus Perhitungan
- 2Implementasi Dasar dengan switch-case
- 3Penjelasan Kode Baris per Baris
- 3.11. Header dan Namespace
- 3.22. Deklarasi Variabel
- 3.33. Konversi Input dengan toupper()
- 3.44. Nested switch-case
- 3.55. Formatting Output dengan iomanip
- 4Implementasi Lanjutan dengan Array 2D
- 5Implementasi Berbasis OOP (Class)
- 5.1Keunggulan Pendekatan OOP
- 6Membandingkan Procedural vs OOP
- 7Panduan Kompilasi
- 7.1Menggunakan g++ (GCC)
- 7.2Menggunakan clang++
- 8Tips Tambahan dan Best Practices
- 9Kesimpulan
- 10Hal yang sering ditanyakan seputar C++: Program Penjualan Susu Kaleng — Panduan Lengkap dari Dasar hingga OOP
- 10.1Apa itu program penjualan susu kaleng dalam C++?
- 10.2Bagaimana cara menentukan harga satuan dalam program penjualan susu kaleng?
- 10.3Apa keuntungan menggunakan OOP dibandingkan switch-case dalam program ini?
- 10.4Bagaimana cara menghitung total pembayaran dalam program?
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, atauC) yang merepresentasikan merek susu:- Kode
A= Dancow - Kode
B= Bendera - Kode
C= SGM
- Kode
- Kode Ukuran Kaleng — input integer (
1,2, atau3) yang merepresentasikan ukuran:- Kode
1= Kecil - Kode
2= Sedang - Kode
3= Besar
- Kode
- Jumlah Beli — input integer yang merepresentasikan jumlah kaleng yang dibeli.
Tabel Harga (Harga Per Kaleng)
| Jenis Susu | Kecil (1) | Sedang (2) | Besar (3) |
|---|---|---|---|
| Dancow (A) | Rp 25.000 | Rp 20.000 | Rp 15.000 |
| Bendera (B) | Rp 20.000 | Rp 17.500 | Rp 13.500 |
| SGM (C) | Rp 22.000 | Rp 18.500 | Rp 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:
#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
#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
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()
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
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:
#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:
#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:
ProdukSusuuntuk data produk,Transaksiuntuk logika transaksi,KatalogSusuuntuk 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
| Aspek | Procedural (switch-case) | OOP (class) |
|---|---|---|
| Kerumitan Kode | Sederhana, langsung | Lebih banyak class & method |
| Maintainability | Sulit jika harga berubah | Mudah — ubah di satu tempat |
| Ekstensibilitas | Perlu tambah case baru | Cukup tambah objek ProdukSusu |
| Enkapsulasi | Tidak ada | Data terproteksi dalam class |
| Ukuran Program | Lebih kecil | Lebih besar tapi terstruktur |
| Cocok untuk | Program kecil & tugas kuliah | Proyek nyata & skala besar |
Panduan Kompilasi
Simpan kode dalam file berekstensi .cpp (misalnya susu.cpp), kemudian kompilasi menggunakan compiler C++.
Menggunakan g++ (GCC)
# 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++
# 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 classlebih type-safe dibandingkan char atau int untuk kode jenis/ukuran. - Format output dengan iomanip — gunakan
setw,left,right, danfixeduntuk 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.
Memuat komentar…