Wednesday, December 21, 2016

Bab 6. C++ Untuk Pemula



Eksplorasi Fungsi







Pada Bab 5, Anda telah belajar bagaimana menggunakan fungsi-fungsi penghasil nilai. Pada bab ini, Anda akan mengeksplorasi fungsi terdefinisi-pengguna secara umum dan, secara khusus, fungsi yang tidak memiliki tipe data, yang dikenal dengan fungsi kosong.


Fungsi Kosong

Fungsi kosong dan fungsi penghasil nilai memiliki struktur yang sama. Keduanya memiliki kepala dan tubuh. Seperti fungsi penghasil nilai, Anda dapat menempatkan fungsi kosong terdefinisi-pengguna sebelum atau sesudah fungsi main. Namun, eksekusi program selalu diawali dengan statemen pertama di dalam fungsi main. Jika Anda menempatkan fungsi kosong terdefinisi-pengguna setelah fungsi main, Anda sebaiknya menempatkan prototipe fungsi sebelum fungsi main. Fungsi kosong tidak  memiliki tipe data. Oleh karena itu, tipeFungsi, yaitu tipe nilai balik, di dalam kepala fungsi dan statemen return di dalam tubuh fungsi kosong tidak ada artinya. Tetapi, di dalam sebuah fungsi kosong, Anda dapat menggunakan statemen return tanpa nilai, yang secara umum dipakai untuk keluar dari fungsi. Seperti fungsi penghasil nilai, fungsi kosong dapat memiliki parameter formal.

Karena fungsi kosong tidak memiliki tipe data, ia tidak digunakan (dipanggil) di dalam sebuah ekspresi. Pemanggilan terhadap fungsi kosong merupakan statemen yang berdiri sendiri. Jadi, untuk memanggil sebuah fungsi kosong, Anda menggunakan nama fungsi disertai dengan parameter aktual (jika ada) pada suatu statemen yang berdiri sendiri. Sebelum contoh fungsi kosong disajikan, sebelumnya akan diberika sintaks dari sebuah fungsi kosong.

Definisi Fungsi
Definisi fungsi dari fungsi kosong yang memiliki parameter memiliki sintaks berikut:

void namaFungsi(daftar parameter formal)
{
    statemen-statemen
}

dimana di dalamnya statemen-statemen biasanya merupakan statemen deklarasi dan/atau statemen tereksekusikan (executable). Daftar parameter format bisa kosong, dan pada kasus itu, kurung kosong tetap dibutuhkan pada kepala fungsi.

Daftar Parameter Formal
Daftar parameter formal memiliki sintaks berikut:

tipeData& variabel, tipeDataa& variabel, ...

Anda harus menspesifikasi kedua tipe data dan nama variabel di dalam daftar parameter formal. Simbol & yang ditempatkan setelah tipeData memiliki makna spesial; ia hanya digunakan untuk parameter formal tertentu dan akan didiskusikan nanti pada bab ini.

Pemanggilan Fungsi
Pemanggilan fungsi mempunyai sintaks berikut:

namaFungsi(daftar parameter aktual);

Daftar Parameter Aktual
Daftar parameter aktual mempunyai sintaks berikut:

ekspresi atau variabel, ekspresi atau variabel, ...

dimana di dalamnya ekspresi dapat memuat nilai konstanta tunggal. Seperti fungsi penghasil nilai, pada pemanggilan fungsi, jumlah parameter aktual berikut dengan tipe datanya masing-masing harus cocok dengan parameter formal dengan urutan yang sesuai. Parameter aktual dan parameter formal memiliki relasi satu-ke-satu. Pemanggilan fungsi menyebabkan eksekusi terhadap tubuh fungsi terpanggil. (Fungsi dengan parameter default akan didiskusikan nanti di akhir bab ini).

Contoh 6.1 menunjukkan sebuah fungsi kosong dengan parameter.

Contoh 6.1


void fungEksp(int a, double b, char c, int x)
{
    .
    .
    .
}

Fungsi fungEksp memiliki empat parameter.

Parameter memfasilitasi komunikasi antara fungsi pemanggil (seperti main) dengan fungsi terpanggil. Parameter memampukan fungsi untuk memanipulasi pelbagai data setiap kali ia dipanggil. Secara umum, ada dua jenis parameter formal: parameter nilai dan parameter referensi.

Parameter nilai: Parameter formal yang menerima sebuah salinan isi dari parameter aktual terkait.

Parameter referensi: Parameter formal yang menerima lokasi (alamat memori) dari parameter aktual terkait.

Ketika Anda membubuhkan simbol & setelah tipeData di dalam daftar parameter formal, variabel yang berada setelah tipeData menjadi parameter referensi.

Contoh 6.2 menunjukkan sebuah fungsi kosong yang memiliki parameter nilai dan parameter referensi.

Contoh 6.2


void ekspFung(int satu, int& dua, char tiga, double& empat)
{
    .
    .
    .
}

Fungsi ekspFung memiliki empat parameter: (1) satu, sebuah parameter nilai bertipe int; (2) dua, sebuah parameter referensi bertipe int; (3) tiga, sebuah parameter nilai bertipe char; dan (4) empat, sebuah parameter referensi bertipe double.

Contoh 6.3


Anda akan menuliskan sebuah program untuk menampilkan pola berikut:

   *
  * *
 * * *
* * * *

Baris pertama memiliki satu bintang dengan beberapa spasi sebelum bintang, baris kedua memiliki dua bintang, beberapa spasi sebelum bintang dan sebuah spasi di antara bintang, dan seterusnya. Selanjutnya, akan dituliskan metode tampilBintang yang memiliki dua parameter, sebuah parameter untuk menspesifikasi jumlah spasi sebelum bintang pada sebuah baris dan sebuah parameter kedua untuk menetapkan jumlah bintang pada sebuah baris. Agar lebih spesifik, definisi atas metode tampilBintang adalah:

void tampilBintang(int spasi, int bintangPdBaris)
{
    int hitung;

    //menampilkan jumlah spasi sebelum bintang pada sebuah baris
    for (hitung = 1; hitung <= spasi; hitung++)
        cout << ' ';

    //menampilkan jumlah bintang dengan sebuah spasi di antaranya
    for (hitung = 1; hitung <= bintangPdBaris; hitung++)
        cout << " *";

    cout << endl;
} //akhir tampilBintang

Parameter pertama, spasi, menentukan berapa banyak spasi yang akan ditampilkan sebelum bintang (atau beberapa bintang); parameter kedua, bintangPdBaris, menentukan berapa banyak bintang yang akan ditampilkan pada sebuah baris. Jika nilai dari parameter spasi adalah 30, misalnya, maka loop for pertama di dalam metode tampilBintang akan dieksekusi sebanyak 30 kali dan menampilkan 30 spasi. Juga, karena Anda ingin menampilkan sebuah spasi di antara bintang, setiap iterasi dari loop for kedua di dalam metode tampilBintang akan menampilkan string “ *”, yaitu sebuah spasi yang diikuti dengan sebuah bintang.

Selanjutnya, perhatikan beberapa statemen berikut:

int jumlahBaris = 15;
int jumlahSpasi = 30;

for (kounter = 1; kounter <= jumlahBaris; kounter++)
{
    tampilBintang(jumlahSpasi, kounter);
    jumlahSpasi--;
}

Loop for memanggil fungsi tampilBintang. Setiap iterasi dari loop for ini menspesifikasi jumlah spasi yang diikuti dengan jumlah bintang yang akan ditampilkan pada sebuah baris, menggunakan variabel jumlahSpasi dan kounter. Setiap pemanggilan terhadap fungsi tampilBintang menerima jumlah spasi yang lebih sedikit satu dan jumlah bintang yang lebih banyak satu dari pemanggilan sebelumnya. Sebagai contoh, iterasi pertama dari loop for di dalam metode main menetapkan 30 spasi dan 1 bintang (yang dilewatkan sebagai parameter jumlahSpasi dan kounter kepada fungsi tampilBintang). Loop for kemudian mendekremen jumlah spasi sebesar 1 dengan mengeksekusi statemen jumlahSpasi--;. Di akhir loop for, jumlah bintang diinkremen sebesar 1 untuk iterasi berikutnya. Ini dilakukan dengan mengeksekusi statemen pembaruan kounter++ di dalam statemen for, yang menginkremen nilai dari variabel kounter sebesar 1. Dengan kata lain, pemanggilan kedua terhadap fungsi tampilBintang menerima 29 spasi dan 2 bintang sebagai parameter.

//Program: Menampilkan pola segitiga bintang

#include <iostream>

using namespace std;

void tampilBintang(int spasi, int bintangPdBaris);

int main()
{
    int jumlahBaris;       //variabel untuk menyimpan jumlah baris
    int kounter;     //variabel kendali loop for
    int jumlahSpasi;       //variabel untuk menyimpan jumlah spasi

    cout << "Masukkan jumlah baris bintang (1 sampai 20) "
         << "yang akan ditampilkan ";                         //Baris 1
    cin >> jumlahBaris;                                       //Baris 2

    while (jumlahBaris < 0 || jumlahBaris > 20)                      //Baris 3
    {
        cout << "Jumlah baris bintang harus "
             << "antara 1 dan 20" << endl;                           //Baris 4

        cout << "Masukkan jumlah baris bintang "
             << "(1 sampai 20) yang akan ditampilkan: ";             //Baris 5

        cin >> jumlahBaris;                                          //Baris 6
    }

    cout << endl << endl;                                     //Baris 7
    jumlahSpasi = 30;                                                //Baris 8

    for (kounter = 1; kounter <= jumlahBaris; kounter++)             //Baris 9
    {
        tampilBintang(jumlahSpasi, kounter);                  //Baris 10
        jumlahSpasi--; //Baris 11
    }

    return 0;                                                        //Baris 12
}


