Pernyataan: Background Cover ini menunjukkan Keaslian ... · Algoritma dalam Bahasa C Apa Itu...

download Pernyataan: Background Cover ini menunjukkan Keaslian ... · Algoritma dalam Bahasa C Apa Itu Algoritma Kata algoritma, mungkin bukan sesuatu yang asing bagi kita. ... bahasa pemrograman.

If you can't read please download the document

Transcript of Pernyataan: Background Cover ini menunjukkan Keaslian ... · Algoritma dalam Bahasa C Apa Itu...

  • Pernyataan: Background Cover ini menunjukkan Keaslian Ebook ini yang sesuai / sama dengan Cover CD depan aslinya. Dan bila background / Cover setiap Ebook yang ada dalam CD tidak sama dengan cover CD depan, maka Ebook tersebut tidak asli.

  • Mahir dan Professional Pemograman C++ [email protected] IlmuKomputer.Com

    Mahir dan professional Pemograman C++ Penulis : Muhammad Syahrizal

  • Kutipan Pasal 44, Ayat 1 dan 2, Undang-Undang Republik Indonesia tentang HAK CIPTA: Tentang Sanksi Pelanggaran Undang-Undang Nomor 6 Tahun 1982 tentang HAK CIPTA, sebgaimana telah diubah dengan Undang-Undang No.7 Tahun 1987 jo. Undang-Undang No.12 Tahun 1997, bahwa: 1. Barangsiapa dengan sengaja dan tanpa hak mengumumkan atau Memperbanyak suatu ciptaan atau memberi izin untuk itu, dipidana dengan pidana penjara paling lama 7 (tujuh) tahun dan/atau denda paling banyak Rp.100.000.000,- (seratus juta rupiah). 2. Barangsiapa dengan sengaja menyiarkan, memamerkan, mengedarkan, atau menjual kepada umum suatu ciptaan atau barang hasil pelanggaran Hak Cipta sebagaimana dimaksud dalam ayat (1), dipidana dengan pidana penjara paling lama 5 (lima) tahun dan/atau denda paling banyak Rp.50.000.000,- (lima puluh juta rupiah).

  • Mahir dan Professional Pemograman C++ Muhammad Syahrizal, SE, SH, S.Komp ©2007, Gratech Media Perkasa, Medan Hak cipta dilindungi undang-undang Diterbitkan pertama kali oleh Penerbit Gratech Media Perkasa Dilarang keras menerjemahkan, memfotokopi, atau memperbanyak sebagian atau seluruh isi buku ini tanpa izin tertulis dari penerbit.

  • Created By Muhammad Syahrizal 1

    Algoritma dalam Bahasa C Apa Itu Algoritma Kata algoritma, mungkin bukan sesuatu yang asing bagi kita. Penemunya adalah seorang ahli matematika dari Uzbekistan yang bernama Abu Abdullah Muhammad Ibn Musa al- Khwarizmi (770-840). Di literatur barat dia lebih terkenal dengan sebutan Algorizm. Panggilan inilah yang kemudian dipakai untuk menyebut konsep algorithm yang ditemukannya. Dalam bahasa Indonesia kita kemudian menyebutkannya sebagai algoritma. Algoritma adalah kunci dari bidang ilmu komputer, karena banyak bidang di bawah ilmu komputer yang lahir berdasarkan konsep algoritma ini. Pada hakekatnya algoritma juga adalah kunci dari kehidupan kita. Cara membuat masakan (resep masakan) adalah juga sebuah contoh nyata dari algoritma. Definisi Algoritma Kita bisa mendefinisikan algoritma seperti dibawah: Algoritma adalah logika, metode dan tahapan (urutan) sistematis yang digunakan untuk memecahkan suatu permasalahan. Kamus besar bahasa Indonesia (Balai Pustaka 1988) secara formal mendefinisikan algoritma sebagai: Algoritma adalah urutan logis pengambilan putusan untuk pemecahan masalah. Beda Algoritma dan Program Program adalah kompulan instruksi komputer, sedangkan metode dan tahapan sistematis dalam program adalah algoritma. Program ini ditulis dengan menggunakan bahasa pemrograman. Jadi bisa kita sebut bahwa program adalah suatu implementasi dari bahasa pemrograman. Beberapa pakar memberi formula bahwa: program = struktur data + algoritma

  • Created By Muhammad Syahrizal 2

    Bagaimanapun juga struktur data dan algoritma berhubungan sangat erat pada sebuah program. Algoritma yang baik tanpa pemilihan struktur data yang tepat akan membuat program menjadi kurang baik, semikian juga sebaliknya. Struktur data disini bisa berupa list, tree, graph, dsb. Akan dibahas secara mendetail pada bab-bab mendatang.

    Menilai Sebuah Algoritma Ketika manusia berusaha memecahkan masalah, metode atau teknik yang digunakan untuk memecahkan masalah itu ada kemungkinan bisa banyak (tidak hanya satu). Dan kita memilih mana yang terbaik diantara teknik-teknik itu. Hal ini sama juga dengan algoritma, yang memungkinkan suatu permasalahan dipecahkan dengan metode dan logika yang berlainan. Lalu bagaimana mengukur mana algoritma yang terbaik ? Beberapa persyaratan untuk menjadi algoritma yang baik adalah: • Tingkat kepercayaannya tinggi (realibility). Hasil yang diperoleh dari proses harus berakurasi tinggi dan benar. • Pemrosesan yang efisien (cost rendah). Proses harus diselesaikan secepat mungkin dan frekuensi kalkulasi yang sependek mungkin. • Sifatnya general. Bukan sesuatu yang hanya untuk menyelesaikan satu kasus saja, tapi juga untuk kasus lain yang lebih general. • Bisa Dikembangkan (expandable). Haruslah sesuatu yang dapat kita kembangkan lebih jauh berdasarkan perubahan requirement yang ada. • Mudah dimengerti. Siapapun yang melihat, dia akan bisa memahami algoritma anda. Susah dimengertinya suatu program akan membuat susah di maintenance (kelola). • Portabilitas yang tinggi (Portability). Bisa dengan mudah diimplementasikan di berbagai platform komputer.

    Contoh Algoritma dan Implementasinya Sebagai contoh sederhana, mari kita berlatih melihat permasalahan, mencoba menyusun algoritma, dan meng-implementasi-kan dalam bahasa C. Permasalahan Anda adalah seorang guru SD yang ingin membuat rangking dari nilai ujian dari 9 orang murid anda. Nilai ujian murid anda adalah sebagai berikut:

    Bagaimana algoritma dalam pembuatan rangking nilai tersebut ? Untuk memecahkan masalah diatas, kita bisa susun algoritma seperti dibawah: 1. Buat satu variable (misalnya rangking) 2. Set variable rangking = 1 3. Ambil satu nilai sebagai data yang ke a, misalnya 56 4. Chek nilai dari paling depan (56) sampai paling belakang (32) (b=0-8). Apabila nilai tersebut lebih tinggi daripada nilai ke a (56), maka set variable rangking = ranking + 1. 5. Ulangi proses nomor 2 dengan mengambil data ke (a) berikutnya.

  • Created By Muhammad Syahrizal 3

    Kemudian mari kita implementasikan algoritma diatas dalam program bahasa C. Program: Rangking Nilai Ujian #include #define banyaknya_nilai 9 main(){ static int nilai[]={56, 78, 43, 96, 67, 83, 51, 74, 32}; int rangking[banyaknya_nilai]; int a,b; for (a=0;a

  • Created By Muhammad Syahrizal 4

    Membilang dalam Bahasa Indonesia Dalam aplikasi yang berhubungan dengan uang , kadang – kadang diperlukan pernyataan nilai nominal tidak hanya dengan angka , tapi juga diperlukan pernyataan dalam bentuk terbilangnya. Tentu saja jika dibandingkan dengan pernyataan dengan angka , pernyataan dengan membilang lebih banyak membutuhkan ruang . Tapi disamping itu pernyataan dengan membilang bisa meminimkan jumlah kesalahan yang terjadi karena faktor kesalahan pembacaan . Untuk itu dalam kesempatan ini kita akan membuat sebuah fungsi yang dapat digunakan untuk merubah nilai menjadi bentuk terbilangnya. Di internet , tentunya sudah sangat banyak sekali source code yang di publish untuk keperluan ini , bahkan dengan listing yang cukup pendek. Tapi tentunya sebagai programer kita akan lebih tertantang jika mampu membuat fungsi tersebut sendiri . Untuk akan saya bahas alur / logika pemrogramannya , sehingga mudah untuk di translasikan dalam bahasa pemrograman lain. Untuk bisa membuat fungsi membilang dalam bahasa Indonesia kita harus tahu dulu , cara manusia membilang bilangan . Untuk itu mari kita analisa proses tersebut !!!!! Bilangan satuan 0 -> nol 1 -> satu 9 -> sembilan Ket : “->” berarti “dibaca” Untuk proses membilang bilangan satuan tentunya tidak terlalu susah jika di implementasikan dalam bahasa C . Anda bisa menggunakan seleksi untuk masing masing bilangan . Tapi penulis akan menggunakan bantuan array Berikut ialah potongan source codenya fungsi untuk membilang bilangan satuan char StrBilangan[10][10] = {"nol","satu","dua","tiga","empat","lima","enam","tujuh","delapan","sembi lan"}; void SaySatuan(char nilai) //0..9 { printf("%s",StrBilangan[nilai]); } Bilangan puluhan 10 -> sepuluh 11 -> sebelas 12 -> dua belas 13 -> tiga belas 19 -> sembilan belas 20 -> dua puluh

  • Created By Muhammad Syahrizal 5

    21 -> dua puluh satu 45 -> empat puluh lima 99 -> sembilan puluh delapan Secara umum untuk membilang bilangan puluhan bisa dilakukan dengan cara membilang puluhannya secara satuan dan kemudian diikuti dengan “puluh” dan dilanjutkan dengan membilang satuannya jika nilaisatuannya bukan 0. Untuk lebih jelas mari kita perhatikan contoh berikut Contoh : Kita akan membilang nilai 35 Kita ambil puluhannya dahulu . Untuk mengambil nilai puluhannya bisa didapat dengan membaginya dengan 10 . NilaiPuluhan = 35 / 10 = 3 Nilai Satuan bisa didapat dengan mengambil sisa pembagian dengan bilangan 10 NilaiSatuan = 35 % 10 = 5 Nah setelah dapat kita tinggal menggunakan cara diatas : SaySatuan(NilaiPuluhan) + “puluh” + SaySatuan(NilaiSatuan)*SaySatuan ialah fungsi untuk mencetak nilai satuan .Maka akan terbentuk tiga puluh lima Contoh berikutnya kita ambil 40 NilaiPuluhan = 4 NilaiSatuan = 0 Karena nilai satuan sama dengan 0 untuk itu kita tidak perlu membilang nilai satuannya jadi cukup dengan : SaySatuan(NilaiPuluhan) + “puluh” Maka akan didapat hasil “empat puluh" Jadi jelaslah maksud kata jika nilainya bukan 0 , yaitu untuk menghindari terjadinya (pada kasus 40) tercetak empat puluh nol Cara diatas memang benar untuk sebagian besar nilai puluhan tapi ada beberapa nilai yang perlu perkecualian . Dari contoh data analisa diatas dapat dilihat bahwa nilai 10,11,12 .. 19 tidak memenuhi cara diatas. Tapi jika dianalisa lebih lanjut bilangan 12..19 ternyata memiliki pola yang sama yaitu : membilang satuan dan diikuti dengan kata belas Untuk contoh saya ambil 14. NilaiSatuan = 4 . Maka dengan menggunakan cara diatas : SaySatuan(NilaiSatuan) + “belas” Untuk 10 dan 11 anda bisa gunakan seleksi biasa . Berikut ialah source code untuk membilang bilangan puluhan . void SayPuluhan(char nilai) // 10..99 { if (nilai < 10) // seleksi , jika lebih kecil dari 10 SaySatuan(nilai); // tentunya masuk ke fungsi SaySatuan else { if (nilai == 10) printf("sepuluh");

  • Created By Muhammad Syahrizal 6

    if (nilai == 11) printf("sebelas"); if (nilai >= 12 && nilai = 20 && nilai seratus 101 -> seratus satu 110 -> seratus sepuluh 189 -> seratus delapan puluh sembilan 200 -> dua ratus 201 -> dua ratus satu 999 -> sembilan ratus sembilan puluh sembilan Dapat dilihat bilangan ratusan juga memilik pola yang secara umum hampir sama yaitu : membilang nilai ratusannya diikuti kata ratus dan dilanjutkan dengan membilang nilai puluhannya jika nilai puluhannya bukan 0. Kita ambil contoh 223 NilaiRatusan = 223 / 100= 2 NilaiPuluhan = 223 % 100 = 23 Dengan cara diatas didapat : SaySatuan(NilaiRatusan) + “ratus” + SayPuluhan(NilaiPuluhan) Tentunya jika fungsi SayPuluhan anda benar akan tercetak : dua ratus dua puluh tiga Untuk perkecualian yaitu bilangan antara 100..199 . Untuk bilangan tersebut dapat dibilang dengan rumus Cetak “seratus” diikuti dengan membilang bilanga puluhannya Berikut ialah cuplikan SourceCodenya dalam C void SayRatusan(int nilai) // 100..999 { if (nilai < 100) SayPuluhan(nilai); // seleksi , jika puluhan else { if(nilai >= 100 && nilai

  • Created By Muhammad Syahrizal 7

    if (nilai >= 200 && nilai seribu 1.100 -> seribu seratus 2.111 -> dua ribu seratus sebelas 10.000 -> sepuluh ribu 25.250 -> dua puluh lima ribu dua ratus lima puluh 130.750 -> seratus tiga puluh ribu , tujuh ratus lima puluh 999.999 -> sembilan ratus sembilan puluh sembilan ribu , sembilan ratus sembilan puluh sembilan Jika diperhatikan ternyata untuk mencetak bilangan ribuan caranya sama sampai mencetak bilangan ratusan ribu yaitu : bilang nilai ribuannya diikuti dengan kata “ribu” dan dilanjutkan dengan bilang nilai ratusannya jika nilai ratusannya bukan 0. Sebagai contoh saya akan ambil 256.750 NilaiRibuan = 256.750 / 1000 = 256 NilaiRatusan = 256.750 % 1000 = 750 Dengan menggunakan cara diatas : SayRatusan(NilaiRibuan) + “ribu” + SayRatusan(NilaiRibuan) Tentunya jika Fungsi SayRatusan anda benar akan tercipta : dua ratus lima puluh enam ribu tujuh ratus lima puluh Dan seperti biasa perkecualian terdapat pada bilangan antara 1000..1999 , yaitu cukup dengan mencetak “seribu” diikuti dengan membilang nilai ratusannya jika tidak 0 void SayRibuan(unsigned long nilai) //1000...999999 { if (nilai < 1000) SayRatusan(nilai); //Seleksi jika ratusan else { if (nilai >= 1000 && nilai = 2000 && nilai

  • Created By Muhammad Syahrizal 8

    Begitu pula halnya untuk bilangan diatas 999.999 . Tidak terlalu susah bukan ? Ternyata untuk membuat fungsi membilang anda hanya perlu operator bagi (/) dan modulus (%), dan tentunya sedikit analisa Sebenarnya program diatas masih cukup panjang dan tentunya masih bisa dipendekkan dan dioptimasi lagi. Nah untuk tugas ini saya serahkan sepenuhnya kepada pembaca saja . Berikut ialah source code lengkap program membilang tersebut #include char StrBilangan[10][10] = {"nol","satu","dua","tiga","empat","lima","enam","tujuh","delapan","sembi lan"}; void SaySatuan(char nilai) //0..9 { printf("%s",StrBilangan[nilai]); } void SayPuluhan(char nilai) // 10..99 { if (nilai < 10) SaySatuan(nilai); else { if (nilai == 10) printf("sepuluh"); if (nilai == 11) printf("sebelas"); if (nilai >= 12 && nilai = 20 && nilai = 100 && nilai = 200 && nilai

  • Created By Muhammad Syahrizal 9

    } void SayRibuan(unsigned long nilai) //1000...999999 { if (nilai < 1000) SayRatusan(nilai); else { if (nilai >= 1000 && nilai = 2000 && nilai 999.999.999 { if (nilai < 1000000) SayRibuan(nilai); else { SayRatusan(nilai / 1000000); printf(" juta "); if(nilai % 1000000 != 0) SayRibuan(nilai % 1000000); } } void SayMilyar(unsigned long nilai) // 1.000.000.000 -> 999.999.999.999 { if (nilai < 1000000000) SayJuta(nilai); else { SayRatusan(nilai / 1000000000); printf(" Milyar "); if(nilai % 1000000000 != 0) SayJuta(nilai % 1000000000); } } void SayBilangan(unsigned long nilai) // Fungsi pengarah { if (nilai = 10 && nilai = 100 && nilai = 1000 && nilai = 1000000 && nilai = 1000000000) SayMilyar(nilai);

  • Created By Muhammad Syahrizal 10

    } void main(void) { SayBilangan(163); SayBilangan(25234); SayBilangan(-1); }

    Analisa Numerik: Mengecek Bilangan Prima Bilangan Prima ialah Bilangan yang hanya memiliki 2 faktor yaitu , 1 dan bilangan itu sendiri. Contoh : 7 merupakan bilangan Prima karena 7 hanya memiliki 2 faktor yaitu 1 dan 7 saja 8 bukan merupakan bilangan Prima karena 8 bisa memiliki lebih dari 2 faktor yaitu : 1 2 4 8 Dengan menggunakan pengertian diatas dapat dibuat algoritma : 1. Input N // N = Bilangan Prima yang akan di cek 2. counter = 0 // counter menyatakan jumlah faktor 3. FOR I = 1 to N step = 1 // step langkah setiap perulangan (i++) Jika N % I == 0 maka // Jika N habis di bagi I counter++ //Tambahkan Counter 4. Jika counter == 2 maka “N Bilangan Prima” Jika Tidak “N Bukan Bilangan Prima” Jika kita telaah lebih lanjut , untuk mengecek bilangan ke N maka diperlukan N kali iterasi (langkah 3 ) . Oke kalau begitu mari kita sederhanakan lagi Kita tahu bahwa 1. Bilangan genap kecuali 2 bukan merupakan bilangan prima 2. Bilangan Genap ialah bilangan yang kelipatan 2 3. Setiap Bilangan pasti memiliki faktor 1 dan bilangan itu sendiri Karena semua bilangan genap kecuali bukan prima dan Bilangan genap merupakan kelipatan 2 jadi kita dapat menskip pembagian dengan bilangan genap (step = 2) asalkan pertama kali dilakukan pengecekan bilangan genap. Karena Setiap bilangan pasti memiliki faktor 1 dan bilangan itu sendiri jadi kita tidak perlu mencek 1 dan bilangan itu sendiri , tapi cukup mulai dari 2 sampai dengan n -1 .Jika ada faktor pada range tersebut sudah barang tentu bahwa bilangan tersebut bukan bilangan prima.

  • Created By Muhammad Syahrizal 11

    Baiklah mari kita sempurnakan algoritmanya 1. Input N 2. Jika N == 2 maka // 2 Merupakan Bilangan Prima “N Bilangan Prima” 3. Jika N % 2 == 0 maka // Bilangan Genap bukan bilangan Prima “N Bukan Bilangan Prima” 4. FOR I = 3 To N-1 STEP 2 // Tidak perlu mengadakan pengecekan Jika N % I == 0 maka // terhadap bilangan genap “N Bukan Bilangan Prima” 5. “N Bilangan Prima Dengan sedikit analisis , algoritma diatas telah mampu dioptimasi . Jika sebelumnya untuk mengecek bilangan ke N pasti memerlukan N iterasi . Maka pada keadaan sekarang jika bilangan itu bilangan genap maka tidak perlu itersi ( best case ) jika bukan bilangan genap maka diperlukan paling banyak N / 2 iterasi ( worst case ) . Ternyata ada sebuah optimasi lagi yang dapat dilakukan . Apa itu ??? . Sebelumnya mari kita lihat sama – sama tabel di bawah ini:

    Tabel Diatas ialah Tabel Faktor dari 8 . Kalau diperhatikan ternyata pada nilai 4 ( kolom 1 baris 3 ) sudah ada pada kolom 2 . Contoh lain

    Tabel diatas ialah Tabel Faktor dari 12 . Kalau diperhatikan ternyata nilai 4 (kolom 1 baris)sudah ada pada kolom 2 . Apa yang bisa diambil dari contoh diatas ? , apa yang bisa dimanfaatkan untuk mengoptimasi algoritma pengecekan bilangan prima diatas ?? Dari tabel dapat disimpulkan : faktor 8 : 8 : 1 = 8 ; 8 : 2 = 4 ; 8 : 4 = 2 dst

  • Created By Muhammad Syahrizal 12

    pada kasus nilai 8 tidak perlu diadakan pengecekan melebihi dari nilai 2 faktor 12 : 12 : 1 = 12 ; 12 : 2 = 6 ; 12 : 3 = 4 ; 12 : 4 = 3 dst pada kasus nilai 12 tidak perlu diadakan pengecekan melebihi dari nilai 3 Artinya kita tidak perlu mengecek semua faktor dari bilangan. melainkan cukup setengahnya dari faktornya saja yaitu pada akar dari bilangan tersebut , karena faktor sisanya merupakan hasil pembagian dari bilangan tersebut dengan faktornya . Nah dengan analisis tersebut algoritma diatas dapat disederhanakan menjadi : 1. Input N 2. Jika N == 2 maka “N Bilangan Prima” 3. Jika N % 2 == 0 maka “N Bukan Bilangan Prima” 4. FOR I = 3 To Sqrt(N) STEP 2 // Sqrt(N) -> Akar dari N Jika N % I == 0 maka “N Bukan Bilangan Prima” 5. “N Bilangan Prima Algoritma diatas membutuhkan 0 itersi saat N bilangan genap . Sedangkan membutuhkan maksimum Akar(N) iterasi saat bilangan tersebut bukan bilangan genap . Berikut Source code lengkap dari algoritma diatas . #include #include int isprima(int n) { int li; if (n == 2) return 1; if (n % 2 == 0 || n == 1) return 0; for(li = 3;li

  • Created By Muhammad Syahrizal 13

    Rekursiif Pengenalan Rekursif ialah salah satu teknik pemrograman dengan cara memanggil sebuah fungsi dari dirinya sendiri, baik itu secara langsung maupun tidak langsung. Pemanggilan fungsi rekursif secara langsung berarti dalam fungsi tersebut terdapat statement untuk memanggil dirinya sendiri sedangkan secara tidak langsung berarti fungsi rekursif tersebut memanggil 1 atau lebih fungsi lain sebelum memanggil dirinya sendiri.

    Fungsi Rekursif Tak Langsung Rekursif tidak selalu lebih jelek daripada iteratif . Ada kalanya sebuah fungsi rekursif justru mempermudah penyelesaian masalah yang ditemui pada kasus iteratif (pengulangan) Kelemahan pada proses rekursif antar lain, memerlukan tempat penampungan stack yang cukup besar. Karena setiap kali pemanggilan fungsi , register – register seperti cs ( untuk memory far ) dan ip harus disimpan , belum lagi untuk penanganan local variable serta parameter fungsi yang tentunya membutuhkan ruang untuk stack lebih banyak lagi . Selain itu karena setiap pemanggilan fungsi , register dan memory harus di push ke stack maka setelah selesai pemanggilan perlu diadakannya pop stack . untuk mengembalikan memory dan register kembali ke keadaan awal , ini sering disebut sebagai overhead . Proses Rekursif Untuk dapat memahami proses yang terjadi dalam sebuah fungsi rekursif , marilah kita simak contoh fungsi rekursif berikut :

  • Created By Muhammad Syahrizal 14

    Misalkan Fungsi tersebut dipanggil dengan nilai a = 3 dan b = 3 maka pertama tama di cek apakah b = 0 (if (b == 0) return), jika sama maka keluar. Ternyata nilai b tidak sama dengan 0 maka tambahkan a dengan 1 dan kurangi b dengan 1 . Maka keadaan sekarang menjadi a = 4 dan b = 2 . Baris berikutnya menampilkan nilai a dan b ke layar (printf("Masuk -> a = %d || b = %d \n",a,b)). Kemudian panggil fungsi rekursi dengan nilai a = 4 dan b = 2 . Langkah – langkah tersebut diulang terus sampai pemanggilan fungsi rekursi dengan nilai a = 6 dan b = 0. Pada saat ini kondisi if bernilai benar sehingga fungsi akan keluar (return) dan melanjutkan perintah setelah pemanggilan fungsi rekursi dengan a = 6 dan b = 0. Yaitu mencetak nilai a dan b (printf("Keluar -> a = %d || b = %d \n",a,b)). Setelah mencetak nilai a dan b maka fungsi rekursif akan keluar lagi , dan melanjutkan perintah setelah pemanggilan fungsi rekursif sebelumnya dimana nilai a = 5 dan b = 1 . Demikian seterusnya sampai nilai a = 4 dan nilai b = 2. yang tidak lain pemanggilan fungsi rekurif yang pertama. Proses pemanggilan fungsi rekursif dapat diilustrasikan :

    Langkah ke : 1. a = 4 ; b = 2 . Cetak : Masuk -> a = 4 || b = 2 2. a = 5 ; b = 1 . Cetak : Masuk -> a = 5 || b = 1 3. a = 6 ; b = 0 . Cetak : Masuk -> a = 6 || b = 0 4. a = 6 ; b = 0 , Cetak : Keluar -> a = 6 || b = 0 5. a = 5 ; b = 1 , Cetak : Keluar -> a = 5 || b = 1 6. a = 4 ; b = 2 , Cetak : Keluar -> a = 4 || b = 2

  • Created By Muhammad Syahrizal 15

    Untuk memperjelas lagi penggunaan fungsi rekursif dibawah ini akan di berikan contoh contoh program dengan menggunakan rekursif . Menghitung Nilai Faktorial dan Fibonacci Dengan Rekursif Untuk menghitung nilai faktorial bilangan bulat positif marilah kita daftarkan dulu nilai – nilai faktorial untuk mempermudah pengambilan algoritma . 0! = 1 1! = 1 2! = 2 x 1 N! = N x (N – 1) ! 3! = 3 x 2 x 1 = 3 x 2! 4! = 4 x 3 x 2 x 1 = 4 x 3! Untuk Mencari Bilangan Fibonacci juga sama . Sebelumnya mari kita daftarkan dulu bilangan Fibonacci untuk mempermudah pencarian algoritma . 1 1 2 3 5 8 13 ... Dapat dilihat bahwa Fibo(0) = 1 Fibo(1) = 1 Fibo(2) = Fibo(1) + Fibo(0) = 1 + 1 = 2 Fibo(3) = Fibo(2) + Fibo(1) = 2 + 1 = 3 Untuk Listing Program dalam bahasa C saya serahkan ke pembaca sebagai latihan. Menara Hanoi Menara Hanoi ialah salah satu permainan yang dulunya dimainkan oleh seorang pendeta di Hanoi . Tujuan permainan ini ialah memindahkan n buah pringan dari tonggak asal (A) melalui tonggak bantu (B) menuju tonggak tujuan (C) .Dengan aturan – aturan bahwa piringan yang lebih kecil tidak boleh berada di bawah piringan yang lebih besar .

    Seperti biasa untuk memecahkan masalah kita daftarkan dulu langkah – langka yang diambil mulai n = 1. Dengan dfinisi piringan yang paling atas ialah piringan 1. Untuk n = 1 : - Pindahkan piringan 1 dari A ke C Untuk n = 2 : - Pindahkan piringan 1 dari A ke B - Pindahkan piringan 2 dari A ke C - Pindahkan piringan 3 dari B ke C

  • Created By Muhammad Syahrizal 16

    Dari contoh diatas dapat diambil kesimpulan , untuk memindahkan N piringan dari tonggak asal (A) ke tonggak tujuan (C) maka piringan ke N harus berada di tonggak tujuan (C) , sedangkan piringan ke 1 sampai (N - 1) harus berada di tonggak bantu (B). Setelah piringan ke 1 sampai (N-1) berada pada tonggak bantu (B) , kemudian pindahkan piringan ke 1 sampai (n-1) tersebut dari tonggak bantu (B) ke tonggak tujuan (C) Nah bagaimana caranya membawa piringan ke 1 sampai (N-1) dari tonggak asal ke tonggak bantu (B) , caranya sama saja yaitu dengan memindahkan piringan ke (n-1) dari tonggak asal (A) ke tonggak tujuan yang pada saat ini berada pada tonggak (B) sedangkan piringan dari 1 sampai ke (N- 2) dipindahkan ke tonggak bantu yang saat ini berada di tonggak (C) , Setelah piringan ke 1 sampai (N-2) berada pada tonggak bantu (C) , kemudian pindahkan piringan ke 1 sampai (N-2) ke tonggak tujuan (B) dan seterusnya. Metode penyelesaian permainan Hanoi diatas sering disebut sebagai metode back tracking , jadi solusi dicari dengan cara mundur ke belakang dahulu , baru kemudian solusi bisa di temukan . Berikut Listing program Menara Hanoi dalam bahasa C #include void Hanoi(int n,char asal,char bantu,char tujuan) // pindahkan piringan ke n { // dari asal menuju tujuan // melalui bantu if (n == 0) return; Hanoi(n-1,asal,tujuan,bantu); //pindahkan piringan ke n-1 // dari asal ke bantu melalui //tonggak tujuan printf("Pindahkan piringan ke %d ke dari %c ke %c\n",n,asal,tujuan); Hanoi(n-1,bantu,asal,tujuan); //pindahkan piringan ke n – 1 // dari bantu menuju tujuan // melalu asal } int main(void) { int n; printf("Jumlah piringan ? "); scanf("%d",&n); Hanoi(n,'a','b','c'); return 0; } Berikut Hasil dari program diatas . Jumlah piringan ? 3 Pindahkan piringan ke 1 ke dari a ke c Pindahkan piringan ke 2 ke dari a ke b Pindahkan piringan ke 1 ke dari c ke b Pindahkan piringan ke 3 ke dari a ke c Pindahkan piringan ke 1 ke dari b ke a Pindahkan piringan ke 2 ke dari b ke c

  • Created By Muhammad Syahrizal 17

    Pindahkan piringan ke 1 ke dari a ke c

    Penggunaan Templlate Dalam pemrograman , terutama yang sangat tergantung pada tipe variable , sering kali kita direpotkan dengan harus membuat fungsi yang berfungsi sama tapi dengan tipe variable berbeda.Untuk itu pada C++ dikeluarkan lah sebuah keyword baru , yaitu template. Dengan penggunaan template kita bisa membuat sebuah fungsi yang bias mendukung segala macam tipe variable , tidak terbatas pada variable yang di definisikan oleh keyword C/C++ tapi juga mendukung penggunaan untuk tipe variable masa depan. Penggunaan template tidak terbatas hanya pada fungsi tapi juga mencakup class ( termasuk juga struct , union) . Secara garis besar penggunaan template dapat dibagi 2 yaitu template pada fungsi ( function template)dan template pada Class ( class template). Oke saya rasa kita langsung saja membahas penggunaan template. Function Template Pertama - tama mari kita membahas tentang function template.Untuk itu marilah kita perhatikan contoh berikut. template void swap(tipe &a,tipe &b) { tipe c; c = a; a = b; b = c; } Pada contoh diatas terdapat sebuah fungsi swap (menukar 2 buah variable) menggunakan template.. Untuk pemanggilan fungsi dilakukan seperti pemanggilan fungsi tanpa template. Untuk itu mari perhatikan penggalan perintah untuk menggunakan fungsi swap. Contoh template dengan instance tipe int void main(void) { int a,b; a = 10; b = 20; swap(a,b); cout

  • Created By Muhammad Syahrizal 18

    tTes a,b; a.a = 10; a.b = 20; b.a = 30; b.b = 40; swap(a,b); cout

  • Created By Muhammad Syahrizal 19

    void swap(float &a,float &b) { float c; a = (a < 0.00)?-a:a; b = (b < 0.00)?-b:b; c = a; a = b; b = c; } void main(void) { float a,b; a = -10.0; b = 20.0; swap(a,b); cout

  • Created By Muhammad Syahrizal 20

    }; Yang perlu diperhatikan dari contoh diatas , antara lain perbedaan antara pendefinisian method didalam atau diluar kelas . Untuk menggunakan sebuah class template sebelumnya kita harus mendefiniskan instance dari template yang akan dibuat. Untuk mendefinisikan instance dari class template dapt dilakukan dengan cara menuliskan tipe data dari instance yang diapit oleh tanda “” . Contoh : void main(void) { CMyTemplate a; // membuat instance CMyTemplate dengan tipe short tMystruct b; // membuat instance tMyStruct dengan tipe short _MyUnion c; // membuat instance _MyUnion dengan tipe float } Pada instance CMyTemplate yang dideklarasikan dengan tipe data short maka MyTipe (pada pendefinisian class ) akan menjadi short .Ini berarti variable m_a dan m_b akan bertipe short begitu pula pada struct dan union. Untuk mendefinisikan lebih dari 1 tipe pada class template dapat anda lakukan sama seperti Function Template yaitu dengan menggunakan tanda koma sebagai pemisah . Contoh : template class CMyTemplate { protected : MyTipe1 m_a MyTipe2 m_b; public : void Init(MyTipe1 a,MyTipe2 b) { m_a = a; m_b = b; } }; Untuk membuat instancenya tinggal ditambahkan tanda koma . Contoh : void main(void) { CMyTemplate a; } Jadi sekarang pada Object a , Variabel m_a akan bertipe short sedangkan pada variable m_b akan bertipe float.

    Analisa Numerik: Menghitung FPB Metode Euclidian FPB ialah isitilah yang digunakan untuk menyatakan sebuah bilangan yang mampu

  • Created By Muhammad Syahrizal 21

    membagi pasangan bilangan lain sehingga didapatkan hasil bilangan bulat yang paling kecil. Dengan kata lain FPB ialah sebuah bilangan terbesar yang mampu membagi habis (sisa = 0) pasangan bilangan lain Contoh : FPB dari 60 dan 80 : 60 = 20 * 3 80 = 20 * 4 Pada contoh diatas FPB dari 60 dan 80 ialah 20. Ada beberapa macam contoh untuk menghitung FPB salah satunya yang terkenal ialah algoritma Euclidian . Berikut adalah Algoritma Euclidian untuk menemukan FPB dari 2 buah bilangan 1. Input Bilangan1 2. Input Bilangan2 3. Sisa = Bilangan1 modulus Bilangan2 4. Jika Sisa != 0 maka Bilangan1 = Bilangan2 Bilangan2 = Sisa 5. Jika Sisa = 0 maka FPB = Bilangan2 Berikut adalah implementasinya dalam Bahasa C #include int FPB(int Bil1,int Bil2) { int sisa; while((sisa = Bil1%Bil2) != 0) { Bil1 = Bil2; Bil2 = sisa; } return Bil2; } void main(void) { int bil1,bil2; int sisa; printf("FPB dari 60 dan 80 = %d\n",FPB(60,80)); printf("FPB dari 40 dan 120 = %d\n",FPB(40,120)); printf("FPB dari 2 dan 3 = %d\n",FPB(2,3)); } Hasil : FPB dari 60 dan 80 = 20 FPB dari 40 dan 120 = 40 FPB dari 2 dan 3 = 1

    Analisa Numerik:

  • Created By Muhammad Syahrizal 22

    Menukar 2 Buah Nilai Metode klasik dalam dalam menukar 2 buah nilai , biasanya dengan menggunakan bantuan sebuah variable penampung. Untuk itu diperlukan minimal 3 buah variable dalam implementasinya. Contoh : Untuk menukar var A dan B temp = A ; A = B; B = temp; Didalam bahasa C pendeklarasian variable harus diletakkan sebelum statemen. Jadi jika program anda cukup panjang ( dalam artinya banyak baris ) tentu saja anda harus ke atas dahulu untuk mendeklarasikan varibale temp. Ada cara lain yang dapat digunakan untuk menukar 2 buah nilai tanpa harus memberikan variable tambahan ( cukup dengan 2 buah variable saja ). Yaitu dengan bantuan logika xor . Untuk itu sebelumnya mari kita melihat sejenak tabel kebenaran xor.

    Contoh : A = 1010 B = 0101 C = A xor B C = 1111 X = C xor A -> X = 0101 // penting !!!! Y = C xor B -> Y = 1010 // penting !!!! Dari contoh diatas dapat ditarik kesimpulan : C = A xor B C xor A akan menghasikan B C xor B akan menghasilkan A Sifat diatas biasanya digunakan untuk membuat sebuah enkripsi data yang sederhana. Tapi yang akan kita bicarakan ialah menggunakan xor untuk menukar 2 buah nilai Mari perhatikan contoh berikut . C = A xor B

  • Created By Muhammad Syahrizal 23

    B = C xor B // pertama A = C xor B // kedua Pada C xor B yang pertama akan dihasilkan nilai A oleh sebab itu nilai tersebut ditaruh di B (karena kita akan menukar) . C xor B yang kedua dimana B merupakan nilai A awal maka akan menghasilkan B oleh sebab itu kita taruh di A. Dengan mensubtitusi nilai C dengan salah satu variable maka akan didapatkan : A = A xor B B = A xor B A = A xor B Karena (A xor B) = (B xor A) , pada statement 2 dapat diganti B = B xor A Sehingga dalam bahasa C dapat ditulis : A ^= B ^= A ^= B; Meakjubkan bukan ?? , Menukar 2 buah nilai hanya dengan 1 perintah ( titik koma ) .

    C++ : Scope Class C++ memperluas pengertian scope (visibility) dalam bahasa C dengan masuknya class dan namespace. Artikel ini membahas scope sebuah class. Pembahasan scope tidak terlepas dari konsep yang saling berkaitan dalam C/C++ yaitu lifetime (storage duration) dan linkage. Lifetime menentukan kapan destructor sebuah class dipanggil. Scope sebuah kaji ulang Komputer, sebagai sebuah mesin, dirancang untuk bekerja mengolah angka. Komputer menyimpan data dan perintah di memori dalam bentuk angka. Manusia tidak menggunakan angka melainkan nama untuk membedakan suatu bentuk dengan bentuk lainnya. Manusia lebih mudah mengenali bentuk/benda melalui nama daripada angka. Sebagai contoh, dalam sebuah jaringan LAN lebih mudah mengenali server melalui nama server daripada alamat IP (sebuah angka) server tersebut. Nama juga sangat berarti bagi sebuah program, seseorang penulis program menggunakan nama untuk membedakan data (variabel), fungsi, atau entity lain yang dikenal dalam sebuah bahasa pemrograman. Istilah formal sebuah nama, dalam bahasa C/C++ disebut identifier. Nama (identifier) digunakan untuk menyatakan,

    • Data • fungsi (function) • typedef • structure/class, dan anggotanya

  • Created By Muhammad Syahrizal 24

    • enumeration, dan anggotanya • union • label

    dalam sebuah program C/C++. Sebuah program mengenali nama obyek melalui deklarasi nama tersebut. Scope membatasi nama (identifier), artinya sebuah nama hanya dapat digunakan dalam scope nama tersebut. Scope sebuah nama sudah ditentukan pada saat nama tersebut dideklarasikan. Nama dalam sebuah scope dapat dikenali di scope yang berbeda apabila sesorang penulis program menghendaki demikian. Sebuah scope dapat mempunyai hubungan (linkage) dengan scope lain, karena menggunakan sebuah nama (identifier) yang sama, dengan kata lain nama (identifier) tersebut visible di scope yang berbeda. Translation Unit Ada perbedaan antara organisasi penulisan program C++, melalui file .h (berisi deklarasi) dan .cpp (berisi definisi), dengan proses pemilahan token (parsing) yang dilakukan compiler. Perbedaan tersebut tidak begitu menentukan dalam memahami konsep scope, lifetime dan linkage dalam C. C++ memiliki batasan scope yang lebih abstrak, oleh karena itu standard C++ memperkenalkan istilah translation unit. Sebuah translation unit mungkin dibentuk dari beberapa file, karena umumnya sebuah program C++ menyertakan satu atau lebih file .h. Pada proses kompilasi, file berisi pernyataan program (source file) dan file lain yang dibutuhkan digabungkan menjadi satu kesatuan sebagai masukan proses pemilahan token.

  • Created By Muhammad Syahrizal 25

    Seperti ditunjukkan pada ilustrasi di atas [3], file main.cpp, h1.h, dan h2.h digabungkan menjadi sebuah translation unit. Compiler tidak mengikutsertakan baris program diantara #ifndef (#if !defined) atau #else jika syarat tidak terpenuhi. Sebagai contoh, jika INCL bernilai 1 maka dihasilkan translation unit TU#1, baris program diantara syarat kondisi pada file h1.h diikutsertakan. Apabila INCL bernilai 0, maka dihasilkan translation unit TU#2, baris program diantara syarat kondisional pada file h1.h tidak diikutsertakan dan baris program diantara syarat kondisi pada file h2.h yang diikutsertakan. Perlu diperhatikan juga bahwa compiler mengikutsertakan file yang dibutuhkan secara rekursif, jika file h1.h mencantumkan file *.h lainnya maka file tersebut termasuk dalam translation unit yang sama. Proses pemilahan token menggunakan pernyataan program yang terdapat dalam translation unit dan bukan yang tertulis pada masing-masing file. Demikian halnya dengan scope, lifetime dan linkage masing-masing identifer ditentukan berdasarkan translation unit. Deklarasi dan Definisi Sebuah deklarasi memperkenalkan sebuah nama dalam sebuah program. Deklarasi sebuah nama sekaligus menentukan scope nama tersebut. Definisi, selain memasukkan nama obyek1 dalam sebuah program juga membentuk (create) obyek tersebut dan melakukan inisialisasi. Deklarasi dan definisi sering dipertukarkan, tetapi sebenarnya terdapat perbedaan deklarasi dan definisi. Secara sederhana, sebuah program hanya mempunyai satu definisi terhadap satu obyek atau fungsi (function) dan sebuah program dapat mempunyai lebih dari satu deklarasi. Persyaratan tersebut dalam C++ dikenal dengan istilah aturan satu definisi (One Definition Rule(ODR)). int i; //definisi int i=0; //definisi extern int i; //deklarasi extern int i=0; //definisi static int j; //definisi static int j=0; //definisi void g(int k) //deklarasi fungsi void f(int k) //definisi fungsi { int l; } Dalam C++, seperti pada beberapa contoh di atas, sebuah deklarasi adalah sebuah definisi kecuali,

    • sebuah deklarasi fungsi tanpa isi (body) fungsi tersebut, contoh fungsi g. • sebuah deklarasi obyek dengan katakunci extern dan tanpa inisialisasi. • sebuah deklarasi obyek (data member) static dalam scope class.

    Jadi deklarasi menurut ODR merupakan bentuk pengecualian definisi, berbeda dengan

  • Created By Muhammad Syahrizal 26

    C yang mengenal definisi tentatif (tentative definition). C++ menyarankan untuk tidak menggunakan “implicit int” dalam deklarasi. Dalam C, jika tidak ditulis type obyek maka dianggap obyek tersebut bertipe int, static a; //a bertipe int const b; //b bertipe int void f(const c); //c bertipe int main(void) { return 0; } //return type int C++ menyarankan untuk menuliskan tipe obyek secara eksplisit, sebagai berikut, static int a; const int b=1; void f(int const c); int main(void) { return 0; } Scope Scope dan lifetime adalah dua konsep yang terkait erat. Visibility sebuah nama (identifier) dalam sebuah program C++ berbeda-beda, sebuah nama dengan scope global mempunyai visibility paling luas sedangkan sebuah nama dengan scope lokal mempunyai visibility lebih sempit misalkan sebatas eksekusi suatu fungsi. Sebuah scope menentukan batas visibility sebuah nama dalam program C++. Scope dapat dibentuk dengan sepasang tanda kurung {}, yang membentuk block scope, misalnya pada forloop, while-loop, dll. Batasan scope dapat juga lebih abstrak seperti pada pembahasan translation unit. Bahasa C mengenal beberapa bentuk scope, antara lain: - block, scope nama adalah bagian program yang dibatasi oleh sepasang tanda kurung { }. Sebuah nama visible sejak deklarasi nama tersebut sampai dengan tanda kurung penutup } yang menandakan akhir masa pakai nama tersebut. - prototipe fungsi (function prototype), scope nama hanya sebatas tanda kurung ( dan ) yang membentuk prototipe fungsi. - fungsi, scope sebuah nama adalah seluruh badan fungsi tersebut. - file, scope sebuah nama adalah keseluruhan file sejak sebuah nama dideklarasikan. Scope block dan prototipe fungsi dikenal dengan scope lokal (local scope). Bahasa C++ menambahkan dua scope lagi, yaitu class dan namespace. Deklarasi class (dan namespace) dibatasi oleh sepasang tanda kurung { }, walaupun definisi member function dapat ditulis di luar deklarasi class. Pada penulisan definisi seperti itu, member function tetap berada dalam scope class. Scope minimal Standar C++ mengubah sedikit aturan mengenai scope sebuah nama variabel dalam pernyataan for-loop, while-loop, atau if-condition. C++ mengijinkan deklarasi variabel sebagai bagian dari sebuah for-loop. Sebagai contoh deklarasi variabel i (loop counter) pada cuplikan baris program berikut ini, for (int i=0; i

  • Created By Muhammad Syahrizal 27

    //dalam sebuah for-statement { cout

  • Created By Muhammad Syahrizal 28

    alokasi (operator new) dan dilepas dengan fungsi dealokasi (operator delete). Obyek dinamik menempati memori heap atau memori dinamik (free store). Storage specifier C++ mengenal lima buah kata kunci yang menyatakan attribut storage duration sebuah nama (storage class specifiers), yaitu: auto, register, extern, static dan mutable. Sedikit perbedaan dengan C, typedef tidak termasuk storage class specifier. Secara umum, dalam sebuah deklarasi tidak boleh menggunakan dua buah storage specifier secara bersamaan. Kata kunci extern dan static dapat menjadi bagian dari deklarasi obyek atau fungsi dalam scope namespace3 dan scope block, akan tetapi static tidak dapat menjadi bagian deklarasi fungsi dalam scope block. static juga dapat menjadi bagian deklarasi dalam sebuah scope class. auto dan register dapat menjadi bagian sebuah deklarasi dalam scope block maupun atau dalam deklarasi argumen fungsi (formal parameter), tetapi tidak dalam scope namespace, sebagai contoh: register char *p; //error – register dalam scope namespace void f(register char *p); //ok – register dalam formal parameter void f(auto int i); //ok di C++, error di C C++ mengijinkan penggunaan auto dalam argumen fungsi walaupun tidak ada pengaruh apapun, sedangkan C tidak memperbolehkannya. mutable tidak berpengaruh terhadap linkage maupun lifetime sebuah nama, mutable hanya dapat digunakan dalam deklarasi obyek (data member) dalam scope class. mutable menyatakan bahwa sebuah obyek tidak pernah konstant. Linkage Sebuah nama yang sama tetapi dalam translation unit yang berbeda dapat mengacu ke sebuah obyek yang sama. Hal ini, dalam C maupun C++, disebut linkage. Ada 3 macam linkage, masing-masing adalah: 1. external linkage, yaitu sebuah nama yang dapat terjangkau dari scope lain meskipun berbeda translation unit. 2. internal linkage, yaitu sebuah nama dalam sebuah translation unit yang dapat terjangkau di scope lain dalam translation unit yang sama. 3. tanpa (no) linkage, yaitu nama sebuah obyek dalam sebuah scope dan tidak terjangkau melalui nama tersebut dari scope lainnya. Linkage sebuah obyek maupun fungsi ditentukan oleh kombinasi beberapa faktor, yaitu: scope, storage class specifier, dan linkage yang ditetapkan melalui deklarasi sebelumnya. Selain itu const juga mempunyai pengaruh terhadap hasil akhir linkage obyek atau fungsi. Secara umum, extern pada deklarasi sebuah obyek atau fungsi dalam scope namespace menyatakan external linkage. Demikian halnya dengan deklarasi tanpa storage class specifier juga menyatakan external linkage. Sebaliknya static pada deklarasi obyek maupun fungsi menyatakan internal linkage. Sebagai contoh, definisi nama dalam file1.cpp dan file2.cpp berikut ini,

  • Created By Muhammad Syahrizal 29

    Pada contoh, definisi nama data tersebut mempunyai scope file, i mempunyai linkage external,sedangkan k mempunyai linkage internal. Hasil kompilasi (dan link) kedua file tersebut menghasilkan sebuah program dengan sebuah obyek i,j dan dua buah obyek k. Deklarasi j pada file1 mengacu ke obyek j di file2, deklarasi i pada file2 mengacu ke obyek i di file1. static pada deklarasi k mengacu ke obyek yang berbeda, walaupun kedua file menggunakan nama yang sama. Dalam C++, berbeda dengan C, const pada sebuah deklarasi menyatakan linkage internal, seperti deklarasi N pada contoh di atas. Namun demikian, extern pada deklarasi sebuah obyek const mengubah linkage obyek tersebut menjadi linkage eksternal. Aturan linkage pada scope block berbeda dengan aturan linkage pada scope namespace (termasuk scope file). Dalam scope blok, nama obyek tidak mempunyai linkage (no linkage), kecuali terdapat extern pada deklarasi obyek tersebut. Nama parameter (formal parameter) juga tidak mempunyai linkage. Sebagai contoh, void f(int i) //f: eksternal { //i:no linkage int j; //no linkage static int k; //no linkage //file1.cpp int i=0; //internal extern j; //external static int k; //internal int const N=100 //internal //file2.cpp extern int i; //external int j; //external static int k; //internal … } Pada contoh tersebut, nama fungsi f mempunyai linkage eksternal, nama parameter i tidak mempunyai linkage, nama variabel lokal j dan k tidak mempunyai linkage. Bagaimana dengan deklarasi yang menggunakan extern pada blok scope, seperti contoh berikut ini, static int i=0; //internal extern int j; //eksternal void f() { extern int i; //internal extern float j; //error extern int k; //external … } Seperti terlihat pada contoh, hasil akhir linkage obyek extern dalam scope blok

  • Created By Muhammad Syahrizal 30

    bergantung kepada linkage obyek pada scope yang memuat scope blok tersebut. Obyek i dalam blok scope mempunyai linkage internal, mengikuti linkage obyek i dalam scope file. Obyek k mempunyai linkage eksternal, mengikuti linkage obyek k dalam scope file. Deklarasi obyek merupakan pelanggaran terhadap aturan linkage, karena tipe data j (float) dalam scope blok berbeda dengan tipe data j (int) dalam scope file. Scope Class Setiap definisi class membentuk sebuah scope baru. Scope class mencakup deklarasi class, masing-masing badan fungsi anggota class (member function), dan constructor initializers. Akses terhadap anggota class dapat dilakukan menggunakan salah satu diantara beberapa cara dibawah ini, a) operator . b) operator -> c) operator :: (scope resolution operator) d) melalui fungsi anggota class tersebut (member function) atau derived class Ketiga cara tersebut harus mengikuti batasan akses (public, protected, private) class tersebut. Keempat cara tersebut dapat digunakan untuk mengakses anggota class dengan batasan akses public. Cara keempat dapat digunakan untuk mengakses anggota class dengan batasan akses protected dan public. Class dalam class (nested class) mempunyai scope terpisah, seperti contoh berikut ini, struct s { struct t { int i; } j; } Jika t tidak tersedia untuk akses public (protected atau private), maka operator :: tidak dapat digunakan untuk mengakses struct t karena batasan akses masih tetap berlaku. Standar C++ sebelum dibakukan, memperkenalkan cara untuk mendefinisikan suatu besaran konstan (compile-time constant) yang mempunyai scope class. Sebagai contoh sebuah class C berikut ini, class C { int buf[10]; public: C(); };

  • Created By Muhammad Syahrizal 31

    mempunyai angota berupa array integer buf dengan jumlah elemen 10. Inisialisasi array buf dalam constructor perlu menggunakan operator sizeof() untuk mendapatkan jumlah elemen array, sebagai berikut: C::C() { for(int i=0;i

  • Created By Muhammad Syahrizal 32

    Masing-masing class Base maupun class Derived membentuk scope tersendiri. Pada contoh, class Derived mempunyai fungsi write dengan signature yang berbeda. Hal ini tidak diperbolehkan dalam C++, karena function overloading tidak dapat menembus batas scope masing-masing class (cross scope). Cara pertama untuk mendapatkan hasil yang diinginkan adalah memanggil fungsi write class Base sebagai berikut,

    Cara kedua adalah menggunakan using directive, namun hanya dapat dilakukan dengan compiler C++ yang sudah mengenal namespace. Dalam menguraikan nama fungsi, linker C++ tidak hanya melihat nama fungsi melainkan signature fungsi tersebut. Signature merupakan rangkaian kata (token) yang dapat membedakan kedua fungsi, yaitu tipe masing-masing argumen (formal parameter) fungsi tersebut. Sebagai contoh, char *strcpy(char *,const char *), mempunyai signature { char*,const char *}. Signature hanya mengambil tipe masing-masing argumen, bukan nama argumen fungsi tersebut. Hal ini yang memungkinkan sebuah program C++ mempunyai deklarasi dua fungsi berbeda dengan nama yang sama dalam scope yang sama. Class Linkage Dalam hal nama obyek data maupun fungsi, external linkage dalam C++ dan C mempunyai pengertian yang sama, yaitu sebuah nama yang mengacu ke satu obyek dan nama tersebut dapat digunakan di translation unit yang berbeda. Sebagai contoh, file1.cpp void f() {} int n;

  • Created By Muhammad Syahrizal 33

    file2.cpp void f(); //mengacu ke fungsi f di file1.cpp extern int n; //mengacu ke obyek data n di file1.cpp Linkage sebuah nama class berbeda dengan pengertian linkage pada nama obyek data maupun fungsi. Sebagai contoh,

    Dalam C++, nama sebuah class, “C” pada contoh di atas, mempunyai linkage external. Pada contoh di atas kedua translation unit mempunyai definisi class C yang sama persis. Pengertian linkage eksternal pada nama obyek dan fungsi tidak dapat digunakan untuk menjelaskan pengertian linkage eksternal pada nama class “C” tersebut. Hal inilah perbedaan yang muncul dengan masuknya konsep class dalam C++. Pengertian linkage eksternal secara umum, berlaku untuk nama data obyek, fungsi dan class, adalah setiap obyek dengan linkage eksternal harus mengikuti aturan “satu definisi” (ODR). Pada contoh, jika TU2 mempunyai definisi class C maka definisi tersebut harus sama dengan definisi class C pada TU1. ODR mensyaratkan, jika satu atau lebih translation unit mempunyai definisi sebuah obyek yang sama, maka definisi tersebut harus sama di semua translation unit (yang memuat definisi obyek tersebut). Salah satu cara praktis, sadar atau tidak sadar, setiap pemrogram memastikan hal ini dengan memasukkan definisi class dalam sebuah file header (.h) dan mengikutsertakan (melalui #include) obyek tersebut bilamana diperlukan, seperti kolom “source file” pada contoh di atas. Static Sebuah class dapat mempunyai anggota berupa data atau fungsi static. Tidak seperti obyek static pada scope file maupun blok, static dalam scope class mempunyai arti linkage eksternal. Selain operator . dan operator ->, anggota class berupa data dan fungsi static dapat diakses dengan operator ::. Anggota class berupa data static harus dinisialisasi sekali saja, diluar scope class, yaitu dalam scope file tetapi tidak dalam file .h (header). Data static dalam scope class bukan merupakan bagian dari obyek class tersebut. Data static berlaku seperti halnya sebuah data global sebuah class, artinya hanya ada satu data static untuk semua obyek

  • Created By Muhammad Syahrizal 34

    class tersebut. Anggota class berupa fungsi static tidak mempunyai pointer this, karena hanya ada satu fungsi static untuk semua obyek class tersebut. Tanpa pointer this, fungsi static tidak dapat mengakses anggota class lainnya yang non-static. Dengan demikian fungsi static umumnya digunakan untuk manipulasi anggota class berupa data statik. Salah satu contoh pemakaian fungsi static adalah pola desain (design pattern) Singleton. Sebuah class dapat menempatkan data static dalam member function maupun sebagai anggota class seperti data member lainnya. Sebagai contoh, class Base { public: int countCalls() { static int count=0; //definisi static dalam member function return ++count; } }; Semua class yang mewarisi (inherit) class Base tersebut juga mewarisi data static tersebut, sehingga count akan bertambah jika countCalls() dipanggil melalui obyek Base maupun Derived. class Derived1 : public Base { }; class Derived2 : public Base { }; int main() { Derived1 d1; Derived2 d2; int d1_count=d1.countCalls(); //d1_count=1 int d2_count=d2.countCalls(); //d2_count=2 } Penjelasan mengenai nilai obyek static pada contoh di atas merupakan latihan bagi para pembaca. Definisi data static sebagai anggota class lebih umum digunakan, seperti ditunjukkan pada contoh berikut, class Base { private: static int i; public: virtual int countCalls() { return ++i; } }; int Base::i; class Derived1 : public Base { private: static int i; //menyembunyikan Base::i public: int countCalls() { return ++i; }

  • Created By Muhammad Syahrizal 35

    }; int Derived1::i; class Derived2 : public Base { private: static int i; //menyembunyikan Base::i public: int countCalls() { return ++i; } }; int Derived2::i; int main() { Derived1 d1; Derived2 d2; int d1_count = d1.countCalls(); //d1_count = 1 int d2_count = d2.countCalls(); //d2_count = 1 return 0; } Scope class Derived terpisah dengan scope Base maka class Derived tidak lagi mewarisi data static i class Base, sehingga countCalls memberikan nilai yang berbeda bila dipanggil dari obyek class Derived. C++ mengenal class local, sebuah definisi class dalam scope blok, sebagai contoh: #include int i=10; int main() { void f(); f(); return 0; } void f() { static int j=20; class Local { int k; public: Local(int i) : k(i) {} void a() { std::cout

  • Created By Muhammad Syahrizal 36

    fungsi f, artinya jika f mempunyai argumen maka argumen tersebut tidak dikenal dalam scope class Local.

    Analisa Numerik: Menghitung Nilai Cosinus Tahukah anda , bagaimana caranya komputer menghitung nilai dari cos(30) ? . Mungkin kalau hanya sekedar menghitung nilai dari cos(30°) kita tidak membutuhkan bantuan komputer. Nah bagaimana halnya dengan cos(30.5°).Komputer tentu saja tidak menyimpan nilai – nilai tersebut dalam sebuah tabel.Selain memakan tempat , juga terbatas hanya pada sudut yang tertentu yang disimpan saja. Dalam beberapa kasus pemrograman, penyimpanan nilai dalam tabel dapat dipertimbangkan terutama dalam program – program yang berjalan secara real time dimana dengan bantuan tabel dapat mengurangi beban dari proses komputasi . Pada kesempatan kali ini saya akan membahas salah satu algoritma yang dapat digunakan sebagai alat membantu mendapatkan nilai dari beberapa fungsi dasar matematika . Untuk itu ada baiknya kita menengok sejenak pembahasan mengenai deret khususnya Deret Taylor dan Deret Maclaurin yang terdapat pada mata kuliah Kalkulus. Deret Taylor dan Deret Maclaurin Bentuk Umum Deret Taylor :

    Nilai a adalah sebuah constanta , Deret MacLaurin merupakan Deret Taylor khusus yang didapat dengan cara mensubtitusi nilai a dengan 0. Dengan bantuan rumus diatas maka menghitung nilai cos bukan merupakan hal yang misteri lagi . Persamaan diatas berlaku tidak hanya untuk menghitung nilai cos saja tapi juga dapat menghitung beberapa fungsi matematika lainnya , seperti fungsi fungsi yang berhubungan dengan trigonometri , exponensial , logaritma , Hyperbolic dan lainnya . Oke saya rasa kita langsung menuju contoh saja . Kali saya akan membuat fungsi untuk menghitung nilai cos dengan menggunakan deret MacLaurin.

  • Created By Muhammad Syahrizal 37

    Pertama – tama kita mencari dulu turunan masing masing tingkat dari cos(x) serta hasilnya bila x = 0 (Maclaurin)

    dan seterusnya jika diterjemahkan dalam bahasa C maka aka menjadi : int turunan(int n) { int hasil; n = n % 4; switch(n) { case 0 : hasil = 1;break; case 1 : hasil = 0;break; case 2 : hasil = -1;break; case 3 : hasil = 0;break; } Fungsi turunan diatas ialah untuk menghitung nilai turunan tingkat ke - n. Melihat dari tabel bahwa pada turunan ke 4 sama dengan turunan ke 0 maka bisa disimpulkan: n = n % 4; Setelah kita tahu turunannya maka dapat disusun algoritma global untuk penyelesaian semua masalah yang menggunakan deret Maclaurin dengan input X. 1. n = 0 // menyatakan turunan ke – n 2. pembilang = 1 // X0 = 1 3. penyebut = 1 // 0! = 1 4. hasil = 0 // hasil keseluruhan 5. suku = turunan(n) * pembilang / penyebut // hitung nilai dari suku ke n 6. hasil = hasil + suku 7. Tambahkan nilai n dengan 1 8. pembilang = pembilang * X // untuk mendapatkan Xk+1 = Xk * X 9. penyebut = penyebut * n // untuk mendapatkan faktorial ke n 10. Ulangi terus langkah ke 4 – 8 sampai keadaan tertentu Dalam perhitungan menggunakan deret MacLauriun dimana fungsi diturunkan terus sampai tak hingga , maka diperlukan adanya sebuah pemotongan pada keadaan tertentu yang menyatakan kapan perhitungan tersebut harus berhenti . Keadaan tertentu yang dipakai biasanya ditentukan oleh nilai dari suku . Pada contoh yang saya berikan , jika

  • Created By Muhammad Syahrizal 38

    nilai suku sudah lebih kecil dari galat maka tidak perlu dilakukan perhitungan lagi alias keluar dari looping. Berikut listing program lengkap dari contoh diatas : #include #define abs(x) ((x >= 0)?x:-x) int turunan(int n) { int hasil; n = n % 4; switch(n) { case 0 : hasil = 1;break; case 1 : hasil = 0;break; case 2 : hasil = -1;break; case 3 : hasil = 0;break; } return hasil; } double cos(double x) { double pembilang,penyebut,hasil,suku; double galat; double n; pembilang = penyebut = 1; galat = 0.00001; hasil = 0.0; n = 0; do { if (turunan(n) != 0) // untuk mengurangi perkalian dengan 0 { suku = turunan(n) * pembilang / penyebut; hasil = hasil + suku; } n++; pembilang = pembilang * x; // pangkat penyebut = penyebut * n; // faktorial }while(abs(suku) >= galat); return hasil; } void main(void) { const double PI = 3.14159265; printf("%8.4f\n",cos(0)); printf("%8.4f\n",cos(PI/6)); printf("%8.4f\n",cos(PI/4)); printf("%8.4f\n",cos(PI/2)); printf("%8.4f\n",cos(PI)); } Hasil : 1.0000 0.8660 0.7071 0.0000 -1.0000 Nah coba dibandingkan hasil yang anda dapat dari program ini dengan kalkulator . Hasilnya pasti sama.

  • Created By Muhammad Syahrizal 39

    Class C++ Dasar Pemrograman C++ memerlukan pemahaman yang memadai untuk menterjemahkan desain ke dalam bentuk implementasi, terutama untuk desain yang menggunakan abstraksi class. Fokus pembahasan pada aspek pembentukan obyek (construction) sebuah class, dan proses sebaliknya pada saat obyek tersebut sudah tidak digunakan lagi (destruction). Deklarasi dan Definisi Deklarasi dan definisi adalah langkah awal dalam setiap penulisan program tidak terkecuali dalam bahasa C++. Deklarasi dan definisi diperlukan untuk semua tipe data termasuk tipe data bentukan user (user-defined type). Bentuk sederhana deklarasi class adalah sebagai berikut, class C { }; atau struct C { }; dalam bahasa C++ struct dan class mempunyai pengertian yang sama. Deklarasi class dengan struct mempunyai anggota dengan akses public kecuali jika dinyatakan lain. struct C { int i; void f(); } class C { public: int i; void f(); } Kedua deklarasi tersebut mempunyai arti yang sama. Hal ini adalah pilihan desain yang diambil oleh desainer C++ (Bjarne Stroustrup) untuk menggunakan C sebagai basis C++ ketimbang membuat bahasa yang sama sekali baru. Tentunya ada konsekuensi atas pilihan desain ini, salah satu contoh adalah kompatibilitas terhadap bahasa C. Dalam bahasa C deklarasi, struct C { … }; menyatakan C sebagai nama tag. Nama tag berbeda dengan nama tipe, sehingga C (nama tag) tidak dapat dipergunakan dalam deklarasi yang membutuhkan C sebagai suatu tipe obyek. Kedua contoh deklarasi berikut ini tidak valid dalam bahasa C, C c; /* error, C adalah nama tag */ C *pc; /* error, C adalah nama tag */ Dalam bahasa C, kedua deklarasi tersebut harus ditulis sebagai berikut, struct C c;

  • Created By Muhammad Syahrizal 40

    struct C *pc; atau menggunakan typedef sebagai berikut, struct C { … }; typedef struct C C; C c; C *pc; C++ memperlakukan nama class, C sebagai nama tag sekaligus nama tipe dan dapat dipergunakan dalam deklarasi. Kata class tetap dapat dipergunakan dalam deklarasi, seperti contoh berikut ini, class C c; Dengan demikian C++ tidak membedakan nama tag dengan nama class, paling tidak dari sudut pandang pemrogram (programmer), dan tetap menerima deklarasi structure seperti dalam bahasa C. Kompatibilitas C++ terhadap tidak sebatas perbedaan nama tag dan nama tipe, karena standar C++ masih perlu mendefinisikan tipe POD (Plain Old Data). POD type mempunyai banyak persamaan dengan structure dalam C. Standar C++ mendefinisikan POD type sebagai obyek suatu class yang tidak mempunyai userdefined constructor, anggota protected maupun private, tidak punya base class, dan tidak memiliki fungsi virtual. Dalam desain suatu aplikasi terdiri atas banyak class, dan masing-masing class tidak berdiri sendiri melainkan saling bergantung atau berhubungan satu sama lain. Salah satu contoh hubungan tersebut adalah hubungan antara satu class dengan satu atau lebih base class atau parent class. Jika class C mempunyai base class B, dikenal dengan inheritance, maka deklarasi class menjadi, class C : public B {}; atau class C : protected B {}; atau class C : private B {}; akses terhadap anggota base class B dapat bersifat public, protected, maupun private, atau disebut dengan istilah public, protected atau private inheritance. Class C disebut dengan istilah derived class. Jika tidak dinyatakan bentuk akses secara eksplisit, seperti dalam deklarasi berikut: class C : B maka interpretasinya adalah private inheritance (default), tetapi jika menggunakan struct maka tetap merupakan public inheritance. Jika desainer class C tersebut menginginkan hubungan multiple inheritance (MI) terhadap class B dan A, maka deklarasi class C menjadi, class C : public B, public A { }; Sebuah class, seperti halnya class C mempunyai anggota berupa data maupun fungsi (member function). Isi class tersebut berada diantara tanda kurung { } dan dipilah-pilah sesuai dengan batasan akses yang ditentukan perancang (desainer) class tersebut. class C : public B { public: (explicit) C()(:member-initializer); C(const C& ); C& operator=(const C&); (virtual)~C();

  • Created By Muhammad Syahrizal 41

    statement lain (protected: statement) (private: statement) }; Secara ringkas batasan akses (access specifiers) mempunyai arti seperti ditunjukkan pada table berikut ini, Batasan Akses Arti public Semua class atau bebas protected Class itu sendiri, friend, atau derived class private Class itu sendiri, friend Sebuah class dapat memberikan ijin untuk class lain mengakses bagian protected maupun private class tersebut melalui hubungan friendship (dinyatakan dengan keyword friend). Sebuah class mempunyai beberapa fungsi khusus, yaitu constructor, copy constructor, destructor dan copy assignment operator. Constructor C() adalah anggota class yang bertugas melakukan inisialisasi obyek (instance) dari suatu class C. Constructor mempunyai nama yang sama dengan nama class, dan tidak mempunyai return value. Sebuah class dapat mempunyai lebih dari satu constructor. Constructor yang tidak mempunyai argumen, disebut default constructor, sebaliknya constructor yang mempunyai lebih dari satu argumen adalah non-default consructor. Constructor dengan satu default argument tetap merupakan sebuah default constructor, class C { public: C(int count=10) : _count(count) {} … private: int _count; }; Compiler C++ dapat menambahkan default constructor bilamana diperlukan, jika dalam definisi class • tidak tertulis secara eksplisit sebuah default constructor dan tidak ada deklarasi constructor lain (copy constructor). • tidak ada anggota class berupa data const maupun reference. Sebagai contoh definisi class C sebagai berikut, class C {…}; C c1; // memerlukan default constructor C c2(c1); // memerlukan copy constructor Compiler C++ memutuskan untuk menambahkan default dan copy construtor setelah menemui kedua baris program tersebut, sehingga definisi class secara efektif menjadi sebagai berikut,

  • Created By Muhammad Syahrizal 42

    class C { public: C(); // default costructor C(const C& rhs); // copy constructor ~C(); // destructor C& operator=(const C& rhs); // assignment operator C* operator&(); // address-of operator const C* operator&(const C& rhs) const; }; compiler menambahkan public constructor, dan destructor. Selain itu, compiler juga menambahkan assignment operator dan address-of operator. Constructor (default dan non-default) tidak harus mempunyai akses public, sebagai contoh adalah pola desain (design pattern) Singleton. class Singleton { public: static Singleton* instance(); protected: Singleton(); private: static Singleton* _instance; }; obyek (instance) singleton tidak dibentuk melalui constructor melainkan melalui fungsi instance. Tidak ada obyek singleton lain yang dapat dibentuk jika sudah ada satu obyek singleton. Umumnya default constructor bentukan compiler (generated default constructor) menggunakan default constructor anggota bertipe class, sedangkan anggota biasa (builtin type) tidak diinisialisasi. Demikian halnya dengan obyek yang dibentuk dari obyek lain (copy), maka copy constructor bentukan compiler (generated copy constructor) menggunakan copy constructor dari anggota bertipe class pada saat inisialisasi. Sebagai contoh deklarasi class C berikut ini, class C { public: C(const char* aName); C(const string& aName); … private: std::string name; }; copy constructor bentukan compiler menggunakan copy constructor class string untuk inisialisasi name dari aName. Jika class C tidak mempunyai constructor, maka compiler menambahkan juga default constructor untuk inisialisasi name menggunakan default constructor class string. Inisialisasi obyek menggunakan constructor (non-default) dapat dilakukan dengan member initializer maupun dengan assignment sebagai berikut, member initialization assignment class C

  • Created By Muhammad Syahrizal 43

    { int i,j; public: C() : i(0),j(1) {} … }; class C { int i,j public: C() { i=0;j=0; } … }; Kedua cara tersebut memberikan hasil yang sama, tidak ada perbedaan signifikan antara kedua cara tersebut untuk data bukan tipe class. Cara member initializer mutlak diperlukan untuk data const maupun reference, seperti kedua contoh berikut ini: class C //:1 { public: C(int hi,int lo) : _hi(hi),_lo(lo) {} … private: const int _hi,_lo; // const member }; class C //:2 { public: C(const string& aName) : name(aName) {} … private: std::string& name; // reference member }; Cara member initialization sebaiknya dilakukan untuk anggota bertipe class (userdefined type) seperti ditunjukkan pada contoh berikut ini, class C { public: C(const string& aName) : name(aName) { } private: std::string name; // bukan reference member }; Pertimbangan menggunakan cara member initialization terletak pada efisiensi eksekusi program. Hal ini berkaitan dengan cara kerja C++ yang membentuk obyek dalam dua tahap, • pertama, inisialisasi data • kedua, eksekusi constructor (assignment)

  • Created By Muhammad Syahrizal 44

    Dengan demikian jika menggunakan cara assignment sebenarnya eksekusi program dilakukan dua kali, pertama inisialisasi kemudian assignment, sedangkan menggunakan member initialization hanya memanggil sekali constructor class string. Semakin kompleks class tersebut (lebih kompleks dari class string) semakin mahal (tidak efisien) proses pembentukan obyek melalui cara assignment. Constructor dengan satu argumen berfungsi juga sebagai implicit conversion operator. Sebagai contoh deklarasi class A dan B berikut ini, class A { public: A(); }; class B { public: B(const A&); }; pada cuplikan baris program di bawah ini terjadi konversi tipe obyek A ke B secara implisit melalui copy constructor class B. A a B b=a; // implicit conversion explicit C++ menyediakan satu sarana, menggunakan keyword explicit, untuk mengubah perilaku constructor dengan satu argumen agar tidak berfungsi sebagai conversion operator. Jika class B menyatakan explicit pada copy constructor sebagai berikut, class B { public: explicit B(const A& a); // explicit ctor }; maka konversi A ke B secara implisit tidak dapat dilakukan. Konversi A ke B dapat dilakukan secara eksplisit menggunakan typecast, A a; B b=static_cast(a); atau B b=(B)a; Konversi secara implisit dapat terjadi melalui argumen fungsi f dengan tipe B void f(const B& ); tetapi f diakses dengan variabel tipe A, f(a). Apabila class B menghalangi konversi secara implisit maka argumen fungsi f menjadi, f((B)a); atau f(static_cast(a)); Konversi tipe obyek secara implisit sebaiknya dihindari karena efeknya mungkin lebih besar terhadap aplikasi program secara keseluruhan dan tidak dapat dicegah pada saat kompilasi, karena construcor dengan argumen tunggal adalah suatu pernyataan program yang sah dan memang dibutuhkan.

  • Created By Muhammad Syahrizal 45

    Copy Constructor dan Copy Assignment Sejauh ini sudah dibahas mengenai copy constructor sebagai anggota class yang berperan penting pada saat pembentukan obyek. Apabila sebuah class tidak menyatakan secara tegas copy constructor class tersebut, maka compiler menambahkan copy constructor dengan bentuk deklarasi, C(const C& c); Bentuk lain copy constructor adalah sebagai berikut, C(C& c); atau C(C volatile& c); atau C(C const volatile& c); Copy constructor class C adalah constructor yang mempunyai satu argumen. Sebuah copy constructor boleh mempunyai lebih dari satu argumen, asalkan argumen tersebut mempunyai nilai default (default argument). C(C c); // bukan copy constructor C(C const& c,A a=b); //copy constructor Constructor dengan argumen bertipe C saja (tanpa reference) bukan merupakan copy constructor. Copy constructor juga dibutuhkan pada saat memanggil suatu fungsi yang menerima argumen berupa obyek suatu class, void f(C x); memerlukan copy onstructor class C untuk mengcopy obyek c bertipe C ke obyek x dengan tipe yang sama, yaitu pada saat memanggil fungsi f(c)(pass-by-value). Hal serupa terjadi pada saat fungsi f sebagai berikut, C f() { C c; … return c; } mengirim obyek c ke fungsi lain yang memanggil fungsi f() tersebut. Copy assignment operator class C adalah operator=, sebuah fungsi yang mempunyai satu argumen bertipe C. Umumnya deklarasi copy assignment mempunyai bentuk, C &operator=(const C &c); Bentuk lain yang mungkin adalah, C &operator=(C &c); atau C &operator=(C volatile &c); atau C &operator=(C const volatile &c); Copy assignment boleh mempunyai argumen dengan tipe C (bukan reference), tetapi tidak boleh mempunyai argumen lebih dari satu walaupun argumen tersebut mempunyai nilai default (default argument). Seperti halnya copy constructor, compiler akan menambahkan copy assignment jika suatu class tidak mempunyai fungsi tersebut. Copy assignment dibutuhkan untuk membentuk obyek melalui assignment, seperti contoh berikut class C {

  • Created By Muhammad Syahrizal 46

    public: C(); //ctor ~C(); //dtor … }; C c1; C c2=c1; //copy constructor C c3; c3=c1; //copy assignment Class C tidak mempunyai copy constructor maupun copy assignment operator, maka pembentukan obyek c2, dan c3 menggunakan copy constructor dan copy assignment yang ditambahkan oleh compiler ke class C tersebut. Suatu class yang mempunyai data dengan alokasi dinamik (pointer) sebaiknya tidak mengandalkan copy constructor maupun copy assignment operator yang ditambahkan compiler. Copy assignment hasil tambahan compiler mengcopy (memberwise copy) pointer dari obyek satu (yang dicopy) ke obyek lainnya (hasil copy), sehingga kedua obyek mengacu ke lokasi memori yang sama. Masalah timbul jika kedua obyek mempunyai masa pakai (lifetime1) yang berbeda. Jika salah satu obyek sudah habis masa pakainya maka destructor obyek tersebut mengembalikan memori (dynamic memory) yang digunakan obyek tersebut, padahal copy obyek tersebut masih mengacu ke lokasi memori yang sama. Pada contoh hasil copy assignment b=a (shalow copy), menunjukkan kedua obyek a dan b mengacu ke lokasi memori p. Apabila obyek a melepas memori p (melalui destructor), maka obyek b mengacu ke lokasi memori yang sudah tidak valid lagi. Lokasi memori p dapat digunakan obyek lain jika obyek a melepasnya. Demikian pula halnya dengan lokasi memori q, apabila obyek b habis masa pakainya (keluar scope, dihapus dll) maka destructor class B tidak melepas memori q. Akibatnya terjadi pemborosan memori (memory leak). Salah satu jalan keluar adalah dengan menyatakan secara tegas copy constructor dan copy assignment yang dibutuhkan suatu class sehingga compiler tidak membuat copy constructor dan copy assignment ke class tersebut. Alternatif lain adalah menempatkan deklarasi copy constructor dan copy assignment operator private sebagai berikut, class C { … private: C(const C&); C &operator=(const C&); }; definisi copy constructor dan copy assignment operator class C pada contoh di atas tidak perlu ada, karena tujuannya adalah menghalangi proses penggandaan (copy) menggunakan kedua fungsi tersebut. Pada tahap kompilasi penggunaan assignment, b=a masih dapat diterima karena deklarasi asignment operator tersebut tersedia. Pada saat link akan gagal karena linker tidak dapat menemukan definisi copy assignment operator. Teknik ini masih mempunyai kelemahan, karena class lain masih mungkin mempunyai akses ke private copy constructor dan copy assignment operator tersebut

  • Created By Muhammad Syahrizal 47

    (melalui hubungan friendship). Destructor Destructor adalah anggota class (member function) yang berfungsi melepas memori pada saat suatu obyek sudah tidak diperlukan lagi. Fungsi destructor kebalikan constructor. Destructor tidak mempunyai atau memerlukan argumen. Destructor juga tidak mengembalikan nilai apapun (tidak mempunyai return type). Seperti halnya constructor, compiler dapat menambahkan sebuah destructor jika sebuah class tidak mempunyai destructor. virtual Destructor Sebuah destructor dapat berupa fungsi virtual. Hal ini menjadi keharusan jika class B, • merupakan base class. • class D yang menggunakan B sebagai base class mempunyai anggota berupa data dengan alokasi memori dinamik (pointer). class B { public: B(); ~B(); }; class D : public B { public: D() : p(new char[256]) {} ~D() { delete[] p; } … private: char *p; }; Pada contoh tersebut destructor base class B bukan fungsi virtual. Dalam C++ umumnya obyek class D digunakan secara polimorphic dengan membentuk obyek class D (derived class) dan menyimpan alamat obyek tersebut dalam pointer class B (base class) seperti pada contoh berikut ini, void main(void) { B *pB=new D(); delete pB; } Dalam standar C++ menghapus obyek D (derived class) melalui pointer class B (base class) sedangkan destructor base class non-virtual mempunyai efek yang tidak menentu (undefined behaviour). Apabila standard C++ tidak menetapkan apa yang seharusnya berlaku, maka terserah kepada pembuat compiler menentukan perilaku program pada kondisi semacam ini. Umumnya pembuat compiler mengambil langkah untuk tidak memanggil destructor class D (derived class). Dengan demikian, pada saat menjalankan

  • Created By Muhammad Syahrizal 48

    perintah delete, destructor class D tidak dieksekusi karena destructor base class B nonvirtual. Akibatnya lokasi memori dinamik yang digunakan class D tidak pernah dilepas. Hal ini adalah contoh lain terjadinya pemborosan memori (memory leak) oleh suatu program. Jalan keluarnya adalah membuat destructor base class B virtual, class B { public: B(); virtual ~B(); } Tidak seperti destructor, tidak ada virtual constructor atau virtual copy constructor. Pada saat membentuk obyek, tipe obyek harus diketahui terlebih dahulu, apakah membentuk obyek class A, B, C dsb. Tidak ada aspek bahasa C++ untuk mewujudkan virtual constructor secara langsung, menempatkan virtual pada deklarasi constructor merupakan kesalahan yang terdeteksi pada proses kompilasi. Efek virtual constructor bukan tidak mungkin dicapai, C++ memungkinkan membuat idiom virtual constructor yang bertumpu pada fungsi virtual dalam kaitannya dengan hubungan antara sebuah class dengan base classnya.

    Konversi Basis Bilangan Biasanya dalam berinteraksi dalam dunia nyata , kita menggunakan bilangan dengan basis 0 (Desimal) sebagai perantaranya. Tapi karena satu dan lain hal kita perlu juga menggunakan basis bilangan lain . Dalam dunia digital misalnya . Ukuran terkecil untuk menyatakan satuan data dalam dunia digital ialah bit. 1 Bit terdiri dari 2 buah keadaan yaitu 1 atau 0 , low atau high dsbnya. Mengingat pentingnya proses konversi tersebut maka kali ini kita akan membahas cara mengkonversi bilangan dengan basis dasar 10 menjadi bilangan dengan basis 2 sampai 16. Dan dengan algoritma yang sama anda bisa kembangkan sendiri untuk mengkonversi sampai basis ke N. Kita akan menggunakan Metode rekursif untuk pembentukan algoritmanya. Metode Konvensional Oke sebelum menginjak kepada metode konvensional , ada beberapa hal yang perlu kita ketahui. Maksud dari basis bilangan 10 ialah karakter bilangan yang tersedia ialah dari ‘0’ sampai dengan ‘9’ . maksud dari basis bilangan 2 , karakter yang tersedia ialah dari ‘0’ sampai ‘1’ . Nah bagaimana dengan basis yang lebih besar dari 10 ? . Jika basis lebih besar dari 10 digunakan karakter abjad . Misalkan basis 16 . Maka karakter bilangan yang tersedia yaitu dari ‘0’ .. ‘9’ , ‘A’ , ‘B’,’C’,’D’,’E’,’F’. Begitu seterusnya untuk bilangan diatas basis 10. Dibawah ini ialah salah satu metode konvensional untuk merubah bilangan dengan basis dasar 10 ke basis lainnya , yang mana penulis dapat ketika masih duduk di bangku sekolah dasar .

  • Created By Muhammad Syahrizal 49

    Misalkan kita ingin mencari berapakah nilai bilangan 10 dalam basis 10 jika di konversi ke basis 2 (biner) . Untuk itu perhatikan gambar berikut

    Pada gambar 1 didapat bahwa 10(10) = 1010(2) Algoritma pada gambar 1 dapat dijelaskan sebagai berikut . Nilai 10 kita bagi dengan basis tujuan yang kita mau (dalam hal ini 2 ) maka akan dihasilkan 5 , dengan sisa 0 . Kemudian 5 kita kembali bagi dengan basis yang kita tuju , sehingga 5 dibagi dengan 2 . Maka akan didapat 2 dengan sisa 1 begitu seterusnya. Langkah ini diulangan terus sampai hasil dari pembagian ialah 0 . Hasil konversinya didapat dari merunut sisa hasil pembagian dari yang paling bawah ke atas ( lihat gambar ) Dari gambar diperoleh 1010 sebagai hasil. Listing Program Setelah kita tahu cara metode pengkonversiannya , maka tentunya tidak sulit lagi untuk membuatnya kedalam bahasa pemrograman C . Untuk memudahkan dan sekalian memahami penggunaan rekursif , maka fungsi akan dibuat dengan menggunakan rekursif Berikut ialah listing programnya : #include char ch[17] = "0123456789ABCDEF"; void CetakBaseN(int base,int nilai) { if (nilai == 0) //jika nilai sudah 0 maka keluar return; CetakBaseN(base,nilai / base); printf("%c",ch[nilai % base]); } void main(void)

  • Created By Muhammad Syahrizal 50

    { CetakBaseN(2,255); printf("\n"); CetakBaseN(8,255); printf("\n"); CetakBaseN(10,255); printf("\n"); CetakBaseN(16,255); printf("\n"); } Cara kerja Fungsi CetakBaseN

    Misalkan kita memanggil fungsi CetakBaseN dengan nilai base = 2 dan nilai = 10 . Maka pertama – tama dicek apakah nilai = 0 , jika sama maka langsung keluar . Ternyata nilai tidak sama dengan 0 maka lanjutkan pada baris berikutnya . Yaitu memanggil dirinya sendiri dengan parameter nilai yang kini bernilai nilai / base ( 10 / 2 = 5) (Langkah 1) Kemudian di cek kembali apakah nilai == 0 , dilanjutkan dengan memanggil dirinya sendiri yang kini parameter nilai bernilai nilai / base (5 / 2 = 2) (Langkah 2) begitu seterusnya . Ketika nilai == 0 (pada pemanggilan fungsi yang ke 5) maka fungsi akan keluar (Langkah 5) dan akan melanjutkan fungsi pemanggilnya yaitu mencetak sisa dari nilai / base . Kemudian fungsi akan keluar lagi (Langkah 6 ) dan kembali mencetak sisa dari nilai / base fungsi pemanggilnya dan begitu seterusnya. CetakBase(2,10) CetakBase(2,5) CetakBase(2,2) CetakBase(2,1) CetakBase(2,0)

  • Created By Muhammad Syahrizal 51

    Memahami Konsep OOP dengan C++. Pembahasan Kelas Dalam C++ Tulisan ini merupakan pengenalan kepada pemrograman berorientasi objek (Object-oriented Programming, selanjutnya disebut OOP) dengan menggunakan ANSI C++. Disarankan agar Anda menguasai dasar-dasar pemrograman struktural terlebih dahulu dengan menggunakan salah satu bahasa pemrograman, baik C, Pascal, Basic atau yang lainnya. Sedikit sejarah tentang C++, C++ diciptakan oleh Bjarne Stroustrup di laboratorium Bell pada awal tahun 80-an, sebagai pengembangan dari bahasa C dan Simula. Saat ini, C++ merupakan salah satu bahasa yang paling populer untuk pengembangan software berbasis OOP. Tulisan ini memperkenalkan paradigma pemrograman berorientasi objek dengan menggunakan C++. Bagaimana Konsep OOP? Konsep utama pemrograman berorientasi objek yaitu melakukan permodelan objek dari kehidupan nyata ke dalam tipe data abstrak. Jelasnya, pemrograman berorientasi objek merupakan konsep pemrograman untuk memodelkan objek yang kita gunakan dalam kehidupan sehari-hari, dan konsep seperti ini membawa perubahan yang mendasar dalam konsep pemrograman terstruktur. Perubahan dramatis dalam konsep dasar disebut paradigma, maka jangan heran bila banyak orang yang menyebut “paradigma OOP” karena memang OOP membawa konsep yang sama sekali berbeda dengan bahasa pemrograman generasi sebelumnya (bahasa pemrograman terstruktur). Setiap objek dalam kehidupan nyata dapat kita pandang sebagai kelas, misalnya kelas Hewan, kelas Manusia, kelas Mobil. Sedangkan objek dari kelas tersebut misalnya sapi dan ayam untuk kelas Hewan, Budi dan Tono untuk kelas Manusia serta Toyota dan VW untuk kelas Mobil. Dengan OOP, kita dapat mengimplementasikan objekt data yang tidak hanya memiliki ciri khas (attribut), melainkan juga memiliki metode untuk memanipulasi attribut tersebut. Singkatnya, OOP memiliki keunggulan dari konsep pemrograman terstruktur, selain itu juga memiliki kemampuan untuk mengimplementasikan objek dalam kehidupan nyata. Struktur Kelas Sebagai langkah pertama dalam OOP akan kita bahas pendefinisian kelas di C++. Dalam bagian 1.2 penulis telah mencontohkan beberapa kelas yang lazim kita temui dalam kehidupan sehari-hari. Mari kita amati contoh lain dari kehidupan kita, dengan mendeklarasikan sebuah kelas bernama BilanganRasional : class BilanganRasional { public : void assign (int,int); void cetak(); private : int pembilang, penyebut;

  • Created By Muhammad Syahrizal 52

    }; Perhatikan contoh di atas. Untuk mendefinisikan sebuah kelas, dipakai kata kunci class, diikuti dengan pendeklarasian nama kelas tersebut. Fungsi assign() dan cetak() disebut member function (member fungsi). Sedangkan variabel pembilang dan penyebut disebut member data (member data atau member variabel). Disebut member karena kesemuanya merupakan anggota dari kelas BilanganRasional. Perhatikan kata kunci Public dan Private. Member functions pada contoh di atas dideklarasikan sebagai fungsi global, sedangkan member data dideklarasikan sebagai lokal. Perbedaannya, member global dapat diakses dari luar kelas, sedangkan member lokal hanya dapat diakses dari kelas itu sendiri. Sekarang, dimana kita telah menciptakan kelas Bilangan Rasional, kita dapat mendeklarasikan sebuah objek dari kelas BilanganRasional sebagai berikut : BilanganRasional objekBilangan; Perhatikan bahwa disini objekBilangan merupakan nama dari objek tersebut, dan BilanganRasional merupakan nama kelas yang ingin kita buat objeknya. Proses pembuatan sebuah objek biasa disebut penginstansian (bukan penginstalasian), dan sebuah objek disebut instans (instance) dari sebuah kelas. Untuk lebih jelasnya, perhatikan listing selengkapnya : class BilanganRasional { public : void assign (int,int); void cetak(); private : int pembilang, penyebut; }; void main() { //mendeklarasikan objekBilangan seperti telah dibahas di atas BilanganRasional objekBilangan; // member fungsi assign() dipanggil. objekBilangan.assign (22,7); // member fungsi cetak() dipanggil. ObjekBilangan.cetak(); } void BilanganRasional::assign(int pemb, int peny) { pembilang = pemb; penyebut = peny; } void BilanganRasional::cetak() { cout

  • Created By Muhammad Syahrizal 53

    tipe BilanganRasional. Sekarang, bagaimana memanggil fungsi dari sebuah objek? Hal ini dapat dicapai dengan menghubungkan nama objek dan fungsi yang ingin dipanggil dengan operator tanda titik (.). Sehingga untuk memanggil fungsi assign(), dapat dilakukan dengan cara sebagai berikut : objekBilangan.assign(22,7); Nilai 22 dan 7 merupakan parameter yang diterima oleh fungsi assign(). Di dalam fungsi tersebut, nilai 22 diinisialisasikan ke dalam member data pembilang, dan nilai 7 diinisialisasikan ke dalam member data penyebut. Sehingga bila fungsi cetak() dipanggil, maka akan diperoleh hasil sebagai berikut : Sebagai tambahan perhatikan ilustrasi di bawah ini :

    Gambar di atas merupakan ilustrasi dari objek objekBilangan dengan 2 member data, yakni pembilang dan penyebut. Perhatikan juga bahwa semua pendeklarasian fungsi, baik fungsi assign() maupun fungsi cetak() didahului dengan penanda BilanganRasional:: . Hal ini untuk menunjukkan kepada compiler agar compiler tidak “bingung”, untuk kelas mana fungsi tersebut dideklarasikan, karena di C++ biasanya sebuah fungsi diletakkan di file yang terpisah. Konstruktor Sebelumnya kita telah menggunakan member fungsi assign() untuk memasukkan nilai ke dalam member variabel pembilang dan penyebut. Sebuah konstruktor melakukan tugas yang sama dengan fungsi assign(), sehingga Anda tidak perlu repot-repot memanggil fungsi assign() untuk setiap objek yang Anda deklarasikan. Sebuah konstruktor harus mempunyai nama yang sama dengan kelas dimana konstruktor tersebut berada, dan dideklarasikan tanpa return value (nilai balik), juga tanpa kata kunci void. Mari kita kembangkan kelas BilanganRasional yang telah kita bahas sebagai berikut : class BilanganRasional { public : //KONSTRUKTOR BilanganRasional BilanganRasional(int pemb, int peny) { pembilang = pemb; penyebut = peny; } private : int pembilang, penyebut; }; Bandingkan struktur konstruktor dengan fungsi assign() yang telah kita bahas sebelumnya. Konstruktor BilanganRasional melakukan tugas yang sama dengan member fungsi assign().

  • Created By Muhammad Syahrizal 54

    Bedanya hanya terletak pada pemanggilan fungsi dan konstruktor tersebut. Jika fungsi assign() harus kita panggil dengan didahului oleh pendeklarasian sebuah objek, kemudian fungsi dari objek tersebut dipanggil dengan operator titik disertai nilai yang ingin kita input, misal BilanganRasional x; x.assign(22,7); maka konstruktor cukup dipanggil sebagai berikut : BilanganRasional x(22,7); Kedua varian tersebut melakukan hal yang sama, yakni menginitialisasikan nilai 22 ke member variabel pembilang, dan nilai 7 ke variabel penyebut. Konstruktor Dengan Initialization Lists Penulisan konstruktor dengan daftar initialisasi (initialization lists) merupakan fasilitas yang disediakan oleh C++ untuk menyederhanakan struktur konstruktor. Ini berarti, contoh konstruktor di atas dapat pula ditulis sebagai berikut : class BilanganRasional { public : BilanganRasional(int pemb, int peny) : pembilang(pemb), penyebut(peny) { } private : int pembilang, penyebut; }; Contoh di atas menghasilkan fungsi yang sama dengan konstruktor yang kita bahas sebelumnya. CopyConstructor Sampai sejauh ini kita telah mempelajari bagaimana struktur sebuah konstruktor serta bagaimana membuat objek dari konstruktor yang telah didefinisikan. Akan tetapi, coba bayangkan apabila Anda telah mempunyai sebuah objek x, dan kemudian Anda menginginkan membuat sebuah objek y yang memiliki nilai member data dan member fungsi yang sama. Tentu saja Anda dapat mendeklarasikan objek baru dengan memanggil konstruktor yang sama sebanyak 2 kali : BilanganRasional x(22,7); BilanganRasional y(22,7); Perintah di atas mendeklarasikan 2 objek, yakni x dan y yang masing-masing memiliki nilai 22 pada member variabel pembilang dan 7 pada member variabel penyebut. Akan tetapi, Anda dapat juga mempersingkat kode diatas dengan perintah berikut : BilanganRasional x(22,7); BilanganRasional y(x); Berikut listing contoh untuk Copy Constructor : class BilanganRasional { public : BilanganRasional(int pemb, int peny) : pembilang(pemb), penyebut(peny) { } //CopyConstructor terdapat disini BilanganRasional(const BilanganRasional& br) : pembilang(br.pembilang), penyebut(br.penyebut) { } private : int pembilang, penyebut; }; void main() { BilanganRasional x(22,7); BilanganRasional y(x); }

  • Created By Muhammad Syahrizal 55

    Deklarasi CopyConstructor otomatis dipanggil ketika Anda mengkopi objek x ke objek y. Perhatikan bahwa x menjadi parameter ketika kita mendeklarasikan objek y. Destruktor Jika kita mendeklarasikan konstruktor untuk membuat sebuah objek, maka kita juga harus mendeklarasikan sebuah destruktor untuk menghapus sebuah objek. Setiap kelas mempunyai tepat satu destruktor. Jika Anda tidak mendeklarasikan sebuah destruktor dalam sebuah kelas, maka destruktor otomatis akan diciptakan sendiri oleh compiler C++. Destruktor dapat kita definisikan sendiri dengan simbol ~. Disarankan untuk mendefinisikan sendiri destruktor walaupun secara otomatis compiler C++ akan mendeklarasikan sebuah destruktor pada saat program Anda dicompile, tetapi dengan mendefinisikan sendiri sebuah destruktor maka Anda mempunyai kontrol penuh terhadap apa yang dilakukan destruktor dari kelas Anda. Perhatikan listing di bawah : class BilanganRasional { public : BilanganRasional() {cout

  • Created By Muhammad Syahrizal 56

    orang. Belakangan muncul toolkit yang memang dirancang untuk memudahkan pembuatan aplikasi dengan bertindak selaku lapis abstraksi, selain juga untuk memicu upaya konsistensi look-and-feel antara satu program dengan program lainnya. Dengan menggunakan toolkit, API X Window yang rumit menjadi disembunyikan melalui sekumpulan fungsi-fungsi yang lebih sederhana. Lebih jauh, setelah kehadiran toolkit, muncul pula desktop environment seperti CDE, KDE, dan GNOME yang meningkatkan derajat abstraksi pengembangan aplikasi menjadi lebih dari sekedar user interface semata. Qt adalah toolkit yang digunakan untuk membangun aplikasi berbasis GUI di Unix. Qt dikembangkan oleh Trolltech [1] dan menjadi fondasi untuk K Desktop Environment (KDE), selain juga telah dipergunakan dalam berbagai aplikasi komersial. Qt digolongkan sebagai software open-source karena dilisensi dual: dengan General Public License (GPL) dan Qt Public License (QPL). Khusus untuk tulisan ini, yang akan dibahas adalah Qt versi 2.x. Qt dirancang untuk pengembangan aplikasi dengan C++. Oleh karenanya, Qt berisi sekumpulan kelas-kelas yang tinggal dimanfaatkan saja, mulai dari urusan antarmuka (user interface), operasi input ouput, networking, timer, template library, dan lain-lain. Qt mendukung penuh Unicode (mulai versi 2.0) sehingga urusan internationalization (I18N) dan encoding teks bukan menjadi masalah. Walaupun merupakan