Bab. 4 Fungsi
Tujuan
Instruksional
|
|
·
Fungsi.
·
Definisi fungsi.
·
Prototipe fungsi.
·
Rekaman aktivasi
dan tumpukan pemanggilan fungsi.
·
Pemanggilan fungsi
dengan nilai dan dengan referensi.
|
·
Pembangkitan
bilangan acak.
·
Kelas penyimpanan.
·
Aturan skop.
·
Rekursi.
·
Rekursi versus
iterasi.
|
4.1 Introduksi
Kebanyakan program komputer yang
menyelesaikan masalah-masalah dunia nyata jauh lebih besar dari program-program
yang disajikan pada beberapa bab terdahulu. Pengalaman membuktikan bahwa cara
terbaik untuk mengembangkan dan merawat suatu program yang besar adalah dengan
mengkonstruksinya dari potongan-potongan atau modul-modul kecil, yang
masing-masing lebih mudah dikelola daripada program yang asli. Teknik ini
dinamakan dengan divide and conquer.
Bab ini akan menjelaskan beberapa fitur bahasa C yang memfasilitas perancangan,
implementasi, operasi, dan pemeliharaan program besar.
4.2 Modul Program Dalam C
Modul di dalam C disebut dengan fungsi.
Program C umumnya ditulis dengan menggabungkan fungsi baru yang Anda tulis
dengan fungsi paket yang tersedia di dalam pustaka standar C. Akan didiskusikan
kedua jenis fungsi tersebut dalam bab ini. Pustaka standar C menyediakan
koleksi fungsi yang kaya untuk melakukan operasi kalkulasi matametik,
manipulasi string, masukan/keluaran, dan banyak operasi lainnya yang berguna.
Modul berguna untuk mempermudah pekerjaan Anda, karena fungsi menyediakan
banyak kapabilitas yang Anda butuhkan.
Meskipun fungsi-fungsi pustaka standar
secara teknis bukan merupakan bagian dari bahasa C, tetapi semuanya disediakan
di dalam sistem C standar. Fungsi printf, scanf, dan pow yang telah
digunakan merupakan fungsi pustaka standar.
Anda dapat menulis fungsi untuk
mendefinisikan beberapa tugas spesifik yang dapat dipakai di banyak tempat di
dalam suatu program. Fungsi yang Anda tulis sendiri disebut pula dengan fungsi
terdefinisi-programer. Statemen-statemen aktual yang mendefinisikan fungsi
tersebut ditulis hanya sekali dan tersembunyi dari fungsi lain.
Fungsi dapat dipanggil melalui
pemanggilan fungsi, yang menspesifikasi nama fungsi dan menyediakan informasi
(sebagai argumen) yang dibutuhkan oleh fungsi yang dipanggil untuk melakukan
pekerjaan yang ditugaskan. Analogi yang umum untuk hal ini adalah suatu hirarki
suatu manajemen. Seorang boss (fungsi pemanggil atau pemanggil) meminta seorang
pekerja (fungsi terpanggil) untuk melakukan suatu pekerjaan dan melaporkan
kembali ketika pekerjaan selesai dilakukan (Gambar 4.1). Sebagai contoh, sebuah
fungsi yang akan menampilkan informasi di layar memanggil fungsi pekerja printf
untuk melakukan tugas tersebut, kemudian printf menampilkan informasi dan
melaporkan kembali, atau mengembalikan hasil, kepada fungsi pemanggil ketika
pekerjaan tersebut selesai dilakukan. Fungsi boss tidak mengetahui bagaimana fungsi pekerja melakukan pekerjaan yang
ditugaskan. Pekerja dibolehkan untuk memanggil fungsi pekerja lainnya, dan boss
tidak mengetahui hal ini. Akan Anda lihat sebentar lagi bagaimana penyembunyian
detil implementasi ini merupakan praktek rekayasa perangkat lunak yanag baik.
Gambar 4.1 menunjukkan fungsi main yang
berkomunikasi dengan beberapa fungsi pekerja di dalam suatu hirarki. Perhatikan
bahwa pekerja1 berperan sebagai sebuah fungsi boss
kepada pekerja4 dan pekerja5.
Gambar 4.1 | Hirarki relasi fungsi boss/fungsi
pekerja
4.3 Fungsi Pustaka Matematika
Fungsi-fungsi pustaka matematika memampukan
Anda untuk melakukan beberapa kalkulasi matematik umum. Akan digunakan beberapa
fungsi pustaka matematika di sini untuk mengenalkan konsep fungsi. Berikutnya
dalam buku ini, akan didiskusikan juga banyak fungsi lain dalam pustaka standar
C. Fungsi umumnya dipakai di dalam suatu program dengan menuliskan nama fungsi
diikuti dengan sebuah kurung kiri diikuti dengan argumen fungsi (atau daftar
argumen yang dipisahkan koma) yang diikuti dengan sebuah kurung kanan. Sebagai
contoh, seorang programer yang ingin menghitung dan menampilkan akar kuadrat
dari 900.0 akan menuliskan
printf( "%.2f", sqrt( 900.0 ) );
Ketika statemen ini dieksekusi, fungsi
pustaka matematika sqrt dipanggil untuk
menghitung akar kuadrat dari angka yang diapit kurung (900.0). Angka 900.0 merupakan
argumen dari fungsi sqrt. Statemen
tersebut akan menampilkan 30.00. Fungsi sqrt mengambil sebuah argumen bertipe double dan mengembalikan suatu hasil bertipe double. Semua fungsi di dalam pustaka
matematika, yang menghasilkan nilai pecahan, mengembalikan hasil tipe data double. Perhatikan bahwa nilai double, seperti nilai float, dapat
ditampilkan menggunakan spesifikasi konversi %f.
Argumen fungsi bisa berupa konstanta,
variabel, atau ekspresi. Jika c1 = 13.0, d = 3.0, dan f = 4.0, maka statemen
printf( "%.2f", sqrt( c1 + d * f ) );
menghitung dan menampilkan akar kuadrat
dari 13.0 + 3.0 * 4.0 = 25.0, menjadi 5.00. Beberapa fungsi pustaka matematika
C disimpulkan pada Gambar 4.2. Pada gambar tersebut, variabel x dan y keduanya
bertipe double.
Fungsi
|
Deskripsi
|
Contoh
|
sqrt(x)
exp(x)
log(x)
log10(x)
fabs(x)
ceil(x)
floor(x)
pow(x,y)
fmod(x,y)
sin(x)
cos(x)
tan(x)
|
akar kuadrat dari x
fungsi pemangkatan
logaritma natural dari x (basis e)
logaritma dari x (basis 10)
nilai absolut dari x
membulatkan x ke integer terkecil tidak kurang dari
x
membulatkan x ke integer terbesar tidak lebih dari x
x dipangkatkan dengan y
sisa dari x/y
sinus trigonometri dari x (x dalam radian)
kosinus trigonometri dari x (x dalam radian)
tangent trigonometri dari x (x dalam radian)
|
sqrt(900.0) adalah 30.0
sqrt( 9.0 ) adalah 3.0
exp(1.0) adalah
2.718282
exp(2.0) adalah
7.389056
log(2.718282) adalah 1
log(7.389056) adalah 2
log10(1.0) adalah 0.0
log10(10.0) adalah 1.0
log10(100.0) adalah 2.0
fabs(13.5) adalah 13.5
fabs(0.0) adalah 0.0
fabs(-13.5) adalah 13.5
ceil(9.2) adalah 10.0
ceil(-9.8) adalah -9.0
floor(9.2) adalah 9.0
floor(-9.8) adalah -10.0
pow(2,7) adalah 128.0
pow(9,.5) adalah 3.0
fmod(13.657,2.333) adalah 1.992
sin(0.0) adalah 0.0
cos(0.0) adalah 1.0
tan(0.0) adalah 0.0
|
Gambar 4.2 | Beberapa fungsi pustaka matematika
yang umum digunakan
4.4 Fungsi
Fungsi membantu Anda untuk
memodularisasi suatu program. Semua variabel yang didefinisikan di dalam
definisi fungsi adalah variabel lokal, yang hanya dikenal di dalam fungsi yang
di dalamnya variabel tersebut didefinisikan. Kebanyakan fungsi memiliki daftar
parameter yang menyediakan cara untuk mengkomunikasikan informasi di antara
fungsi. Sebuah parameter fungsi juga merupakan variabel lokal dari fungsi
tersebut.
Ada beberapa motivasi dalam
memfungsionalisasi suatu program. Pendekatan divide-and-conquer membuat
pengembangan program menjadi lebih mudah dikelola. Motivasi lainnya adalah
pendaur-ulangan kode, menggunakan fungsi-fungsi yang sudah ada sebagai
blok-blok pembangun untuk menciptakan kode baru. Pendaur-ulangan kode merupakan
faktor utama dalam gerakan pemrograman berorientasi objek, seperti C++, Java,
dan C# (C sharp).
4.5 Definisi Fungsi
Setiap program yang telah disajikan
memuat sebuah fungsi yang dinamakan main, yang memanggil
fungsi pustaka standar untuk mengerjakan tugasnya. Sekarang akan dipelajari
bagaimana menulis fungsi sendiri. Perhatikan suatu program yang menggunakan
fungsi kuadrat untuk menghitung dan menampilkan
kuadrat dari integer dari 1 sampai 10 (Gambar 4.3).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
/* Gambar4.3: gambar04_03.c
Menciptakan dan menggunakan fungsi terdefinisi-pengguna */
#include <stdio.h>
int kuadrat( int y ); /* prototipe fungsi */
/* fungsi main memulai eksekusi */
int main( void )
{
int
x; /* kounter */
/*
loop 10 kali dan menghitung dan menampilkan kuadrat dari x */
for
( x = 1; x <= 10; x++ ) {
printf( "%d ", kuadrat( x )); /* pemanggilan fungsi */
} /*
akhir for */
printf( "\n" );
return 0; /* indikasi terminasi sukses */
} /* akhir main */
/* definisi fungsi kuadrat menghasilkan
kuadrat dari parameter */
int kuadrat( int y ) /* y adalah salinan dari
argumen fungsi */
{
return y * y; /*
menghasilkan kuadrat dari y sebagai int */
} /* akhir fungsi kuadrat */
|
1 4 9 16 25 36 49 64 81 100
Gambar 4.3 | Penggunaan
suatu fungsi terdefinisi-programer
Fungsi kuadrat dipanggil pada main di dalam statemen printf (baris 14)
printf(
"%d ", kuadrat( x )); /* pemanggilan fungsi */
Fungsi kuadrat menerima sebuah salinan dari nilai x di dalam parameter y (baris 22). Kemudian kuadrat menghitung y * y (baris 24). Hasilnya dilewatkan kembali kepada fungsi printf di dalam main dimana kuadrat dipanggil
(baris 14), dan printf menampilkan
hasilnya. Proses ini diulangi 10 kali menggunakan statemen repetisi for.
Definisi fungsi kuadrat menunjukkan bahwa kuadrat mengharapkan sebuah parameter integer y. Katakunci int sebelum nama
fungsi (baris 22) mengindikasikan bahwa kuadrat menghasilkan nilai balik berupa
suatu integer. Statemen return di dalam kuadrat melewatkan kembali hasil perhitungan
kepada fungsi pemanggil.
Baris 5
int kuadrat( int y ); /* prototipe fungsi */
merupakan suatu prototipe fungsi.
Katakunci int yang diapit kurung menginformasikan
kompiler bahwa kuadrat berharap untuk
menerima suatu nilai integer dari pemanggil. Katakunci int di sebelah kiri nama fungsi menginformasikan kompiler bahwa
kuadrat menghasilkan nilai balik, berupa suatu integer, yang diberikan kepada
pemanggil. Kompiler merujuk kepada prototipe fungsi untuk memeriksa pemanggilan
terhadap kuadrat (baris 14) apakah memuat tipe nilai balik, jumlah argumen yang
tepat, tipe data argumen yang sesuai, dan apakah argumen memiliki urutan yang
benar. Prototipe fungsi didiskusikan secara detil pada Bagian 4.6.
Format suatu definisi fungsi adalah
tipe-nilai-balik nama-fungsi(
daftar-parameter )
{
definisi-definisi
statemen-statemen
}
nama-fungsi adalah
sembarang pengenal yang sah. tipe-nilai-balik
adalah tipe data dari hasil yang dikembalikan kepada pemanggil. tipe-nilai-balik void mengindikasikan bahwa sebuah fungsi tidak menghasilkan
suatu nilai. Semuanya bila digabungkan, tipe-nilai-balik,
nama-fungsi, dan daftar-parameter disebut pula dengan header fungsi.
daftar-parameter merupakan suatu daftar parameter yang dipisahkan dengan koma yang
menspesifikasi parameter-parameter yang diterima oleh fungsi ketika dipanggil.
Jika sebuah fungsi tidak menerima sembarang nilai, daftar-parameter berupa void. Suatu tipe data harus dicantumkan secara eksplisit untuk
setiap parameter.
definisi-definisi dan statemen-statemen yang
diapit kurung kurawal membentuk tubuh fungsi. Tubuh fungsi dikenal pula dengan
blok. Variabel dapat di dideklarasikan di dalam sembarang blok, dan blok dapat
dibuat menjadi bersarang. Fungsi tidak dapat didefinisikan di dalam fungsi
lain.
Ada tiga cara untuk mengembalikan
kendali program dari suatu fungsi terpanggil ke titik dimana fungsi dipanggil.
Jika fungsi tidak menghasilkan suatu nilai, kendali program dikembalikan ketika
kurung kurawal dari fungsi terpanggil dicapai, atau dengan mengeksekusi
statemen
return;
Jika fungsi menghasilkan suatu nilai
balik, statemen
return ekspresi;
menghasilkan nilai balik kepada
pemanggil berupa nilai dari ekspresi.
Fungsi maksimum
Contoh kedua berikut menggunakan suatu
fungsi maksimum yang didefinisikan sendiri untuk
menentukan dan menghasilkan nilai balik berupa integer terbesar dari tiga
integer (Gambar 4.4). Ketiga integer dientrikan dengan scanf (baris 15). Berikutnya, ketiga integer tersebut dilewatkan
kepada maksimum (baris 19), yang menentukan integer
terbesar. Nilai ini dikembalikan kepada main melalui statemen return di dalam maksimum (baris 37). Nilai balik yang
dikembalikan kemudian ditampilkan di dalam statemen printf (baris 19).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
/* Gambar 4.4: gambar04_04.c
Mencari nilai maksimum dari tiga integer */
#include <stdio.h>
int maksimum( int x, int y, int
z ); /* prototipe fungsi */
/* fungsi main memulai eksekusi */
int main( void )
{
int
angka1; /* integer pertama */
int
angka2; /* integer kedua */
int
angka3; /* integer ketiga */
printf( "Masukkan tiga integer: " );
scanf( "%d%d%d", &angka1, &angka2, &angka3 );
/*
angka1, angka12 dan angka3 adalah argumen
pada pemanggilan fungsi maksimum */
printf( "Nilai maksimum : %d\n", maksimum( angka1, angka2,
angka3 ));
return
0; /* indikasi terminasi sukses */
} /* akhir dari main */
/* Definisi fungsi maksimum */
/* x, y dan z adalah parameter */
int maksimum( int x, int y, int
z )
{
int
maks = x; /* diasumsikan x adalah terbesar */
if
( y > maks ) { /* jika y lebih besar dari maks,
tugaskan y kepada maks */
maks = y;
} /*
akhir if */
if
( z > maks ) { /* jika z lebih besar dari maks,
tugaskan z kepada maks */
maks = z;
} /*
akhir if */
return
maks; /* maks adalah nilai terbesar */
} /* akhir fungsi maksimum */
|
Masukkan tiga integer: 22 85 17
Nilai maksimum : 85
Masukkan tiga integer: 85 22 17
Nilai maksimum : 85
Masukkan tiga integer: 22 17 85
Nilai maksimum : 85
Gambar 4.4 | Pencarian
nilai maksimum di antara tiga integer
4.6 Prototipe Fungsi
Salah satu fitur yang penting dalam C
adalah prototipe fungsi. Fitur ini dipinjam oleh komite standar C dari para pengembang
C++. Prototipe fungsi memberitahu kompiler tentang tipe data nilai balik
fungsi, jumlah parameter yang diterima fungsi, tipe data tiap parameter, dan
urutan parameter. Kompiler menggunakan prototipe fungsi untuk memvalidasi
pemanggilan fungsi.
Versi awal C tidak melakukan jenis
pemeriksaan seperti ini, jadi sangat dimungkinkan bahwa pemanggilan fungsi
berakhir dengan error. Pemanggilan semacam itu bisa berakibat error yang fatal
atau error yang tidak fatal seperti error logika. Prototipe fungsi mengatasi
masalah seperti ini.
Prototipe fungsi untuk maksimum pada Gambar 4.4 (baris 5) adalah
int maksimum( int x, int y, int z ); /* prototipe fungsi */
Prototipe fungsi ini menyatakan bahwa maksimum mengambil tiga argumen bertipe int dan menghasilkan nilai balik bertipe int. Perhatikan bahwa prototipe fungsi sama seperti baris
pertama pada definisi fungsi maksimum.
Suatu pemanggilan fungsi yang tidak
cocok dengan prototipe fungsi menyebabkan error kompilasi. Error tersebut dibangkitkan
jika prototipe fungsi dan definisi fungsi tidak sesuai. Sebagai contoh, pada
Gambar 4.4, jika prototipe fungsi dituliskan menjadi
void maksimum( int x, int y, int z );
maka kompiler akan membangkitkan suatu
error karena tipe data nilai balik void di dalam
protipe fungsi berbeda dari tipe nilai balik int pada header fungsi.
Fitur penting lainnya dari prototipe
fungsi adalah pemaksaan argumen, yaitu memaksa argumen menjadi tipe yang
sesuai. Sebagai contoh, fungsi pustaka matematika sqrt dapat dipanggil dengan suatu argumen integer meskipun prototipe fungsi di
dalam <math.h> menspesifikasi suatu argumen double, dan fungsi tersebut masih bisa
bekerja dengan benar. Statemen
printf( "%.3f\n", sqrt( 4 ) );
secara benar mengevaluasi sqrt(4), dan menampilkan nilai 2.000.
Prototipe fungsi menyebabkan kompiler untuk mengkonversi nilai integer 4
menjadi nilai double 4.0 sebelum
nilai tersebut dilewatkan kepada sqrt. Secara umum,
nilai argumen yang tidak persis sama dengan tipe parameter di dalam prototipe
fungsi akan dikonversi menjadi tipe yang sesuai sebelum fungsi tersebut
dipangil. Konversi ini dapat menyebabkan hasil yang tidak tepat jika aturan
promosi C tidak diikuti. Aturan promosi mengatur bagaimana suatu tipe dapat
dikonversi menjadi tipe lain tanpa harus kehilangan data. Pada contoh sqrt tersebut, sebuah int secara otomatis dikonversi menjadi sebuah double tanpa terjadi pengubahan nilai. Namun, konversi sebuah double menjadi int akan menyebabkan pemotongan bagian pecahan (fraksional) dari nilai double. Konversi tipe integer yang lebih
besar menjadi tipe integer yang lebih kecil (misalnya, long menjadi short) juga dapat
mengakibatkan pengubahan nilai.
Gambar 4.5 | Hirarki promosi untuk semua tipe
data
Aturan promosi secara otomatis
diterapkan terhadap ekspresi yang memuat nilai dari dua atau lebih tipe data
(yang dikenal juga sebagai ekspresi tipe-gabungan). Tipe data dari setiap nilai
di dalam suatu ekspresi tipe-gabungan secara otomatis dipromosikan menjadi tipe
tertinggi di dalam ekspresi tersebut (sebenarnya sebuah versi temporer dari
setiap nilai yang diciptakan dan digunakan dalam ekspresi, dimana nilai-nilai
awal tetap tidak berubah). Gambar 4.5 mencantumkan semua tipe data dengan
urutan dari tipe tertinggi ke tipe terendah.
Konversi nilai menjadi tipe lebih
rendah biasanya menghasilkan nilai yang tidak tepat. Oleh karena itu, sebuah
nilai dapat dikonversi menjadi tipe yang lebih rendah hanya melalui penugasan nilai
tersebut secara eksplisit kepada suatu variabel bertipe rendah, atau dengan
menggunakan operator cast. Nilai argumen fungsi dikonversi menjadi tipe
parameter di dalam suatu prototipe fungsi, yang sama halnya dengan menugaskan
nilai tersebut secara langsung kapada variabel di dalam prototipe fungsi. Jika
fungsi kuadrat yang menggunakan sebuah parameter
integer (Gambar 4.3) dipanggil dengan sebuah argumen titik-mengambang
(misalnya, double atau float), maka argumen tersebut dikonversi menjadi int (tipe yang lebih rendah), dan kuadrat akan menghasilkan
hasil yang tidak tepat. Sebagai contoh, kuadrat(4.5) akan menghasilkan 16, bukan 20.25.
4.7 Tumpukan Pemanggilan Fungsi dan
Rekaman Aktivasi
Untuk memahami bagaimana C melakukan
pemanggilan fungsi, Anda terlebih dahulu perlu mempelajari struktur data, yang
dikenal sebagai tumpukan (stack).
Anda dapat menganalogikan tumpukan sebagai tumpukan piring. Ketika sebuah
piring diletakkan pada tumpukan, normalnya piring tersebut ditempatkan di atas
tumpukan (yang dikenal juga sebagai operasi push).
Sama halnya, ketika sebuah piring diambil dari tumpukan, normalnya piring
tersebut diambil dari atas tumpukan (yang dikenal juga dengan operasi pop). Tumpukan dikenal sebagai struktur
data LIFO (last-in, first-out), dimana item terakhir yang
ditempatkan (disisipkan) pada tumpukan merupakan item pertama yang diambil
(dibuang) dari tumpukan.
Ketika program memanggil suatu fungsi,
fungsi terpanggil harus mengetahui bagaimana kembali (mengembalikan nilai
balik, jika ada) ke pemanggil, jadi alamat kembali dari fungsi pemanggil
ditempatkan pada tumpukan eksekusi program (dikenal pula sebagai tumpukan
pemanggilan fungsi). Jika sederet pemanggilan fungsi dilakukan, alamat kembali
yang berurutan ditempatkan pada tumpukan secara LIFO, sehingga setiap fungsi
dapat kembali ke pemanggilnya.
Tumpukan eksekusi program juga memuat
memori untuk variabel lokal yang digunakan di dalam setiap pemanggilan fungsi.
Data ini, disimpan sebagai suatu potongan tumpukan eksekusi program, yang
dikenal sebagai rekaman aktivasi atau rekaman frame dari pemanggilan fungsi.
Ketika suatu pemanggilan fungsi dilakukan, rekaman aktivasi untuk pemanggilan
fungsi tersebut ditempatkan pada tumpukan eksekusi program. Ketika fungsi
kembali kepada pemanggilnya, rekaman aktivasi untuk fungsi ini dihapus atau
dibuang dari tumpukan dan variabel lokalnya tidak lagi dikenali oleh program.
4.8 Header
Setiap pustaka standar memiliki header
yang memuat prototipe fungsi untuk semua fungsi yang ada di dalam pustaka
tersebut dan definisi atas berbagai tipe data dan konstanta yang dibutuhkan
untuk semua fungsi tersebut. Gambar 4.6 mencantumkan secara alfabetikal
beberapa header pustaka standar. Istilah “macros” yang digunakan beberapa kali
pada Gambar 4.6 akan didiskusikan secara detil pada Bab 12.
Anda dapat menciptakan header sendiri.
Header yang didefinisikan sendiri juga harus menggunakan ekstensi nama file.
Header tersebut dapat disertakan menggunakan direktif preprosesor #include. Sebagai contoh, jika prototipe dari
fungsi kuadrat ditempatkan di dalam header kuadrat.h, maka
Anda menyertakan header tersebut di dalam program Anda menggunakan direktif
yang berada di atas program:
#include "kuadrat.h"
Fungsi
|
Deskripsi
|
<assert.h>
<ctype.h>
<errno.h>
<float.h>
<limits.h>
<locale.h>
<math.h>
<setjmp.h>
<signal.h>
<stdarg.h>
<stddef.h>
<stdio.h>
<stdlib.h>
<string.h>
<time.h>
|
Memuat macro dan informasi untuk membantu melakukan
debugging program.
Memuat prototipe fungsi untuk fungsi-fungsi yang
menguji karakter dan untuk fungsi-fungsi yang dapat dipakai untuk
mengkonversi huruf kecil menjadi huruf besar dan sebaliknya.
Mendefinisikan macro yang berguna untuk melaporkan
kesalahan.
Memuat ukuran titik-mengambang dari sistem.
Memuat ukuran integral suatu sistem.
Memuat prototipe fungsi dan informasi lainnya yang
memampukan suatu program untuk dimodifikasi pada sistem tertentu, seperti
tanggal, jam, dan lainnya.
Memuat prototipe fungsi untuk fungsi-fungsi pustaka
matematika.
Memuat prototipe fungsi untuk fungsi yang melakukan
bypassing pemanggilan fungsi dan runtun pengembalian.
Memuat prototipe fungsi dan macros untuk menangani
berbagai kondisi yang timbul selama eksekusi program.
Mendefinisikan macro untuk menangani daftar argumen
suatu fungsi yang memiliki jumlah dan tipe yang tidak diketahui.
Memuat definisi-definisi tipe yang digunakan C untuk
melakukan perhitungan.
Memuat prototipe fungsi untuk fungsi-fungsi pustaka
masukan/keluaran, dan informasi yang digunakan.
Memuat prototipe fungsi untuk konversi angka menjadi
teks dan teks menjadi angka, alokasi memori, bilangan acak, dan fungsi
utilitas lainnya.
Memuat prototipe fungsi untuk fungsi-fungsi
pemrosesan string.
Memuat prototipe fungsi dan tipe untuk memanipulasi
waktu dan tanggal.
|
Gambar 4.6 | Beberapa header pustaka standar
4.9 Pemanggilan Fungsi Dengan Nilai dan
Dengan Referensi
Ada dua cara untuk memanggil fungsi
dalam banyak bahasa pemrograman, pemanggilan-dengan-nilai dan
pemanggilan-dengan-referensi. Ketika argumen dilewatkan dengan nilai, nilai
argumen disalin dan dilewatkan kepada fungsi terpanggil. Perubahan terhadap
salinan tersebut tidak mempengaruhi nilai variabel asli di dalam pemanggil.
Ketika argumen dilewatkan dengan referensi, pemanggil membolehkan fungsi
terpanggil untuk memodifikasi nilai variabel asli.
Pemanggilan-dengan-nilai harus
digunakan ketika fungsi terpanggil tidak perlu memodifikasi nilai dari variabel
asli pemanggil. Hal ini mencegah efek samping yang tak sengaja dilakukan
(modifikasi variabel). Pemanggilan-dengan-referensi harus digunakan hanya
dengan fungsi terpanggil yang dapat dipercaya untuk memodifikasi variabel asli.
Dalam C, semua pemanggilan dilakukan
dengan nilai. Seperti yang akan Anda lihat pada Bab 6, adalah hal yang mungkin
untuk mensimulasikan pemanggilan-dengan-referensi dengan menggunakan operator
alamat dan operator indireksi. Pada Bab 5, akan Anda lihat bahwa array secara
otomatis dilewatkan dengan referensi.
4.10 Pembangkitan Bilangan Acak
Akan dikembangkan suatu program game
sederhana yang memuat banyak fungsi. Program menggunakan beberapa struktur
kendali yang telah dipelajari. Elemen peluang yang dipakai dalam aplikasi
komputer menggunakan fungsi pustaka standar C rand dari header <stdlib.h>. Perhatikan statemen berikut:
i = rand();
Fungsi rand membangkitkan integer antara 0 dan RAND_MAX (suatu konstanta simbolik yang
didefinisikan dalam header <stdlib.h>). C standar menyatakan bahwa nilai RAND_MAX sedikitnya bernilai 32767, yang merupakan
nilai maksimum untuk integer dua-byte (16 bit). Program pada bagian ini diuji
pada sistem C dengan nilai maksimum 32767 untuk RAND_MAX. Jika rand benar-benar menghasilkan
integer secara acak, maka setiap angka antara 0 dan RAND_MAX memiliki probabilitas yang sama.
Rentang nilai yang dihasilkan secara langsung
menggunakan rand seringkali berbeda dari apa yang dibutuhkan pada aplikasi
tertentu. Sebagai contoh, suatu program yang mensimulasikan pelemparan koin
hanya memerlukan 9 untuk “kepala” dan 1 untuk “ekor”. Program pelemparan dadu
yang mensimulasikan pelemparan dadu enam-sisi hanya memerlukan integer acak
dari 1 sampai 6.
Pelemparan Dadu
Enam-Sisi
Untuk mendemonstrasikan rand, akan dikembangkan suatu program untuk mensimulasikan 20
kali pelemparan suatu dadu enam-sisi dan menampilkan nilai setiap lemparan.
Prototipe fungsi untuk rand berada dalam <stdlib.h>. Akan digunakan operator sisa (%) sebagai berikut
rand() % 6
untuk menghasilkan integer dalam
rentang 0 sampai 5. Ini disebut dengan penskalaan. Angka 6 dikatakan sebagai
faktor penskala. Rentang angka yang dihasilkan kemudian digeser dengan
menambahkan 1 pada hasil sebelumnya. Keluaran
pada Gambar 4.7 memastikan bahwa hasil berada dalam rentang 1 sampai 6.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/* Gambar 4.7: gambar04_07.c
Menggeser integer terskala dengan 1 + rand() % 6 */
#include <stdio.h>
#include <stdlib.h>
/* fungsi main memulai eksekusi program */
int main( void )
{
int
i; /* kounter */
/*
loop 20 kali */
for
( i = 1; i <= 20; i++ ) {
/*
memilih angka acak dari 1 sampai 6 dan menampilkannya */
printf( "%10d", 1 + ( rand() % 6 ));
/*
jika kounter dapat dibagi 5, mulai garis baru */
if
( i % 5 == 0 ) {
printf( "\n" );
}
/* akhir dari if */
} /*
akhir dari for */
return
0; /* indikasi terminasi sukses */
} /* akhir main */
|
6 6 5 5 6
5 1 1 5 3
6 6 2 4 2
6 2 3 4 1
Gambar 4.7 | Menggeser dan
menskalakan integer menggunakan 1 + rand() % 6
Pelemparan Dadu
Enam-Sisi Sebanyak 6000 Kali
Untuk menunjukkan bahwa semua angka
acak yang dibangkitkan memiliki peluang yang (mendekati) sama, berikut akan
disimulasikan 6000 kali pelemparan dadu pada program Gambar 4.8. Setiap integer
dari 1 sampai 6 harus muncul berkisar 1000 kali. Seperti yang ditampilkan pada
keluaran program, simulasi pelemparan dadu enam-sisi dilakukan dengan menskalakan
dan menggeser fungsi rand. Tidak
diperlukan kasus default di dalam
statemen switch. Perhatikan pula kegunaan
penspesifikasi konversi %s untuk
menampilkan string karakter “Muka” dan “Frekuensi” sebagai kepala kolom (baris 53).
Setelah Array dipelajari pada Bab 5, akan ditunjukkan bagaimana mengganti
statemen switch ini dengan satu-baris statemen.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
/* Gambar 4.8: gambar04_08.c
Pelemparan dadu enam-sisi sebanyak 6000 kali */
#include <stdio.h>
#include <stdlib.h>
/* fungsi main memulai eksekusi program */
int main( void )
{
int
frekuensi1 = 0; /* kounter 1 */
int frekuensi2 = 0; /* kounter 2 */
int frekuensi3 = 0; /* kounter 3 */
int frekuensi4 = 0; /* kounter 4 */
int frekuensi5 = 0; /* kounter 5 */
int frekuensi6 = 0; /* kounter 6 */
int pelemparan; /* kounter
pelemparan, nilai 1 sampai 6000 */
int muka; /* merepresentasikan satu kali pelemparan dadu, nilai
1 sampai 6 */
/* loop 6000 kali dan menyimpulkan hasil */
for ( pelemparan = 1; pelemparan
<= 6000; pelemparan++ ) {
muka = 1 + rand() % 6; /* angka acak
dari 1 sampai 6 */
/* menentukan nilai muka dan menginkremen
kounter yang sesuai */
switch ( muka ) {
case
1: /* muka 1 */
++frekuensi1;
break;
case 2: /* muka 2 */
++frekuensi2;
break;
case 3: /* muka 3 */
++frekuensi3;
break;
case 4: /* muka 4 */
++frekuensi4;
break;
case 5: /* muka 5 */
++frekuensi5;
break;
case 6: /* muka 6 */
++frekuensi6;
break; /* opsional */
}
/* akhir dari switch */
} /*
akhir dari for */
/*
menampilkan hasil dalam format tabular */
printf( "%s%13s\n", "Muka", "Frekuensi"
);
printf( " 1%15d\n", frekuensi1 );
printf( " 2%15d\n", frekuensi2 );
printf( " 3%15d\n", frekuensi3 );
printf( " 4%15d\n", frekuensi4 );
printf( " 5%15d\n", frekuensi5 );
printf( " 6%15d\n", frekuensi6 );
return
0; /* indikasi terminasi sukses */
} /* akhir dari main */
|
Muka
Frekuensi
1
1003
2
1017
3
983
4
994
5
1004
6
999
Gambar 4.8 | Pelemparan
dadu enam-sisi sebanyak 6000 kali
Mengacak
Pembangkit Bilangan Acak
Eksekusi kembali terhadap program pada
Gambar 4.7 menghasilkan
6 6 5 5 6
5 1 1 5 3
6 6 2 4 2
6 2 3 4 1
Perhatikan bahwa runtun nilai yang sama
persis yang ditampilkan. Bagaimana hal ini dikatakan angka acak? ironisnya,
pengulangan ini merupakan karakteristik penting dari fungsi rand. Ketika mendebug suatu program, perulangan ini penting
untuk membuktikan bahwa koreksi pada suatu program berjalan dengan benar.
Fungsi rand sebenarnya membangkitkan bilangan semi-acak (pseudorandom). Pemanggilan rand secara berulang menghasilkan runtun
angka yang terlihat seperti acak. Tetapi, runtun tersebut berulang setiap kali
program dieksekusi. Begitu suatu program didebug, program tersebut dapat
dikondisikan untuk menghasilkan runtun acak yang berbeda pada tiap eksekusinya.
Ini dikatakan dengan pengacakan atau randomizing
dan dilakukan menggunakan fungsi pustaka standar srand. Fungsi srand memerlukan sebuah argumen integer unsigned yang akan
menghasilkan runtun acak yang berbeda pada tiap eksekusinya.
Akan didemonstrasikan srand pada Gambar 4.9. Pada program,
digunakan tipe data unsigned, yang merupakan
singkatan dari unsigned int. Sebuah int disimpan sedikitnya dua byte di dalam memori dan bisa
bernilai positif atau negatif. Variabel bertipe unsigned juga dapat disimpan sedikitnya dua-byte memori. Tipe data unsigned int dua-byte hanya bisa memuat nilai
positif dalam rentang dari 0 sampai 65535. Tipe data empat-byte unsigned int hanya bisa memuat nilai positif dalam
rentang dari 0 sampai 4294967295. Fungsi srand mengambil sebuah nilai unsigned
sebagai argumen. Penspesifikasi konversi %u digunakan untuk membaca
nilai unsigned dengan scanf. Prototipe fungsi untuk srand berada di dalam <stdlib.h>.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
/* Gambar 4.9: gambar04_09.c
Pengacakan program pelemparan-dadu */
#include <stdlib.h>
#include <stdio.h>
/* fungsi main memulai eksekusi program */
int main( void )
{
int
i; /* kounter */
unsigned benih; /* angka yang dipakai
sebagai benih pembangkit acak */
printf( "Masukkan benih: " );
scanf( "%u", &benih ); /* perhatikan %u untuk
unsigned */
srand( benih ); /* benih dari
pembangkit angka acak */
/*
loop 10 kali */
for
( i = 1; i <= 10; i++ ) {
/*
pilih suatu angka acak dari 1 dan 6 dan menampilkannya */
printf( "%10d", 1 + ( rand() % 6 ) );
/*
jika kounter dapat dibagi 5, maka mulai garis baru */
if
( i % 5 == 0 ) {
printf( "\n" );
}
/* akhir if */
} /*
akhir for */
return
0; /* indikasi terminasi sukses */
} /*
akhir main */
|
Masukkan benih: 67
6 1 4 6 2
1 6 1 6 4
Masukkan benih: 867
2 4 6 1 6
1 1 3 6 2
Masukkan benih: 67
6 1 4 6 2
1 6 1 6 4
Gambar 4.9 | Pengacakan
program pelemparan dadu enam-sisi
Akan dijalankan program tersebut
beberapa kali dan diamati hasilnya. Perhatikan bahwa runtun angka acak yang
berbeda dihasilkan setiap kali dijalankan dengan benih yang berbeda.
Untuk mengacak tanpa perlu menyuplai
benih setiap kali, gunakan statemen seperti
srand( time( NULL ) );
Ini menyebabkan komputer untuk membaca
waktu dalam mendapatkan nilai untuk benih secara otomatis. Fungsi time menghasilkan nilai balik berupa jumlah detik (setelah
tengah malam pada 1 Januari 1970). Nilai ini dikonversi menjadi sebuah integer
tak-bertanda dan digunakan sebagai benih untuk pembangkit bilangan acak. Fungsi
time mengambil NULL sebagai argumen (time mampu
menyediakan kapabilitas berupa string untuk merepresentasikan sebuah nilai yang
dijadikan nilai balik; NULL menon-aktifkan kapabilitas ini). Prototipe fungsi time disediakan di dalam <time.h>.
Generalisasi
Penskalaan dan Penggeseran Bilangan Acak
Nilai-nilai yang dihasilkan secara
langsung dari rand selalui berada
dalam rentang:
0
rand()
RAND_MAX
Seperti Anda ketahui, statemen berikut
mensimulasikan pelemparan dadu enam-sisi:
muka = 1 + rand() % 6;
Statemen ini selalu menugaskan nilai
integer (secara acak) kepada variabel muka dalam rentang 1
muka
6. Lebar rentang ini (jumlah integer berurutan
di dalam rentang) adalah 6 dan angka awal dalam rentang adalah 1. Hasil ini
dapat digeneralisir sebagai berikut
n = a + rand()
% b;
dimana a adalah nilai penggeser (yang sama dengan angka pertama di dalam rentang
yang diinginkan) dan b adalah faktor
penskala (yang sama dengan lebar rentang yang diinginkan).
4.11 Contoh: Permainan Peluang
Salah satu permainan (game) peluang
yang paling populer dikenal sebagai “craps”,
yang dimainkan di kasino di seluruh dunia. Aturan permainan ini adalah:
Seorang pemain melempar dua dadu. Setiap dadu mempunyai enam muka. Keenam
muka ini memuat titik bundar 1, 2, 3, 4, 5, dan 6. Setelah dadu berhenti,
jumlah titik-bundar pada dua muka yang menghadap ke atas dijumlahkan. Jika
penjumlahan sebesar 7 atau 11 pada pelemparan pertama, pemain menang. Jika
penjumlahannya adalah 2, 3, atau 12 pada pelemparan pertama (disebut dengan
“craps”), maka pemain kalah. Jika penjumlahannya adalah 4, 5, 6, 8, 9, atau 10
pada pelemparan pertama, maka penjumlahan tersebut menjadi poin untuk pemain.
Untuk memenangkan permainan, Anda harus terus melemparkan dadu sampai Anda
“mencetak poin”. Pemain akan kalah bila mendapatkan nilai lemparan 7 sebelum
mencetak poin.
Gambar 4.10 mensimulasikan permainan craps dan Gambar 4.11 menunjukkan
beberapa contoh keluaran program.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
/* Gambar 4.10: gambar04_10.c
Permainan Craps */
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* memuat prototipe fungsi time */
/* enumerasi merepresentasikan status
permainan */
enum Status { LANJUT, MENANG, KALAH };
int lemparDadu( void ); /* prototipe fungsi */
/* fungsi main memulai eksekusi program */
int main( void )
{
int
jum; /* jumlah dadu yang dilempar */
int
poinKu; /* poin yang didapatkan */
enum Status gameStatus; /* dapat
memuat LANJUT, MENANG, atau KALAH */
/*
mengacak pembangkit bilangan acak menggunakan waktu sekarang */
srand( time( NULL ) );
jum = lemparDadu(); /*
lemparan pertama dadu */
/*
menentukan status game berdasarkan pada jumlah dadu */
switch(
jum ) {
/*
menang pada pelemparan pertama */
case
7:
case
11:
gameStatus = MENANG;
break;
/*
kalah pada pelemparan pertama */
case
2:
case
3:
case
12:
gameStatus = KALAH;
break;
/*
mengingat poin */
default:
gameStatus = LANJUT;
poinKu = jum;
printf( "Poin adalah %d\n", poinKu );
break;
/* opsional */
} /*
end switch */
/*
jika game belum selesai */
while
( gameStatus == LANJUT ) {
jum = lemparDadu(); /*
melempar dadu kembali */
/*
menentukan status game */
if
( jum == poinKu ) { /* menang dengan mencetak poin */
gameStatus = MENANG; /* game selesai, pemain menang */
}
/* akhir if */
else
{
if
( jum == 7 ) { /* kalah karena pelemparan 7 */
gameStatus = KALAH; /* game selesai, pemain kalah */
}
/* akhir if */
}
/* akhir else */
} /*
akhir while */
/*
menampilkan pesan menang atau kalah */
if
( gameStatus == MENANG ) { /* apakah pemain menang? */
printf( "Pemain menang\n" );
} /*
akhir if */
else
{ /* pemain kalah */
printf( "Pemain kalah\n" );
} /*
akhir else */
return
0; /* indikasi terminasi sukses */
} /*
akhir main */
/* melempar dadu, menghitung dan menampilkan
hasil */
int lemparDadu( void )
{
int dadu1; /* dadu pertama */
int dadu2; /* dadu kedua */
int jumDadu; /* jumlah dadu */
dadu1 = 1 + ( rand() % 6 ); /* memilih nilai
dadu1 */
dadu2 = 1 + ( rand() % 6 ); /* memilih nilai
dadu2 */
jumDadu = dadu1 + dadu2; /* jumlah dadu1 dan
dadu2 */
/* menampilkan hasil dari pelemparan ini */
printf( "Pemain melemparkan %d +
%d = %d\n", dadu1, dadu2, jumDadu );
return jumDadu; /* menghasilkan
jumlah dadu */
} /* akhir funsi lemparDadu */
|
Gambar 4.10 | Program untuk
mensimulasikan permainan craps
Pemain melemparkan 3 + 1 = 4
Poin adalah 4
Pemain melemparkan 3 + 6 = 9
Pemain melemparkan 2 + 5 = 7
Pemain kalah
Pemain melemparkan 2 + 5 = 7
Pemain menang
Pemain melemparkan 3 + 2 = 5
Poin adalah 5
Pemain melemparkan 3 + 2 = 5
Pemain menang
Pemain melemparkan 3 + 1 = 4
Poin adalah 4
Pemain melemparkan 5 + 3 = 8
Pemain melemparkan 5 + 6 = 11
Pemain melemparkan 3 + 6 = 9
Pemain melemparkan 6 + 3 = 9
Pemain melemparkan 4 + 6 = 10
Pemain melemparkan 4 + 2 = 6
Pemain melemparkan 5 + 2 = 7
Pemain kalah
Gambar 4.11 | Contoh
keluaran program pada Gambar 4.10
Dalam aturan game, perhatikan bahwa
pemain harus melemparkan dua dadu pada pelemparan pertama, dan harus melakukan
hal yang sama pada pelemparan berikutnya. Anda telah mendefinisikan suatu
fungsi lemparDadu untuk melemparkan dadu dan menghitung
dan menampilkan penjumlahannya. Fungsi lemparDadu didefinisikan sekali, tetapi dipanggil dari dua tempat di dalam program
(baris 23 dan 51). Menariknya adalah lemparDadu tidak memerlukan argumen, seperti diindikasikan dengan void di dalam daftar parameter (baris 76). Fungsi lemparDadu mengembalikan nilai balik berupa
penjumlahan dua dadu, sehingga tipe nilai balik adalah int yang diindikasikan di dalam header
fungsi.
Pemain dapat menang atau kalah pada
lemparan pertama, atau dapat atau menang pada lemparan berikutnya. Variabel gameStatus, yang didefinisikan menjadi tipe baru
(enum Status), menyimpan status sekarang. Baris 8
menciptakan sebuah tipe yang didefinisikan sendiri yang dinamakan dengan
enumerasi. Suatu enumerasi, yang diawali dengan katakunci enum, merupakan sehimpunan konstanta integer yang
direpresentasikan oleh pengenal. Konstanta enumerasi kadangkala disebut pula
dengan konstanta simbolik. Nilai di dalam suatu enum dimulai dari 0 dan diinkremen sebesar 1.
Pada baris 8, konstanta LANJUT memiliki nilai
0, MENANG memiliki nilai 1, dan KALAH memiliki nilai 2. Adalah hal yang memungkinkan untuk
menugaskan suatu nilai integer kepada setiap pengenal di dalam enum (lihat Bab 9). Pengenal yang ada di dalam enumerasi harus
unik, tetapi nilainya dapat diduplikasi.
Ketika permainan dimenangkan, baik pada
lemparan pertama atau pada lemparan sesudahnya, gameStatus ditetapkan menjadi MENANG. Ketika
permainan kalah, baik pada lemparan pertama atau pada lemparan sesudahnya, gameStatus ditetapkan menjadi KALAH. Sebaliknya, gameStatus ditetapkan
menjadi LANJUT dan permainan berlanjut.
Setelah lemparan pertama, jika
permainan selesai, statemen while (baris 50)
dilompati karena gameStatus tidak LANJUT. Program berlanjut ke statemen if...else pada baris 65, yang akan menampilkan “Pemain menang” jika gameStatus adalah MENANG dan “Pemain kalah” jika sebaliknya.
Setelah pelemparan pertama, jika permainan
belum selesai, maka jum akan disimpan
di dalam poinKu. Eksekusi berlanjut ke statemen while (baris 50) karena gameStatus adalah LANJUT. Setiap kali
melalui while, lemparDadu dipanggil untuk menghasilkan jum baru. Jika jum cocok dengan poinKu, maka gameStatus ditetapkan menjadi MENANG untuk mengindikasikan bahwa pemain
menang, sedangkan jika uji pada while gagal, maka statemen if...else (baris 65) akan
menampilkan “Pemain menang” dan eksekusi
berhenti. Jika jum sama dengan 7
(baris 58), maka gameStatus ditetapkan
menjadi KALAH untuk mengindikasikan bahwa pemain
kalah, sedangkan jika uji pada while gagal, maka statemen if...else (baris 65) akan
menampilkan “Pemain kalah” dan eksekusi
berhenti.
Perhatikan arsitektur kendali program
yang menarik. Anda telah menggunakan dua fungsi, main dan lemparDadu, statemen switch, while, if...else bersarang, dan if bersarang.
4.12 Aturan Skop
Skop suatu pengenal adalah bagian
program dimana di dalamnya pengenal dapat direferensi. Sebagai contoh, ketika
sebuah variabel lokal didefinisikan di dalam suatu blok, ia dapat direferensi
hanya di dalam blok tersebut atau di dalam blok yang bersarang di dalam blok
tersebut. Empat jenis skop pengenal adalah skop fungsi, skop file, skop blok,
dan skop prototipe-fungsi.
Label (sebuah pengenal yang ditempatkan
setelah titik dua seperti mulai:) adalah
pengenal dengan skop fungsi. Label dapat digunakan dimana saja di dalam fungsi,
tetapi tidak dapat direferensi di luar tubuh fungsi. Label digunakan di dalam
statemen switch (seperti label dari case) dan di dalam statemen goto (lihat Bab 13). Label merupakan detil implementasi yang disembunyikan
fungsi dari fungsi lainnya.
Pengenal yang dideklarasikan di luar
sembarang fungsi disebut pula dengan skop. Pengenal semacam itu “dikenal” (dapat
diakses) di dalam semua fungsi mulai dari titik dimana pengenal tersebut
dideklarasikan sampai akhir dari file. Variabel global, definisi fungsi, dan
prototipe fungsi yang ditempatkan di luar suatu fungsi memiliki skop file.
Pengenal yang didefinisikan di dalam
sebuah blok memiliki skop blok. Skop blok berakhir pada kurung kurawal kanan
dari blok. Variabel lokal yang didefinisikan di awal suatu fungsi memiliki skop
blok, sama seperti parameter fungsi yang dipandang sebagai variabel lokal oleh
fungsi tersebut. Sembarang blok bisa memuat definisi fungsi. Ketika blok
tersebut bersarang, dan sebuah pengenal yang didefinisikan di dalam blok
sebelah luar memiliki nama sama dengan pengenal yang berada di blok sebelah
dalam, maka blok sebelah luar “tersembunyi” sampai blok sebelah dalam berhenti.
Ini berarti bahwa ketika blok sebelah dalam dieksekusi, blok tersebut melihat
nilai dari pengenal lokalnya sendiri dan bukan nilai dari pengenal (dengan nama
sama) yang didefinisikan di dalam blok sebelah luar.
Pengenal dengan skop prototipe-fungsi
adalah yang digunakan di dalam daftar parameter suatu prototipe fungsi. Seperti
disebutkan sebelumnya, prototipe fungsi tidak memerlukan nama di dalam daftar
parameter, karena hanya tipe data saja yang diperlukan. Jika sebuah nama
digunakan di dalam daftar parameter suatu prototipe fungsi, kompiler akan
mengabaikan nama tersebut. Pengenal yang digunakan di dalam prototipe fungsi
dapat digunakan kembali dimana saja di dalam program tanpa mengalami ambiguitas.
Gambar 4.12 mendemonstrasikan isu skop
dengan variabel global, variabal lokal otomatis, dan variabel lokal statis.
Variabel global x didefinisikan
dan diinisialisasi dengan 1 (baris 9). Variabel global ini tidak dikenal di
dalam sembarang blok (atau fungsi). Di dalam main, variabel lokal x didefinisikan
dan diinisialisasi dengan 5 (baris 14). Variabel ini kemudian ditampilkan untuk
menunjukkan bahwa variabel global x tidak dikenali
di dalam main. Berikutnya, blok baru didefinisikan
di dalam main dengan variabel lokal lainnya x yang diinisialisasi dengan 7 (baris 19). Variabel ini
ditampilkan untuk menunjukkan bahwa ia menyembunyikan x yang berada di blok sebelah luar dari main. Variabel x dengan nilai 7
secara otomatis dihancurkan ketika ekskusi keluar dari blok tersebut, dan
variabel lokal x yang berada di
blok sebelah luar dari main yang
ditampilkan kembali.
Program mendefinisikan tiga fungsi yang
masing-masing tidak memerlukan argumen dan tidak mengembalikan informasi
apapun. Fungsi gunakanLokal mendefinisikan
sebuah variabel otomatis x dan
menginisialisasinya dengan 25 (baris 40). Ketika gunakanLokal dipanggil, variabel tersebut ditampilkan, diinkremen, dan ditampilkan
kembali sebelum keluar dari fungsi. Setiap kali fungsi ini dipanggil, variabel
otomatis x diinisialisasi-ulang dengan 25. Fungsi
gunakanLokalStatis mendefinisikan sebuah variabel statis x dan menginisialisasinya dengan 50 (baris 53). Variabel
lokal yang didefinisikan static mempertahankan
nilainya meskipun berada di luar skopnya. Ketika gunakanLokalStatis dipanggil, x akan
ditampilkan, diinkremen, dan ditampilkan kembali sebelum keluar dari fungsi.
Dalam pemanggilan berikutnya terhadap fungsi ini, variabel lokal statis x akan memuat nilai 51. Fungsi gunakanGlobal tidak mendefinisikan variabel apapun. Oleh karena itu, ketika
ia merujuk ke variabel x, x global (baris 9) yang digunakan. Ketika gunakanGlobal dipanggil, maka variabel global
ditampilkan, dikalikan dengan 10, dan ditampilkan kembali sebelum keluar dari
fungsi. Pada pemanggilan kembali atas fungsi gunakanGlobal, variabel global masih memiliki nilai termodifikasinya, 10.
Terakhir, program menampilkan variabel lokal x di dalam main kembali (baris 33) untuk menunjukkan bahwa tidak ada
satupun pemanggilan fungsi yang dilakukan memodifikasi nilai x karena semua fungsi tersebut memanipulasi variabel di dalam
skopnya masing-masing.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
/* Gambar 4.12: gambar04_12.c
Contoh aturan skop */
#include <stdio.h>
void gunakanLokal( void ); /* prototipe fungsi
*/
void gunakanLokalStatis( void ); /* prototipe
fungsi */
void gunakanGlobal( void ); /* prototipe fungsi
*/
int x = 1; /* variabel global */
/* fungsi main memulai eksekusi program */
int main( void )
{
int
x = 5; /* variabel lokal main */
printf("x lokal di skop sebelar luar main adalah
%d\n", x );
{ /*
mulai skop baru */
int
x = 7; /* variabel lokal dalam skop baru */
printf(
"x lokal di dalam skop sebelah dalam dari main adalah %d\n", x );
} /*
akhir dari skop baru */
printf( "x lokal di skop sebelah luar dari main adalah %d\n", x );
gunakanLokal(); /* gunakanLokal memuat lokal otomatis
x */
gunakanLokalStatis(); /* gunakanLokalStatis
memuat lokal statis x */
gunakanGlobal(); /* gunakanGlobal menggunakan x
global */
gunakanLokal(); /* gunakanLokal
menginisialisasi-ulang lokal otomatis x */
gunakanLokalStatis(); /* lokal statis x
mempertahankan nilai sebelumnya */
gunakanGlobal(); /* x global mempertahankan
nilainya */
printf( "\nx lokal di dalam main adalah %d\n", x );
return
0; /* indikasi terminasi sukses */
} /* akhir main */
/* gunakanLokal menginisialisasi-ulang
variabel lokal x pada tiap pemanggilan */
void gunakanLokal( void )
{
int x = 25; /* menginisialisasi
setiap gunakanLokal dipanggil */
printf("\nx lokal
di dalam gunakanLokal adalah %d setelah memasuki gunakanLokal\n", x);
x++;
printf("x lokal
di dalam gunakanLokal adalah %d sebelum keluar dari gunakanLokal\n", x);
} /*
akhir fungsi gunakanLokal */
/* gunakanLokalStatis
menginisialisasi variabel lokal statis x hanya saat pertama
kali fungsi dipanggil; nilai dari x disimpan di
antara pemanggilan terhadap
fungsi ini */
void gunakanLokalStatis( void )
{
/*
menginisialisasi hanya saat pertama kali gunakanLokalStatis dipanggil */
static int x = 50;
printf("\nlokal statis x adalah %d pada saat memasuki gunakanLokalStatis\n", x);
x++;
printf("lokal statis x adalah %d pada saat keluar dari
gunakanLokalStatis\n", x);
} /* akhir dari fungsi gunakanLokalStatis */
/*fungsi gunakanGlobal memodifikasi variabel global
x selama tiap pemanggilan*/
void gunakanGlobal( void )
{
printf("\nglobal x adalah %d pada
saat memasuki gunakanGlobal\n", x);
x *=
10;
printf("global x adalah %d pada
saat keluar dari gunakanGlobal\n", x);
} /* akhir dari fungsi gunakanGlobal */
|
x lokal di skop sebelar luar main
adalah 5
x lokal di dalam skop sebelah dalam
dari main adalah 7
x lokal di skop sebelah luar dari main
adalah 5
x lokal di dalam gunakanLokal adalah
25 setelah memasuki gunakanLokal
x lokal di dalam gunakanLokal adalah 26 sebelum keluar
dari gunakanLokal
lokal statis x adalah 50 pada saat
memasuki gunakanLokalStatis
lokal statis x adalah 51 pada saat
keluar dari gunakanLokalStatis
global x adalah 1 pada saat memasuki
gunakanGlobal
global x adalah 10 pada saat keluar
dari gunakanGlobal
x lokal di dalam gunakanLokal adalah
25 setelah memasuki gunakanLokal
x lokal di dalam gunakanLokal adalah 26 sebelum keluar
dari gunakanLokal
lokal statis x adalah 51 pada saat
memasuki gunakanLokalStatis
lokal statis x adalah 52 pada saat
keluar dari gunakanLokalStatis
global x adalah 10 pada saat memasuki
gunakanGlobal
global x adalah 100 pada saat keluar
dari gunakanGlobal
x lokal di dalam main adalah 5
Gambar 4.12 | Program untuk
mendemonstrasikan aturan skop
4.13 Rekursi
Faktorial atas suatu integer
tak-negatif n, ditulis n! (dan diucapkan “n faktorial”), adalah
perkalian dari
n · (n –1) · (n –
2) · … · 1
dengan 1! sama dengan 1, dan 0! didefinisikan
menjadi 1. Sebagai contoh, 5! adalah
perkalian dari 5 * 4 * 3 * 2 * 1, yang bernilai sama dengan 120.
Faktorial atas sebuah integer, angka, yang lebih besar dari atau sama dengan 0, dapat dihitung
secara iteratif (tak-rekursif) menggunakan statemen for sebagai berikut:
faktorial = 1;
for ( kounter = angka; kounter >= 1; kounter-- )
faktorial *= kounter;
Definisi rekursif dari fungsi faktorial
didapatkan dari relasi berikut:
n! = n ·
(n
– 1)!
Sebagai contoh, 5! sama dengan 5 * 4! seperti
ditunjukkan berikut:
5! = 5 · 4 · 3 · 2 · 1
5! = 5 · (4 · 3 · 2 · 1)
5! = 5 · (4!)
Evaluasi terhadap 5! akan berlangsung
seperti pada Gambar 4.13. Gambar 4.13a menunjukkan bagaimana pemanggilan
rekursif dilakukan sampai 1!, yang
menghentikan rekursi. Gambar 4.13b menunjukkan nilai-nilai yang dijadikan nilai
balik dari setiap pemanggilan rekursif kepada pemanggilnya.
Gambar 4.13 | Evaluasi rekursif dari 5!
Gambar 4.14 menggunakan rekursi untuk
menghitung dan menampilkan faktorial integer dari 0 sampai 10. Fungsi faktorial rekursif pertama-tama menguji apakah
kondisi penghenti bernilai true, yaitu apakah jumlah kurang dari atau sama dengan 1. Jika jumlah kurang dari atau sama dengan 1, maka faktorial akan menghasilkan nilai balik 1, dan
tidak perlu rekursi lebih lanjut dan program berhenti. Jika jumlah lebih besar dari 1, maka
return jumlah * faktorial( angka - 1 );
mengekspresikan permasalahan sebagai
perkalian dari angka dengan suatu
pemanggilan rekursif terhadap faktorial(angka – 1). Pemanggilan terhadap faktorial(angka
– 1) sedikit lebih sederhana dari perhitungan awal faktorial(angka).
Fungsi faktorial (baris 22) dideklarasikan untuk menerima suatu parameter bertipe long dan mengembalikan nilai balik bertipe long. Tipe data long merupakan
kependekan dari long int. Standar C
menspesifikasi bahwa variabel bertipe long int disimpan sedikitnya pada 4 byte memori, jadi dapat menampung nilai
maksimum sebesar +2147483647. Seperti terlihat pada Gambar 4.14, nilai-nilai
faktorial menjadi besar dengan cepat. Alasan dipilihnya tipe data long adalah agar program dapat menghitung faktorial yang lebih
besar dari 7! pada komputer.
Penspesifikasi konversi %ld digunakan untuk
menampilkan nilai long.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/* Gambar 4.14: gambar04_14.c
Fungsi faktorial rekursif */
#include <stdio.h>
long faktorial( long angka ); /* prototipe
fungsi */
/* fungsi main memulai eksekusi */
int main( void )
{
int i; /* kounter */
/* loop 11 kali; selama tiap iterasi,
menghitung
faktorial( i ) dan menampilkan hasilnya */
for ( i = 0; i <= 10; i++ ) {
printf( "%2d! = %ld\n", i, faktorial( i ));
} /* akhir for */
return
0; /* indikasi terminasi sukses */
} /* akhir main */
/* definisi rekursif atas fungsi faktorial
*/
long faktorial( long angka )
{
/*
kasus basis */
if
( angka <= 1 ) {
return
1;
} /*
akhir if */
else
{ /* langkah rekursif */
return
( angka * faktorial( angka - 1 ) );
} /*
akhir else */
} /* akhir fungsi faktorial */
|
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
Gambar 4.14 | Penghitungan
faktorial dengan suatu fungsi rekursif
4.14 Contoh Penggunaan Rekursi: Deret
Fibonacci
Deret Fibonacci
0, 1, 1, 2, 3, 5, 8, 13, 21, …
dimulai dengan 0 dan 1 dan memiliki
watak bahwa setiap suku deret Fibonacci merupakan penjumlahan dari dua suku
Fibonacci sebelumnya.
Deret ini terjadi di alam dan, secara
khusus, mendeskripsikan suatu bentuk spiral. Rasio dari suku-suku Fibonacci
yang berurutan kenvergen menjadi suatu angka konstanta 1.618.... Angka ini,
juga, terjadi di alam dan telah dikenal sebagai rasio emas (golden ratio) atau rerata emas (golden rmean). Manusia cenderung
merasakan secara estetika bahwa rasio emas menyenangkan. Para arsitek seringkali
merancang jendela, kamar, dan bangunan yang memiliki panjang dan lebar dengan
rasio emas. Bahkan kartu pos pun didesain dengan panjang/lebar rasio emas.
Deret Fibbonacci didefinisikan secara
rekursif sebagai berikut:
fibonacci(0)
= 0
fibonacci(1)
= 1
fibonacci(n) = fibonacci(n – 1) + fibonacci(n – 2)
Gambar 4.15 menghitung suku Fibonacci
ke-n secara rekursif menggunakan fungsi fibonacci. Perhatikan bahwa suku Fobonacci cenderung membesar dengan sangat cepat.
Oleh karena itu, dipilih tipe data long untuk tipe
parameter dan tipe nilai balik di dalam fungsi fibonacci. Pada Gambar 4.15, setiap pasang baris keluaran menunjukkan eksekusi
program yang terpisah.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
/* Gambar 4.15: gambar04_15.c
Fungsi fibonacci rekursif */
#include <stdio.h>
long fibonacci( long n ); /* prototipe fungsi
*/
/* fungsi main memulai eksekusi program */
int main( void )
{
long
hasil; /* nilai fibonacci */
long
angka; /* angka yang dimasukkan pengguna */
/*
mendapatkan integer dari pengguna */
printf( "Masukkan sebuah integer: " );
scanf( "%ld", &angka );
/*
menghitung nilai fibonacci untuk angka dari pengguna */
hasil = fibonacci( angka );
/*
menampilkan hasil */
printf( "Fibonacci( %ld ) = %ld\n", angka, hasil );
return 0; /* indikasi terminasi sukses */
} /* akhir main */
/* definisi rekursif atas fungsi fibonacci
*/
long fibonacci( long n )
{
/*
kasus basis */
if
( n == 0 || n == 1 ) {
return
n;
} /*
akhir if */
else
{ /* langkah rekursif */
return
fibonacci( n - 1 ) + fibonacci( n - 2 );
} /*
akhir else */
} /* akhir fungsi fibonacci */
|
Masukkan sebuah integer: 0
Fibonacci( 0 ) = 0
Masukkan sebuah integer: 1
Fibonacci( 1 ) = 1
Masukkan sebuah integer: 2
Fibonacci( 2 ) = 1
Masukkan sebuah integer: 3
Fibonacci( 3 ) = 2
Masukkan sebuah integer: 4
Fibonacci( 4 ) = 3
Masukkan sebuah integer: 5
Fibonacci( 5 ) = 5
Masukkan sebuah integer: 6
Fibonacci( 6 ) = 8
Masukkan sebuah integer: 10
Fibonacci( 10 ) = 55
Masukkan sebuah integer: 20
Fibonacci( 20 ) = 6765
Gambar 4.15 | Pembangkitan
rekursif atas deret Fibonacci
Pemanggilan terhadap fibonacci dari main bukanlah pemanggilan rekursif (baris 18), tetapi semua pemanggilan
rekursif terhadap fibonacci dilakukan pada
baris 33. Setiap kali fibonacci dipanggil, ia
menguji apakah merupakan kasus basis, yaitu apakah n sama dengan 0 atau 1. Jika bernilai true, maka n akan dijadikan
nilai balik. Jika n lebih besar
dari 1, langkah rekursif akan menghasilkan dua pemanggilan rekursif. Gambar
4.16 menunjukkan bagaimana fungsi fibonacci mengevaluasi fibonacci(3).
Gambar 4.16 | Himpunan pemanggilan untuk fibonacci(3)
Kesimpulan
§
Modul di dalam C disebut dengan fungsi. Pustaka standar C menyediakan
koleksi fungsi yang kaya untuk melakukan operasi kalkulasi matametik,
manipulasi string, masukan/keluaran, dan banyak operasi lainnya yang berguna.
Modul berguna untuk mempermudah pekerjaan Anda, karena fungsi menyediakan
banyak kapabilitas yang Anda butuhkan.
§
Fungsi dapat dipanggil melalui pemanggilan fungsi, yang menspesifikasi
nama fungsi dan menyediakan informasi (sebagai argumen) yang dibutuhkan oleh
fungsi yang dipanggil untuk melakukan pekerjaan yang ditugaskan. Analogi yang
umum untuk hal ini adalah suatu hirarki suatu manajemen. Seorang boss (fungsi
pemanggil atau pemanggil) meminta seorang pekerja (fungsi terpanggil) untuk
melakukan suatu pekerjaan dan melaporkan kembali ketika pekerjaan selesai
dilakukan.
§
Fungsi-fungsi pustaka matematika memampukan Anda untuk melakukan beberapa
kalkulasi matematik umum.
§
Fungsi membantu Anda untuk memodularisasi suatu program. Semua variabel
yang didefinisikan di dalam definisi fungsi adalah variabel lokal, yang hanya
dikenal di dalam fungsi yang di dalamnya variabel tersebut didefinisikan.
Kebanyakan fungsi memiliki daftar parameter yang menyediakan cara untuk
mengkomunikasikan informasi di antara fungsi. Sebuah parameter fungsi juga
merupakan variabel lokal dari fungsi tersebut.
§
Salah satu fitur yang penting dalam C adalah prototipe fungsi. Fitur ini
dipinjam oleh komite standar C dari para pengembang C++. Prototipe fungsi
memberitahu kompiler tentang tipe data nilai balik fungsi, jumlah parameter
yang diterima fungsi, tipe data tiap parameter, dan urutan parameter. Kompiler
menggunakan prototipe fungsi untuk memvalidasi pemanggilan fungsi.
§
Fitur penting lainnya dari prototipe fungsi adalah pemaksaan argumen,
yaitu memaksa argumen menjadi tipe yang sesuai. Sebagai contoh, fungsi pustaka
matematika sqrt dapat dipanggil
dengan suatu argumen integer meskipun prototipe fungsi di dalam <math.h> menspesifikasi suatu argumen double, dan fungsi tersebut masih bisa
bekerja dengan benar.
§
Aturan promosi secara otomatis diterapkan terhadap ekspresi yang memuat
nilai dari dua atau lebih tipe data (yang dikenal juga sebagai ekspresi
tipe-gabungan). Tipe data dari setiap nilai di dalam suatu ekspresi
tipe-gabungan secara otomatis dipromosikan menjadi tipe tertinggi di dalam
ekspresi tersebut (sebenarnya sebuah versi temporer dari setiap nilai yang
diciptakan dan digunakan dalam ekspresi, dimana nilai-nilai awal tetap tidak
berubah).
§
Ketika program memanggil suatu fungsi, fungsi terpanggil harus mengetahui
bagaimana kembali (mengembalikan nilai balik, jika ada) ke pemanggil, jadi
alamat kembali dari fungsi pemanggil ditempatkan pada tumpukan eksekusi program
(dikenal pula sebagai tumpukan pemanggilan fungsi). Jika sederet pemanggilan
fungsi dilakukan, alamat kembali yang berurutan ditempatkan pada tumpukan
secara LIFO, sehingga setiap fungsi dapat kembali ke pemanggilnya.
§
Setiap pustaka standar memiliki header yang memuat prototipe fungsi untuk
semua fungsi yang ada di dalam pustaka tersebut dan definisi atas berbagai tipe
data dan konstanta yang dibutuhkan untuk semua fungsi tersebut.
§
Pemanggilan-dengan-nilai harus digunakan ketika fungsi terpanggil tidak perlu
memodifikasi nilai dari variabel asli pemanggil. Hal ini mencegah efek samping
yang tak sengaja dilakukan (modifikasi variabel). Pemanggilan-dengan-referensi
harus digunakan hanya dengan fungsi terpanggil yang dapat dipercaya untuk
memodifikasi variabel asli.
§ Skop suatu pengenal adalah bagian
program dimana di dalamnya pengenal dapat direferensi. Sebagai contoh, ketika
sebuah variabel lokal didefinisikan di dalam suatu blok, ia dapat direferensi
hanya di dalam blok tersebut atau di dalam blok yang bersarang di dalam blok
tersebut. Empat jenis skop pengenal adalah skop fungsi, skop file, skop blok,
dan skop prototipe-fungsi.
Soal
1.
Tulislah suatu program untuk mengujia contoh-contoh pemanggilan
fungsi pustakan matematika yang ditampilkan pada Gambar 4.2 dan buktikan
hasilnya.
2.
Temukan kesalahan pada tiap potongan program berikut
dan jelaskan bagaimana kesalahan tersebut dapat dikoreksi:
a)
int g( void )
{
printf( "Di dalam fungsi g\n" );
int h( void )
{
printf( "Di dalam fungsi h\n" );
}
}
b)
int jum( int x, int y )
{
int hasil;
hasil
= x + y;
}
c)
int jum( int n )
{
if ( n == 0 ) {
return
0;
}
else {
n +
jum( n - 1 );
}
}
d)
void f( float a );
{
float
a;
printf(
"%f", a );
}
e)
void perkalian( void )
{
int a, b, c, hasil;
printf( "Masukkan tiga integer: " )
scanf( "%d%d%d", &a, &b, &c );
hasil = a * b *
c;
printf( "Hasil adalah %d", hasil);
return hasil;
}
3.
Apakah yang dilakukan program berikut ini:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
/*
coba.c */
/*
Tebak sendiri */
#include
<stdio.h>
#include
<math.h>
/*
fungsi main memulai eksekusi program */
int
main( void )
{
/* menghitung dan menampilkan akar kuadrat
*/
printf( "sqrt(%.1f) = %.1f\n", 900.0, sqrt( 900.0 ) );
printf( "sqrt(%.1f) = %.1f\n", 9.0, sqrt( 9.0
) );
/* menghitung dan menampilkan fungsi
eksponensial e */
printf( "exp(%.1f) = %f\n", 1.0, exp( 1.0
) );
printf( "exp(%.1f) = %f\n", 2.0, exp( 2.0
) );
/* menghitung dan menampilkan logaritma (basis
e) */
printf( "log(%f) = %.1f\n", 2.718282, log( 2.718282 ) );
printf( "log(%f) = %.1f\n", 7.389056, log( 7.389056 ) );
/* menghitung dan menampilkan logaritma (basis
10) */
printf( "log10(%.1f) = %.1f\n", 1.0, log10( 1.0
) );
printf( "log10(%.1f) = %.1f\n", 10.0, log10( 10.0
) );
printf( "log10(%.1f) = %.1f\n", 100.0, log10( 100.0 ) );
/* menghitung dan menampilkan nilai absolut
*/
printf( "fabs(%.1f) = %.1f\n", 13.5, fabs( 13.5
) );
printf( "fabs(%.1f) = %.1f\n", 0.0, fabs( 0.0
) );
printf( "fabs(%.1f) = %.1f\n", -13.5, fabs( -13.5 ) );
/* menghitung dan menampilkan ceil( x ) */
printf( "ceil(%.1f) = %.1f\n", 9.2, ceil( 9.2
) );
printf( "ceil(%.1f) = %.1f\n", -9.8, ceil( -9.8
) );
/* menghitung dan menampilkan floor( x ) */
printf( "floor(%.1f) = %.1f\n", 9.2, floor( 9.2
) );
printf( "floor(%.1f) = %.1f\n", -9.8, floor( -9.8
) );
/* menghitung dan menampilkan pow( x, y ) */
printf( "pow(%.1f, %.1f) = %.1f\n", 2.0, 7.0, pow( 2.0, 7.0 )
);
printf( "pow(%.1f, %.1f) = %.1f\n", 9.0, 0.5, pow( 9.0, 0.5 )
);
/* menghitung dan menampilkan fmod( x, y )
*/
printf( "fmod(%.3f/%.3f) = %.3f\n", 13.675, 2.333,
fmod( 13.675, 2.333 ) );
/* menghitung dan menampilkan sin( x ) */
printf( "sin(%.1f) = %.1f\n", 0.0, sin( 0.0
) );
/* menghitung dan menampilkan cos( x ) */
printf( "cos(%.1f) = %.1f\n", 0.0, cos( 0.0
) );
/* menghitung dan menampilkan tan( x ) */
printf( "tan(%.1f) = %.1f\n", 0.0, tan( 0.0
) );
return 0; /* indikasi terminasi sukses */
} /* akhir main */
|
4.
Tampilkan nilai dari x setelah setiap statemen berikut dieksekusi:
a)
x = fabs( 7.5 );
b)
x = floor( 7.5 );
c)
x = fabs( 0.0 );
d)
x = ceil( 0.0 );
e)
x = fabs( -6.4 );
f)
x = ceil( -6.4 );
g)
x = ceil( -fabs( -8 + floor( -5.5 ) ) );
5.
Tulislah suatu aplikasi dari fungsi floor untuk membulatkan
sebuah nilai menjadi integer terdekat. Statemen
y = floor( x + .5 );
akan membulatan x menjadi integer terdekat dan menugaskan
hasilnya kepada y. Tulislah suatu program yang membaca
beberapa angka dan menggunakan statemen tersebut untuk membulatkan setiap angka
yang dibaca menjadi integer terdekat. Untuk setiap angka yang diproses,
tampilkan angka asli dan angka hasil pembulatan.
6.
Tulislah suatu fungsi kelipatan yang menentukan untuk sepasang integer yang
diberikan apakah integer kedua merupakan kelipatan dari integer pertama. Fungsi
tersebut mengambil dua argumen dan menghasilkan nilai balik 1 (true) jika integer kedua
adalah kelipatan dari integer pertama, dan 0 (false) jika sebaliknya.
7.
Tulislah
suatu program yang mengentrikan sederet integer dan melewatkannya satu demi
satu kepada fungsi genap, yang menggunakan operator sisa dalam menentukan
apakah suatu integer genap atau tidak. Fungsi ini mengambil sebuah argumen
integer dan menghasilkan nilai balik 1 jika integer genap dan nilai balik 0
jika sebaliknya.
8.
Dapatkah main dipanggil secara
rekursif? Tulislah suatu program yang memuat sebuah fungsi main. Sertakan sebuah
variabel lokal statis, hitung, yang diinisialisasi
dengan 1. Lakukan post-inkremen dan tampilkan nilai dari hitung setiap kali main dipanggil. Jalankan
program Anda dan amati apa yang terjadi?
9.
Tulislah suatu fungsi jarak yang menghitung jarak
antaran dua titik (x1,y1) dan (x2,y2). Semua angka dan
nilai balik harus bertipe double.
10.
Deret Fibonacci didefinisikan sebagai
0, 1, 1, 2, 3, 5, 8, 13, 21, …
dimulai dengan suku 0 dan 1 dan memiliki watak bahwa setiap suku
merupakan penjumlahan dari dua suku sebelumnya. a) Tulislah sebuah fungsi
tak-rekursif fibonacci(n) yang menghitung suku Fibonacci ke-n. b) Tentukan suku Fibonacci
terbesar yang dapat ditampilkan pada sistem Anda. Modifikasi program pada
bagian a) untuk menggantikan int dengan double dalam menghitung deret
Fibonacce. Biarkan program beriterasi sampai mengalami kegagalan akibat nilai
yang terlalu tinggi.
11.
Apakah yang dilakukan program berikut ini?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#include <stdio.h>
/* fungsi main memulai eksekusi program */
int main( void )
{
int c; /* variabel untuk menampung masukan
karakter dari pengguna */
if ( ( c = getchar() ) != EOF
) {
main();
printf( "%c",
c );
}
/* akhir if */
return
0; /* indikasi terminasi sukses */
} /* akhir main */
|
12.
Apakah yang dilakukan program berikut ini?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
#include <stdio.h>
int misteri( int a, int b ); /* prototipe fungsi */
/* fungsi main memulai eksekusi program */
int main( void )
{
int x; /* integer pertama */
int y; /* integer kedua */
printf( "Masukkan dua integer: " );
scanf( "%d%d",
&x, &y );
printf( "Hasilnya adalah %d\n",
misteri( x, y ) );
return 0; /* indikasi terminasi sukses */
} /* akhir main */
/* Parameter b harus integer positif
untuk mencegah
rekursi tak-terhingga */
int misteri( int a, int b )
{
/*
kasus basis */
if ( b == 1 ) {
return a;
} /* akhir if */
else { /* langkah rekursif */
return a + misteri( a, b - 1
);
} /* akhir else */
} /* akhir fungsi misteri */
|
13.
Temukan kesalahan pada tiap potongan program dan
jelaskan bagaimana mengoreksinya:
a)
double kubik( float ); /* prototipe fungsi
*/
kubik ( float angka ) /* definisi fungsi */
{
return angka * angka * angka;
}
b)
register auto int x = 7;
c)
int bilanganAcak = srand();
d)
double y = 123.45678;
int x;
x = y;
printf(
"%f\n", (double) x );
e)
double kuadrat( double angka )
{
double
angka;
return
angka * angka;
}
f)
int sum( int n )
{
if ( n
== 0 ) {
return
0;
}
else {
return
n + sum( n );
}
}
14.
Tulislah
suatu fungsi yang mengambil sebuah nilai integer dan menghasilkan nilai balik
berupa angka dengan dijit-dijit terbalik. Sebagai contoh, jika diberikan angka
7823, maka fungsi akan menghasilkan nilai balik 3287.
No comments:
Post a Comment