05 November 2026

, ,

Membangun Proyek Pemrograman

PEMROGRAMAN C++ · PROYEK AKHIR PEMBELAJARAN

Membangun Proyek Pemrograman

Dari ide sederhana menjadi program yang dapat digunakan. Pelajari cara merencanakan, merancang, menulis kode, menguji, dan mengembangkan proyek pemrograman menggunakan C++.

Selama mempelajari C++, kita telah mengenal berbagai konsep pemrograman. Kita sudah belajar menggunakan variabel, menerima input, membuat keputusan, mengulang instruksi, mengelola banyak data, menyusun fungsi, memahami pointer, mengenal pemrograman berorientasi objek, hingga mengolah file.

Namun, mempelajari setiap konsep secara terpisah belum tentu membuat kita langsung mampu membangun sebuah program yang utuh.

Bayangkan kamu diminta membuat aplikasi sederhana untuk mengelola data nilai murid di sebuah kelas. Program tersebut harus dapat menerima nama murid, menyimpan nilai, menghitung rata-rata, menentukan nilai tertinggi, dan menyimpan hasilnya agar dapat dibuka kembali.

Apakah kita cukup menulis beberapa baris kode lalu selesai? Tidak sesederhana itu.

Kita perlu menentukan masalah yang ingin diselesaikan, merancang fitur, menyusun alur kerja, memilih cara menyimpan data, menulis kode secara terstruktur, kemudian menguji apakah seluruh fitur berjalan sesuai kebutuhan.

Apa yang akan dipelajari?

Dalam pembahasan ini, kita akan mengikuti proses membangun sebuah proyek pemrograman dari awal hingga selesai. Contoh proyek yang digunakan adalah Program Pengelolaan Nilai Murid berbasis C++.

Proyek ini akan menjadi latihan untuk menggabungkan berbagai konsep yang telah dipelajari sebelumnya.

1. Proyek Pemrograman Dimulai dari Sebuah Masalah

Ketika seseorang ingin membuat program, langkah pertama seharusnya bukan langsung membuka editor kode dan mulai mengetik.

Langkah pertama adalah memahami masalah yang ingin diselesaikan.

Misalnya, seorang guru memiliki banyak data nilai murid. Selama ini, nilai dicatat secara manual di kertas atau spreadsheet. Ketika ingin menghitung rata-rata kelas, mencari nilai tertinggi, atau memeriksa nilai seorang murid, guru harus melakukan beberapa langkah secara berulang.

Dari situ muncul sebuah kebutuhan: bagaimana jika dibuat program sederhana yang dapat membantu mengelola data nilai tersebut?

Identifikasi masalah

Program dibutuhkan untuk membantu pengelolaan nilai murid agar proses pencatatan, perhitungan, pencarian, dan penyimpanan data menjadi lebih mudah.

Perhatikan bahwa kita belum membicarakan bahasa pemrograman, variabel, atau fungsi. Kita baru menentukan masalah yang ingin diselesaikan.

Hal ini penting karena program dibuat untuk memenuhi kebutuhan tertentu. Jika masalahnya belum dipahami, fitur yang dibuat bisa saja tidak sesuai dengan kebutuhan pengguna.

Menentukan tujuan proyek

Setelah masalah ditemukan, kita perlu menentukan tujuan proyek. Tujuan ini menjadi acuan agar proses pengembangan tidak melebar ke mana-mana.

Tujuan proyek pengelolaan nilai

(- ) Membantu pengguna memasukkan data nama dan nilai murid.

(- ) Menampilkan seluruh data yang sudah dimasukkan.

(- ) Menghitung rata-rata nilai.

(- ) Menentukan nilai tertinggi dan terendah.

(- ) Mencari data murid berdasarkan nama.

(- ) Menyimpan data ke dalam file agar tidak hilang ketika program ditutup.

Daftar tersebut sudah memberikan gambaran tentang apa yang harus dapat dilakukan oleh program.

2. Menentukan Fitur dan Batasan Proyek

Setelah mengetahui tujuan proyek, kita perlu menentukan fitur yang akan dibuat.

Fitur adalah kemampuan atau fungsi tertentu yang disediakan oleh program untuk membantu pengguna melakukan suatu pekerjaan.

Misalnya, program pengelolaan nilai memiliki fitur tambah data, tampilkan data, hitung statistik, cari data, dan simpan data.

Namun, ada satu hal yang perlu diperhatikan: proyek pertama tidak harus memiliki semua fitur yang mungkin dibayangkan.

Jika kita langsung mencoba membuat aplikasi yang terlalu besar, proses pengembangannya akan menjadi lebih sulit. Kita dapat menghabiskan banyak waktu untuk fitur tambahan sebelum fitur utamanya benar-benar berjalan.

Menentukan ruang lingkup proyek

Ruang lingkup atau scope adalah batasan mengenai apa saja yang akan dikerjakan dalam sebuah proyek.

Untuk proyek latihan ini, kita membatasi program pada pengelolaan nilai dalam satu kelas menggunakan aplikasi berbasis teks atau console.

Fitur Keterangan Prioritas
Tambah data Memasukkan nama dan nilai murid. Utama
Tampilkan data Menampilkan seluruh data. Utama
Statistik nilai Menghitung rata-rata, tertinggi, dan terendah. Utama
Pencarian Mencari data berdasarkan nama. Utama
Penyimpanan file Menyimpan dan membaca kembali data. Utama
Login pengguna Menggunakan akun untuk mengakses program. Pengembangan
Grafik nilai Menampilkan statistik dalam bentuk grafik. Pengembangan

Dengan pembagian tersebut, kita mengetahui mana fitur yang harus diselesaikan terlebih dahulu dan mana yang dapat dikembangkan setelah program utama berjalan.

Mengapa proyek perlu memiliki batasan?

Tanpa batasan, sebuah proyek dapat terus berkembang karena selalu muncul ide fitur baru.

Akibatnya, program mungkin tidak pernah selesai. Dalam pengembangan perangkat lunak, menyelesaikan versi sederhana yang benar-benar berfungsi sering kali lebih bermanfaat daripada merencanakan aplikasi besar yang tidak pernah selesai dibuat.

Setelah versi awal berjalan dengan baik, fitur baru dapat ditambahkan secara bertahap.

3. Merancang Alur Kerja Program

Setelah fitur ditentukan, kita perlu merancang bagaimana pengguna akan berinteraksi dengan program.

Bayangkan pengguna menjalankan program. Apa yang pertama kali ditampilkan? Bagaimana pengguna memilih fitur? Apa yang terjadi setelah pengguna memasukkan data?

Program yang baik memiliki alur yang jelas sehingga pengguna tidak kebingungan.

Membuat menu utama

Untuk proyek pengelolaan nilai, kita dapat menyediakan menu utama seperti berikut:

Rancangan tampilan menu program
================================
   PROGRAM PENGELOLAAN NILAI
================================
1. Tambah Data Murid
2. Tampilkan Semua Data
3. Hitung Statistik Nilai
4. Cari Data Murid
5. Simpan Data
6. Keluar
================================
Pilih menu: _

Setiap pilihan akan mengarahkan pengguna ke proses yang berbeda.

Misalnya, ketika pengguna memilih menu nomor 1, program meminta nama dan nilai murid. Jika memilih nomor 3, program menghitung statistik dari data yang sudah tersimpan.

Mulai Program
↓
Tampilkan Menu
↓
Pengguna Memilih Menu
↓
Jalankan Fitur Terpilih
↓
Kembali ke Menu?
↓
Selesai jika memilih Keluar

Alur tersebut dapat diterjemahkan menjadi struktur percabangan dan perulangan dalam C++.

4. Menentukan Data yang Dibutuhkan

Selanjutnya, kita perlu menentukan jenis informasi yang akan disimpan oleh program.

Dalam proyek ini, setiap murid memiliki setidaknya dua informasi utama, yaitu nama dan nilai.

Nama merupakan teks, sedangkan nilai merupakan bilangan. Oleh karena itu, kita perlu menentukan tipe data yang sesuai.

Informasi Tipe Data Contoh
Nama murid string "Andi Pratama"
Nilai murid double 85.5

Jika hanya menyimpan satu data, kita dapat menggunakan variabel biasa. Namun, program ini perlu menyimpan banyak murid. Karena itu, kita membutuhkan struktur data yang dapat mengelola sekumpulan informasi.

Menggunakan struct untuk mengelompokkan data

Dalam C++, kita dapat menggunakan struct untuk mengelompokkan beberapa informasi yang saling berkaitan.

Membuat struktur data Murid
struct Murid {
    string nama;
    double nilai;
};

Dengan struktur tersebut, satu objek Murid dapat menyimpan nama dan nilai secara bersamaan.

Untuk menyimpan banyak murid, kita dapat menggunakan vector.

Menggabungkan struct dan vector
#include <iostream>
#include <string>
#include <vector>
using namespace std;

struct Murid {
    string nama;
    double nilai;
};

int main() {
    vector<Murid> daftarMurid;

    return 0;
}

Sekarang kita memiliki tempat untuk menyimpan banyak objek Murid dalam satu kumpulan data.