void tampilBintang(int spasi, int bintangPdBaris)
{
    int hitung;

    for (hitung = 1; hitung <= spasi; hitung++)                      //Baris 13
        cout << ' ';                                                 //Baris 14

    for (hitung = 1; hitung <= bintangPdBaris; hitung++)             //Baris 15
        cout << " * ";                                        //Baris 16
    cout << endl;
}

Keluaran Program:

Masukkan jumlah baris bintang (1 sampai 20) yang akan ditampilkan 15

                               *
                              *  *
                             *  *  *
                            *  *  *  *
                           *  *  *  *  *
                          *  *  *  *  *  *
                         *  *  *  *  *  *  *
                        *  *  *  *  *  *  *  *
                       *  *  *  *  *  *  *  *  *
                      *  *  *  *  *  *  *  *  *  *
                     *  *  *  *  *  *  *  *  *  *  *
                    *  *  *  *  *  *  *  *  *  *  *  *
                   *  *  *  *  *  *  *  *  *  *  *  *  *
                  *  *  *  *  *  *  *  *  *  *  *  *  *  *
                 *  *  *  *  *  *  *  *  *  *  *  *  *  *  *

Pada fungsi main, pengguna pertama-tama diminta untuk menetapkan berapa banyak baris bintang yang akan ditampilkan (baris 1). Pada program ini, pengguna dibatasi dengan 20 baris karena 20 baris cocok untuk ditampilkan pada layar. Karena program dibatasi menjadi hanya 20 baris, loop while pada baris 3 sampai baris 6 memastikan bahwa program hanya menampilkan 1 sampai 20 baris bintang.


Parameter Nilai

Bagian sebelumnya telah mendefinisikan dua tipe parameter, yaitu parameter nilai dan parameter referensi. Contoh 6.3 menunjukkan sebuah program yang menggunakan sebuah fungsi dengan parameter. Sebelum mempelajari contoh-contoh lain dari fungsi kosong dengan parameter, Anda perlu mengamati parameter nilai dan parameter referensi. Ketika sebuah fungsi dipanggil, nilai dari parameter aktual disalin ke parameter formal terkait. Jika parameter formal merupakan parameter nilai, maka setelah penyalinan nilai dari parameter aktual, tidak ada lagi hubungan antara parameter formal dan parameter aktual; jadi, parameter formal memiliki salinan data sendiri. Oleh karena itu, selama eksekusi program, parameter formal memanipulasi data yang disimpan di ruang memorinya sendiri. Program pada contoh 6.4 lebih lanjut mengilustrasikan bagaimana sebuah parameter nilai bekerja.

Contoh 6.4


Program berikut menunjukkan bagaimana sebuah parameter formal dari tipe data primitif bekerja.

//Contoh 6.4
//Program mengilustrasikan bagaimana sebuah parameter nilai bekerja.

#include <iostream>

using namespace std;

void fungsiNilaiParam(int angka);

int main()
{
    int bilangan = 6;                                         //Baris 1

    cout << "Baris 2: Sebelum memanggil fungsi "
         << "fungsiNilaiParam, bilangan = " << bilangan
         << endl;                                      //Baris 2

    fungsiNilaiParam(bilangan);                        //Baris 3

    cout << "Baris 4: Setelah memanggil fungsi "
         << "fungsiNilaiParam, bilangan = " << bilangan
         << endl; //Baris 4

    return 0;
}

void fungsiNilaiParam(int angka)
{
    cout << "Baris 5: Di dalam fungsi fungsiNilaiParam, "
         << "sebelum pengubahan, angka = " << angka
         << endl;                                      //Baris 5

    angka = 15;                                        //Baris 6

    cout << "Baris 7: Di dalam fungsi fungsiNilaiParam, "
         << "setelah pengubahan, angka = " << angka
         << endl;                                      //Baris 7
}

Keluaran Program:

Baris 2: Sebelum memanggil fungsi fungsiNilaiParam, bilangan = 6
Baris 5: Di dalam fungsi fungsiNilaiParam, sebelum pengubahan, angka = 6
Baris 7: Di dalam fungsi fungsiNilaiParam, setelah pengubahan, angka = 15
Baris 4: Setelah memanggil fungsi fungsiNilaiParam, bilangan = 6

Program ini bekerja sebagai berikut. Eksekusi dimulai pada fungsi main. Statemen pada baris 1 mendeklarasikan dan menginisialisasi variabel int, bilangan. Statemen pada baris 2 menampilkan nilai dari bilangan sebelum pemanggilan fungsi fungsiNilaiParam; statemen pada baris 3 memanggil fungsi fungsiNilaiParam. Nilai dari variabel bilangan kemudian dilewatkan kepada parameter formal angka. Kendali program sekarang beralih ke fungsi fungsiNilaiParam.

Statemen pada baris 5 menampilkan nilai dari angka sebelum pengubahan nilainya. Statemen pada baris 6 mengubah nilai dari angka menjadi 15; statemen pada baris 7 menampilkan nilai dari angka. Setelah statemen ini dieksekusi, fungsi fungsiNilaiParam keluar dan kendali program kembali kepada fungsi main.

Statemen pada baris 4 menampilkan nilai dari bilangan setelah pemanggilan fungsi fungsiNilaiParam. Contoh keluaran program menunjukkan bahwa nilai dari bilangan (baris 2 dan baris 4) tetap sama meskipun nilai dari parameter formal terkaitnya, angka, berubah di dalam fungsi fungsiNilaiParam.

Keluaran menunjukkan urutan dimana statemen-statemen dieksekusi.

Setelah penyalinan data, sebuah parameter nilai tidak lagi memiliki koneksi dengan parameter aktual, jadi parameter nilai tidak dapat melewatkan sembarang hasil kembali kepada fungsi pemanggil. Ketika fungsi dieksekusi, apapun perubahan yang dilakukan terhadap parameter formal tidak akan berpengaruh terhadap parameter aktual. Parameter aktual tidak lagi ada hubungan dengan apa yang terjadi pada parameter formal. Jadi, parameter nilai memberikan hubungan satu-arah antara parameter aktual dan parameter formal. Inilah mengapa dikatakan bahwa fungsi dengan parameter nilai memiliki keterbatasan.


Variabel Referensi sebagai Parameter

Program pada contoh 6.4 mengilustrasikan bagaimana sebuah parameter nilai bekerja. Di sisi lain, dimisalkan bahwa parameter formal merupakan sebuah parameter referensi. Karena parameter referensi menerima alamat (lokasi memori) dari parameter aktual, ia dapat melewatkan satu atau lebih nilai dari sebuah fungsi dan dapat mengubah nilai dari parameter aktual.

Parameter referensi berguna dalam tiga situasi:
·         Ketika nilai dari parameter aktual perlu diubah.
·         Ketika Anda ingin menghasilkan satu atau lebih nilai balik dari sebuah fungsi.
·         Ketika pelewatan alamat dapat menghemat ruang memori dan waktu komputasi pada kasus pemrosesan data besar.

Ingat bahwa ketika Anda membubuhi & yang ditempatkan setelah tipeData di dalam daftar parameter formal pada sebuah fungsi, variabel yang ditempatkan setelah tipeData menjadi parameter referensi.

Contoh 6.5


Menghitung Nilai
Program berikut mengambil skor sebuah matakuliah sebagai argumen (sebuah nilai dari 0 dan 100) dan menentukan nilai matakuliah seorang mahasiswa. Program ini mempunyai tiga fungsi: main, dapatSkor, dan tampilNilai, sebagai berikut:
1.      main
a.       Mendapatkan skor matakuliah.
b.      Menampilkan nilai matakuliah.
2.      dapatSkor
a.       Meminta pengguna untuk memberikan masukan.
b.      Membaca masukan.
c.       Menampilkan skor mahasiswa.
3.      tampilNilai
a.       Menghitung nilai matakuliah.
b.      Menampilkan nilai matakuliah.

Program utuh adalah sebagai berikut:

//Program ini membaca skor matakuliah dan menampilkan
//nilai matakuliah terkait.

#include <iostream>

using namespace std;

void dapatSkor(int& skor);
void tampilNilai(int skor);

int main()
{
    int skorMtKuliah;

    cout << "Baris 1: Berdasarkan pada skor matakuliah, \n"
         << " program ini menghitung "
         << "nilai matakuliah." << endl;                      //Baris 1

    dapatSkor(skorMtKuliah);                                         //Baris 2

    tampilNilai(skorMtKuliah);                                //Baris 3

    return 0;
}

void dapatSkor(int& skor)
{
    cout << "Baris 4: Masukkan skor matakuliah: ";                   //Baris 4
    cin >> skor;                                              //Baris 5

    cout << endl << "Baris 6: Skor matakuliah adalah "
         << skor << endl;                                     //Baris 6
}

