Selasa, Agustus 04, 2015

Programming in C - Part 17: Fungsi, array dan pointer dalam bahasa C

Pada artikel sebelumnya kita sudah membahas tentang dasar-dasar fungsi dalam bahasa C. Pada artikel ini akan dibahas lebih lanjut mengenai fungsi termasuk metode memanggil array atau pointer sebagai parameter dan luaran dari sebuah fungsi.

Pada dasarnya ada dua cara untuk membuat parameter dalam fungsi yaitu Call by value (menggunakan nilai), dan Call by reference (menggunakan alamat dari suatu variabel dalam memori).

Call by value adalah metode memanggil suatu fungsi dengan memberikan parameter nilai (baik memberikan angka langsung atau menggunakan variabel) secara langsung. contoh dari metode ini adalah pada fungsi tampilkanHasil, dimana value yang diberikan adalah 100 dan 20.

tampilkanHasil(100,20);

atau
int a = 100 ; int b= 20 ;
tampilkanHasil(a,b) ;


Call by reference adalah pemanggilan fungsi dengan memberikan parameter alamat suatu memori dan bukan nilainya. Contoh sederhana adalah sebagai berikut :

int a = 100 ; int b= 20 ;
tampilkanHasil(&a,&b) ;


Karena memberikan alamat memori, maka digunakan tanda ampersand &. Perlu diingat bahwa untuk array, alamatnya selalu adalah alamat elemen pertama. Pada contoh di atas, fungsi tampilkanArray sebenarnya menggunakan teknik call by reference. Sekarang muncul pertanyaan di benak anda mengapa demikian ?, bukankan tidak ada tanda & ?. Jawabannya adalah bahwa nama array sebenarnya adalah alamat elemen pertama pada array tersebut. Jadi
int angka[]={100,20,10,5,10};
tampilkanArray(angka, sizeof(angka)/4) ;

sama dengan
tampilkanArray(&angka[0], sizeof(angka)/4) ;

bagaimana fungsi sum?. Benar sekali, fungsi ini juga menggunakan teknik call by reference.

Saat ini kita sudah dapat memanggil array menjadi parameter pada sebuah fungsi dengan memanfaatkan teknik call by reference. Sekarang bagaimana kita mengeluarkan hasil berupa array atau pointer dari sebuah fungsi. Ingat bahwa fungsi dapat memberikan nilai luaran. Tipe data untuk luaran ini harus dideklarasikan bersamaan dengan deklarasi fungsi. Jadi, jika anda ingin memberikan nilai luaran berupa integer, maka anda harus menulis seperti berikut ini
int jumlah(int a, int b);
Fungsi jumlah memberikan luaran bertipe integer. Masukannya (parameternya) juga berupa dua bilangan integer a dan b). Untuk memberikan luaran berupa suatu array atau pointer maka dapat digunakan teknik:

char *namaBulan(int angkaBulan)   ;

fungsi namaBulan akan menghasilkan sebuah pointer yang mengarah pada array of char. Untuk memahami hal ini perhatikan studi kasus di bawah ini.

Studi kasus 2: 

Membuat fungsi yang memberikan luaran berupa jumlah dan rata-rata dari sebuah array yang diberikan.
Untuk menyelesaikan studi kasus ini maka anda harus memahami bagaimana memanggil array ke dalam sebuah fungsi dan bagaimana menghasilkan / mengembalikan array ke dalam program yang memanggil fungsi tersebut.

Untuk memasukkan array sebagai parameter dalam sebuah fungsi (memasukkan array ke dalam fungsi), maka anda dapat menggunakan nama array secara langsung ke dalam suatu parameter. Ingat bahwa nama array dalam parameter fungsi adalah sebenarnya pemanggilan ALAMAT komponen array yang dimaksud. Dengan demikian dalam pembuatan fungsi anda dapat menggunakan pointer !.

perhatikan fungsi berikut ini:


double *aritmatik(int *data, int panjang)
{
    int i, jum;
    double rata, djum;
    jum = 0; rata = 0;
  
    for(i=0;i<panjang;i++){   
        jum += *(data+i);
    }
    rata = (double)jum/panjang ;
    djum= (double)jum;
    static double hasil[2];
    hasil[0] = djum;
    hasil[1] = rata;
    return hasil ;
    }

Penjelasan :
Baris

double *aritmatik(int *data, int panjang)

fungsi ini akan mengembalikan hasil berupa pointer yang mengarah kepada tipe data double.
Parameter pertama adalah sebuah pointer (*) yang mengarah kepada data bertipe integer. Tentu saja yang dimaksud disini adalah array bertipe integer. Sedangkan parameter kedua adalah sebuah integer berupa panjang dari array yang dimasukkan. Anda juga bisa mengganti baris tersebut dengan baris berikut dengan hasil yang identik

double *aritmatik(int data[], int panjang)

Perbedaannya adalah bahwa pada cara pertama, hanya alamat yang diberikan sedangkan pada cara kedua adalah arraynya sendiri.


perintah :

    for(i=0;i<panjang;i++){   
        jum += *(data+i);
    }