5. Membagi Program Menjadi Beberapa Fungsi

Ketika program mulai memiliki banyak fitur, menulis seluruh instruksi di dalam fungsi main() akan membuat kode menjadi panjang dan sulit dipahami.

Bayangkan seluruh proses tambah data, pencarian, perhitungan statistik, dan penyimpanan file ditulis dalam satu bagian besar. Ketika terjadi kesalahan, kita harus memeriksa banyak kode untuk menemukan sumber masalahnya.

Untuk menghindari hal tersebut, kita dapat membagi program menjadi beberapa fungsi.

Fungsi dalam proyek pemrograman

Fungsi memungkinkan kita mengelompokkan instruksi berdasarkan tugas tertentu. Setiap fungsi dapat memiliki tanggung jawab yang lebih jelas sehingga program lebih mudah dibaca, diuji, dan dikembangkan.

Contoh pembagian fungsi dalam proyek kita:

Nama Fungsi Tugas
tampilkanMenu() Menampilkan menu utama.
tambahMurid() Memasukkan data murid.
tampilkanMurid() Menampilkan seluruh data.
hitungStatistik() Menghitung rata-rata, tertinggi, dan terendah.
cariMurid() Mencari data berdasarkan nama.
simpanData() Menyimpan data ke file.
muatData() Membaca data dari file.

Dengan pembagian tersebut, fungsi main() dapat berperan sebagai pengatur alur utama program, sedangkan pekerjaan khusus dilakukan oleh fungsi masing-masing.

Ilustrasi pembagian fungsi
int main() {
    // Memuat data awal

    // Menampilkan menu

    // Memproses pilihan pengguna

    // Menyimpan data ketika diperlukan

    return 0;
}

Ini baru gambaran tanggung jawab fungsi utama. Implementasi lengkapnya akan kita susun pada bagian berikutnya.

6. Mulai Menulis Kode Program

Setelah masalah, fitur, alur, dan struktur data dirancang, sekarang kita dapat mulai menulis kode.

Dalam proyek ini, kita akan membangun program secara bertahap. Tidak perlu langsung menulis semua fitur sekaligus.

Tahap pertama: membuat kerangka program

Kita mulai dengan menyiapkan pustaka yang dibutuhkan dan membuat struktur data Murid.

Tahap 1 — Kerangka program
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <limits>
#include <algorithm>

using namespace std;

struct Murid {
    string nama;
    double nilai;
};

int main() {
    vector<Murid> daftarMurid;

    cout << "Program Pengelolaan Nilai Murid";

    return 0;
}

Beberapa pustaka yang digunakan memiliki fungsi berbeda:

(- ) <iostream> untuk input dan output melalui console.

(- ) <vector> untuk menyimpan kumpulan data secara dinamis.

(- ) <string> untuk mengelola teks.

(- ) <fstream> untuk membaca dan menulis file.

(- ) <limits> untuk membantu membersihkan input yang tidak valid.

(- ) <algorithm> untuk menggunakan algoritma seperti pengurutan.

Tahap kedua: membuat fitur tambah data

Fitur pertama yang kita buat adalah memasukkan data murid.

Pengguna akan memasukkan nama dan nilai. Data tersebut kemudian disimpan ke dalam vector.

Tahap 2 — Fungsi tambahMurid()
void tambahMurid(vector<Murid>& daftar) {
    Murid murid;

    cout << "Masukkan nama: ";
    getline(cin, murid.nama);

    cout << "Masukkan nilai: ";
    cin >> murid.nilai;

    daftar.push_back(murid);

    cout << "Data berhasil ditambahkan.\n";
}

Perhatikan bahwa parameter vector<Murid>& daftar menggunakan reference. Dengan demikian, fungsi dapat menambahkan data langsung ke vector yang digunakan oleh program utama.

Untuk versi proyek yang lebih kuat, input nilai juga perlu divalidasi agar pengguna tidak memasukkan teks atau angka di luar rentang nilai yang diperbolehkan. Validasi akan kita terapkan dalam implementasi akhir.

Tahap ketiga: menampilkan seluruh data

Setelah data berhasil dimasukkan, kita perlu menyediakan fitur untuk melihat seluruh data yang tersimpan.

Tahap 3 — Fungsi tampilkanMurid()
void tampilkanMurid(const vector<Murid>& daftar) {
    if (daftar.empty()) {
        cout << "Belum ada data murid.\n";
        return;
    }

    for (const Murid& murid : daftar) {
        cout << "Nama: " << murid.nama << endl;
        cout << "Nilai: " << murid.nilai << endl;
        cout << "-------------------\n";
    }
}

Fungsi tersebut menggunakan perulangan untuk membaca setiap elemen vector. Kata kunci const menunjukkan bahwa fungsi hanya membaca data dan tidak mengubah isinya.

Tahap keempat: menghitung statistik nilai

Berikutnya, kita membuat fitur untuk menghitung rata-rata, nilai tertinggi, dan nilai terendah.

Tahap 4 — Fungsi hitungStatistik()
void hitungStatistik(const vector<Murid>& daftar) {
    if (daftar.empty()) {
        cout << "Belum ada data.\n";
        return;
    }

    double total = 0;
    double tertinggi = daftar[0].nilai;
    double terendah = daftar[0].nilai;

    for (const Murid& murid : daftar) {
        total += murid.nilai;

        if (murid.nilai > tertinggi) {
            tertinggi = murid.nilai;
        }

        if (murid.nilai < terendah) {
            terendah = murid.nilai;
        }
    }

    double rataRata = total / daftar.size();

    cout << "Rata-rata: " << rataRata << endl;
    cout << "Nilai tertinggi: " << tertinggi << endl;
    cout << "Nilai terendah: " << terendah << endl;
}

Di sini kita menggunakan algoritma perulangan untuk memproses seluruh data. Setiap nilai dijumlahkan, kemudian dibandingkan dengan nilai tertinggi dan terendah sementara.

Tahap kelima: membuat fitur pencarian

Program juga perlu membantu pengguna menemukan data berdasarkan nama murid.

Tahap 5 — Fungsi cariMurid()
void cariMurid(const vector<Murid>& daftar) {
    string namaDicari;

    cout << "Masukkan nama yang dicari: ";
    getline(cin, namaDicari);

    bool ditemukan = false;

    for (const Murid& murid : daftar) {
        if (murid.nama == namaDicari) {
            cout << "Nama: " << murid.nama << endl;
            cout << "Nilai: " << murid.nilai << endl;

            ditemukan = true;
            break;
        }
    }

    if (!ditemukan) {
        cout << "Data tidak ditemukan.\n";
    }
}

Pencarian pada contoh ini menggunakan Linear Search. Program memeriksa nama satu per satu hingga menemukan data yang sesuai.

Jika data semakin banyak, kita dapat mempertimbangkan struktur data atau algoritma pencarian yang lebih sesuai.

7. Menambahkan Fitur Penyimpanan Data

Sampai tahap ini, program sudah dapat menerima, menampilkan, menghitung, dan mencari data. Namun, masih ada satu masalah penting.

Bagaimana jika program ditutup?

Data yang tersimpan di dalam vector hanya berada di memori selama program berjalan. Ketika program selesai, data tersebut tidak otomatis tersimpan sebagai file permanen.

Oleh karena itu, kita perlu menambahkan mekanisme penyimpanan ke dalam file.

Menggunakan file untuk menyimpan data

Dengan pustaka <fstream>, program C++ dapat menulis data ke file dan membaca kembali data tersebut ketika program dijalankan.

Kita akan menggunakan file bernama data_murid.txt.

Tahap 6 — Menyimpan data ke file
void simpanData(const vector<Murid>& daftar) {
    ofstream file("data_murid.txt");

    if (!file) {
        cout << "Gagal membuka file.\n";
        return;
    }

    for (const Murid& murid : daftar) {
        file << murid.nama << endl;
        file << murid.nilai << endl;
    }

    cout << "Data berhasil disimpan.\n";
}

Setiap murid disimpan dalam dua baris: baris pertama berisi nama dan baris kedua berisi nilai.

Ketika program dijalankan kembali, kita perlu membaca file tersebut untuk memulihkan data.

Tahap 7 — Membaca data dari file
void muatData(vector<Murid>& daftar) {
    ifstream file("data_murid.txt");

    if (!file) {
        return;
    }

    Murid murid;

    while (getline(file, murid.nama)) {
        if (!(file >> murid.nilai)) {
            break;
        }

        file.ignore(numeric_limits<streamsize>::max(), '\n');

        daftar.push_back(murid);
    }

    cout << "Data berhasil dimuat.\n";
}

Dengan mekanisme tersebut, data dapat dibaca kembali ketika program dijalankan. Nama yang mengandung spasi juga dapat disimpan karena kita menggunakan getline().

Contoh ini menggunakan format teks sederhana. Untuk aplikasi yang lebih kompleks, format penyimpanan perlu dirancang lebih kuat agar dapat menangani data yang tidak lengkap, karakter khusus, dan perubahan struktur data.