void tampilNilai(int cSkor)
{
    cout << "Baris 7: Nilai Anda untuk matakuliah ini adalah ";      //Baris 7

    if (cSkor >= 90)                                                 //Baris 8
        cout << "A." << endl;
    else if (cSkor >= 80)
        cout << "B." << endl;
    else if(cSkor >= 70)
        cout << "C." << endl;
    else if (cSkor >= 60)
        cout << "D." << endl;
    else
        cout << "F." << endl;
}

Keluaran Program:

Baris 1: Berdasarkan pada skor matakuliah,
program ini menghitung nilai matakuliah.
Baris 4: Masukkan skor matakuliah: 85

Baris 6: Skor matakuliah adalah 85
Baris 7: Nilai Anda untuk matakuliah ini adalah B.

Program ini bekerja sebagai berikut. Program mulai dieksekusi pada baris 1, yang menampilkan baris pertama dari keluaran (lihat contoh keluaran program). Statemen pada baris 2 memanggil fungsi dapatSkor dengan parameter aktual skorMtKuliah (sebuah variabel yang dideklarasikan di dalam main). Karena parameter formal, skor, dari fungsi dapatSkor merupakan parameter referensi, alamat (yaitu, lokasi memori dari variabel skorMtKuliah) yang dilewatkan kepada skor. Jadi, kedua skor dan skorMtKuliah menunjuk ke lokasi memori yang sama. Lihat Gambar 6.1.



Gambar 6.1 Variabel skorMtKuliah dan parameter skor


Apapun perubahan yang dilakukan terhadap skor akan mengubah nilai dari skorMtKuliah.

Kendali kemudian beralih ke fungsi getSkor, dan statemen pada baris 4 dieksekusi, menampilkan baris kedua pada keluaran. Statemen ini meminta pengguna untuk memasukkan skor matakuliah. Statemen pada baris 5 membaca dan menyimpan nilai yang dimasukkan oleh pengguna (85 pada contoh keluaran program) di dalam skor, yang sebenarnya adalah skorMtKuliah (karena skor merupakan parameter referensi). Jadi, pada titik ini, nilai dari variabel skor dan skorMtKuliah adalah 85 (lihat Gambar 6.2).


Gambar 6.2 Variabel skorMtKuliah dan parameter skor setelah statemen pada baris 5 dieksekusi


Selanjutnya, statemen pada baris 6 menampilkan nilai dari skor seperti yang ditunjukkan pada baris ketiga dari contoh keluaran program. Setelah baris 6 dieksekusi, kendali program kembali kepada fungsi main (lihat Gambar 6.3).


Gambar 6.3 Variabel skorMtKuliah setelah statemen pada baris 6 dieksekusi dan kendali program kembali kepada main

Statemen pada baris 3 dieksekusi berikutnya. Ia merupakan sebuah pemanggilan terhadap fungsi tampilNilai dengan parameter aktual skorMtKuliah. Karena parameter formal cSkor dari fungsi tampilNilai adalah sebuah parameter nilai, parameter cSkor menerima nilai dari parameter aktual terkait, skorMtKuliah. Jadi, nilai dari cSkor adalah 85. Setelah penyalinan nilai dari skorMtKuliah ke dalam cSkor, tidak ada lagi komunikasi antara cSkor dan skorMtKuliah. (Lihat Gambar 6.4).


Gambar 6.4 Variabel skorMtKuliah dan parameter cSkor


Program kemudian mengeksekusi statemen pada baris 7, yang menampilkan baris keempat keluaran. Statemen if...else pada baris 8 menentukan dan menampilkan nilai matakuliah. Karena statemen keluaran pada baris 7 tidak memuat karakter garis-baru atau manipulator endl, keluaran dari statemen if...else merupakah bagian dari baris keempat pada keluaran program. Setelah statemen if...else dieksekusi, kendali kembali ke fungsi main. Karena statemen berikutnya yang akan dieksekusi di dalam fungsi main adalah statemen terakhir pada fungsi tersebut, program berhenti.

Pada program ini, fungsi main pertama-tama memanggil fungsi dapatSkor untuk mendapatkan skor matakuliah dari pengguna. Fungsi main kemudian memanggil fungsi tampilNilai untuk menghitung dan menampilkan nilai berdasarkan skor matakuliah. Skor matakuliah didapatkan melalui fungsi dapatSkor; kemudian, skor matakuliah ini dipakai oleh fungsi tampilNilai. Karena nilai yang didapatkan oleh fungsi dapatSkor digunakan nanti pada program, fungsi dapatSkor harus melewatkan nilai ini ke luar. Jadi, parameter formal yang menampung nilai ini harus berupa parameter referensi.


Parameter Nilai dan Parameter Referensi: Alokasi Memori

Ketika sebuah fungsi dipanggil, memori untuk tiap parameter formal dan variabelnya yang dideklarasikan di dalam tubuh fungsi (disebut juga dengan variabel lokal) dialokasikan di dalam area data fungsi. Ingat bahwa pada kasus parameter nilai, nilai dari parameter aktual disalin ke dalam sel memori dari parameter formal terkait. Pada kasus parameter referensi, alamat dari parameter aktual dilewatkan kepada parameter formal. Yaitu, isi dari parameter formal adalah sebuah alamat. Selama manipulasi data, isi dari parameter formal memerintahkan komputer untuk memanipulasi data di dalam sel memori yang diindikasikan oleh isi parameter formal. Jadi, pada kasus parameter referensi, baik parameter aktual maupun parameter formal menunjuk ke lokasi memori yang sama. Konsekuensinya, selama eksekusi program, perubahan apapun yang dilakukan terhadap parameter formal akan mengubah nilai dari parameter aktual.

Karena pelewatan parameter merupakan hal yang fundamental dalam bahasa pemrograman, contoh 6.6 dan contoh 6.7 lebih lanjut akan mengilustrasikan konsep ini. Setiap contoh merangkum skenario yang berbeda.

Contoh 6.6


Program berikut menunjukkan bagaimana parameter referensi dan parameter nilai bekerja.

//Contoh 6.6: Parameter referensi dan parameter nilai

#include <iostream>

using namespace std;

void fungsiSatu(int a, int& b, char v);
void fungsiDua(int& x, int y, char& w);

int main()
{
    int angka1, angka2;
    char ch;

    angka1 = 10;                                              //Baris 1
    angka2 = 15;                                              //Baris 2
    ch = 'A';                                                        //Baris 3

    cout << "Baris 4: Di dalam main: angka1 = " << angka1
         << ", angka2 = " << angka2 << ", dan ch = "
         << ch << endl;                                       //Baris 4

    fungsiSatu(angka1, angka2, ch);                                  //Baris 5

    cout << "Baris 6: Setelah fungsiSatu: angka1 = " << angka1
         << ", angka2 = " << angka2 << ", dan ch = "
         << ch << endl;                                       //Baris 6

    fungsiDua(angka2, 25, ch);                                //Baris 7
   
       cout << "Baris 8: Setelah fungsiDua: angka1 = " << angka1
         << ", angka2 = " << angka2 << ", dan ch = "
         << ch << endl;                                       //Baris 8

    return 0;
}

void fungsiSatu(int a, int& b, char v)
{
    int satu;
    satu = a;                                                        //Baris 9
    a++;                                                      //Baris 10
    b = b * 2;                                                //Baris 11
    v = 'B';                                                  //Baris 12

    cout << "Baris 13: Di dalam fungsiSatu: a = " << a
         << ", b = " << b << ", v = " << v
         << ", dan satu = " << satu << endl;                  //Baris 13
}

void fungsiDua(int& x, int y, char& w)
{
    x++;                                                      //Baris 14
    y = y * 2;                                                //Baris 15
    w = 'G';                                                  //Baris 16

    cout << "Baris 17: Di dalam fungsiDua: x = " << x
         << ", y = " << y << ", dan w = " << w
         << endl;                                             //Baris 17
}

Keluaran Program:

Baris 4: Di dalam main: angka1 = 10, angka2 = 15, dan ch = A
Baris 13: Di dalam fungsiSatu: a = 11, b = 30, v = B, dan satu = 10
Baris 6: Setelah fungsiSatu: angka1 = 10, angka2 = 30, dan ch = A
Baris 17: Di dalam fungsiDua: x = 31, y = 50, dan w = G
Baris 8: Setelah fungsiDua: angka1 = 10, angka2 = 31, dan ch = G

Sekarang akan dijejak program ini untuk meningkatkan pemahaman Anda. Setiap nilai variabel ditunjukkan sebelum dan/atau sesudah tiap statemen dieksekusi.
Tepat sebelum statemen pada baris 1 dieksekusi, memori dialokasikan hanya untuk variabel-variabel dari fungsi main; memori ini tidak diinisialisasi. Setelah statemen pada baris 3 dieksekusi, tiap variabel tersebut ditunjukkan pada Gambar 6.5.
Gambar 6.5 Nilai tiap variabel setelah baris 3 dieksekusi


Statemen pada baris 4 menghasilkan keluaran berikut:

Baris 4: Di dalam main: angka1 = 10, angka2 = 15, dan ch = A

Statemen pada baris 5 merupakan sebuah pemanggilan terhadap fungsi fungsiSatu. Sekarang, fungsi fungsiSatu memiliki tiga parameter dan satu variabel lokal. Memori untuk ketiga parameter dan variabel lokal pada fungsi fungsiSatu dialokasikan. Karena parameter formal b adalah parameter referensi, maka ia menerima alamat (lokasi memori) dari parameter aktual terkait, pada kasus ini angka2. Dua parameter yang lain adalah parameter nilai, jadi keduanya menerima salinan nilai dari dua parameter aktual terkait. Tepat sebelum statemen pada baris 9 dieksekusi, tiap variabel ditampilkan pada Gambar 6.6.


