Pemrograman Dasar C Minggu 8 Topik Bahasan • Fungsi – Fungsi main dan keseluruhan kontrol program – Prototype fungsi – Cakupan (scope) dari deklarasi variabel • Teknik Desain – Implementasi Bottom Up – Testing dengan Stubs dan Drivers – printf sebagai alat debug Tambahan tentang Main • main mempunyai tipe yang dapat di-return. Biasanya int yang dipergunakan. Maka program dapat return sebuah nilai kepada System Operasi, berguna untuk mengindikasikan keberhasilan dari eksekusi program (0) atau sebuah error (-1) terjadi. • ‘void’ adalah tipe spesial yang berarti ‘tanpa_tipe’. Sebuah main bertipe void tanpa return. void main (void) { /* statemen yang berguna disini tapi tanpa statemen return */ } Tambahan tentang Main • Kasus spesial untuk parameter tipe void. Jika fungsi main dideklarasikan mempunyai parameter formal bertipe void, contoh: int main (void) atau variabel dengan { /* beberapa statemen disini */ kode error return (0); } Ini memperjelas bahwa fungsi ii tidak membutuhkan parameter dari command line. • Semua fungsi yang dideklarasikan dengan void sebagai parameter formal tidak membutuhkan parameter yang dikirim. Prototype Fungsi • Mendefinisikan fungsi sebelum digunakan (terletak diatas main) tidak selalu diinginkan, tapi mereka harus dideklarasikan, sehingga kompiler dapat mengecek angka dan tipe parameter dll ketika fungsi tsb dilihat. • Sebuah prototype fungsi mirip dengan ‘spesifikasi antar-muka (interface)’ yang terdiri dari: – – – – tipe return dari fungsi, contoh int nama fungsi daftar dari parameter formal diakhiri langsung dengan ; (tanpa {}), contoh: float fungsi_saya (int x, double y); Prototype Fungsi float fungsi_saya (int x, double y); • Hanya itulah yang dibutuhkan, asalkan linker tidak menemukan sebuah definisi penuh dari fungsi_saya di tempat lain (seperti setelah main). • Statemen #include <stdio.h> yang digunakan dalam program kita telah menyertakan sebuah file (stdio.h) ke dalam program dengan prototype fungsi (dengan hal-hal lain) seperti printf & scanf dll. Linker menemukan definisi (atau kode objek) setelahnya di library standard C. #include <stdio.h> /* deklarasi global pertama */ const double my_pi = 3.14159261; /* deklarasi prototype fungsi */ double rectance (double c, double f); /* definisi fungsi main */ int main (void) { double cap, freq, x; int in_c; /* deklarasi lokal */ Contoh Prototype Fungsi printf(“\nMasukkan nilai kapasitansi: “); scanf(“ %lf”, &cap); printf(“\nMasukkan frekuensi: “); scanf(“ %lf”, &freq); x = reactance( cap, freq ); printf(“\nReaktansi = %g”, x); printf(“\nTekan ‘q’ dan ENTER untuk keluar:”); scanf(“ %c”, &in_c); return (in_c); } /* CATATAN: ini akhir dari main */ /* Akhirnya definisi dari prototype */ double reactance (double c, double f) { double reac; /* deklarasi lokal */ reac = 1 / (2 * my_pi * f * c); return (reac); } Lingkup Deklarasi • Deklarasi (misalnya variabel) mempunyai lingkup tertentu tergantung letak dimana deklarasi berada. Ini berarti kita bisa menggunakan sesuatu yang dideklarasikan di suatu tempat tapi tidak di lain tempat. • Variabel Lokal & Global: jika variabel dideklarasikan: – Pada tingkat file (jadi tidak di dalam fungsi, tidak juga termasuk didalam main()), lingkupnya dapat diakses di mana saja di file tsb. (Dikenal sebagai variabel GLOBAL di dalam program file tunggal) – Di dalam sebuah fungsi (termasuk main()), lingkupnya pada batas dalam dari fungsi tsb, tidak dapat diakses diluar fungsi tsb. (Dikenal sebagai variable LOKAL). Contoh Lingkup Deklarasi Jika kita mempunyai variabel Apel dideklarasikan pada tingkat file (global) dan satu variabel lagi bernama Apel dideklarasikan di dalam sebuah fungsi (lokal) pada file tsb. maka: – Semua referensi ke Apel yang dibuat di dalam fungsi mengakses Apel lokal yang dideklarasikan pada fungsi dan bukan versi global pada tingkat file. – Semua referensi ke Apel di tempat lainnya pada file (di fungsi lain termasuk main) mengakses Apel global yang dideklarasikan pada tingkat file. Lingkup Deklarasi • Dari contoh prototype fungsi sebelumnya (menghitung reaktansi) kita dapat menggambarkan lingkup dari variabel dan konstan sbb: Tingkat File: GLOBAL berikut dikenal dimana-saja: konstan my_pi Tingkat fungsi reactance LOKAL berikut dikenal disini saja: reac dan parameter lokal konstan c dan f Juga konstan GLOBAL my_pi Tingkat fungsi main LOKAL berikut dikenal disini saja cap, freq, x dan in_c Juga konstan GLOBAL my_pi #include <stdio.h> int y, v = 2; Contoh Problem Lingkup deklarasi global tingkat file deklarasi tingkat fungsi lokal utk fungsi sum int sum (int x) { int rslt, w; ‘v’ mana yang dipakai? w = x * y * v; rslt = w + z; /* #1# */ return (rslt); } int main (void) { int v, z; lokal di main z = 2; y =3; v = sum (6) * w; /* #2# */ return (0); } ‘v’ mana yang dipakai? Error saat kompilasi: •ERROR Undefined symbol z (lihat #1#) •ERROR Undefined symbol w (lihat #2#) Kelas Penyimpanan untuk Variabel • Kita tahu bahwa variabel yang dideklarasikan di dalam fungsi (variabel lokal) “hidup dan mati bersama dengan fungsi” jadi semua yang disimpan di dalamnya pada akhir panggilan untuk fungsi hilang dan tidak ada saat fungsinya dipanggil lagi kemudian. Ini adalah kelas penyimpanan untuk variabel yang otomatis. int inc_add (int a) { int b; b += a; /* sama dengan b = b + a */ return (b); } Disini nilai b hilang diantara panggilan-panggilan sehingga statemen b += tidak berguna Kelas Penyimpanan untuk Variabel • Variabel diatas dapat dibuat untuk mempunyai kelas penyimpanan statis, yang berarti “hidup terus” setelah penggunaan pertama sehingga mengingat semua yang disimpan di dalamnya diantara panggilan-panggilan, dengan menambahkan kata kunci static seperti dibawah ini: int inc_add (int a) { static int b = 10; b += a; return (b); } Layout dari sebuah Program • Program kita terdiri dari 4 bagian, yang biasanya ditemukan dalam urutan sbb: – Direktif pre-prosesor (#include, #define) – Deklarasi dan definisi tingkat file: Atau • • • • Definisi tipe (contoh: enum dll) Konstan dan Variabel global Prototype Fungsi (baris pertama saja) Definisi Fungsi – definisi lengkap (tidak untuk prototype, definisinya muncul diakhir) – Deklarasi variabel lokal – Statemen ‘buatlah sesuatu’ termasuk panggilan untuk fungsi lain Layout dari sebuah Program • Bagian program (cont’d) – Fungsi ‘main’ yang spesial • Deklarasi variabel lokal • Statemen ‘buatlah sesuatu’ (termasuk panggilan untuk fungsi lain) – Definisi fungsi untuk semua prototype diatasnya • Deklarasi variabel lokal • Statemen ‘buatlah sesuatu’ (termasuk panggilan untuk fungsi lain) Implementasi Bottom Up • Sebelumnya kita mendiskusikan Desain Top Down diikuti Implementasi Bottom Up untuk berhasil menulis program: – Desain Top Down berarti dimulai dengan deskripsi tingkat tinggi dari apa yang seharusnya dilakukan program (contoh: sebuah diagram struktur sederhana dengan hanya beberapa blok masing-masing sebuah tugas besar). Kemudian memecah blok desain menjadi ‘potongan’ lebih banyak dan lebih kecil, menjadi lebih detail pada setiap tingkatan hirarki sampai kita mempunyai sebuah gambar (atau kumpulan gambar) dengan banya sub-blok, masing-masing merepresentasikan sebuah tugas tingkat rendah tunggal. Implementasi Bottom Up • Diikuti dengan ... – “Implementasi Bottom Up” ketika kita menulis kode ‘C’ pada program kita, dimulai dengan menulis kode untuk mengimplementasikan setiap tugas-tugas termudah (sub-blok) yang digambarkan pada deskripsi hirarki tingkat terbawah dari program yang dibuat selama fase “Top-Down”, selanjutnya mengintegrasikannya pada blok lebih besar secara bertingkat, bekerja naik hirarki, sampai seluruh program selesai. Stub dan Driver • Dengan menggunakan jalur Implementasi Bottom Up, adalah bijaksana untuk mengetes setiap blok kode yang tertulis sebelum bergerak untuk mengintegrasikannya ke dalam blok yang lebih besar dimana error mungkin lebih sukar untuk dicari dan diselesaikan. • Driver adalah program pendek yang spesial, terdiri dari sebuah fungsi main yang kecil, yang tugas tunggalnya adalah mencoba fungsi yang akan dites dengan memanggilnya (mengirim parameter yang sesuai?) dan meneliti (dan menampilkan?) hasil yang dikembalikan, sehingga kita dapat mengecek apakah berfungsi dengan benar sebelum digunakan dalam sebuah program yang besar Stub dan Driver • Stub adalah fungsi dummy, jadi fungsi-fungsi yang akan digunakan pada bagian lain dari kode sebagai pengganti dari fungsi sesungguhnya yang belum ditulis. Mereka memungkinkan bahwa bagian lain dari kode dapat dites sebelum semua fungsi yang berkaitan ada. ( Deklarasi prototype stub akan sama dengan fungsi sebenarnya yang final tapi isinya mungkin hanya mengembalikan nilai tetap. Ini memungkinkan bagian diluar dari kode untuk dites). Stub dapat diganti dengan fungsi sesungguhnya dengan isi yang benar pada saatnya nanti. • Berikut sebuah ‘driver’ main rutin yang ditulis hanya untuk mengetes fungsi calc_n_fac #include <stdio.h> Contoh Driver long calc_n_fac (int y) { long i; for (i = (long)y; --y; y>1; y--) { i *= y; } return (i); } int main (void) { int n; long rslt; Fungsi yang dites DRIVER /* driver untuk mengetes calc_n_fac */ memanggil fungsi yg dites for (n=1; n<=10; n++) { rslt = calc_n_fac(n); printf(“\n%2d faktorial = “, n); printf(“%7ld”, rslt); } mengecek output fungsi return (0); } • Dua stub telah digunakan pada program dibawah sehingga rutin main dapat dites sebelum versi final dari fungsi ini tersedia #include <stdio.h> int get_input (void) { return (4); } /* mengembalikan nilai tetap */ long calc_n_fac (int y) { return ((long)y * 2.0) /* mengembalikan input x 2 */ Contoh Stub /*stub*/ /*stub*/ void display_hasil (int n, long x) { printf(“\n%d faktorial = %ld, n, x);} int main (void) { int n; long rslt; char in_c; do { n = get_input(); rslt = calc_n_fac(n); display_hasil(n, rslt); printf(“\nTekan ‘y’ untuk lanjut: “); scanf(“ %c”, &in_c); } while (in_c = = ‘Y’ || in_c = = ‘y’); return (0); } Fungsi yang dites Menggunakan printf sebagai alat pencari kesalahan • Sering, ketika mengetes pertama kali sebuah program, anda akan mendapat bahwa ia tidak bekerja atau berperilaku seperti yang diharapkan – Jika anda telah menulis banyak kode semuanya bersama-sama, dan kemudian mengetesnya, mencari problem akan sukar, bahkan tidak mungkin! – Jika anda mengikuti petunjuk sebelumnya dan melakukan jalur setahap demi setahap “Bottom Up” untuk implementasi kemudian anda mempunyai hanya bagian kecil dari kode yang belum terbukti pada setiap tahap, untuk menguji terhadap problem menjadi lebih mudah! Menggunakan printf sebagai alat pencari kesalahan • Memasukkan statemen “printf” (dengan pesan yang sesuai) pada lokasi penting yang strategis dapat memungkinkan anda untuk melacak perilaku sebenarnya dari program anda. – Gunakan untuk menampilkan nilai saat itu dari variabel pada tahap operasi tertentu, apakah sesuai yang diharapkan? Membantu mencari letak error. – Gunakan untuk mengindikasikan bahwa sebuah bagian tertentu dari kode telah dicapai, atau untuk menunjukkan setiap iterasi dari loop dll. • Gunakan printf untuk mengecek asumsi anda! Contoh printf untuk debug • Ini adalah fungsi ‘n faktorial’ sebelumnya dengan printf ditambahkan untuk menunjukkan apa yang terjadi pada setiap iterasi dari for loop. long calc_n_fac (int y) { long i; 1 printf(“\nstart y = %d”, y); for (i = (long)y, --y; y>1; y--) { printf(“\ni = %ld y = %d”, i, y); 2 i *= y; printf(“ i berubah menjadi = %ld” i); 3 } return (i); } Contoh printf untuk debug 1. Printf yang pertama menunjukkan nilai dari parameter yang masuk ‘y’ sebelum for loop. 1. Yang kedua menunjukkan nilai dari ‘i’ dan ‘y’ pada awal dari setiap iterasi dari for loop. 2. Yang ketiga menunjukkan bagaimana ‘i’ berubah selama setiap iterasi dari for loop. • Maka, anda dapat mengecek bahwa fungsi berperilaku sesuai harapan dengan membandingkan nilai-nilai yang tertampilkan dengan nilai-nilai yang dihitung sendiri. Ringkasan • Fungsi – main adalah fungsi dan permulaan dari eksekusi program dikontrol dari sini. – Prototype fungsi memungkinkan fungsi diberi nama diatas main tapi detailnya terletak setelah main. – Lingkup dari variabel: Global/lokal, file/fungsi, Static – menyimpan nilai, mempromosikan kemudahan membaca. Ringkasan • Teknik Desain – Perencanaan kertas dengan Top-Down, implementasi kode dengan Bottom-Up. – Layout Skeleton dari program – Testing dengan Stub dan Driver selama bottom up. – printf sebagai alat debug untuk menunjukkan perilaku yang memungkinkan verifikasi.