8. Menggabungkan Seluruh Fitur Menjadi Program Utuh

Setelah setiap fitur dibuat, kita perlu menggabungkannya menjadi satu program yang dapat dijalankan dari awal hingga akhir.

Di sinilah fungsi main() berperan sebagai pengatur alur program.

Program akan memuat data dari file terlebih dahulu, kemudian menampilkan menu. Pengguna dapat memilih fitur yang ingin digunakan. Setelah memilih keluar, program menyimpan data dan mengakhiri proses.

Berikut implementasi lengkap proyek pengelolaan nilai murid.

Catatan implementasi

Versi berikut menggabungkan fitur yang telah dirancang, sekaligus menambahkan validasi input angka dan rentang nilai 0–100. Data disimpan dalam format teks sederhana dengan pemisah baris.

Proyek C++ — Program Pengelolaan Nilai Murid
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <limits>
#include <algorithm>
#include <iomanip>

using namespace std;

struct Murid {
    string nama;
    double nilai;
};

// Membaca input angka dengan validasi
double inputNilai() {
    double nilai;

    while (true) {
        cout << "Masukkan nilai (0-100): ";

        if (cin >> nilai && nilai >= 0 && nilai <= 100) {
            cin.ignore(
                numeric_limits<streamsize>::max(),
                '\n'
            );
            return nilai;
        }

        cout << "Input tidak valid.\n";

        cin.clear();
        cin.ignore(
            numeric_limits<streamsize>::max(),
            '\n'
        );
    }
}

// Menambahkan data murid
void tambahMurid(vector<Murid>& daftar) {
    Murid murid;

    cout << "Masukkan nama murid: ";
    getline(cin, murid.nama);

    if (murid.nama.empty()) {
        cout << "Nama tidak boleh kosong.\n";
        return;
    }

    murid.nilai = inputNilai();

    daftar.push_back(murid);

    cout << "Data berhasil ditambahkan.\n";
}

// Menampilkan seluruh data
void tampilkanMurid(const vector<Murid>& daftar) {
    if (daftar.empty()) {
        cout << "Belum ada data murid.\n";
        return;
    }

    cout << "\nDAFTAR NILAI MURID\n";
    cout << "------------------------------\n";

    for (size_t i = 0; i < daftar.size(); i++) {
        cout << i + 1 << ". "
             << daftar[i].nama
             << " - "
             << daftar[i].nilai
             << endl;
    }
}

// Menghitung statistik
void hitungStatistik(const vector<Murid>& daftar) {
    if (daftar.empty()) {
        cout << "Belum ada data.\n";
        return;
    }

    double total = 0;
    double tertinggi = daftar[0].nilai;
    double terendah = daftar[0].nilai;

    for (const Murid& murid : daftar) {
        total += murid.nilai;

        tertinggi = max(tertinggi, murid.nilai);
        terendah = min(terendah, murid.nilai);
    }

    double rataRata = total / daftar.size();

    cout << fixed << setprecision(2);
    cout << "\nSTATISTIK NILAI\n";
    cout << "Rata-rata       : " << rataRata << endl;
    cout << "Nilai tertinggi : " << tertinggi << endl;
    cout << "Nilai terendah  : " << terendah << endl;
}

// Mencari data murid
void cariMurid(const vector<Murid>& daftar) {
    string namaDicari;

    cout << "Masukkan nama yang dicari: ";
    getline(cin, namaDicari);

    bool ditemukan = false;

    for (const Murid& murid : daftar) {
        if (murid.nama == namaDicari) {
            cout << "Nama  : " << murid.nama << endl;
            cout << "Nilai : " << murid.nilai << endl;
            ditemukan = true;
        }
    }

    if (!ditemukan) {
        cout << "Data tidak ditemukan.\n";
    }
}

// Menyimpan data
bool simpanData(const vector<Murid>& daftar) {
    ofstream file("data_murid.txt");

    if (!file) {
        cout << "Gagal membuka file untuk menyimpan.\n";
        return false;
    }

    for (const Murid& murid : daftar) {
        file << murid.nama << '\n';
        file << murid.nilai << '\n';
    }

    if (!file) {
        cout << "Terjadi kesalahan saat menulis file.\n";
        return false;
    }

    return true;
}

// Memuat data
void muatData(vector<Murid>& daftar) {
    ifstream file("data_murid.txt");

    if (!file) {
        cout << "Belum ada file data. Mulai dengan data kosong.\n";
        return;
    }

    vector<Murid> dataSementara;
    Murid murid;

    while (getline(file, murid.nama)) {
        if (!(file >> murid.nilai)) {
            cout << "Format data tidak lengkap.\n";
            break;
        }

        file.ignore(
            numeric_limits<streamsize>::max(),
            '\n'
        );

        if (murid.nama.empty() ||
            murid.nilai < 0 ||
            murid.nilai > 100) {
            cout << "Data tidak valid ditemukan.\n";
            break;
        }

        dataSementara.push_back(murid);
    }

    if (file.bad()) {
        cout << "Terjadi kesalahan saat membaca file.\n";
        return;
    }

    daftar = dataSementara;

    cout << "Data berhasil dimuat: "
         << daftar.size()
         << " murid.\n";
}

// Menampilkan menu
void tampilkanMenu() {
    cout << "\n================================\n";
    cout << "   PROGRAM PENGELOLAAN NILAI\n";
    cout << "================================\n";
    cout << "1. Tambah Data Murid\n";
    cout << "2. Tampilkan Semua Data\n";
    cout << "3. Hitung Statistik Nilai\n";
    cout << "4. Cari Data Murid\n";
    cout << "5. Simpan Data\n";
    cout << "6. Keluar\n";
    cout << "================================\n";
    cout << "Pilih menu: ";
}

int main() {
    vector<Murid> daftarMurid;

    muatData(daftarMurid);

    int pilihan;

    do {
        tampilkanMenu();

        if (!(cin >> pilihan)) {
            cout << "Pilihan harus berupa angka.\n";
            cin.clear();
            cin.ignore(
                numeric_limits<streamsize>::max(),
                '\n'
            );
            continue;
        }

        cin.ignore(
            numeric_limits<streamsize>::max(),
            '\n'
        );

        switch (pilihan) {
            case 1:
                tambahMurid(daftarMurid);
                break;

            case 2:
                tampilkanMurid(daftarMurid);
                break;

            case 3:
                hitungStatistik(daftarMurid);
                break;

            case 4:
                cariMurid(daftarMurid);
                break;

            case 5:
                if (simpanData(daftarMurid)) {
                    cout << "Data berhasil disimpan.\n";
                }
                break;

            case 6:
                if (simpanData(daftarMurid)) {
                    cout << "Data tersimpan. Program selesai.\n";
                }
                break;

            default:
                cout << "Pilihan tidak tersedia.\n";
        }

    } while (pilihan != 6);

    return 0;
}

Program di atas sudah menggabungkan beberapa konsep C++ yang telah dipelajari sebelumnya. Pengguna dapat menambahkan data, menampilkan daftar nilai, menghitung statistik, mencari nama, menyimpan data, dan memuat kembali data dari file.

Perhatikan juga bahwa program tidak hanya berisi fungsi utama. Setiap fitur memiliki fungsi tersendiri sehingga kode lebih mudah dipahami dan dikelola.

Bagaimana menjalankan proyek ini?

1. Salin kode program ke editor C++.

2. Simpan dengan nama file, misalnya pengelolaan_nilai.cpp.

3. Kompilasi menggunakan compiler C++ yang mendukung standar C++11 atau lebih baru.

4. Jalankan program.

5. Tambahkan beberapa data murid, lalu coba seluruh menu.

6. Tutup program dan jalankan kembali. Periksa apakah data sebelumnya berhasil dimuat.

File data_murid.txt akan dibuat di direktori kerja program. Lokasi tersebut bergantung pada cara program dijalankan dan pengaturan IDE.

9. Menguji Program: Apakah Semua Fitur Berjalan?

Program yang berhasil dikompilasi belum tentu sudah benar.

Compiler hanya memastikan bahwa kode memenuhi aturan sintaks dan proses kompilasi. Program tetap perlu diuji untuk mengetahui apakah hasilnya sesuai dengan tujuan yang sudah ditentukan.

Misalnya, program berhasil dijalankan. Namun, apakah data benar-benar tersimpan? Apakah perhitungan rata-rata sudah tepat? Apakah pencarian nama bekerja? Bagaimana jika pengguna memasukkan input yang salah?

Semua pertanyaan tersebut perlu diperiksa melalui pengujian.

Membuat skenario pengujian

Pengujian Input atau Kondisi Hasil yang Diharapkan
Tambah data Nama Andi, nilai 85. Data berhasil ditambahkan.
Input nilai tidak valid Nilai 150 atau teks. Program meminta input ulang.
Menampilkan data Terdapat tiga data murid. Ketiga data ditampilkan.
Statistik Nilai 80, 90, 70. Rata-rata 80, tertinggi 90, terendah 70.
Pencarian Mencari nama yang tersedia. Data yang sesuai ditemukan.
Data kosong Belum ada murid. Program menampilkan informasi bahwa data kosong.
Penyimpanan Memilih menu simpan. Data tersimpan ke file.
Membaca file Program dijalankan kembali. Data sebelumnya dapat dimuat.