Gambar 6.6 Nilai tiap variabel tepat sebelum statemen pada baris 9 dieksekusi


Setelah statemen pada baris 9 dieksekusi, satu = a;, dieksekusi, tiap variabel ditunjukkan pada Gambar 6.7.

Gambar 6.7 Nilai tiap variabel setelah statemen pada baris 9 dieksekusi

Setelah statemen pada baris 10, a++;, dieksekusi, tiap variabel ditunjukkan pada Gambar 6.8.


Gambar 6.8 Nilai tiap variabel setelah statemen pada baris 10 dieksekusi


Setelah statemen pada baris 11, b = b * 2;, dieksekusi, tiap variabel ditunjukkan pada Gambar 6.9. (Perhatikan bahwa variabel b mengubah nilai dari angka2).


Gambar 6.9 Nilai tiap variabel setelah statemen pada baris 11 dieksekusi

Setelah statemen pada baris 12, v = ‘B’;, dieksekusi, tiap variabel ditunjukkan pada Gambar 6.10.


Gambar 6.10 Nilai tiap variabel setelah statemen pada baris 12 dieksekusi


Statemen pada baris 13 menghasilkan keluaran berikut:

Baris 13: Di dalam fungsiSatu: a = 11, b = 30, v = B, dan satu = 10

Setelah statemen pada baris 13 dieksekusi, kendali program kembali ke baris 6 dan memori yang teralokasi untuk tiap variabel pada fungsi fungsiSatu didealokasi (dibebaskan). Gambar 6.11 menunjukkan nilai tiap variabel dari fungsi main.

Gambar 6.11 Nilai tiap variabel ketika kendali program kembali ke baris 6


Baris 6 menghasilkan keluaran:

Baris 6: Setelah fungsiSatu: angka1 = 10, angka2 = 30, dan ch = A

Statemen pada baris 7 merupakan sebuah pemanggilan terhadap fungsi fungsiDua. Sekarang, fungsiDua memiliki tiga parameter: x, y, dan w. Selain itu, x dan w merupakan parameter referensi, dan y adalah sebuah parameter nilai. Jadi, x menerima alamat dari parameter aktual terkait, yaitu angka2, dan w menerima alamat dari parameter aktual terkait, yaitu ch. Variabel y menyalin nilai 25 ke dalam sel memorinya. Gambar 6.12 menunjukkan nilai tiap variabel sebelum statemen pada baris 14 dieksekusi.

Gambar 6.12 Nilai tiap variabel sebelum statemen pada baris 14 dieksekusi


Setelah statemen pada baris 14, x++;, dieksekusi, tiap variabel ditampilkan pada Gambar 6.13. (Perhatikan bahwa variabel x mengubah nilai dari angka2).


Gambar 6.13 Nilai tiap variabel setelah statemen pada baris 14 dieksekusi


Setelah statemen pada baris 15, y = y * 2;, dieksekusi, tiap variabel ditunjukkan pada Gambar 6.14.


Gambar 6.14 Nilai tiap variabel setelah statemen pada baris 15 dieksekusi

Setelah statemen pada baris 16, w = ‘G’;, dieksekusi, tiap variabel ditampilkan pada Gambar 6.15. (Perhatikan bahwa variabel w mengubah nilai dari ch).


Gambar 6.15 Nilai tiap variabel setelah statemen pada baris 16 dieksekusi

Baris 17 menghasilkan keluaran berikut:

Baris 17: Di dalam fungsiDua: x = 31, y = 50, dan w = G

Setelah statemen pada baris 17 dieksekusi, kendali program kendali ke baris 8. Memori yang dialokasikan untuk tiap variabel dari fungsi fungsiDua didealokasikan (dibebaskan). Nilai tiap variabel pada fungsi main ditunjukkan pada Gambar 6.16.

Gambar 6.16 Nilai tiap variabel ketika kendali program kembali ke baris 8

Statemen pada baris 8 menghasilkan keluaran berikut:

Baris 8: Setelah fungsiDua: angka1 = 10, angka2 = 31, dan ch = G

Setelah statemen pada baris 8 dieksekusi, program berhenti.

Contoh 6.7


Contoh ini juga menunjukkan bagaimana parameter referensi memanipulasi parameter aktual.

//Contoh 6.7: Parameter referensi dan parameter nilai.
//Program: Membuat Anda berpikir.

#include <iostream>

using namespace std;

void tambahPertama(int& pertama, int& kedua);
void gandaPertama(int satu, int dua);
void kuadratPertama(int& ref, int nil);

int main()
{
    int angka = 5;

    cout << "Baris 1: Di dalam main: angka = " << angka
         << endl;                                             //Baris 1

    tambahPertama(angka, angka);                              //Baris 2

    cout << "Baris 3: Di dalam main setelah tambahPertama:"
         << " angka = " << angka << endl;                            //Baris 3

    gandaPertama(angka, angka);                               //Baris 4

    cout << "Baris 5: Di dalam main setelah "
         << "gandaPertama: angka = " << angka << endl;               //Baris 5

    kuadratPertama(angka, angka);                             //Baris 6

    cout << "Baris 7: Di dalam main setelah "
         << "kuadratPertama: angka = " << angka << endl;             //Baris 7

    return 0;
}

void tambahPertama(int& pertama, int& kedua)
{
    cout << "Baris 8: Di dalam tambahPertama: pertama = "
         << pertama << ", kedua = " << kedua << endl;         //Baris 8

    pertama = pertama + 2;                                    //Baris 9

    cout << "Baris 10: Di dalam tambahPertama: pertama = "
         << pertama << ", kedua = " << kedua << endl;         //Baris 10

    kedua = kedua * 2;                                        //Baris 11

    cout << "Baris 12: Di dalam tambahPertama: pertama = "
         << pertama << ", kedua = " << kedua << endl;        //Baris 12
}

void gandaPertama(int satu, int dua)
{
    cout << "Baris 13: Di dalam gandaPertama: satu = "
         << satu << ", dua = " << dua << endl;                //Baris 13

    satu = satu * 2;                                                 //Baris 14

    cout << "Baris 15: Di dalam gandaPertama: satu = "
         << satu << ", dua = " << dua << endl;                //Baris 15

    dua = dua + 2;                                            //Baris 16

    cout << "Baris 17: Di dalam gandaPertama: satu = "
         << satu << ", dua = " << dua << endl;                //Baris 17
}

void kuadratPertama(int& ref, int nil)
{
    cout << "Baris 18: Di dalam kuadratPertama: ref = "
         << ref << ", nil = " << nil << endl;                 //Baris 18

    ref = ref * ref;                                                 //Baris 19

    cout << "Baris 20: Di dalam kuadratPertama: ref = "
         << ref << ", nil = " << nil << endl;                 //Baris 20

    nil = nil + 2;                                            //Baris 21

    cout << "Baris 22: Di dalam kuadratPertama: ref = "
         << ref << ", nil = " << nil << endl;                 //Baris 22
}

Keluaran Program:

Baris 1: Di dalam main: angka = 5
Baris 8: Di dalam tambahPertama: pertama = 5, kedua = 5
Baris 10: Di dalam tambahPertama: pertama = 7, kedua = 7
Baris 12: Di dalam tambahPertama: pertama = 14, kedua = 14
Baris 3: Di dalam main setelah tambahPertama: angka = 14
Baris 13: Di dalam gandaPertama: satu = 14, dua = 14
Baris 15: Di dalam gandaPertama: satu = 28, dua = 14
Baris 17: Di dalam gandaPertama: satu = 28, dua = 16
Baris 5: Di dalam main setelah gandaPertama: angka = 14
Baris 18: Di dalam kuadratPertama: ref = 14, nil = 14
Baris 20: Di dalam kuadratPertama: ref = 196, nil = 14
Baris 22: Di dalam kuadratPertama: ref = 196, nil = 16
Baris 7: Di dalam main setelah kuadratPertama: angka = 196

Kedua parameter dari fungsi tambahPertama adalah parameter referensi, dan kedua parameter dari fungsi gandaPertama adalah parameter nilai. Statemen:

tambahPertama(angka, angka);

di dalam fungsi main (baris 2) melewatkan referensi dari angka kepada kedua parameter formal pertama dan kedua dari fungsi tambahPertama, karena kedua parameter aktual terkait untuk kedua parameter formal tersebut adalah sama. Yaitu, variabel pertama dan kedua merujuk ke lokasi memori yang sama, yaitu angka. Gambar 6.17 mengilustrasikan situasi ini.


Gambar 6.17 Tiap parameter dari fungsi tambahPertama

Sembarang perubahan yang dilakukan pertama terhadap nilainya akan mengubah nilai dari kedua dan angka. Sama halnya, apapun perubahan yang dilakukan kedua terhadap nilainya akan mengubah nilai dari pertama dan angka, karena ketiga variabel merujuk ke lokasi memori yang sama. (Perhatikan bahwa angka diinisialisasi dengan 5).

Tiap parameter formal pada gandaPertama merupakan parameter nilai. Jadi statemen:

gandaPertama(angka, angka);

di dalam fungsi main (baris 4) menyalin nilai dari angka ke dalam satu dan dua karena kedua parameter aktual untuk kedua parameter formal adalah sama. Gambar 6.18 mengilustrasikan skenario ini.