perintah ini melakukan looping dan perhitungan jumlah setiap elemen array. Teknik yang digunakan disini adalah penambahan pointer. Isi setiap elemen diakses dengan pointer dengan penambahan i pada setiap loopingnya. Ingat bahwa hal ini bisa dilakukan karena dalam sebuah array, data diletakkan secara berurutan dalam memori. Dengan demikian membaca memori mulai alamat tertentu secara berurutan sebanyak kali tertentu akan memberikan efek seperti membaca elemen array secara berurutan!

perintah;

    static double hasil[2];
    hasil[0] = djum;
    hasil[1] = rata;

mendeklarasikan aray hasil yang terdiri dari dua elemen dan akan digunakan untuk menampung hasil perhitungan jumlah dan rata-rata dari array yang diberikan. Elemen pertama (indeks= 0) diisi dengan jumlah dan elemen ke dua diisi dengan angka rata-rata. Tipe data double digunakan karena perhitungan rata-rata akan menghasilkan data dalam bentuk desimal. Kata kunci static digunakan untuk membuah array hasil menjadi global dan dapat diakses dari luar fungsi ini. Tanpa kata kunci static, variabel hasil akan menjadi variabel lokal saja.

Kode selengkapnya adalah sebagai berikut :
/* =======================================
 * Membuat fungsi dengan parameter pointer
 * Created by: Sastrawan
 * Topik : Membuat dan menggunakan fungsi untuk
 * menghasilkan hasil perhitungan dan rata-rata
 * file : fungsiDenganArrayInt_2.c
 * ========================================
 */


double *aritmatik(int *data, int panjang) ;


 
 #include<stdio.h>

 int main( int argc, char *argv[])
 {
    
    int *baris,i;
    double *hasilHitung;
  
    int angka[] = {1,2,3,4,6} ;
    printf("Angka : ")   ;
    for (i=0; i < 5; i++) {
        printf("%d ",angka[i]);
    }
    baris = angka;
  

    hasilHitung = aritmatik(baris,5);
    printf("\nJumlahnya adalah : %.1f \n", *hasilHitung);
    printf("Rata-rata adalah : %.2f \n", *(hasilHitung+1));

 return 0  ;
 }


double *aritmatik(int *data, int panjang)
{
    int i, jum;
    double rata, djum;
    jum = 0; rata = 0;
    for(i=0;i<panjang;i++){
        jum += *(data+i);
    }
    rata = (double)jum/panjang ;
    djum= (double)jum;
    static double hasil[2];
    hasil[0] = djum;
    hasil[1] = rata;
    return hasil ;
    }


Jika kode diatas dikompilasi dan dijalakan akan menghasilkan Output sebagai berikut
 
Angka : 1 2 3 4 6
Jumlahnya adalah : 16.0
Rata-rata adalah : 3.20


Studi kasus 2 : 

Membuat fungsi untuk menyebutkan nama bulan bila diketahui angkanya. Misalnya jika user memasukkan angka 12, maka nama bulan yang ditampilkan adalah Desember. Jika yang dimasukkan angka selain 1 -12 akan menyebabkan program keluar. Perlu diingat bahwa string nama bulan adalah array of character !


Penyelesaian :

/* =======================================
 * Program untuk menyebut nama bulan
 * Created by: Sastrawan
 * Topik : Membuat dan menggunakan fungsi untuk
 * menghasilkan arraystring nama bulan
 * ========================================
 */


 char *namaBulan(int angkaBulan)   ;

 int i;
 
 #include<stdio.h>

 int main( int argc, char *argv[])
 {
    

     int angkaBulan ;
    

     printf("Untuk Keluar ketik angka > 12 \n\n");
    while(angkaBulan <= 12)
    {   printf("Tulis bulan ke berapa (angka 1-12) : ") ;
       scanf("%d",&angkaBulan);
       if((angkaBulan > 12)||(angkaBulan<1))
       {
           printf("Mana ada bulan %d, Jenius!", angkaBulan);
           break;
       }

      // printf("pilihan : %d",angkaBulan );
       
   printf("Bulan : %s \n",namaBulan(angkaBulan));       //array string dapat dicetak langsung dengan namanya
    }

    
 return 0  ;
 }


char *namaBulan(int angkaBulan)     //menggunakan pointer karena
                                    //akan menghasilkan array sebagai
                                    //luaran dari return
 {
    angkaBulan -= 1;   // dikurangi 1 agar elemen ke 0 adalah bulan 1
    char *bulan[12] = {"Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"};

    return bulan[angkaBulan] ;  
 }
 

Jika program ini dicompile dan dijalankan maka outputnya adalah sbb :

Untuk Keluar ketik angka > 12

Tulis bulan ke berapa (angka 1-12) : 12
Bulan : Desember
Tulis bulan ke berapa (angka 1-12) : 4
Bulan : April
Tulis bulan ke berapa (angka 1-12) : 5
Bulan : Mei
Tulis bulan ke berapa (angka 1-12) : 8
Bulan : Agustus
Tulis bulan ke berapa (angka 1-12) : 10
Bulan : Oktober
Tulis bulan ke berapa (angka 1-12) : 1
Bulan : Januari
Tulis bulan ke berapa (angka 1-12) : 15
Mana ada bulan 15, Jenius!