Pengujian sebaiknya tidak hanya dilakukan menggunakan kondisi normal. Kita juga perlu mencoba kondisi yang tidak biasa, seperti data kosong, input salah, atau file yang tidak tersedia.

Prinsip pengujian:

Jangan hanya menguji apakah program dapat berjalan. Ujilah apakah program memberikan hasil yang benar pada berbagai kondisi yang mungkin terjadi.

10. Memahami Debugging: Menemukan dan Memperbaiki Kesalahan

Ketika membuat program, kita hampir pasti akan menemukan kesalahan. Bahkan program yang terlihat sederhana dapat menghasilkan output yang tidak sesuai harapan.

Proses mencari penyebab kesalahan dan memperbaikinya disebut debugging.

Kesalahan dalam program dapat muncul dalam beberapa bentuk.

A. Syntax Error

Kesalahan yang terjadi karena penulisan kode tidak mengikuti aturan bahasa pemrograman.

Contohnya, lupa menambahkan titik koma, salah menulis nama fungsi, atau menggunakan tanda kurung yang tidak lengkap.

B. Runtime Error

Kesalahan yang terjadi ketika program sedang dijalankan.

Contohnya, mengakses elemen di luar batas array, membagi dengan nol pada operasi tertentu, atau mengalami masalah ketika membaca file.

C. Logic Error

Kesalahan pada logika program. Kode mungkin berhasil dikompilasi dan dijalankan, tetapi hasilnya tidak sesuai dengan yang seharusnya.

Contohnya, menghitung rata-rata dengan membagi jumlah nilai menggunakan angka yang salah.

Contoh menemukan logic error

Misalnya, kita ingin menghitung rata-rata tiga nilai. Namun, program menggunakan rumus berikut:

Contoh rumus yang salah
double rataRata = (80 + 90 + 70) / 2;

Hasilnya adalah 120, padahal rata-rata yang benar adalah 80.

Kesalahannya bukan pada sintaks, melainkan pada logika perhitungan. Kita seharusnya membagi jumlah nilai dengan banyaknya data, yaitu tiga.

Perbaikan rumus
double rataRata = (80 + 90 + 70) / 3.0;

Melalui debugging, kita belajar bahwa menemukan kesalahan bukan sekadar memperbaiki kode yang ditandai compiler. Kita juga perlu memeriksa apakah proses dan hasil program sudah sesuai dengan tujuan awal.

11. Membuat Program Lebih Mudah Dikembangkan

Setelah seluruh fitur utama berjalan, pekerjaan kita belum tentu selesai. Sebuah proyek pemrograman dapat terus dikembangkan untuk memenuhi kebutuhan baru.

Misalnya, program pengelolaan nilai yang sudah dibuat masih memiliki beberapa keterbatasan:

(- ) Belum memiliki fitur mengubah nilai yang sudah dimasukkan.

(- ) Belum memiliki fitur menghapus data murid.

(- ) Belum dapat mengelompokkan murid berdasarkan kelas.

(- ) Belum memiliki tampilan grafik statistik.

(- ) Belum memiliki sistem akun pengguna.

Fitur-fitur tersebut dapat ditambahkan secara bertahap. Namun, semakin besar proyek, semakin penting pula kualitas struktur kode.

Mengenal modularisasi

Modularisasi adalah pendekatan membagi program menjadi bagian-bagian yang lebih kecil berdasarkan tanggung jawabnya.

Misalnya, jika proyek berkembang, kita dapat memisahkan kode menjadi beberapa file:

pengelolaan_nilai.cpp
↓
data.h
menu.h
statistik.h
file.h

Ilustrasi pemisahan tanggung jawab program

Dengan pendekatan ini, kode dapat lebih mudah dikelola. Ketika ingin memperbaiki fitur penyimpanan, kita tidak harus mengubah seluruh bagian program.

Mengenal pemrograman berorientasi objek

Ketika proyek semakin kompleks, kita juga dapat mempertimbangkan penggunaan Object-Oriented Programming (OOP).

Dalam OOP, program dirancang menggunakan objek yang memiliki data dan perilaku. Misalnya, objek Murid dapat memiliki atribut nama dan nilai, serta perilaku tertentu yang berkaitan dengan pengelolaan data murid.

Namun, tidak semua proyek harus menggunakan OOP. Pemilihan pendekatan pemrograman sebaiknya disesuaikan dengan ukuran dan kebutuhan proyek.

12. Tahapan Umum dalam Membangun Proyek Pemrograman

Dari contoh proyek yang telah kita kerjakan, kita dapat menyimpulkan bahwa membangun program bukan hanya aktivitas menulis kode. Ada beberapa tahapan yang saling berkaitan.

1
Identifikasi masalah Tentukan masalah atau kebutuhan yang ingin diselesaikan melalui program.
2
Menentukan tujuan dan ruang lingkup Tentukan hasil yang ingin dicapai dan batasan fitur proyek.
3
Merancang solusi Susun algoritma, pseudocode, flowchart, dan alur interaksi program.
4
Menentukan struktur data Pilih cara menyimpan dan mengorganisasi data sesuai kebutuhan.
5
Implementasi Terjemahkan rancangan menjadi kode program menggunakan bahasa pemrograman.
6
Pengujian dan debugging Periksa apakah program berjalan sesuai tujuan dan perbaiki kesalahan yang ditemukan.
7
Evaluasi dan pengembangan Perbaiki kualitas program dan tambahkan fitur berdasarkan kebutuhan.
Perlu diingat:

Tahapan tersebut bukan aturan yang harus selalu berjalan satu arah. Dalam praktiknya, pengembang sering kembali ke tahap sebelumnya ketika menemukan masalah atau mendapatkan kebutuhan baru.

13. Mengenal Pengembangan Proyek Secara Iteratif

Dalam proyek sederhana, kita mungkin dapat merancang seluruh fitur terlebih dahulu kemudian menulis kode sampai selesai. Namun, pada proyek yang lebih besar, pendekatan seperti itu tidak selalu efektif.

Pengembang perangkat lunak sering menggunakan pendekatan iteratif, yaitu membangun program secara bertahap melalui beberapa siklus pengembangan.

Contohnya, proyek pengelolaan nilai dapat dikembangkan menjadi beberapa versi.

Versi 1 — Program dasar

Program dapat menerima dan menampilkan data murid.

Input Output

Versi 2 — Pengolahan data

Program dapat menghitung rata-rata, nilai tertinggi, dan nilai terendah.

Perulangan Algoritma

Versi 3 — Penyimpanan data

Program dapat menyimpan dan membaca data dari file.

File I/O Persistensi

Versi 4 — Penyempurnaan

Program mendapatkan validasi input, pencarian, pengubahan data, dan penghapusan data.

Validasi Debugging

Dengan pendekatan bertahap, kita dapat menguji setiap versi sebelum menambahkan fitur berikutnya. Jika ada kesalahan, ruang pencarian sumber masalah juga lebih terbatas.

Apakah proyek pemrograman harus langsung sempurna?

Tidak. Dalam pengembangan perangkat lunak, versi awal dapat disebut prototype atau MVP (Minimum Viable Product), tergantung tujuan pengembangannya.

Prototype digunakan untuk menunjukkan atau menguji gagasan. MVP merupakan versi awal dengan fitur inti yang cukup untuk memberikan manfaat dan memperoleh umpan balik pengguna.

Untuk latihan belajar, kita dapat memulai dari program sederhana yang sudah menyelesaikan satu masalah dengan benar, lalu mengembangkannya secara bertahap.

15. Tantangan Proyek Mandiri

Sekarang kamu sudah melihat bagaimana sebuah program dibangun dari awal hingga dapat digunakan. Sebagai latihan, cobalah membuat proyek lain secara mandiri.

Pilih salah satu proyek berikut dan terapkan tahapan pengembangan yang sudah dipelajari.

Proyek 1 — Program Pengelolaan Inventaris

Buat program untuk mencatat barang yang tersedia di sebuah ruangan atau toko.

Fitur yang dapat dibuat:

(- ) Menambahkan barang.

(- ) Menampilkan daftar barang.

(- ) Mengubah jumlah stok.

(- ) Mencari barang berdasarkan nama.

(- ) Menyimpan data ke file.

Proyek 2 — Program Pengelolaan Keuangan Sederhana

Buat program untuk mencatat pemasukan dan pengeluaran.

Fitur yang dapat dibuat:

(- ) Mencatat pemasukan.

(- ) Mencatat pengeluaran.

(- ) Menghitung saldo.

(- ) Menampilkan riwayat transaksi.

(- ) Menyimpan riwayat transaksi ke file.

Proyek 3 — Program Perpustakaan Sederhana

Buat program untuk mengelola data buku dan peminjaman.

Fitur yang dapat dibuat:

(- ) Menambahkan data buku.

(- ) Menampilkan daftar buku.

(- ) Mencari buku.