Gambar 6.18 Tiap parameter dari fungsi gandaPertama


Karena kedua satu dan dua merupakan parameter nilai, apapun perubahan yang dilakukan satu terhadap nilainya tidak akan berpengaruh terhadap nilai satu dan angka. Sama halnya, apapun perubahan yang dilakukan dua terhadap nilainya tidak akan berpengaruh terhadap satu dan angka. (Perhatikan bahwa nilai dari angka sebelum fungsi gandaPertama dieksekusi adalah 14).

Parameter formal ref dari fungsi kuadratPertama adalah sebuah parameter referensi, dan parameter formal nil adalah sebuah variabel nilai. Variabel ref menerima alamat dari parameter aktual terkaitnya, yaitu angka, dan variabel nil menyalin nilai dari parameter aktual terkaitnya, yang juga angka. Jadi, kedua angka dan ref merujuk ke lokasi memori yang sama, yaitu angka. Gambar 6.19 mengilustrasikan situasi ini.

Gambar 6.19 Tiap parameter dari fungsi kuadratPertama


Sembarang perubahan yang dilakukan ref akan mengubah angka. Sembarang perubahan yang dilakukan nil tidak mempengaruhi angka. (Perhatikan bahwa nilai dari angka sebelum fungsi kuadratPertama dieksekusi adalah 14).


Skop Pengenal

Beberapa bagian terdahulu dan Bab 5 telah menyajikan beberapa contoh program dengan fungsi-fungsi terdefinisi-pengguna. Pengenal dideklarasikan di dalam sebuah kepala fungsi, di dalam suatu blok, atau di suatu luar blok. Pertanyaan umum yang diajukan adalah: Apakah Anda diijinkan untuk mengakses sembarang pengenal di mana saja di dalam program? Jawabannya adalah tidak. Anda harus mengikut beberapa aturan dalam mengakses sebuah pengenal. Skop sebuah pengenal berkaitan dengan di mana di dalam program sebuah pengenal dapat diakses (visibel atau dikenali). Ingat bahwa sebuah pengenal adalah nama sesuatu di dalam C++, seperti nama variabel atau nama fungsi.

Bagian ini akan memeriksa skop sebuah pengenal. Pertama, didefinisikan dua istilah berikut:

Pengenal lokal: Pengenal yang didefinisikan di dalam sebuah fungsi (atau blok).
Pengenal lokal tidak dapat diakses atau tidak dikenali di luar fungsi (blok).

Pengenal global: Pengenal yang dideklarasikan di luar setiap definisi fungsi.

Selain itu, C++ juga tidak mengijinkan fungsi bersarang. Yaitu, Anda tidak boleh mencantumkan definisi sebuah fungsi di dalam tubuh fungsi lain.

Secara umum, beberapa aturan berikut diterapkan ketika sebuah pengenal diakses:
1.      Pengenal global (seperti variabel) dapat diakses oleh sebuah fungsi atau sebuah blok jika:
a.       Pengenal tersebut dideklarasikan sebelum definisi fungsi (blok).
b.      Nama fungsi berbeda dari pengenal tersebut.
c.       Semua parameter pada fungsi memiliki nama berbeda dari nama pengenal tersebut.
d.      Semua pengenal lokal (seperti variabel lokal) memiliki nama berbeda dari nama pengenal tersebut.
2.      (Blok bersarang) Sebuah pengenal yang dideklarasikan di dalam sebuah blok dapat diakses:
a.       hanya di dalam blok dimulai dari titik di mana ia dideklarasikan sampai akhir blok tersebut.
b.      Oleh blok-blok yang bersarang di dalam blok tersebut jika blok bersarang tidak memiliki pengenal dengan nama sama.
3.      Skop dari nama fungsi sama dengan skop pengenal yang dideklarasikan di luar sembarang blok. Jadi, skop dari nama fungsi sama dengan skop variabel global.
Sebelum mempelajari contoh untuk menjelaskan aturan-aturan skop, pertama-tama Anda perlu memperhatikan skop dari pengenal yang dideklarasikan di dalam statemen for. C++ mengijinkan programer untuk mendeklarasikan sebuah variabel di dalam statemen inisialisasi pada statemen for. Sebagai contoh, statemen for berikut:

for (int hitung = 1; hitung < 10; hitung++)
    cout << hitung << endl;

mendeklarasikan variabel hitung dan menginisialisasinya dengan 1. Skop dari variabel hitung dibatasi hanya di dalam tubuh loop for.

Program C++ berikut membantu mengilustrasikan aturan-aturan skop:

#include <iostream>

using namespace std;

const double LAJU = 10.50;

int z;
double t;

void satu(int x, char y);
void dua(int a, int b, char x);
void tiga(int satu, double y, int z);

int main()
{
    int angka, pertama;
    double x, y, z;
    char nama, akhir;
    .
    .
    .
    return 0;
}

void satu(int x, char y)
{
.
.
.
}

int w;

void two(int a, int b, char x)
{
    int hitung;
    .
    .
    .
}

void tiga(int satu, double y, int z)
{
    char ch;
    int a;
    .
    .
    .
   
    //Blok empat
    {
        int x;
        char a;
       .
       .
    }//akhir blok empat
    .
    .
    .
}

Perhatikan bahwa fungsi tiga tidak dapat memanggil fungsi satu, karena fungsi tiga memiliki parameter formal bernama satu. Sama halnya, blok yang ditandai empat di dalam fungsi tiga tidak dapat menggunakan variabel int, a, yang dideklarasikan di dalam fungsi tiga, karena blok empat memiliki sebuah pengenal bernama a. Sebelum menutup diskusi pada bagian ini, akan dicatat beberapa hal tentang variabel global:
1.      Bab 1 telah menyatakan bahwa C++ tidak secara otomatis menginisialisasi variabel. Namun, beberapa kompiler menginisialisasi variabel global dengan nilai defaultnya. Sebagai contoh, jika sebuah variabel global yang tidak diinisialisasi adalah bertipe int, char, atau double, maka ia akan diinisialisasi dengan nol.
2.      Dalam C++, :: disebut dengan operator resolusi skop. Dengan menggunakan operator resolusi skop, sebuah variabel global yang berada sebelum definisi sebuah fungsi (blok) dapat diakses oleh fungsi (atau blok) bahkan jika fungsi (atau blok) memiliki sebuah pengenal dengan nama sama dengan variabel global tersebut. Dalam program sebelumnya, dengan menggunakan operator resolusi skop, fungsi main dapat merujuk variabel global sebagai ::z. Sama halnya, dimisalkan bahwa sebuah variabel global t dideklarasikan sebelum definisi fungsi, katakanlan, fungsiContoh. Maka, fungsiContoh dapat mengakses variabel t menggunakan operator resolusi skop bahkan jika fungsiContoh memiliki sebuah pengenal t. Dengan menggunakan operator resolusi skop, fungsiContoh dapat merujuk variabel global t sebagai ::t. Selain itu, dalam program sebelumnya, dengan menggunakan operator resolusi skop, fungsi tiga dapat memanggil fungsi satu.
3.      C++ menyediakan sebuah cara dalam mengakses variabel global yang dideklarasikan setelah definisi sebuah fungsi. Pada kasus ini, fungsi harus tidak memuat sembarang pengenal dengan nama sama dengan variabel global tersebut. Pada program sebelumnya, variabel global w dideklarasikan setelah definisi fungsi satu. Fungsi satu tidak memuat sembarang pengenal bernama w. Oleh karena itu, w dapat diakses oleh fungsi satu jika Anda mendeklarasikan w sebagai variabel eksternal di dalam fungsi satu. Untuk mendeklarasikan w sebagai variabel eksternal di dalam fungsi satu, fungsi satu harus memuat statemen berikut:

extern int w;

Dalam C++, extern merupakan katakunci. Kata extern pada statemen tersebut mengumumkan bahwa w adalah sebuah variabel global yang dideklarasikan di suatu tempat. Jadi, ketika fungsi satu dipanggil, tidak ada memori yang dideklarasikan untuk w.


Variabel Global dan Konstanta Bernama

Sebuah program C++ dapat memuat variabel global. Penggunaan variabel global dapat menyebabkan efek samping. Jika lebih dari satu fungsi menggunakan variabel global yang sama dan masalah terjadi, maka akan menjadi sulit untuk menemukan apa yang terjadi dan di mana. Masalah yang disebabkan oleh variabel global pada suatu tempat di dalam program dapat disalahpahami sebagai masalah yang disebabkan di tempat lain.

Sebagai contoh, perhatikan program berikut:

//Variabel global

#include <iostream>

using namespace std;

int t;

void fungsiSatu(int& a);

int main()
{
    t = 15;                                                   //Baris 1

    cout << "Baris 2: Di dalam main: t = " << t << endl;             //Baris 2

    fungsiSatu(t);                                            //Baris 3

    cout << "Baris 4: di dalam main setelah fungsiSatu: "
         << " t = " << t << endl;                             //Baris 4

    return 0; //Baris 5
}

void fungsiSatu(int& a)
{
    cout << "Baris 6: Di dalam fungsiSatu: a = " << a
         << " dan t = " << t << endl;                         //Baris 6

    a = a + 12;                                               //Baris 7

    cout << "Baris 8: Di dalam fungsiSatu: a = " << a
         << " dan t = " << t << endl;                         //Baris 8

    t = t + 13;                                               //Baris 9

    cout << "Baris 10: Di dalam fungsiSatu: a = " << a
         << " dan t = " << t << endl;                         //Baris 10
}