Studi kasus 3 : 

Buatlah fungsi untuk membuat duplikat dari suatu array dengan mengalikan setiap elemen dari array hasil dengan angka tertentu untuk kemudian dibuat menjadi array baru dan menjadi luaran / balikan dari fungsi tersebut !.

Kasus ini cukup sederhana tetapi menantang logika pemrograman anda. Jika anda berhasil membuat fungsi ini dengan cara yang efisien, maka anda boleh mengklaim sudah memahami array dan pointer dengan menggunakan C. Untuk itu sebelum anda melihat penyelesaiannya, silahkan dicoba terlebih dahulu. Jika mengalami kesulitan anda dapat melihat solusi yang saya berikan.

Penyelesaian :

Saya akan menggunakan pointer untuk menyelesaikan soal ini karena saya ingin mendemonstrasikan teknik penggunaan pointer untuk membuat copy dari sebuah array. Sebenarnya library c juga sudah menyediakan perintah tersendiri untuk mengcopy array ke dalam array lainnya. Namun demikian perintah itu digunakan hanya untuk membuat copy yang sama persis, oleh karenanya dalam latihan ini kita akan mengcopy dan memanipulasi isi sebuah array dalam sekali jalan saja. Artinya kita akan membuat versi yang berbeda. "Wow.."


/* =======================================
 * Fungsi untuk mengcopy array secara manual
 * Created by: Sastrawan
 * Topik :  Menggunakan pointer untuk mengcopy
 *             array
 * ========================================
 */


int *copyArray(int *hasil, int *asal, int panjang) ;

 
 #include<stdio.h>

 int main( int argc, char *argv[])
 {
    
int dataAsal[] = {1,2,3,4,5} ;
int dataHasil[5];
int i;

copyArray(dataHasil,dataAsal,5);
printf("\nData Asal : ") ;
for (i=0;i<5;i++) printf("%d\t",dataAsal[i]) ;
printf("\nData Hasil :") ;
for (i=0;i<5;i++) printf("%d\t",dataHasil[i]) ;

return 0 ;
}

int *copyArray(int *hasil, int *asal, int panjang) {
  
    int *h = hasil;
    int i;
    for(i=0;i<panjang;i++){
         *h++ = *asal++ * 5;
    }
  
return hasil ;
}


Penjelasan :

Saya memberi nama fungsi ini copyArray. Fungsinya adalah untuk membuat sebuah array baru dari array asal yang masing-masing elemennya dikalikan (misalnya 5).

perintah  

int *copyArray(int *hasil, int *asal, int panjang)

adalah memeritahkan kepada komputer untuk mengeluarkan hasil berupa array of integer dengan menggunakan 3 parameter yaitu array hasil (yang akan menampung hasil copy), array asal, dan panjang array yang akan dicopy.

perintah :

int *h = hasil;
    int i;
    for(i=0;i<panjang;i++){
         *h++ = *asal++ * 5;

menciptakan pointer lokal bernama h sebagai bantuan saja, selanjutnya pointer h diarahkan ke alamat elemen pertama dari hasil yang pada saat ini belum berisi data.

perintah
*h++ = *asal++ * 5; 
ini adalah perintah 'magic' yang akan mengisi NILAI pada alamat yang dituju oleh h - yaitu alamat elemen array hasil - dan berpindah ke alamat berikutnya lalu mengcopy nilai elemen berikutnya dari array asal dan meletakkannya di arrayHasil dengan bantuan pointer h. Jika anda bingung dengan penjelasan ini, perhatikan contoh sederhana berikut ini

int asal = 10 ;  // deklarasi dan inisiasi variabel asal dengan 10 ;
int *ptr ;       // deklarasi pointer ptr tipe sama
ptr = &asal ;     // mengarahkan pointer ptr ke alamat asal


pada saat ini isi dari variabel asal adalah 10. Dengan demikian nilai dari *ptr juga adalah 10 karena mengarah kepada alamat yang sama. Sekarang kita tambahkan perintah berikut ini

*ptr = 20 ;   

Perintah diatas akan  mengisi nilai 20 kepada alamat variabel yang dituju oleh ptr, dalam hal ini adalah variabel asal. Hasilnya pada saat ini asal tidak lagi berisi 10 tapi berubah menjadi 20 !. What a magic !. Inilah salah satu kekuatan pointer yang sangat berbahaya jika tidak digunakan dengan hat-hati. Pengisian nilai dengan teknik ini dikenal dengan istilah 'dereferencing'

Kembali ke fungsi yang dibuat di atas, pada akhirnya fungsi memberikan perintah
return hasil ;
yang mengeluarkan pointer hasil dan mengembalikannya kepada program pemanggil.

Inilah yang terjadi dibelakang layar pada saat perintah strcpy (bawaan dari c) diberikan. Kini anda pastinya dapat membayangkan metode untuk mengcopy string, memotong string pada titik tertentu sebanyak bilangan tertentu dan seterusnya. Ingat bahwa string adalah array of char yang diakhiri dengan character null (\0).

0 comments:

Posting Komentar

Write your comment here