(- ) Mencatat peminjaman dan pengembalian.

(- ) Menyimpan data buku ke file.

Untuk setiap proyek, jangan langsung mulai dengan menulis kode. Buat terlebih dahulu daftar masalah, tujuan, fitur, alur program, dan struktur data yang dibutuhkan.

Setelah itu, kembangkan program secara bertahap. Pastikan setiap fitur dapat berjalan sebelum melanjutkan ke fitur berikutnya.

16. Kesimpulan: Belajar Pemrograman dengan Membangun Sesuatu

Belajar pemrograman tidak berhenti ketika kita sudah memahami sintaks bahasa pemrograman. Kemampuan yang lebih penting adalah menggunakan berbagai konsep tersebut untuk menyelesaikan masalah nyata.

Melalui sebuah proyek, kita belajar menggabungkan variabel, tipe data, input-output, percabangan, perulangan, fungsi, struktur data, algoritma, dan pengolahan file menjadi satu program yang memiliki tujuan jelas.

Kita juga belajar bahwa proses pengembangan tidak selalu berjalan mulus. Ada kesalahan yang harus ditemukan, fitur yang perlu diperbaiki, dan kebutuhan yang mungkin berubah selama proyek berlangsung.

Hal utama yang perlu diingat

(- ) Mulailah dari masalah, bukan langsung dari kode.

(- ) Tentukan tujuan dan ruang lingkup proyek.

(- ) Rancang alur dan struktur data sebelum implementasi.

(- ) Bagi program menjadi fungsi-fungsi yang memiliki tanggung jawab jelas.

(- ) Bangun program secara bertahap.

(- ) Uji setiap fitur dan lakukan debugging.

(- ) Kembangkan program berdasarkan kebutuhan yang nyata.

Pada akhirnya, kemampuan membangun proyek merupakan salah satu tahap penting dalam perjalanan belajar pemrograman. Dari proyek sederhana, kita dapat memahami bagaimana konsep-konsep yang sebelumnya dipelajari secara terpisah ternyata saling terhubung untuk menghasilkan sebuah aplikasi.

Continue reading Membangun Proyek Pemrograman
, ,

Mempelajari Algoritma dan Struktur Data

PEMROGRAMAN C++ · PENGEMBANGAN KONSEP

Mempelajari Algoritma dan Struktur Data

Bagaimana sebuah program menyelesaikan masalah dan mengelola informasi? Pelajari hubungan antara algoritma, struktur data, efisiensi, dan penerapannya menggunakan C++.

Bayangkan kita diminta membuat sebuah program untuk mengelola nilai murid dalam satu kelas. Program tersebut harus mampu menyimpan banyak nilai, mencari nilai tertentu, mengurutkan nilai dari yang tertinggi, dan menghitung rata-rata kelas.

Sekilas, tugas tersebut terlihat seperti pekerjaan menulis beberapa baris kode. Namun, sebelum menulis kode, ada dua pertanyaan penting yang perlu dijawab:

1. Bagaimana program menyelesaikan masalah tersebut?

Apakah nilai diperiksa satu per satu? Apakah perlu diurutkan terlebih dahulu? Bagaimana langkah-langkah penyelesaiannya?

2. Bagaimana data nilai disimpan dan diatur?

Apakah setiap nilai disimpan dalam variabel terpisah? Apakah lebih baik menggunakan array atau struktur data lainnya?

Pertanyaan pertama berkaitan dengan algoritma, sedangkan pertanyaan kedua berkaitan dengan struktur data. Keduanya merupakan konsep penting dalam pemrograman karena program yang baik bukan hanya harus menghasilkan jawaban yang benar, tetapi juga perlu mengelola data dan menyelesaikan masalah secara efektif.

1. Memahami Apa Itu Algoritma

Sebelum mengenal struktur data, kita perlu memahami terlebih dahulu bagaimana sebuah program dapat menyelesaikan masalah.

Misalnya, kamu ingin mengetahui apakah nilai ujian seorang murid sudah mencapai batas ketuntasan. Jika batas ketuntasan adalah 75, tentu kamu dapat membandingkan nilai murid dengan angka tersebut.

Jika nilainya 85, hasilnya adalah tuntas. Jika nilainya 65, hasilnya belum tuntas.

Manusia dapat menyelesaikan persoalan sederhana tersebut secara spontan. Namun, komputer membutuhkan instruksi yang jelas dan tersusun agar dapat melakukan hal yang sama.

Pengertian Algoritma

Algoritma adalah urutan langkah-langkah logis dan sistematis yang dirancang untuk menyelesaikan suatu masalah atau mencapai tujuan tertentu.

Dalam pemrograman, algoritma menjadi rancangan penyelesaian masalah yang nantinya dapat diterjemahkan ke dalam bahasa pemrograman seperti C++.

Perhatikan contoh algoritma untuk menentukan kelulusan berdasarkan nilai:

Mulai
↓
Masukkan nilai
↓
Apakah nilai ≥ 75?
↓
Ya
Tampilkan "Tuntas"
Tidak
Tampilkan "Belum Tuntas"
↓
Selesai

Urutan tersebut merupakan algoritma sederhana. Ada masukan berupa nilai, proses perbandingan, kemudian keluaran berupa informasi ketuntasan.

Perhatikan bahwa algoritma belum tentu ditulis menggunakan bahasa pemrograman. Kita dapat menyusun algoritma menggunakan bahasa sehari-hari, pseudocode, atau flowchart terlebih dahulu.

2. Algoritma Bukan Sekadar Kode Program

Salah satu hal yang sering membingungkan pemula adalah menganggap algoritma sama dengan kode program. Padahal, keduanya memiliki peran yang berbeda.

Algoritma menjelaskan bagaimana suatu masalah diselesaikan, sedangkan kode program merupakan bentuk instruksi yang ditulis menggunakan bahasa pemrograman agar dapat dijalankan oleh komputer.

Misalnya, kita ingin menghitung rata-rata tiga nilai. Algoritmanya dapat ditulis seperti berikut:

Algoritma menghitung rata-rata

1
Masukkan tiga nilai.
2
Jumlahkan ketiga nilai tersebut.
3
Bagi hasil penjumlahan dengan tiga.
4
Tampilkan hasil rata-rata.

Setelah algoritma dipahami, kita dapat menerjemahkannya ke dalam C++.

Contoh implementasi algoritma dalam C++
#include <iostream>
using namespace std;

int main() {
    double nilai1, nilai2, nilai3;
    double rataRata;

    cout << "Masukkan nilai pertama: ";
    cin >> nilai1;

    cout << "Masukkan nilai kedua: ";
    cin >> nilai2;

    cout << "Masukkan nilai ketiga: ";
    cin >> nilai3;

    rataRata = (nilai1 + nilai2 + nilai3) / 3;

    cout << "Rata-rata: " << rataRata;

    return 0;
}

Program tersebut merupakan salah satu penerapan algoritma menghitung rata-rata. Algoritma yang sama juga dapat diterapkan menggunakan bahasa pemrograman lain, misalnya Python, Java, atau JavaScript.

Hal yang perlu dipahami

Bahasa pemrograman dapat berbeda, tetapi algoritma penyelesaian masalahnya bisa tetap sama. Karena itu, belajar algoritma membantu kita memahami cara berpikir komputasional, bukan sekadar menghafalkan sintaks bahasa pemrograman.

3. Mengapa Algoritma Perlu Efisien?

Bayangkan kita memiliki daftar berisi 10 nama murid dan ingin mencari nama seseorang. Kita dapat memeriksa nama dari urutan pertama sampai menemukan nama yang dicari.

Bagaimana jika jumlahnya bukan 10, melainkan 10.000 atau bahkan 1.000.000 data?

Jika cara yang digunakan tetap sama, program mungkin harus memeriksa banyak data sebelum menemukan hasilnya. Inilah alasan mengapa efisiensi algoritma perlu diperhatikan.

Contoh: mencari sebuah angka dalam kumpulan data

Misalnya, kita memiliki kumpulan angka berikut:

12
25
37
42
58

Angka yang ingin dicari: 42

Cara pertama adalah memeriksa angka satu per satu dari awal. Cara ini disebut Linear Search.

Linear Search (Pencarian Linear)

Linear Search merupakan algoritma pencarian dengan cara memeriksa setiap elemen secara berurutan hingga data yang dicari ditemukan atau seluruh data selesai diperiksa.

Untuk contoh di atas, program memeriksa 12, kemudian 25, 37, dan akhirnya menemukan 42. Artinya, diperlukan empat kali pemeriksaan.

Cara kedua adalah menggunakan Binary Search. Namun, metode ini memiliki syarat: data harus sudah terurut.

Binary Search (Pencarian Biner)

Binary Search mencari data dengan membagi area pencarian menjadi dua bagian secara berulang. Program membandingkan data yang dicari dengan elemen tengah, lalu menentukan bagian mana yang masih perlu diperiksa.

Jika data lebih kecil dari elemen tengah, pencarian dilanjutkan ke bagian kiri. Jika lebih besar, pencarian dilanjutkan ke bagian kanan.