Keluaran Program:

Baris 2: Di dalam main: t = 15
Baris 6: Di dalam fungsiSatu: a = 15 dan t = 15
Baris 8: Di dalam fungsiSatu: a = 27 dan t = 27
Baris 10: Di dalam fungsiSatu: a = 40 dan t = 40
Baris 4: di dalam main setelah fungsiSatu:  t = 40

Program ini memiliki sebuah variabel t yang dideklarasikan sebelum definisi atas sembarang fungsi. Karena tidak ada fungsi yang memiliki pengenal t, variabel t dapat diakses di mana saja di dalam program. Selain itu, program memuat sebuah fungsi kosong dengan sebuah parameter referensi.

Pada baris 3, fungsi main memanggil fungsi fungsiSatu, dan parameter aktual yang dilewatkan kepada fungsiSatu adalah t. Jadi, a, parameter formal dari fungsiSatu, menerima alamat dari t. Apapun perubahan yang dilakukan oleh a terhadap nilainya akan mengubah t. Karena t dapat secara langsung diakses di mana saja di dalam program, pada baris 9, fungsi fungsiSatu mengubah nilai dari t menggunakan t sendiri. Jadi, Anda dapat memanipulasi nilai dari t menggunakan sebuah parameter referensi atau lewat dirinya sendiri.

Pada program tersebut, jika nilai terakhir dari t tidak benar, maka akan menjadi sulit untuk menentukan apa yang telah terjadi dan di mana masalah terjadi. Direkomendasikan bahwa Anda tidak menggunakan variabel global.

Contoh 6.8


Berikut merupakan sebuah contoh program menu-driven. Ketika program dieksekusi, ia memberikan pengguna sebuah daftar pilihan untuk dipilih. Program ini lebih lanjut akan mengilustrasikan bagaimana parameter nilai dan parameter referensi bekerja. Program ini mengkonversi panjang dari kaki dan inci ke dalam meter dan sentimeter dan sebaliknya. Program memuat tiga fungsi: tampilPilihan, kakiDanInciKeMeterDanSenti, dan meterDanSentiKe-KakiDanInci. Fungsi tampilPilihan menginformasikan pengguna tentang bagaimana menggunakan program.

//Program menu-driven.

#include <iostream>

using namespace std;

const double KONVERSI = 2.54;
const int INCI_DALAM_KAKI = 12;
const int SENTIMETER_DALAM_METER = 100;

void tampilPilihan();
void kakiDanInciKeMeterDanSenti(int f, int in, int& mt, int& ct);
void meterDanSentiKeKakiDanInci(int mt, int ct, int& f, int& in);

int main()
{
    int kaki, inci;
    int meter, sentimeter;
    int pilihan;

    do
    {
        tampilPilihan();

        cin >> pilihan;
        cout << endl;

        switch (pilihan)
        {
        case 1:
            cout << "Masukkan kaki dan inci: ";
            cin >> kaki >> inci;
            cout << endl;

            kakiDanInciKeMeterDanSenti(kaki, inci, meter, sentimeter);

            cout << kaki << " kaki, "
                 << inci << " inci = "
                 << meter << " meter, "
                 << sentimeter << " sentimeter." << endl;
            break;
        case 2:
            cout << "Masukkan meter dan sentimeter: ";
            cin >> meter >> sentimeter;
            cout << endl;

            meterDanSentiKeKakiDanInci(meter, sentimeter, kaki, inci);

            cout << meter << " meter, "
                 << sentimeter << " sentimeter = "
                 << kaki << " kaki, "
                 << inci << " inci."
                 << endl;
            break;
        case 99:
            break;
        default:
            cout << "Masukan tak-valid." << endl;
        }
    }
    while (pilihan != 99);

    return 0;
}

void tampilPilihan()
{
    cout << "Tekan--" << endl;
    cout << "1: Untuk mengkonversi dari kaki dan inci ke meter "
         << "dan sentimeter." << endl;

    cout << "2: Untuk mengkonversi dari meter dan sentimeter ke kaki "
         << "dan inci." << endl;

    cout << "99: Untuk keluar program." << endl;
}

void kakiDanInciKeMeterDanSenti(int f, int in, int& mt, int& ct)
{
    int inci;

    inci = f * INCI_DALAM_KAKI + in;
    ct = static_cast<int>(inci * KONVERSI);
    mt = ct / SENTIMETER_DALAM_METER;
    ct = ct % SENTIMETER_DALAM_METER;
}

void meterDanSentiKeKakiDanInci(int mt, int ct, int& f, int& in)
{
    int sentimeter;

    sentimeter = mt * SENTIMETER_DALAM_METER + ct;
    in = static_cast<int>(sentimeter / KONVERSI);
    f = in / INCI_DALAM_KAKI;
    in = in % INCI_DALAM_KAKI;
}

Keluaran Program:

Tekan--
1: Untuk mengkonversi dari kaki dan inci ke meter dan sentimeter.
2: Untuk mengkonversi dari meter dan sentimeter ke kaki dan inci.
99: Untuk keluar program.
2

Masukkan meter dan sentimeter: 4 25

4 meter, 25 sentimeter = 13 kaki, 11 inci.
Tekan--
1: Untuk mengkonversi dari kaki dan inci ke meter dan sentimeter.
2: Untuk mengkonversi dari meter dan sentimeter ke kaki dan inci.
99: Untuk keluar program.
1

Masukkan kaki dan inci: 15 8

15 kaki, 8 inci = 4 meter, 77 sentimeter.
Tekan--
1: Untuk mengkonversi dari kaki dan inci ke meter dan sentimeter.
2: Untuk mengkonversi dari meter dan sentimeter ke kaki dan inci.
99: Untuk keluar program.
99


Variabel Statis dan Variabel Otomatis

Variabel-variabel yang dideklarasikan sejauh ini memiliki dua aturan sederhana:
1.      Memori untuk variabel global tetap teralokasi sepanjang program dieksekusi.
2.      Memori untuk variabel yang dideklarasikan di dalam sebuah blok dialokasikan saat kendali program memasuki blok dan didealokasikan (dibebaskan) saat kendali program keluar dari blok. Sebagai contoh, memori untuk parameter formal dan variabel lokal pada sebuah fungsi dialokasikan ketika fungsi dipanggil dan didealokasikan ketika fungsi keluar atau berhenti.
Sebuah variabel pada aturan 2 disebut dengan variabel otomatis. Sebuah variabel pada aturan 1 disebut dengan variabel statis. Variabel global adalah variabel statis, dan secara default, variabel yang dideklarasikan di dalam sebuah blok adalah variabel otomatis. Anda dapat mendeklarasikan sebuah variabel statis di dalam sebuah blok menggunakan katakunci static. Sintaks untuk mendeklarasikan sebuah variabel statis adalah:

static tipeData pengenal;

Statemen:

static int x;

mendeklarasikan x sebagai sebuah variabel statis bertipe int.

Variabel statis yang dideklarasikan di dalam sebuah blok bersifat lokal di dalam blok tersebut, dan skopnya sama dengan pengenal lokal yang lain di dalam blok tersebut.

Kebanyakan kompiler menginisialisasi variabel static dengan nilai defaultnya. Sebagai contoh, variabel static int diinisialisasi dengan 0. Tetapi, akan lebih baik bila Anda sendiri yang menginisialisasi variabel static. Pada kasus ini, variabel static diinisialisasi ketika ia dideklarasikan. Statemen:

static int x = 0;

mendeklarasikan x sebagai sebuah variabel statis bertipe int dan menginisialisasinya dengan 0.

Contoh 6.9


Program berikut menunjukkan bagaimana variabel statis dan variabel otomatis bekerja.

//Program: Variabel statis dan variabel otomatis

#include <iostream>

using namespace std;

void test();

int main()
{
    int hitung;

    for (hitung = 1; hitung <= 5; hitung++)
        test();

    return 0;
}

void test()
{
    static int x = 0;
    int y = 10;

    x = x + 2;
    y = y + 1;

    cout << "Di dalam test x = " << x << " dan y = "
         << y << endl;
}

Keluaran Program:

Di dalam test x = 2 dan y = 11
Di dalam test x = 4 dan y = 11
Di dalam test x = 6 dan y = 11
Di dalam test x = 8 dan y = 11
Di dalam test x = 10 dan y = 11

Pada fungsi test, x merupakan sebuah variabel static yang diinisialisasi dengan 0, dan y adalah sebuah variabel otomatis yang diinisialisasi dengan 0. Fungsi main memanggil fungsi test sebanyak lima kali. Memori untuk variabel y dialokasikan setiap kali fungsi test dipanggil dan didealokasi ketika kendali program keluar dari fungsi tersebut. Jadi, setiap kali test dipanggil, ia akan menampilkan nilai yang sama untuk y. Namun, karena x adalah variabel statis, memori untuk x tetap teralokasi sepanjang program dieksekusi. Variabel x diinisialisasi dengan 0. Pemanggilan beruntun terhadap fungsi test menggunakan nilai terkini dari x.


Pengoverloadan Fungsi: Pengenalan

Dalam sebuah program C++, beberapa fungsi bisa memiliki nama sama. Ini disebut dengan pengoverloadan fungsi. Sebelum dijelaskan beberapa aturan dalam mengoverload sebuah fungsi, akan didefinisikan beberapa hal berikut:

Dua fungsi dikatakan memiliki daftar parameter formal berbeda jika kedua fungsi memiliki:
·         Jumlah parameter formal yang berbeda atau
·         Jika jumlah parameter formal sama, maka tipe data dari parameter formal harus berbeda sedikitnya satu parameter formal.

Sebagai contoh, perhatikan beberapa kepala fungsi berikut:

void fungsiSatu(int x)
void fungsiDua(int x, double y)
void fungsiTiga(double y, int x)
int fungsiEmpat(char ch, int x, double y)
int fungsiLima(char ch, int x, string nama)

Semua fungsi tersebut memiliki daftar parameter formal yang berbeda.

Sekarang, perhatikan beberapa kepala fungsi berikut:

void fungsiEnam(int x, double y, char ch)
void fungsiTujuh(int satu, double u, char chPertama)

Fungsi fungsiEnam dan fungsiTujuh keduanya memiliki tiga parameter formal, dan tipe data dari tiap parameter terkait sama. Oleh karena itu, kedua fungsi ini memiliki daftar parameter formal.

Pengoverloadan fungsi: Menciptakan beberapa fungsi dengan nama sama.

Sidik sebuah fungsi terdiri-dari nama fungsi dan daftar parameter formalnya. Dua fungsi memiliki sidik berbeda jika keduanya memiliki nama sama atau memiliki daftar parameter formal yang berbeda. (Perhatikan bahwa sidik sebuah fungsi tidak mencakup tipe fungsi (tipe nilai balik)).

Jika sebuah fungsi dioverload, maka semua fungsi teroverload dan fungsi dioverload akan memiliki nama sama. Oleh karena itu, semua fungsi yang bernama sama akan memiliki sidik berbeda jika masing-masing memiliki daftar parameter formal yang berbeda. Jadi, beberapa kepala fungsi berikut secara tepat mengoverload fungsiXYZ:

void fungsiXYZ()
void fungsiXYZ(int x, double y)
void fungsiXYZ(double satu, int y)
void fungsiXYZ(int x, double y, char ch)

Perhatikan beberapa kepala fungsi berikut yang dipakai untuk mengoverload fungsiABC:

void fungsiABC(int x, double y)
int fungsiABC(int x, double y)

Kedua kepala fungsi memiliki nama sama dan daftar parameter formal sama. Oleh karena itu, kedua kepala fungsi yang dipakai untuk mengoverlod fungsi fungsiABC adalah tidak benar. Pada kasus ini, kompiler akan membangkitkan error sintaks. (Perhatikan bahwa tipe nilai balik dari tiap fungsi berbeda).

Jika sebuah fungsi dioverload, maka di dalam sebuah pemanggilan terhadap fungsi tersebut, sidik fungsi (daftar parameter formal) menentukan fungsi mana yang akan dieksekusi.

Dimisalkan bahwa Anda perlu menuliskan sebuah fungsi untuk menentukan yang terbesar dari dua item. Kedua item bisa integer, angka titik-mengambang, karakter, atau string. Anda dapat menuliskan beberapa fungsi sebagai berikut:

int terbesarInt(int x, int y);
char terbesarChar(char pertama, char kedua);
double terbesarDouble(double u, double v);
string terbesarString(string pertama, string kedua);

Fugsi terbesarInt menentukan terbesar dari dua integer; fungsi terbesarChar menentukan terbesar dari dua karakter; dan seterusnya. Semua fungsi ini melakukan operasi yang sama. Daripada harus memberikan nama yang berbeda


untuk tiap fungsi tersebut, Anda dapat menggunakan nama sama untuk semua fungsi, katakanlah terbesar. Pada kasus ini, Anda dapat mengoverload fungsi terbesar. Jadi, Anda dapat menuliskan beberapa prototipe fungsi tersebut menjadi:

int terbesar(int x, int y);
char terbesar(char pertama, char kedua);
double terbesar(double u, double v);
string terbesar(string pertama, string kedua);

Jika pemanggilan adalah terbesar(5, 3), misalnya, maka fungsi pertama yang dieksekusi. Jika pemanggilan adalah terbesar(‘A’, ‘9’), maka fungsi kedua yang dieksekusi, dan seterusnya.


Fungsi dengan Parameter Default

Bagian ini akan mendiskusikan fungsi dengan parameter default. Ingat bahwa ketika sebuah fungsi dipanggil, jumlah parameter aktual dan parameter formal harus sama. C++ melonggarkan kondisi ini untuk fungsi dengan parameter formal. Anda menspesifikasi nilai dari sebuah parameter default ketika nama fungsi muncul di dalam program untuk pertama kalinya, seperti di dalam prototipe. Secara umum, aturan-aturan berikut diterapkan terhadap fungsi dengan parameter default:
·         Jika Anda tidak menspesifikasi nilai dari sebuah parameter default, maka nilai default akan dipakai untuk parameter tersebut.
·         Semua parameter default harus berupa parameter far-right dari fungsi.
·         Dimisalkan bahwa sebuah fungsi memiliki lebih dari satu parameter default. Dalam sebuah pemanggilan fungsi, jika nilai dari sebuah parameter default tidak dispesifikasi, maka Anda harus mengabaikan semua argumen yang ada di kanannya.
·         Nilai default dapat berupa konstanta, variabel global, atau pemanggilan fungsi.
·         Anda tidak dapat menugaskan sebuah nilai konstanta sebagai nilai default kepada parameter referensi.

Perhatikan prototipe fungsi berikut:

void fungsiEksp(int x, int y, double t, char z = 'A', int u = 67,
             char v = 'G', double w = 78.34);

Fungsi fungsiEksp memiliki tujuh parameter. Parameter z, u, v, dan w adalah parameter default. Jika tidak ada nilai yang dispesifikasi untuk z, u, v, dan w di dalam sebuah pemanggilan terhadap fungsi fungsiEksp, maka nilai-nilai defaultnya digunakan.

Dimisalkan bahwa Anda memiliki beberapa statemen berikut:

int a, b;
char ch;
double d;

Beberapa pemanggilan fungsi berikut adalah benar:


fungsiEksp(a, b, d);
fungsiEksp(a, 15, 34.6, 'B', 87, ch);
fungsiEksp(b, a, 14.56, 'D');

Pada statemen 1, nilai default dari z, u, v, dan w digunakan. Pada statemen 2, nilai default dari z diganti dengan ‘B’, nilai default dari u digantikan dengan 87, nilai default dari v digantikan dengan nilai dari ch, dan nilai default dari w digunakan. Pada statemen 3, nilai default dari z digantikan dengan ‘D’, dan nilai default dari u, v, dan w digunakan.

Beberapa pemanggilan fungsi berikut adalah tidak benar:
1.       fungsiEksp(a, 15, 34.6, 46.7);
2.      fungsiEksp(b, 25, 48.76, 'D', 4567, 78.34);
Pada statemen 1, karena nilai dari z diabaikan, maka semua nilai default lainnya harus diabaikan. Pada statemen 2, karena nilai dari v diabaikan, maka nilai dari w harus diabaikan pula.

Berikut merupakan beberapa prototipe fungsi ilegal dengan parameter default:

1.        void fungsiSatu(int x, double z = 23.45, char ch, int u = 45);
2.        int fungsiDua(int panjang = 1, int lebar, int tinggi = 1);
3.        void fungsiTiga(int x, int& y = 16, double z = 34);

Pada statemen 1, karena parameter kedua z adalah parameter default, semua parameter yang berada setelah z harus parameter default. Pada statemen 2, karena parameter pertama adalah parameter default, semua parameter lain harus parameter default. Pada statemen 3, nilai konstanta tidak bisa ditugaskan kepada y karena y adalah parameter referensi.

Contoh 6.10 lebih lanjut mengilustrasikan beberapa fungsi dengan parameter default.

Contoh 6.110



#include <iostream>
#include <iomanip>

using namespace std;

int volume(int l = 1, int w = 1, int h = 1);
void fungsiSatu(int& x, double y = 12.34, char z = 'B');

int main()
{
    int a = 23;
    double b = 48.78;
    char ch = 'M';

    cout << fixed << showpoint;
    cout << setprecision(2);

    cout << "Baris 1: a = " << a << ", b = "
         << b << ", ch = " << ch << endl;                            //Baris 1

    cout << "Baris 2: Volume = " << volume()
         << endl;                                             //Baris 2

    cout << "Baris 3: Volume = " << volume(5, 4)
         << endl;                                             //Baris 3

    cout << "Baris 4: Volume = " << volume(34)
         << endl;                                             //Baris 4

    cout << "Baris 5: Volume = "
         << volume(6, 4, 5) << endl;                                 //Baris 5

    fungsiSatu(a);                                            //Baris 6
    fungsiSatu(a, 42.68);                                     //Baris 7
    fungsiSatu(a, 34.65, 'Q');                                //Baris 8

    cout << "Baris 9: a = " << a << ", b = "
         << b << ", ch = " << ch << endl;                            //Baris 9

    return 0;
}

int volume(int l, int w, int h)
{
    return l * w * h;                                                //Baris 10
}

void fungsiSatu(int& x, double y, char z)
{
    x = 2 * x;                                                //Baris 11

    cout << "Baris 12: x = " << x << ", y = "
         << y << ", z = " << z << endl;                       //Baris 12
}