Perbedaan cara kerja kedua algoritma tersebut dapat menjadi sangat penting ketika jumlah data semakin besar.

Bagaimana Binary Search bekerja?

Misalnya, kita mencari angka 42 pada data terurut berikut:

12
25
37
42
58

1. Tentukan elemen tengah, yaitu 37.

2. Bandingkan 42 dengan 37. Karena 42 lebih besar, bagian kiri tidak perlu diperiksa lagi.

3. Periksa bagian kanan yang tersisa. Pada contoh ini, angka 42 ditemukan.

Semakin besar jumlah data terurut, semakin terasa keuntungan metode pembagian area pencarian ini.

4. Mengenal Kompleksitas Algoritma

Ketika membandingkan algoritma, kita tidak cukup hanya melihat berapa banyak baris kode yang ditulis. Kita juga perlu memperkirakan bagaimana kebutuhan waktu dan sumber daya program berubah ketika jumlah data bertambah.

Salah satu cara untuk menggambarkan pertumbuhan tersebut adalah menggunakan konsep kompleksitas algoritma. Dalam pembahasan dasar, kita sering mengenal istilah Big O Notation.

Apa itu Big O?

Big O merupakan notasi untuk menggambarkan bagaimana kebutuhan komputasi suatu algoritma bertumbuh terhadap ukuran input, terutama ketika ukuran data semakin besar.

Big O bukan angka pasti durasi eksekusi dalam detik. Notasi ini membantu kita membandingkan pola pertumbuhan algoritma.

Berikut beberapa kompleksitas yang sering dijumpai:

Kompleksitas Nama Gambaran sederhana
O(1) Konstan Jumlah langkah relatif tetap.
O(log n) Logaritmik Jumlah langkah bertambah secara lambat saat data membesar.
O(n) Linear Jumlah langkah bertumbuh sebanding dengan jumlah data.
O(n log n) Linear-logaritmik Sering ditemukan pada algoritma pengurutan yang efisien.
O(n²) Kuadratik Jumlah langkah dapat bertumbuh jauh lebih cepat.

Misalnya, sebuah algoritma O(n) memeriksa setiap data satu kali. Jika jumlah data bertambah sepuluh kali lipat, jumlah pemeriksaan juga kira-kira bertambah sepuluh kali lipat.

Sementara itu, algoritma O(n²) memiliki pertumbuhan yang lebih cepat. Jika jumlah data menjadi sepuluh kali lipat, skala operasinya dapat bertambah sekitar seratus kali lipat.

Catatan penting

Kompleksitas bukan satu-satunya penentu kecepatan program. Perangkat keras, implementasi, jenis data, dan kondisi input juga berpengaruh. Namun, Big O membantu kita memahami karakteristik pertumbuhan algoritma secara lebih umum.

Contoh sederhana kompleksitas O(1), O(n), dan O(n²)

O(1): mengambil satu elemen array berdasarkan indeks.

int angka[5] = {10, 20, 30, 40, 50};
cout << angka[2];

O(n): memeriksa seluruh elemen dalam array.

for (int i = 0; i < 5; i++) {
    cout << angka[i] << endl;
}

O(n²): menggunakan dua perulangan bersarang yang masing-masing berjalan mengikuti jumlah data.

for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        cout << angka[i] << " ";
    }
}

Contoh terakhir menjalankan operasi di bagian dalam sebanyak 25 kali untuk ukuran data 5. Dalam kasus umum, pola dua perulangan penuh seperti ini memiliki kompleksitas O(n²).

5. Beralih ke Struktur Data: Bagaimana Informasi Disimpan?

Sekarang kita kembali ke persoalan awal: mengelola nilai murid dalam satu kelas.

Jika hanya ada satu nilai, kita bisa menyimpannya dalam satu variabel. Namun, jika terdapat 30, 100, atau 1.000 nilai, membuat variabel satu per satu tentu tidak praktis.

Kita membutuhkan cara untuk menyimpan dan mengatur sekumpulan data agar mudah diakses, diubah, dicari, atau diolah.

Pengertian Struktur Data

Struktur data adalah cara mengorganisasi dan menyimpan data di dalam komputer agar data tersebut dapat digunakan dan diolah secara efektif.

Setiap struktur data memiliki karakteristik dan cara penggunaan yang berbeda. Pemilihan struktur data akan memengaruhi bagaimana program mengakses, menambah, menghapus, dan mencari informasi.

Dalam C++, terdapat beberapa struktur data yang umum digunakan. Kita akan mulai dari yang paling sederhana.

A. Array: Menyimpan Banyak Data dengan Tipe yang Sama

Array memungkinkan kita menyimpan beberapa nilai dalam satu nama variabel. Setiap elemen memiliki indeks yang digunakan untuk mengakses posisinya.

Misalnya, kita ingin menyimpan lima nilai ujian:

80
Indeks 0
75
Indeks 1
90
Indeks 2
85
Indeks 3
88
Indeks 4

Lima elemen dalam satu array

Contoh array dalam C++
#include <iostream>
using namespace std;

int main() {
    int nilai[5] = {80, 75, 90, 85, 88};

    cout << "Nilai murid ketiga: " << nilai[2];

    return 0;
}

Perhatikan bahwa indeks array dimulai dari 0, bukan 1. Oleh karena itu, elemen ketiga berada pada indeks 2.

Array cocok digunakan ketika kita membutuhkan sekumpulan data dengan tipe yang sama dan jumlah elemennya sudah ditentukan.

B. Vector: Array yang Lebih Fleksibel

Array biasa memiliki ukuran yang ditentukan ketika dideklarasikan. Bagaimana jika jumlah data belum diketahui sejak awal?

Contohnya, program pendaftaran peserta lomba. Hari ini ada 10 pendaftar, tetapi besok jumlahnya mungkin bertambah menjadi 20 atau 100 orang.

Untuk situasi seperti ini, kita dapat menggunakan vector dari pustaka standar C++.

Apa itu Vector?

Vector adalah struktur data dalam C++ yang dapat menyimpan kumpulan elemen secara berurutan dan memungkinkan ukurannya bertambah atau berkurang selama program berjalan.

Contoh penggunaan vector
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> nilai;

    nilai.push_back(80);
    nilai.push_back(75);
    nilai.push_back(90);

    for (int i = 0; i < nilai.size(); i++) {
        cout << nilai[i] << endl;
    }

    return 0;
}

Perhatikan beberapa bagian penting:

(- ) #include <vector> digunakan untuk mengakses fasilitas vector.

(- ) vector<int> nilai; membuat vector bernama nilai yang menyimpan bilangan bulat.

(- ) push_back() menambahkan elemen baru di bagian akhir.

(- ) size() memberikan informasi jumlah elemen yang tersimpan.

Berbeda dengan array biasa yang ukurannya ditentukan sejak awal, vector dapat menyesuaikan jumlah elemennya sesuai kebutuhan program.

Beberapa operasi penting pada vector
OperasiKegunaan
push_back(x)Menambahkan elemen x di akhir.
pop_back()Menghapus elemen terakhir.
size()Mengambil jumlah elemen.
empty()Memeriksa apakah vector kosong.
clear()Menghapus seluruh elemen.
at(i)Mengakses elemen dengan pemeriksaan batas indeks.

C. Linked List: Data yang Terhubung

Array dan vector menyimpan elemen dalam urutan tertentu dan mendukung akses berdasarkan indeks. Namun, ada pendekatan lain dalam mengorganisasi data, yaitu menghubungkan setiap elemen dengan elemen berikutnya.

Pendekatan ini dikenal sebagai Linked List.

Apa itu Linked List?

Linked List adalah struktur data yang terdiri dari sejumlah elemen atau node. Setiap node menyimpan data dan informasi yang menghubungkannya dengan node lain.

Data 10
Node 1
→
Data 20
Node 2
→
Data 30
Node 3
→
NULL

Ilustrasi sederhana Single Linked List

Berbeda dengan array, kita tidak mengakses elemen Linked List secara langsung menggunakan indeks. Kita perlu mengikuti hubungan dari satu node ke node berikutnya.

Linked List dapat memudahkan penyisipan atau penghapusan elemen pada posisi tertentu setelah node yang bersangkutan ditemukan. Namun, pencarian berdasarkan posisi umumnya perlu menelusuri node satu per satu.

Contoh bentuk node dalam C++

Untuk membuat Linked List sederhana, kita dapat menggunakan struct dan pointer.

struct Node {
    int data;
    Node* next;
};

data menyimpan nilai, sedangkan next menyimpan alamat node berikutnya.

Konsep ini berkaitan erat dengan materi pointer dan reference dalam C++.

D. Stack: Data dengan Prinsip Terakhir Masuk, Pertama Keluar

Bayangkan kamu menumpuk beberapa buku di atas meja. Buku pertama diletakkan di bawah, buku kedua di atasnya, kemudian buku ketiga diletakkan paling atas.

Jika ingin mengambil buku tanpa merusak tumpukan, buku yang terakhir diletakkan harus diambil terlebih dahulu.

Prinsip tersebut dikenal sebagai Last In, First Out (LIFO).