Keluaran Program:

Baris 1: a = 23, b = 48.78, ch = M
Baris 2: Volume = 1
Baris 3: Volume = 20
Baris 4: Volume = 34
Baris 5: Volume = 120
Baris 12: x = 46, y = 12.34, z = B
Baris 12: x = 92, y = 42.68, z = B
Baris 12: x = 184, y = 34.65, z = Q
Baris 9: a = 184, b = 48.78, ch = M


CONTOH PEMROGRAMAN: Klasifikasi Angka

Pada contoh ini, akan digunakan beberapa fungsi untuk menulis-ulang program yang menentukan angka genap dan angka ganjil atas sederet integer yang diberikan. Program ini telah dituliskan pada Bab 4. Algoritma utama tetap sama:
1.      Menginisialisasi variabel nol, ganjil, dan genap dengan 0.
2.      Membaca sebuah angka.
3.      Jika angka genap, maka genap diinkremen, dan jika angka nol, maka nol diinkremen; sebaliknya, ganjil diinkremen.
4.      Mengulangi langkah 2 dan 3 untuk setiap angka di dalam daftar.
Bagian-bagian utama program adalah: menginisialisasi variabel, membaca dan mengklasifikasi angka, dan kemudian menampilkan hasil. Untuk menyederhanakan fungsi main dan lebih lanjut mengilustrasikan pelewatan parameter, program mencakup:
·         Sebuah fungsi inisialisasi untuk menginisialisasi variabel, seperti nol, ganjil, dan genap.
·         Sebuah fungsi dapatAngka untuk mendapatkan angka.
·         Sebuah fungsi klasifikasiAngka untuk menentukan apakah angka ganjil atau genap (dan apakah ia juga nol).
·         Sebuah fungsi tampilHasil untuk menampilkan hasil.

Selanjutnya, akan didiskusikan tiap fungsi ini.

Fungsi inisialisasi
Fungsi inisialisasi dipakai untuk menginisialisasi variabel dengan nilai default. Variabl-variabel yang perlu diinisialisasi adalah nol, ganjil, dan genap. Seperti sebelumnya, semua nilai awalnya adalah nol. Jelaslah bahwa fungsi ini memiliki tiga parameter. Karena nilai dari tiap parameter formal yang menginisialisasi tiap variabel ini harus dilewatkan ke luar fungsi, ketiga parameter formal ini harus berupa parameter referensi. Fungsi ini didefinisikan sebagai berikut:

void inisialisasi(int& hitungNol, int& hitungGanjil, int& hitungGenap)
{
    hitungNol = 0;
    hitungGanjil = 0;
    hitungGenap = 0;
}

Fungsi dapatAngka
Fungsi dapatAngka membaca sebuah angka dan kemudian melewatkan angka ini kepada fungsi main. Karena Anda hanya perlu melewatkan satu angka, fungsi ini hanya memiliki satu parameter. Parameter formal fungsi ini harus berupa parameter referensi karena angka yang dibaca dilewatkan ke luar fungsi. Fungsi ini didefinisikan sebagai berikut:

void dapatAngka(int& angka)
{
    cin >> angka;
}

Anda dapat pula menuliskan fungsi dapatAngka sebagai fungsi penghasil nilai.

Fungsi klasifikasiAngka
Fungsi klasifikasiAngka menentukan apakah angka berupa angka ganjil atau angka genap, dan jika angka genap, ia juga memeriksa apakah angka itu nol. Fungsi ini juga memperbarui nilai dari beberapa variabel nol, ganjil, dan genap. Fungsi ini perlu mengetahui angka yang akan dianalisa; oleh karena itu, angka harus dilewatkan sebagai parameter. Karena fungsi ini juga menginkremen penghitungan tertentu, beberapa variabel (variabel nol, ganjil, dan genap yang dideklarasikan di dalam main) yang memuat penghitungan harus dideklarasikan sebagai parameter kepada fungsi ini. Jadi, fungsi ini memiliki empat parameter.

Karena angka hanya akan dianalisa, Anda hanya perlu melewatkan nilainya. Jadi, parameter formal yang terkait dengan variabel ini adalah parameter nilai. Setelah menganalisa angka, fungsi ini menginkrmen nilai dari tiap variabel, nol, ganjil, dan genap. Oleh karena itu, tiap parameter formal yang berkaitan dengan variabel ini harus berupa parameter referensi. Algoritma untuk menganalisa angka dan menginkremen penghitungan tertentu sama seperti sebelumnya. Fungsi ini didefinisikan sebagai berikut:

void klasifikasiAngka(int angka, int& hitungNol, int& hitungGanjil,
                      int& hitungGenap)
{
    switch (angka % 2)
    {
        case 0:
            hitungGenap++;

            if (angka == 0)
                hitungNol++;
            break;
        case 1:
        case -1:
            hitungGanjil++;
    } //akhir switch
} //akhir klasifikasiAngka

Fungsi tampilHasil
Fungsi tampilHasil menampilkan hasil akhir. Untuk menampilkan hasil (yaitu, jumlah nol, jumlah genap, dan jumlah ganjil), fungsi ini harus memiliki akses terhadap tiap variabel nol, ganjil, dan genap yang dideklarasikan di dalam fungsi main. Oleh karena itu, fungsi ini memiliki tiga parameter. Karena fungsi ini hanya menampilkan tiap nilai variabel, tiap parameter adalah parameter nilai. Fungsi ini didefinisikan sebagai berikut:

void tampilHasil(int hitungNol, int hitungGanjil, int hitungGenap)
{
    cout << "Terdapat " << hitungGenap << " genap, "
         << "yang mencakup " << hitungNol << " nol"
         << endl;

    cout << "Jumlah angka ganjil adalah: " << hitungGanjil
         << endl;
} //akhir tampilHasil

Algoritma Utama
1.      Memanggil fungsi inisialisasi untuk menginisialisasi variabel-variabel.
2.      Meminta pengguna untuk memasukkan 20 angka.
3.      Untuk tiap angka di dalam daftar:
a.       Memanggil fungsi dapatAngka untuk membaca sebuah angka.
b.      Menampilkan angka.
c.       Memanggil fungsi klasifikasiAngka untuk mengklasifikasi angka dan menginkremen penghitungan tertentu.
4.      Memanggil fungsi tampilHasil untuk menampilkan hasil akhir.


Program Utuh

//******************************************************************
// Program: Klasifikasi Angka
// Program ini membaca 20 angka dan menampilkan jumlah angka nol,
// ganjil, dan genap.
//******************************************************************

#include <iostream>
#include <iomanip>

using namespace std;

const int N = 20;

//Prototipe fungsi
void inisialisasi(int& hitungNol, int& hitungGanjil, int& hitungGenap);
void dapatAngka(int& angka);
void klasifikasiAngka(int angka, int& hitungNol, int& hitungGanjil, int& hitungGenap);
void tampilHasil(int hitungNol, int hitungGanjil, int hitungGenap);

int main()
{
    //Deklarasi variabel
    int kounter;     //variabel kendali loop
    int angka;       //variabel untuk menyimpan angka baru
    int nol;         //variabel untuk menyimpan jumlah angka nol
    int ganjil;      //variabel untuk menyimpan jumlah angka ganjil
    int genap;       //variabel untuk menyimpan jumlah angka genap

    inisialisasi(nol, ganjil, genap);                  //Langkah 1

    cout << "Masukkan sebanyak " << N << " integer."
         << endl;                                      //Langkah 2

    cout << "Angka-Angka yang Anda masukkan adalah: "
         << endl;

    for (kounter = 1; kounter <= N; kounter++)         //Langkah 3
    {
        dapatAngka(angka);                             //Langkah 3a
        cout << angka << " ";                          //Langkah 3b
        klasifikasiAngka(angka, nol, ganjil, genap);   //Langkah 3c
    } // akhir loop for
    cout << endl;

    tampilHasil(nol, ganjil, genap);                          //Langkah 4

    return 0;
}

void inisialisasi(int& hitungNol, int& hitungGanjil, int& hitungGenap)
{
    hitungNol = 0;
    hitungGanjil = 0;
    hitungGenap = 0;
}


void dapatAngka(int& angka)
{
    cin >> angka;
}

void klasifikasiAngka(int angka, int& hitungNol, int& hitungGanjil,
                      int& hitungGenap)
{
    switch (angka % 2)
    {
        case 0:
            hitungGenap++;

            if (angka == 0)
                hitungNol++;
            break;
        case 1:
        case -1:
            hitungGanjil++;
    } //akhir switch
} //akhir klasifikasiAngka


void tampilHasil(int hitungNol, int hitungGanjil, int hitungGenap)
{
    cout << "Terdapat " << hitungGenap << " genap, "
         << "yang mencakup " << hitungNol << " nol"
         << endl;

    cout << "Jumlah angka ganjil adalah: " << hitungGanjil
         << endl;
} //akhir tampilHasil

Keluaran Program:

Masukkan sebanyak 20 integer.
Angka-Angka yang Anda masukkan adalah:
0 0 12 34 -3 -9 -57 89 48 65 78 0 0 23 32 0 0 0 21 45
0 0 12 34 -3 -9 -57 89 48 65 78 0 0 23 32 0 0 0 21 45
Terdapat 12 genap, yang mencakup 7 nol
Jumlah angka ganjil adalah: 8











No comments:

Post a Comment