Apa itu Stack?

Stack adalah struktur data yang menerapkan prinsip Last In, First Out. Elemen terakhir yang dimasukkan menjadi elemen pertama yang dikeluarkan.

Buku A
Buku B
Buku C
← Diambil pertama

Buku C berada paling atas sehingga diambil lebih dahulu.

Dalam C++, kita dapat menggunakan fasilitas stack dari pustaka standar.

Contoh penggunaan stack
#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> data;

    data.push(10);
    data.push(20);
    data.push(30);

    cout << data.top() << endl;

    data.pop();

    cout << data.top() << endl;

    return 0;
}

Hasil program:

30
20

Angka 30 ditampilkan terlebih dahulu karena berada di posisi paling atas. Setelah pop() dipanggil, angka 30 dikeluarkan dan angka 20 menjadi elemen teratas.

Stack dapat digunakan dalam berbagai kebutuhan, seperti fitur undo pada aplikasi, pengelolaan pemanggilan fungsi, dan evaluasi ekspresi matematika.

E. Queue: Data dengan Prinsip Pertama Masuk, Pertama Keluar

Sekarang bayangkan kamu sedang mengantre untuk membeli tiket. Orang yang datang lebih dahulu biasanya dilayani lebih dahulu.

Orang yang baru datang harus menunggu di belakang antrean. Prinsip ini dikenal sebagai First In, First Out (FIFO).

Apa itu Queue?

Queue adalah struktur data yang menerapkan prinsip First In, First Out. Elemen yang dimasukkan lebih dahulu akan dikeluarkan lebih dahulu.

10
Keluar dulu
20
30
40
Masuk terakhir

Urutan antrean dari depan ke belakang

Contoh penggunaan queue
#include <iostream>
#include <queue>
using namespace std;

int main() {
    queue<int> antrean;

    antrean.push(10);
    antrean.push(20);
    antrean.push(30);

    cout << antrean.front() << endl;

    antrean.pop();

    cout << antrean.front() << endl;

    return 0;
}

Hasil program:

10
20

Angka 10 keluar lebih dahulu karena dimasukkan pertama kali. Setelah itu, angka 20 menjadi elemen paling depan.

Queue dapat digunakan untuk mengatur antrean layanan, tugas pencetakan dokumen, dan proses yang perlu dijalankan berdasarkan urutan kedatangan.

F. Map: Menyimpan Data Berdasarkan Kunci

Bayangkan kita ingin menyimpan nilai murid berdasarkan nama. Kita ingin dapat mencari nilai seseorang dengan menggunakan namanya, bukan dengan mengingat posisi data di dalam array.

Untuk kebutuhan seperti ini, C++ menyediakan struktur data map.

Apa itu Map?

Map merupakan struktur data yang menyimpan pasangan antara kunci (key) dan nilai (value). Setiap kunci bersifat unik dalam satu map.

Key (Nama)Value (Nilai)
Andi85
Siti92
Budi78
Contoh penggunaan map
#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    map<string, int> nilai;

    nilai["Andi"] = 85;
    nilai["Siti"] = 92;
    nilai["Budi"] = 78;

    cout << "Nilai Siti: "
         << nilai["Siti"];

    return 0;
}

Program tersebut menyimpan nama sebagai kunci dan nilai ujian sebagai data yang terkait. Ketika kita membutuhkan nilai Siti, kita dapat mengaksesnya melalui nilai["Siti"].

Map berguna ketika kita membutuhkan pencarian berdasarkan identitas atau kunci tertentu, bukan sekadar posisi elemen.

Apa perbedaan map dan unordered_map?

C++ juga menyediakan unordered_map. Perbedaannya antara lain:

(- ) map menyimpan pasangan key-value dalam urutan berdasarkan kunci dan umumnya menggunakan struktur pohon seimbang.

(- ) unordered_map tidak menjamin urutan berdasarkan kunci dan umumnya menggunakan hash table.

Keduanya dapat digunakan untuk mencari data berdasarkan key, tetapi karakteristik dan kompleksitas operasinya berbeda.

G. Set: Menyimpan Data yang Unik

Misalnya, sebuah program ingin mencatat daftar kode peserta yang sudah mendaftar. Satu kode peserta tidak boleh tercatat lebih dari satu kali.

Kita dapat menggunakan struktur data set.

Apa itu Set?

Set adalah struktur data yang menyimpan kumpulan elemen unik. Jika kita mencoba memasukkan elemen yang sama lebih dari satu kali, set hanya menyimpan satu salinannya.

Contoh penggunaan set
#include <iostream>
#include <set>
using namespace std;

int main() {
    set<int> nomor;

    nomor.insert(10);
    nomor.insert(20);
    nomor.insert(10);
    nomor.insert(30);

    for (int x : nomor) {
        cout << x << endl;
    }

    return 0;
}

Hasilnya:

10
20
30

Angka 10 hanya muncul satu kali karena set tidak menyimpan duplikasi. Pada set biasa, elemen juga disajikan dalam urutan terurut berdasarkan aturan perbandingannya.

6. Memahami Perbedaan Berbagai Struktur Data

Setelah mengenal beberapa struktur data, mungkin muncul pertanyaan: mana yang paling baik digunakan?

Jawabannya bergantung pada kebutuhan program. Tidak ada satu struktur data yang selalu menjadi pilihan terbaik untuk semua masalah.

Struktur Data Karakteristik Contoh Penggunaan
Array Ukuran tetap, akses berdasarkan indeks. Daftar nilai dengan jumlah tetap.
Vector Urutan elemen dinamis, akses berdasarkan indeks. Daftar peserta yang terus bertambah.
Linked List Node saling terhubung. Data yang sering disisipkan atau dihapus pada posisi tertentu.
Stack LIFO. Undo, riwayat pemanggilan fungsi.
Queue FIFO. Antrean layanan atau tugas.
Map Pasangan key-value. Pencarian nilai berdasarkan nama.
Set Elemen unik. Menyimpan kode tanpa duplikasi.

Contohnya, jika kita ingin mengambil data berdasarkan posisi tertentu, vector dapat menjadi pilihan yang praktis. Jika kita ingin mengelola antrean, queue lebih sesuai. Jika kita membutuhkan data unik, set dapat membantu.

Ingat:

Memilih struktur data bukan sekadar memilih yang paling mudah ditulis. Kita perlu mempertimbangkan operasi yang paling sering dilakukan oleh program, seperti pencarian, penambahan, penghapusan, dan pengurutan.

7. Algoritma dan Struktur Data Saling Berkaitan

Sampai di sini, kita sudah mempelajari algoritma sebagai langkah penyelesaian masalah dan struktur data sebagai cara mengorganisasi informasi.

Keduanya sebenarnya tidak berdiri sendiri. Algoritma bekerja dengan memanfaatkan struktur data untuk mengolah informasi.

Mari kembali ke contoh pengelolaan nilai murid.

Misalnya, kita ingin membuat program yang dapat:

(- ) Menyimpan nilai seluruh murid.

(- ) Menampilkan seluruh nilai.

(- ) Menghitung rata-rata kelas.

(- ) Mencari nilai tertinggi.

(- ) Menentukan apakah suatu nilai tertentu terdapat dalam daftar.

Kita dapat menggunakan vector sebagai tempat penyimpanan data, kemudian menerapkan algoritma perulangan untuk menghitung rata-rata dan mencari nilai tertinggi.

Contoh program: mengolah nilai menggunakan vector
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> nilai = {80, 75, 90, 85, 88};

    int total = 0;
    int tertinggi = nilai[0];

    // Mengolah seluruh data
    for (int i = 0; i < nilai.size(); i++) {
        total += nilai[i];

        if (nilai[i] > tertinggi) {
            tertinggi = nilai[i];
        }
    }

    double rataRata =
        static_cast<double>(total) / nilai.size();

    cout << "Jumlah murid: "
         << nilai.size() << endl;

    cout << "Rata-rata: "
         << rataRata << endl;

    cout << "Nilai tertinggi: "
         << tertinggi << endl;

    return 0;
}

Program tersebut menggunakan dua konsep sekaligus:

Struktur Data

vector<int> digunakan untuk menyimpan kumpulan nilai murid dalam satu wadah.

Algoritma

Perulangan for digunakan untuk memeriksa seluruh nilai. Di dalamnya terdapat proses penjumlahan dan perbandingan untuk menentukan nilai tertinggi.

Dengan demikian, struktur data menyediakan tempat untuk menyimpan informasi, sedangkan algoritma menentukan bagaimana informasi tersebut diproses untuk menghasilkan jawaban.

8. Mengenal Algoritma Pengurutan (Sorting)

Selain mencari dan menghitung data, program juga sering perlu mengurutkan informasi.

Misalnya, daftar nilai murid ingin ditampilkan dari nilai terkecil ke terbesar. Jika datanya hanya tiga atau empat, kita mungkin dapat mengurutkannya secara manual. Namun, bagaimana jika jumlahnya ratusan atau ribuan?

Komputer membutuhkan algoritma pengurutan atau sorting algorithm.

Apa itu Sorting?

Sorting adalah proses menyusun sekumpulan data berdasarkan aturan tertentu, misalnya dari nilai terkecil ke terbesar (ascending) atau dari terbesar ke terkecil (descending).

Ada berbagai algoritma pengurutan. Beberapa di antaranya adalah:

Bubble Sort

Membandingkan dua elemen yang berdekatan dan menukarnya jika urutannya tidak sesuai. Proses tersebut diulang sampai data tersusun.

Mudah dipahami O(n²) rata-rata dan terburuk

Selection Sort

Mencari elemen terkecil dari bagian data yang belum terurut, kemudian menempatkannya pada posisi yang tepat.

Konsep sederhana O(n²)

Insertion Sort

Menyisipkan setiap elemen ke posisi yang tepat dalam bagian data yang sudah terurut. Metode ini dapat bekerja cukup baik pada kumpulan data kecil atau hampir terurut.

Cocok untuk data kecil O(n²) rata-rata dan terburuk

Merge Sort

Membagi data menjadi bagian-bagian lebih kecil, mengurutkan setiap bagian, kemudian menggabungkannya kembali dalam keadaan terurut.

Divide and Conquer O(n log n)

Dalam C++, kita tidak selalu harus membuat algoritma pengurutan dari awal. Pustaka standar C++ menyediakan fungsi sort() yang dapat digunakan untuk mengurutkan data.

Mengurutkan vector menggunakan sort()
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> nilai = {80, 75, 90, 85, 88};

    sort(nilai.begin(), nilai.end());

    for (int x : nilai) {
        cout << x << " ";
    }

    return 0;
}

Hasilnya:

75 80 85 88 90

Untuk mengurutkan dari terbesar ke terkecil, kita dapat menggunakan greater<int>().

Sorting secara descending
sort(nilai.begin(), nilai.end(), greater<int>());

Fungsi sort() pada pustaka standar C++ umumnya memiliki kompleksitas O(n log n). Untuk mempelajari cara kerja setiap algoritma secara lebih mendalam, kita tetap perlu memahami proses di baliknya.

9. Bagaimana Memilih Algoritma dan Struktur Data?

Ketika membuat program, kita sering dihadapkan pada beberapa pilihan. Sebuah masalah mungkin dapat diselesaikan menggunakan lebih dari satu algoritma atau struktur data.

Untuk menentukan pilihan, kita perlu memahami karakteristik masalah yang akan diselesaikan.

Contoh 1: Menyimpan daftar nilai murid

Jika jumlah murid sudah diketahui dan tidak berubah, array dapat digunakan. Jika jumlah data dapat bertambah atau berkurang, vector lebih fleksibel.

Contoh 2: Mengelola antrean pendaftaran

Jika orang harus dilayani sesuai urutan kedatangan, queue merupakan struktur data yang sesuai karena menerapkan prinsip FIFO.

Contoh 3: Mencari data berdasarkan nama

Jika program sering mencari nilai berdasarkan nama murid, map dapat menjadi pilihan karena data disimpan sebagai pasangan key-value.

Contoh 4: Mencari angka dalam data yang sudah terurut

Jika data sudah terurut dan jumlahnya besar, Binary Search dapat menjadi pilihan yang lebih efisien dibandingkan Linear Search.

Secara umum, beberapa pertanyaan berikut dapat membantu menentukan pilihan:

(- ) Apakah data memiliki jumlah tetap atau dapat berubah?

(- ) Apakah data lebih sering dicari, ditambahkan, dihapus, atau diurutkan?

(- ) Apakah urutan data perlu dipertahankan?

(- ) Apakah data harus unik atau boleh memiliki nilai yang sama?

(- ) Seberapa besar jumlah data yang akan diproses?

Dengan mempertimbangkan hal tersebut, kita dapat membuat program yang lebih sesuai dengan kebutuhan, bukan sekadar program yang berhasil dijalankan.

10. Latihan Pemahaman

Setelah mempelajari algoritma dan struktur data, coba jawab beberapa pertanyaan berikut untuk menguji pemahamanmu.

1. Apa yang dimaksud dengan algoritma?

A. Kumpulan perangkat keras komputer

B. Urutan langkah logis untuk menyelesaikan masalah

C. Tempat menyimpan seluruh data

D. Bahasa yang digunakan untuk membuat komputer

Lihat pembahasan

Jawaban: B. Algoritma merupakan urutan langkah logis dan sistematis untuk menyelesaikan suatu masalah.

2. Struktur data yang menggunakan prinsip Last In, First Out adalah ...

A. Queue

B. Array

C. Stack

D. Map

Lihat pembahasan

Jawaban: C. Stack menggunakan prinsip LIFO, yaitu data yang terakhir dimasukkan akan dikeluarkan terlebih dahulu.

3. Struktur data yang tepat untuk menyimpan pasangan nama dan nilai adalah ...

A. Map

B. Stack

C. Queue

D. Set

Lihat pembahasan

Jawaban: A. Map menyimpan data dalam bentuk pasangan key-value, misalnya nama sebagai key dan nilai sebagai value.

4. Mengapa Binary Search membutuhkan data yang sudah terurut?

A. Agar komputer dapat menghapus data

B. Agar pencarian dapat menentukan bagian mana yang tidak perlu diperiksa

C. Agar semua data memiliki nilai sama

D. Agar jumlah data selalu tetap

Lihat pembahasan

Jawaban: B. Binary Search menggunakan perbandingan terhadap elemen tengah untuk mempersempit area pencarian. Proses ini hanya dapat dilakukan dengan benar jika data terurut.

5. Jika sebuah program harus mengelola antrean peserta berdasarkan urutan pendaftaran, struktur data yang paling sesuai adalah ...

A. Stack

B. Set

C. Queue

D. Map

Lihat pembahasan

Jawaban: C. Queue menerapkan prinsip FIFO sehingga peserta yang mendaftar lebih dahulu akan diproses lebih dahulu.

11. Tantangan Praktik: Membuat Program Pengelolaan Nilai

Sekarang saatnya menggabungkan konsep algoritma dan struktur data ke dalam sebuah program sederhana.

Buatlah program C++ untuk mengelola nilai beberapa murid menggunakan vector. Program tersebut harus memiliki kemampuan berikut:

Ketentuan program

(- ) Meminta pengguna memasukkan jumlah nilai yang akan disimpan.

(- ) Menerima nilai dari pengguna dan menyimpannya dalam vector.

(- ) Menampilkan seluruh nilai yang sudah dimasukkan.

(- ) Menghitung rata-rata nilai.

(- ) Menentukan nilai tertinggi dan terendah.

(- ) Mengurutkan nilai dari yang terkecil ke terbesar.

Petunjuk konsep yang dapat digunakan:

(- ) Gunakan vector<int> untuk menyimpan nilai.

(- ) Gunakan push_back() untuk menambahkan nilai.

(- ) Gunakan perulangan untuk memproses seluruh data.

(- ) Gunakan sort() dari pustaka <algorithm> untuk mengurutkan data.

Lihat petunjuk tambahan jika mengalami kesulitan

Untuk menghitung rata-rata, jumlahkan seluruh elemen kemudian bagi dengan jumlah data.

Untuk mencari nilai tertinggi dan terendah, kamu dapat membandingkan setiap elemen dengan nilai sementara.

Jangan lupa memeriksa jumlah data agar tidak membagi dengan nol ketika vector kosong.

Untuk mengurutkan nilai, pelajari penggunaan sort() pada bagian sebelumnya.

12. Kesimpulan: Program yang Baik Dimulai dari Cara Berpikir yang Tepat

Ketika seseorang mulai belajar pemrograman, perhatian biasanya tertuju pada sintaks dan cara menulis kode. Namun, semakin kompleks program yang dibuat, semakin penting kemampuan untuk merancang penyelesaian masalah dan mengelola data.

Algoritma membantu kita menentukan langkah-langkah untuk menyelesaikan masalah. Struktur data membantu kita menyimpan dan mengorganisasi informasi agar dapat diolah dengan tepat.

Keduanya saling melengkapi. Algoritma yang baik membutuhkan cara pengelolaan data yang sesuai, sementara pemilihan struktur data juga perlu mempertimbangkan operasi yang akan dilakukan oleh algoritma.

Hal utama yang perlu diingat

(- ) Algoritma adalah urutan langkah logis untuk menyelesaikan masalah.

(- ) Efisiensi algoritma berkaitan dengan pertumbuhan kebutuhan komputasi ketika jumlah data bertambah.

(- ) Struktur data adalah cara mengorganisasi dan menyimpan data.

(- ) Array, vector, Linked List, Stack, Queue, Map, dan Set memiliki karakteristik berbeda.

(- ) Algoritma dan struktur data bekerja bersama untuk membangun program yang efektif.

Dengan memahami kedua konsep ini, kita tidak lagi hanya belajar bagaimana menulis instruksi menggunakan C++, tetapi juga mulai belajar bagaimana merancang solusi komputasi yang lebih terstruktur dan efisien.

Continue reading Mempelajari Algoritma dan Struktur Data