Anda di halaman 1dari 58

C PROGRAMMING Foundation Level

DAFTAR ISI C Programming 1 DAFTAR ISI 2 Pengantar 5 1. Perspektif 6 Sejarah Bahasa C 6 Struktur Bahasa C 6 Titik koma atau semicolons (;) 6 Free Form 7 Case-sensitive 7 Variabel 7 printf() dan scanf() 8 Program Entry Point 8 C Keywords 9 2. Tipe Data 10 Tipe data Integer dalam C 10 Tipe Bilangan Real 10 Konstanta 11 Konstanta dengan tipe data 11 Konstanta dengan preprocessor 11 3. Operator 13 Operator Aritmetika 13 Casting Operator 14 Operator Increment dan Decrement 14 Prefix ++ dan 14 Posfix ++ dan 15 Operator Komparasi 15 Operator Logika 15 Bitwise Operator 16 Assignment Operators 17 Operator sizeof 18 Operator Kondisional 18 4. Control Flow (Alur Program) 19 Pengambilan keputusan dengan if else 19 Pengujian kondisi dengan switch 20 while 22 do-while 22 for 23 break 24 continue 24 5. Fungsi 25 Nilai balik (return value) 25 Nama fungsi 25 Parameter 25 Pemanggilan fungsi 26 Penulisan Prototipe 26 Penulisan definisi fungsi 26 Lebih lanjut tentang pemanggilan fungsi 27 C dan stack 27 Code Segment 28 Stack Segment 28 Data Segment 28 Heap 28

Variabel qualifier 28 auto 28 static 29 register 29 6. Pointer 30 Deklarasi Pointer 30 Inisialisasi Pointer 32 Melewatkan parameter dengan pointer 32 Pointer ke data konstan 34 Pointer ke pointer 34 Pointer ke fungsi (function pointer) 35 7. Array 39 Deklarasi array 39 Inisialisasi array 39 Mengakses elemen array 39 Array sebagai paramater fungsi 41 Array Multidimensional 42 8. String 43 Deklarasi 43 Mencetak String 43 String Assignment 43 char * strcpy(char * dest,const char * src); 44 char * strncpy(char * dest,const char * src,size_t count); Manipulasi string 44 size_t strlen(const char* str); 44 char * strrev(char * str); 44 char *strcat(char * dest, const char * src); 45 char * strchr(const char* str,int c); 45 int strcmp(const char* str1,const char* str2); 45 char *strstr(const char * str,const char * sub); 45 size_t strspn(const char * str,const char * cset); 46 char *strtok(char * str,const char * delim); 46 9. Struktur 48 Deklarasi 48 Penggunaan struktur 48 Struktur dalam struktur 49 Mengakses struktur dengan pointer 49 Assignment antara struktur 49 Melewatkan parameter non-primitive data 50 10. Operasi File 51 Stream 51 File teks (text file) 51 Penanganan kesalahan (error handling) 52 File biner (binary file) 53 Pencarian dalam file biner (binary file) 54 11. Memori Dinamis 58 Pointer dan Memori Dinamis 58 void * malloc(size_t n); 58 void * calloc(size_t nelem, size_t elemsize); 59 void * realloc(void * ptr, size_t n); 59 void free(void * ptr); 61 Lebih lanjut tentang realloc() 61 Struktur data dinamis 61 12. Tanggal dan waktu 65 13. Union, tipe enumerasi dan preprocessor 69 Union 69 Enumerasi 69 Preprocessor (front end processor) 70 Menyertakan file 70 Mendeklarasikan Konstanta 70

44

Mendefinisikan makro 71 Debugging 71 Appendix 73 ANSI C Escape Sequences and Trigraph 73 ANSI Library Header Files 73 Fungsi-fungsi untuk konversi 74 double atof(const char* str); 74 int atoi(const char * str); 74 int atol(const char * str); 74 int tolower(int c); 75 int toupper(int c); 75 int isalnum(int c); 75 int isalpha(int c); 75 int sprintf(char * str, const char * fmt,); Kepustakaan 76 The C Programming Language 2nd Edition 76 Thinking in C++2nd Edition 76 The C Standard Library 76 Microsoft C/C++ Developers Guide 76 WHATs next 77 Catatan 78

75

PENGANTAR Tulisan (buku?) ini diharapkan dapat memberikan pengetahuan dasar bahasa pemrogr aman C dengan sedapat mungkin berpedoman pada Standard C. Dengan pendekatan ini kami berharap peserta dapat menulis program dalam bentuk yang murni yang dapat d ikompilasi dengan semua jenis compiler C yang ada dengan penyesuaian yang semini mal mungkin. Karena C sendiri tidak tampil dengan bentuk yang sederhana dan cenderung rumit t erutama bagi yang tidak memiliki latar belakang pemrograman sema sekali, maka pe ngalaman dalam bahasa pemrograman sebelumnya akan sangat membantu. Namun jika an da termasuk pemula dalam pemrograman, anda dapat mengikuti modul ini mulai dari awal sampai akhir dan secara aktif mencoba sebanyak mungkin latihan dan mencari sumber-sumber lain tentang pemrograman C. Dengan investasi anda di C, memudahkan anda mempelajari bahasa yang lebih lanjut seperti C++ yang merupakan superset dari C. Semua contoh program dalam modul ini menggunakan compiler Visual C++ 6 dengan te tap berpedoman pada Standard C, namun anda dapat menggunakan compiler C apa saja yang compatible.

Malang, Chipmunk - 2003 1. PERSPEKTIF Sejarah Bahasa C Bahasa C pertama kali dikembangkan oleh Brian Kernighan dan Dennis Ritchie di AT & T Bell Labs pada tahun 1972. Pada tahun 1980 C manjadi sangat populer dikalangan programmer dari berbagai kom unitas sehingga dirasa diperlukan standarisasi. Di Amerika, yang bertugas untuk membuat standarisasi adalah American National Standards Institute (ANSI). ANSI m embentuk komite X3J11 untuk mengembangkan standarisasi C yang selanjutnya dikena l dengan X3.159.

Pada tingkat internasional, organisasi dunia yang bernama International Standard s Organization (ISO) bertanggungjawab untuk membuat standarisasi bahasa komputer . ISO membentuk komite teknis JTC1/SC22/WG14 untuk meninjau hasil X3J11. Standar isasi C oleh ISO yaitu ISO 9889:1990 hampir sama dengan X3.159. Untuk selanjutnya standarisasi ini dikenal dengan C Standard. Struktur Bahasa C LISTING 1.1. Hello.C #include<stdio.h> /*komentar*/

int main(void) { printf(hello C !\n) ; return 0; } Pernyataan #include memerintahkan preprocessor untuk mencari file stdio.h. Komentar untuk program ditulis di antara /* dan */ dan tidak akan ikut dikompila si. Fungsi main sangat penting karena merupakan awal dimana program dimulai. Tanpa f ungsi ini program anda tidak akan dapat dikompilasi. Tanda kurung { dan } menandakan awal dan akhir. Fungsi printf() berfungsi untuk mencetak ke layar. Karakter \n berfungsi untuk pindah baris Kata kunci return yang dalam program ini ditulis return 0, menyebabkan nilai dal am hal ini 0 dikembalikan ke sistem operasi yang biasanya berarti proses berhasi l dijalankan dengan baik. Jadi nilai ini lebih berguna bagi operating system itu sendiri. Titik koma atau semicolons (;) Karakter ini sangat penting dalam C yang menunjukkan akhir dari sebuah pernyataa n yang dimengerti oleh kompiler. Free Form C memiliki struktur program yang sangat bebas (free form). Kita dapat meletakkan semicolon di sembarang tempat. Tapi tentunya kita tidak akan menulis program ya ng selanjutnya sangat sulit untuk dibaca oleh kita sendiri apalagi oleh orang la in. Dengan kata lain kita harus mengikuti suatu tata cara penulisan yang baik da n selalu konsisten. Kalau tidak maka kita akan menyetujui bahwa C sering dujuluk i sebagai write only program. Case-sensitive Penulisan dalam C sangat sensitive yang membedakan huruf besar dengan huruf keci l. Jadi int sangat berbeda dengan INT atau dengan Int. Sebagai konvensi, nama-na ma fungsi atau variabel biasanya ditulis dalam huruf kecil untuk memudahkan penu lisan. Ketikkan program berikut : LISTING 1.2. Printf.C #include <stdio.h> int main(void) { int a,b; printf(Masukkan dua buah bilangan : ); scanf(%i %i,&a,&b); printf(Bilangan yang dimasukkan : %i dan %i\n,a,b);

return 0; } Kata kunci int sebelum nama variabel a dan b adalah deklarasi variabel dengan de ngan tipe integer. printf() digunakan untuk menuliskan teks ke layar sedangkan scanf() untuk membac a apa yang diketikkan dan dimasukkan ke dalam variabel a dan b. %i digunakan untuk memerintahkan scanf() atau printf() bahwa bilangan yang akan diproses adalah tipe integer. Variabel Variabel berfungsi untuk menyimpan suatu data dengan tipe tertentu dengan ukuran tertentu pula. Variabel harus dideklarasikan sebelum digunakan biasanya setelah tanda { (tanpa ta nda kutip). Karakter yang diijinkan adalah huruf abjad, angka, dan karakter _. Karakter pertama tidak boleh angka. Nama variabel maksimal 31 karakter. Jika ditulis lebih maka kelebihannya akan di abaikan. Huruf besar dan kecil dianggap berbeda (case sensitive). int a; double d1,d2; Deklarasi variabel juga dapat sekaligus memberikan nilai awal atau inisialisasi seperti : int a = 0; double d1 = 12.5,d2 = 0.34; printf() dan scanf() Fungsi-fungsi ini paling sering digunakan dalam program dalam mode text yang pro totipenya dideklarasikan dalam stdio.h. Fungsi printf() digunakan untuk menulis ke layar dengan format tertentu. Jika fo rmat yang digunakan %i maka integer akan dituliskan ke layar. Sedangkan fungsi scanf() digunakan untuk membaca masukan dari keyboard. Jika sca nf() menemukan format tertentu misalnya %i, maka ia akan menunggu bilangan integ er diketikkan. Tanda & sangat penting dalam scanf() yang mengijinkan untuk mengu bah variabel yang dilewatkan misalnya : scanf(%i,&a); Penjelasan tentang & ada pada bagian selanjutnya dari modul ini yaitu pada bagia n pointer. Program Entry Point Dalam C program utama dimulai dari fungsi main() yang dapat mempunyai bentuk : int main(void) int main(int argc,char ** argv) int main(int argc,char *argv[]) Fungsi main() dengan parameter seperti bentuk kedua dan ketiga berguna kalau and a ingin mendapatkan program arguments yang disimpan dalam argv sebanyak argc. In dex nol adalah nama program itu sendiri lengkap dengan nama direktorinya. Contoh : LISTING 1.3. Args.C #include <stdio.h> int main(int argc,char *argv[])

{ int i; for (i = 0;i < argc ;i++) printf(Arguments %i : %s\n,argv[i]); return 0; } Misalnya kita namakan program ini prog1.exe. Ketikkan : prog1 arg1 arg2, dan amati keluaran program. C Keywords ANSI C dan juga Standard C menggunakan kata-kata kunci (keywords) berikut : auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while

2. TIPE DATA Tipe data Integer dalam C C memiliki beberapa tipe data yang tergolong integer (bilangan bulat) dengan bat as-batas minimal dan maksimal dideklarasikan dalam unit header limits.h. Tipe Format Bytes char signed char unsigned char short unsigned short int unsigned int Minimum Maksimum

long int unsigned long %c %c %c %hi %hu %i %u %li %lu 1 1 1 2 2 2 atau 4 2 atau 4 4 4 CHAR_MIN SCHAR_MIN 0 SHRT_MIN 0 INT_MIN 0 LONG_MIN 0 CHAR_MAX SCHAR_MAX UCHAR_MAX SHRT_MAX USHRT_MAX INT_MAX UINT_MAX LONG_MAX ULONG_MAX Kita dapat bekerja dengan tipe data integer dengan basis yang lain misalnya octa l atau hexadesimal. Untuk bekerja dengan bilangan octal bilangan diawali dengan angka 0 jadi 08 akan berbeda dengan 8. Jika bekerja dengan bilangan hexadesimal, kita harus menambahkan 0x didepan sebuah angka dan selanjutnya huruf a,b,c,d,e, f bisa digunakan dalam bilangan. Untuk format penampilan dengan fungsi printf, kita gunakan %o untuk menampilkan dalam bilangan octal dan %x jika dikehendaki dalam bilangan hexadesimal dengan h uruf abcdef (dalam huruf kecil). Sedangkan %X akan menampilkan dalam huruf besar jika bilangan yang ditampilkan mengandung huruf-huruf tersebut. Tipe Bilangan Real Bahasa C mendukung secara luas tipe data real yang jangkauannya dideklarasikan d alam header file floats.h. Tipe data yang termasuk bilangan real dicantumkan dalam tabel Tipe Format float double long double %lf %le %lg %Lf %Le %Lg 8 10 FLT_MIN DBL_MIN LDBL_MIN Bytes %f %e %g 4 Minimum Maksimum

FLT_MAX

DBL_MAX LDBL_MAX Tipe data float adalah tipe bilangan real yang paling kecil yang memerlukan ruan g 4 bytes diikuti oleh double dan yang paling besar adalah long double. Program berikut adalah contoh penggunaan tipe data real dengan menggunakan fungs i printf() untuk menampilkan hasilnya : LISTING 2.1. Real.C #include<stdio.h> #include<float.h> int main(void) { double f = 3.14,g = 1.2e-5,h = 500000000.0; printf(f=%lf\tg=%lf\th=%lf\n,f,g,h); printf(f=%le\tg=%le\th=%le\n,f,g,h); printf(f=%lg\tg=%lg\th=%lg\n,f,g,h); printf(f=%7.2lf\tg=%.2le\th=%.4lg\n,f,g,h); return 0; } Output program adalah, f=3.140000 f=3.140000 f=3.140000e+00 f=3.14 f=3.14 f=3.140000 f=3.140000e+00 f=3.14 f=3.14 g=0.000012 g=0.000012 g=1.200000e-05 g=1.2e-05 g=1.20e-05 g=0.000012 g=1.200000e-05 g=1.2e-05 g=1.20e-05 g=50000000.000000 g=50000000.000000 g=5.000000e+07 g=5e+07 g=5e+07 g=50000000.000000 g=5.000000e+07 g=5e+07 g=5e+07

Konstanta Konstanta dengan tipe data Konstanta digunakan untuk membuat suatu nilai tidak bisa diubah atau konstan. De ngan kata lain menarik garis yang tegas antara apa yang boleh dan tidak untuk di modifikasi. Dalam C, kontanta dideklarasikan dengan const tipe nama = inisialisasi; Contoh : const double f = 100.5; Bilangan yang mengandung ., e (tanpa tanda kutip) adalah tipe double misalnya 1.2, 2 e-3. Akhiran F mendeklarasikan konstanta sebagai float misalnya 12.5F. Akhiran L mendeklarasikan konstanta sebagai long double misalnya 1.29e15L. Bilangan yang tidak mengandung .,e atau F adalah tipe int, namun beberapa compiler aka n mengubah menjadi long int jika tidak mencukupi sebagai int. Untuk kontanta long int, diakhiri dengan L misalnya 9000000L. Konstanta dengan preprocessor Konstanta juga dapat dideklarasikan dengan preprocessor misalnya

#define PI 3.1415925 #define DAYS_IN_WEEK 7 Biasanya konstanta preprocessor ditulis dengan huruf besar. Dalam melakukan tuga snya compiler tidak memproses apa yang anda ketikkan, namun hasil output dari pr eprocessor. Jadi pada saat sebuah unit dikompilasi, preprocessor akan dijalankan terlebih dahulu yang akan mengganti setiap simbol yang ditemukan sesuai dengan deklarasi tanpa memandang tipe data. Karena itu preprocessor seringkali disebut sebagai front end processor.

3. OPERATOR Dalam setiap bahasa pemrograman selalu memiliki operator yang berguna untuk mela kukan suatu operasi (sehingga dinamakan operator) dengan menggunakan simbol-simb ol tertentu. Dalam bab ini akan dibahasa operator-operator dalam C yang dikelomp okkan dalam katagori operasionalnya. Operator Aritmetika C mendukung operator untuk operasi artimetika seperti dalam tabel : Operator Deskripsi + * / % Untuk operasi penjumlahan Untuk operasi penguranga Untuk operasi perkalian Untuk operasi pembagian Untuk mendapatkan sisa hasil pembagian Perhatikan cuplikan program berikut , LISTING 3.1. Oprs.C int main(void) { int i = 5, j = 4, k; double f = 5.0, g = 4.0 , h; k = i / j; h = f / g; h = i / j; return 0; } Pada baris k = i / j, compiler akan menggunakan pembagian integer karena kedua o perand adalah tipe integer. Pada baris h = f / g, compiler menggunakan pembagian double karena jelas kedua o perand adalah tipe double. Pada baris h = i / j, compiler tetap menggunakan pembagian integer dengan mengab aikan bahwa variabel untuk menampung hasilnya adalah tipe double. Hasil yang dip eroleh akan disimpan dalam bentuk double. Casting Operator Istilah casting sering diartikan sebagai berperilaku seperti sesuatu yang lain d

an untuk tujuan tertentu. Perhatikan baris program berikut : LISTING 3.2. Cast.C int main(void) { int i = 5, j = 4, k; double f; f f f f } Pada baris f = (double)i / j, f = i / (double)j dan f = (double)i / (double)j, c ompiler menggunakan pembagian tipe double karena salah satu operand adalah tipe double yang secara otomatis operand yang berukuran lebih kecil akan diubah semen tara menjadi double. Operasi ini disebut type promotion. Sedangkan pada f = (double) (i / j), compiler tetap menggunakan pembagian intege r namun hasilnya diubah ke double. Operator Increment dan Decrement C sebagai tersed-language (bahasa yang ringkas) memiliki operator khusus yang di gunakan untuk menambah (increment) dan mengurangi (decrement) suatu variabel den gan bentuk yang unik namun sangat ringkas yaitu ++ dan --. Ada dua versi untuk masing-masing operator ini yang biasa disebut prefix dan pos tfix sesuai dengan letak penulisannya. Prefix ++ dan Dengan prefix operator, operator-operator ini ditempatkan sebelum sebuah variabe l yang akan dioperasikan misalnya : int x = 5; y = ++x; z = --x; Prefix operator ini bekerja dengan prinsip Tambahkan (untuk ++) atau kurangkan (untuk --) nilai sebuah variabel dengan satu dan simpan nilai itu dalam sebuah variabel yang diletakkan di sebelah kiri jika ada. Jadi untuk contoh ini, nilai x yang semula bernilai 5 akan ditambahkan dengan sa tu (menjadi 6) dan disimpan dalam y, selanjutnya dikurangi satu dan disimpan dal am z (nilai 5); Posfix ++ dan Operator ini bekerja dengan mengambil data sebelum dilakukan operasi postfix. int x = 5; y = x++; z = x--; Operator Komparasi Bahasa C dalam melakukan operasi logika menggunakan dua logika yaitu benar (true ) atau salah (false) namun C tidak memiliki kata kunci khusus untuk true/false. Semua nilai yang tidak nol (non-zero) akan dianggap true dan nilai nol akan dian ggap false. Logika benar dan salah ini digunakan untuk melakukan operasi perbandingan dengan berbagai kondisi yang dalam C dapat dilakukan dengan operator- operator seperti = = = = (double)i / j; i / (double)j; (double)i / (double)j; (double) (i / j);

return 0;

dalam tabel : Operator Deskripsi < <= > >= != Kurang dari Kurang atau sama dengan Lebih besar dari Lebih besar atausama dengan TIdak sama dengan Perhatikan contoh program berikut , int i = 10, j, k; j = i > 5; k = i < 2; Hasil dari baris program ini akan membuat j bernilai 1 (true) karena i memang le bih besar dari 5 dan k bernilai 0 (false) karena i lebih besar dari 2. Operator Logika Dalam melakukan operasi pembandingan atau komparasi seringkali dilakukan untuk d ua atau lebih pernyataan logika untuk mengambil sebuah keputusan. C menyediakan operator untuk melakukan pembandingan logika : Operator Deskripsi && || ! Dan (and) Atau (or) Tidak (not) Operator-operator ini juga menganggap nilai tidak nol sebagai nilai yang benar ( true) dan nol sebagai nilai yang salah (false). Beberapa hal yang perlu diketahui dari perilaku compiler dalam mengevaluasi sebu ah pernyataan logika : Evaluasi dilakukan dari kiri ke kanan Evaluasi dilakukan dengan berpedoman pada prinsip short circuit. int j = 5, k = 2; if (j > 10 && k <= 2) Untuk baris program ini, compiler tidak akan mengevaluasi k <= 2 karena operator && (and) yang akan bernilai benar hanya jika kedua operand yang dibandingkan be rnilai benar (tidak nol). Jadi untuk hal ini karena j > 10 bernilai salah maka c ompiler sudah yakin bahwa pernyataan ini bernilai salah (false). Mekanisme ini d isebut short-circuit. Dengan mekanisme ini juga, compiler dapat menghasilkan pro gram yang lebih efisien. Sebagai saran praktis, gunakan tanda kurung untuk memisahakan masing-masing kond isi agar alur program menjadi jelas. Bitwise Operator Operator-operator ini digunakan untuk memanipulasi bit-bit (bitwise) dalam sebua h variabel yang sering digunakan dalam bahasa assembly. Keberadaan operator ini sangat masuk akal karena C pertama kali dirancang untuk membuat abstraksi dari a ssembly dan dijuluki sebagai high level assembly.

Operator-operator yang disediakan antara lain : Operator Deskripsi & | ~ >> << ^ and or not (negasi) geser ke kiri geser ke kanan xor Bagi anda yang tidak memiliki latar belakang pemrograman sama sekali, operator-o perator ini perlu mendapat penjelasan lebih lanjut. Untuk memahami operator-oper ator ini perlu juga dijelaskan tentang tabel kebenaran untuk operasi-operasi and , or dan xor. Untuk operator-operator yang lain dapat dipahami dengan mudah sesu ai dengan namanya. or 0 1 and 0 1 xor 0 1 0 0 1 0 0 0 0 0 1 1 1 1 1 0 1 1 1 0

Operator ~ akan mengubah sebuat bit menjadi kebalikannya yaitu 1 menjadi 0 dan 0 menjadi 1. Operator >> akan mengeser bit-bit dalam sebuah operand ke kiri sebanyak angka ya ng diletakkan di sebelah kanan operator ini. Misalnya, int a = 2; a = 2 >> 1; Assignment Operators Operator ini berfungsi untuk mentransfer suatu nilai antara dua operand. Bentuk dari assigment dalam C adalah : ekspresi1 (operator)= ekspresi2 yang ekuivalen dengan ekspresi1 = ekspresi1 (operator) ekspresi2 Jadi C menyedikan bentuk singkat untuk operasi assignment seperti dalam tabel : Operator op1 += op2 op1 -= op2 op1 *= op2 op1 /= op2 op1 %= op2 op1 &= op2 Deskripsi

op1 op1 op1 op1 op1 op1 op1 op1 op1 op1 op1 op1 op1

|= op2 ^= op2 <<= op2 >>= op2 op1 = op1 + op2 = op1 op2 = op1 * op2 = op1 / op2 = op1 % op2 = op1 & op2 = op1 | op2 = op1 ^ op2 = op1 << op2 = op1 >> op2

Contoh : int a = 10,b = 12.5; a += b; b /= 10; Setelah program dijalankan akan membuat nilai-nilai variabel menjadi: a = 22.5 b = 1.35 Seringkali kesalahan timbul karena salah menuliskan assignment dengan komparasi, Ditulis, if (a = b) { } yang sebenarnya dimaksud, if (a == b) { } Yang paling menyulitkan adalah dengan kesalahan itu compiler tidak akan menginform asikan sebagai kesalahan sintak karena dianggap kita mengerti apa yang kita laku kan. Jadi tergantung pada konteks, kalau yang kita maksud adalah memang assignme nt, pernyataan itu menjadi benar dan sebaliknya. Operator sizeof Walaupun operator ini bukan termasuk dalam standar C namun hampir setiap compile r mengimplementasikannya.Operator ini mempunyai bentuk yang sangat mirip dengan sebuah fungsi yang memungkinkan kita mengetahui jumlah bytes yang diperlukan seb uah tipe data atau variabel. Penggunaan operator ini sangat mudah misalnya: sizeof(double) ; dapat juga ditulis sizeof double;

Operator Kondisional Operator ini berguna untuk menguji suatu kondisi. Operator ini mempunyai bentuk kondisi ? ekspresi_jika_kondisi_benar : ekspresi_jika_kondisi_salah; yang sama jika ditulis, if (kondisi) ekspresi_jika_kondisi_benar; else ekspresi_jika_kondisi_salah; Contoh : int a,b = 20, c = -10; a = (b > c) ? b : c; Baris perintah itu membuat nilai a menjadi 20; Operator ini biasa disebut ternary operator. 4. CONTROL FLOW (ALUR PROGRAM) Program komputer ditulis untuk menyelesaikan suatu tugas. Dalam prosesnya sebuah program akan menerima masukan selanjutnya melakukan perbandingan, pengujian, pe nerapan algoritma tertentu dan menampilkan hasil proses itu dalam bentuk informa si yang berguna (opsional). Untuk memahami proses itu kita perlu mengetahui baga imana masing-masing sub-proses itu dilakukan. Secara umum program melakukan pros es itu dengan mengikuti suatu alur (flow) tertentu. Pada bab ini akan dibahas ba gaimana alur itu diikuti dengan mengenalkan kepada anda tentang komparasi dan it erasi atau perulangan. Pengambilan keputusan dengan if else Bentuk umumnya dapat ditulis dalam bentuk : if (kondisi1) ekspresi1; else if (kondisi2) ekspresi2; else ekspresi3; atau multi baris harus disertakan tanda kurung { }, if (kondisi1) { ekspresi; . } else if (kondisi2) { ekspresi; } else { ekspresi;

} Pengujian dilakukan mulai dari kondisi1 berlanjut ke kondisi2 dan seterusnya. Ji ka semua tidak dipenuhi maka ekspresi terakhir setelah else akan dijalankan. Kesalahan yang sering terjadi adalah penulisan pernyataan if dengan diakhiri den gan semicolons (;) misalnya : if (a > b); ekspresi1; dengan adanya ; setelah pengujian kondisi itu, maka akan dianggap sebagai akhir da ri sebuah ekspresi sehingga baris expresi1 akan selalu dijalankan tanpa memandan g hasil pengujian kondisi. Pernyatan if-else juga dapat nested yaitu berada dalam pernyataan if-else yang l ain. Contoh : int a = 100; if (a > 0) { if (a > 100) printf(a adalah besar\n); else printf(a adalah sedang\n); } Pengujian kondisi dengan switch Jika pengujian melibatkan banyak kondisi dengan tipe integer (bilangan bulat), m aka penggunaan if else menjadi kurang efisien. C mempunyai kata kunci switch unt uk melakukan pengujian dengan banyak kondisi dengan bentuk : switch(nilai_integer) { case nilai1 : ekspresi1; break; case nilai2 : ekspresi2; break; default : ekspresi_default; break; } Kata kunci break berguna untuk segera keluar dari blok switch sehingga begitu se tiap ekspresi dijalankan, maka kontrol akan dipindahkan keluar switch atau denga n kata lain untuk menjamin hanya satu ekspresi saja yang dijalankan. default berperan seperti else yaitu sebagai alternatif dari suatu kondisi yang t idak dipenuhi. Namun ada saatnya dimana break tidak digunakan, misalnya untuk menjalankan ekspr esi yang sama untuk beberapa kondisi. Contoh penggunaan switch : LISTING 4.1. Switch.C

#include<stdio.h> int main(void) { char n =

E ;

printf("Masukkan sebuah nilai : "); scanf("%c",&n); printf("%c",n); switch(n) { case A :case a : printf("Nilai antara 80-100\n"); break; case B :case b : printf("Nilai antara 70-80\n"); break; case C :case c : printf("Nilai antara 60-70\n"); break; case D :case d : printf("Nilai kurang dari 60\n"); break; default : printf("Kriteria nilai tidak ada\n"); } return 0; } Perhatikan baris yang mengandung : case A:case a: printf("Nilai antara 80-100\n"); break; Pernyataan itu dapat ditulis dengan : case A: case a: printf("Nilai antara 80-100\n"); break; Dalam program ini berguna agar kita dapat memasukkan huruf besar ataupun huruf k ecil (case insensitive). while Seringkali dibutuhkan untuk melaksanakan tugas berulang sampai suatu kondisi ter tentu tercapai (termination criteria). C memiliki tiga jenis loop atau iterasi a tau perulangan, dan yang paling sederhana adalah while-do yang memiliki bentuk : while (kondisi) ekspresi; atau while (kondisi) { ekspresi; }

Selama kondisi bernilai benar, maka ekspresi akan dijalankan terus menerus. Bias anya ekspresi itu sendiri mengandung perintah untuk membuat kondisi menjadi fals e sehingga loop berhenti. Contoh : int a = 10; printf(mulai\n); while (a > 0) { printf(a = %i\n,a--); } printf(akhir\n); Program ini akan mencetak nilai a terus menerus sampai nilai a sama dengan 0 yan g tidak akan ditampilkan. Seperti hal lainnya dalam C, kesalahan umum dalam penulisan loop ini misalnya de ngan meletakkan semicolon (;) setelah while: while (kondisi); ekspresi; yang menyebabkan program akan terjebak dalam menjalankan loop tak berhingga (inf inite loop) karena kondisi tidak pernah diperbaharui untuk menghentikan loop. do-while Tidak seperti while yang mengevaluasi kondisi pada awal setiap iterasi, do-while akan melakukannya pada akhir setiap iterasi. Dengan kata lain paling tidak satu kali iterasi akan dilakukan. Contoh : int a = -10; printf(mulai\n); do { printf(a = %i\n,a--); } while (a > 0); printf(akhir\n); Program ini akan menjalankan perintah dalam blok { } sekali saja karena pada akh ir iterasi pertama pengujian dilakukan yang menemukan bahwa a memang kurang dari 0 dan loop berhenti. for Jenis loop ini memiliki bentuk : for (inisialisasi;kondisi;bagian_update) ekspresi; Yang perlu diperhatikan adalah tanda semicolon (;) yang memisahkan masing-masing bagian. Contoh : LISTING 4.2. Loop.C

#include<stdio.h> #include<math.h> #define PI 3.14 int main(void) { double sudut; for (sudut = 0.0; sudut < PI;sudut += 0.5) printf(Sudut %.2lf = %.2lf\n,sudut,sin(sudut)); return 0; } Tidak seperti bahasa Pascal atau Ada yang hanya memungkinkan langkah penambahan atau pengurangan variabel loop (sudut) hanya sebesar satu, C memungkinkan semua jangkauan bilangan. Header file math.h diperlukan dalam program ini untuk menghitung nilai sinus dar i sebuah sudut dalam radian. Perlu juga diketahui bahwa loop ini dapat melakukan inisialisasi lebih dari satu yang dipisahkan dengan koma (,) misalnya : int a,b,c; for (a = 0,b = 1,c = 20;a < 10;a++,b++,c--) Atau bagian inisialisasi dan bagian update tidak mengandung pernyataan sama seka li : int a = 0,b,c; for ( ; a < 10;) atau tidak mengandung sama sekali for (;;)

programmer biasa menulisnya dengan bentuk : #define EVER ;; for (EVER) { } break Kata kunci ini dapat anda gunakan untuk keluar dari suatu loop terdekat. Contoh : int a = 0; for (;;) { printf(Masukkan sebuah angka : ); if ((scanf(%i,&a)==1) && (a==0)) break; }

continue Berfungsi untuk menjalankan iterasi berikutnya walaupun eksekusi program belum m encapai akhir sebuah iterasi. Misalnya program untuk melewati bilangan dengan ke lipatan 3 : int a; for (a = 1;a < =10;a++) { if (a % 3 == 0) continue; printf(%i\n,a); } akan menghasilkan 1,2,4,5,7,8,10. 5. FUNGSI Pada awal penulisan program, kita jarang berpikir untuk masalah efisiensi misaln ya kita membuat sebuah program yang melakukan operasi matrik (perkalian, inverse dan sebagainya), kita akan langsung menuliskan algoritma yang sesuai dengan pro gram kita berjalan sesuai dengan rencana yaitu program untuk operasi matrik. Sua tu saat kita diharuskan menambahkan fasilitas dalam program kita sehingga bisa m elakukan penyelesaian persamaan linear. Kita tahu untuk menyelesaikan persamaan linear yang umum kita dapat menggunakan metode matrik. Masalah muncul karena kit a telah membuat rutin-rutin untuk operasi matrik menjadi satu dengan program uta ma. Kita dapat melakukan dua hal untuk itu. Pertama kita dapat menduplikat rutin-rutin operasi matrik itu ke bagian lain dar i program yang digunakan untuk menyelesaikan persamaan linear, jadi dua rutin ya ng identik akan ditulis dua kali dalam satu program. Kedua kita dapat mengorganisir rutin-rutin itu ke dalam bentuk yang disebut fung si dan memanggil fungsi itu dengan parameter tertentu baik untuk melakukan opera si matrik atau penyelesaian persamaan linear, jadi kita hanya perlu sekali saja menuliskan rutin untuk operasi matrik. Pilihan kedua nampak lebih efisien ditinjau dari segi penulisan dan tentunya uku ran program. Untuk itu dalam bab ini kita akan membahas bagaimana fungsi itu dap at membuat program kita menjadi modular dan mudah dikembangkan. Kita sudah sering menggunakan fungsi seperti printf() yang dapat menerima masuka n parameter yang tidak terbatas. Atau kita juga dapat membuat sebuah fungsi yang tidak menerima masukkan sama sekali misalnya dalam fungsi utama : int main(void) Beberapa hal yang perlu diperhatikan dalam penulisan fungsi : Nilai balik (return value) Jika sebuah fungsi menghasilkan nilai keluaran, maka nilai keluaran itu dideklar asikan dengan tipe data yang sesuai dan ditulis pertama misalnya int get_value(void); Nama fungsi Penamaan fungsi harus unik (tidak boleh sama) yang membedakannya dengan fungsi l ain dalam program. Parameter Parameter adalah nilai yang kita lewatkan pada saat pemanggilan sebuah fungsi. P enulisan parameter harus diawali dengan tipe data dan diikuti dengan nama yang u

nik dengan parameter yang lain dalam satu fungsi. Masing-masing parameter dipisahkan dengan koma. Misalnya : int check_values(int parameter1, int parameter2); Pemanggilan fungsi Fungsi dipanggil dengan menuliskan namanya dan diikuti dengan parameter-paramete r yang sesuai. Jika tidak menerima paramater, maka nama fungsi diakhiri dengan t anda kurung () Contoh berikut dengan asumsi fungsi get_value() sudah ada : int main(void) { int a,b; {fungsi tanpa parameter} a = get_value(); {dengan parameter} check_values(a,b); return 0; } Penulisan Prototipe Dalam C pembuatan fungsi diawali dengan penulisan prototipe atau deklarasi dan d ilanjutkan dengan definisi. Prototipe menginformasikan compiler bagaimana fungsi ini digunakan dengan benar misalnya : int check_three_value(int,double, char); Penulisan prototipe diakhiri dengan semicolon (;). Penulisan nama-nama parameter untuk prototipe adalah opsional dan diabaikan oleh compiler. Dengan bantuan prototipe ini, compiler akan menjamin fungsi yang dipanggil dilew atkan parameter dengan tipe yang benar. Karena pentingnya prototipe fungsi, maka kita mulai saat ini kita akan mengangga p itu sebagai keharusan dalam pembuatan fungsi walaupun C sendiri menganggapnya opsional. Penulisan definisi fungsi Setelah kita menuliskan prototipe, kita selanjutnya harus menuliskan fungsi itu sendiri yang biasa dikenal dengan definisi atau implementasi. Contoh :

LISTING 5.1. Fungsi.C #include <stdio.h> /* prototipe */ int is_negative(double); /* untuk menghitung luas segiempat */ double luas_segiempat(double,double);

int main(void) { double P = 100,L = 10, luas; if (!is_negative(P) && !is_negative(L)) { luas = luas_segiempat(P,L); printf(Luas = %.2lf\n,luas); } else printf(Nilai masukkan harus positif\n); return 0; } /* definisi */ int is_negative(double value) { return value < 0; } double luas_segiempat(double panjang,double lebar) { return panjang * lebar; } Perlu diingat bahwa semua variabel dalam fungsi adalah bersifat lokal dan hanya dapat digunakan oleh fungsi itu sendiri, jadi nama sebuah variabel lokal dalam s uatu fungsi tidak akan konflik dengan nama yang sama dalam fungsi yang lain. Lebih lanjut tentang pemanggilan fungsi Pada saat sebuah fungsi dipanggil, parameter-parameter yang dilewatkan akan di-k opi sebelum digunakan atau dikenal dengan call by value. Dengan cara ini nampakn ya sebuah fungsi tidak bisa memodifikasi sebuah variabel di luar fungsi. Pada ba gian selanjutnya nanti yaitu pada topik pointer, kita akan membahas tentang mele watkan parameter yang berupa pointer sehingga kita dapat melakukan modifikasi te rhadap variabel diluar fungsi. C dan stack C menggunakan stack untuk menyimpan variabel lokal dan juga parameter-parameter dalam pemanggilan fungsi. Pada saat pemanggilan fungsi proses proses berikut akan dilakukan: Fungsi pemanggil akan menyimpan parameter-parameter ke dalam stack. Fungsi dipanggil. Fungsi yang dipanggil mengambil parameter-parameter dalam stack. Fungsi yang dipanggil mengalokasikan variabel-variabel lokal juga di dalam stack . Setelah proses dilakukan oleh fungsi yang dipanggil, semua variabel lokal akan d ibersihkan dan kembali ke fungsi pemanggil (biasanya dengan memodifikasi nilai p ada stack pointer misalnya register SP dalam processor Intel x86). Fungsi pemanggil membersihkan parameter-parameter yang sebelumnya disimpan dalam stack (poping up). Nilai balik disimpan dalam suatu register atau dalam stack. Anda dapat membayangkan stack itu sebagai sebuah tumpukkan buku. Setiap kita aka n menambahkan buku ke tumpukan itu,kita akan meletakkannya di atas tumpukan. Dem ikian juga jika kita ingin mengambil salah satu buku maka kita harus mengambilny a mulai dari buku yang paling atas dari tumpukan itu. Jika kita mengambil buku y ang ada ditengah-tengah maka tumpukan akan berantakan (last in first out atau LI FO). Dalam C setiap kita meletakkan sebuah variabel dalam stack, maka nilai itu akan diletakkan pada lokasi berikutnya dan penunjuk akan menunjuk ke lokasi berikutny a yang kosong (top of the stack).

Secara umum C memiliki lokasi-lokasi penyimpanan yang dikelompokkan secara logis yaitu Code Segment, Stack Segment, Data Segment dan Heap (free store). Code Segment Lokasi ini menyimpan semua kode program dan tentunya harus read-only. Stack Segment Seperti telah disebutkan sebelumnya lokasi ini berguna untuk menyimpan variabelvariabel lokal dan parameter-parameter pada saat pemanggilan fungsi. Data Segment Untuk menyimpan variabel-variabel global Heap Lokasi ini untuk menyimpan data-data yang dialokasikan secara dinamis dengan fun gsi-fungsi C malloc(), calloc(), realloc(), dan free(). Variabel qualifier Deklarasi sebuah variabel juga dapat diawali dengan menambahkan kata-kata kuci y ang disebut qualifier yang memberikan arti lain kepada variabel itu. C memiliki beberapa qualifier untuk variabel. auto Secara otomatis C akan menganggap sebuah variabel lokal sebagai auto jika kita t idak secara eksplisit menuliskannya yang sama dengan variabel dalam stack. static Walaupun kita mendeklarasikan variabel dalam sebuah fungsi (variabel lokal) namu n jika kita awali dengan kata kunci static, maka variabel ini akan dialokasikan di data segment dan akan tetap berada di sana selama program berjalan. Variabel static dalam fungsi akan diinisialisasi sekali pada saat fungsi pertama kali dip anggil. register Dengan kata kunci ini, kita menginstruksikan compiler untuk menggunakan register CPU untuk meletakkan variabel-variabel tertentu. Dengan dikembangkannya optimiz ed compiler, kata kunci ini hampir tidak berpengaruh sama sekali karena compiler biasanya lebih bisa membuat kode program yang efisien dari pada secara manual. Untuk sebagian besar kegiatan pemrograman dengan C, anda tidak perlu mengetahui terlalu detail tentang peta memori yang digunakan, namun dengan memahami ini and a dapat memahami C dengan lebih baik. 6. POINTER C kadang-kadang dikatakan sebagai high level assembly. Hal itu masuk akal karena pada awalnya C dirancang untuk memudahkan pemrograman yang sebelumnya menggunak an assembly sehingga C akhirnya dibuat sebagai abstraksi dari bahasa assembly, misalnya dalam hal indirection yang dalam C diimplementasikan dengan pointer yai tu sebuah variabel yang menyimpan alamat dari variabel atau lokasi data yang lai n. Pointer seringkali dianggap salah satu topik yang paling sulit bagi pemula da lam C. Deklarasi Pointer Pointer dalam C dideklarasikan sebagai : type *variabel [= initialisasi]; misalnya int n = 0; int * pn = &n; Yang mendeklarasikan sebuah variabel n dengan tipe integer dan sebuah variabel d engan tipe pointer ke integer dengan nama pn yang diinisialisasi dengan alamat v ariabel n.

Pointer ke suatu tipe ditandai dengan *, sehingga int *pn berarti pointer ke int eger. Penempatan * sering menjadi perdebatan yang pada akhirnya menjadi masalah prefer ensi atau pilihan saja: int* pn,x; int *pn,x; Bentuk yang pertama sering disalahartikan dengan melihat bahwa pn dan x adalah p ointer ke integer namun pada kenyataannya hanya pn saja yang bertipe pointer sed angkan x adalah dengan tipe integer. Disinilah kerancuan muncul sehingga bentuk kedua lebih sering digunakan karena tanda pointer * ditulis berdekatan dengan va riabel yang dimaksudkan sebagai pointer, sehingga lebih mudah untuk melihat bahw a pn adalah tipe pointer sedangkan x bukan. Dengan deklarasi ini kita dapat memanipulasi variabel n dengan menggunakan pn, m isalnya : *pn = 20; Perhatikan tanda * dalam pernyataan ini berarti dereference atau dapat diartikan sebagai nilai yang disimpan pada alamat yang berada pada pn. Atau dengan kata l ain *pn berarti merujuk ke nilai yang disimpan pada alamat yang disimpan di pn. Kesalahan yang sering dilakukan dalam operasi pointer adalah dalam assignment (d engan operator = ). int x1 = 12,x2 = 20; int *p1 = &x1; int *p2 = &x2; Untuk memudahkan ilustrasi, kita akan mengandaikan x1 dan x2 secara berturut-tur ut berada dalam memori dengan alamat : 0xFFF4 dan 0xFFF2. Karena pointer juga adalah variabel maka sudah tentu menempati suatu lokasi memo ri dan juga memiliki alamat, namun dalam ilustrasi ini kita tidak menganggap per lu untuk mengetahui alamat dari suatu pointer.

Dari gambar dapat dilihat p1 dan p2 setelah diinisialisasi masing-masing dengan alamat x1 dan x2 dengan menggunakan operator &. Misalnya setelah deklarasi kita bermaksud untuk membuat x1 menjadi nilai x2 yait u 20 dengan cara : p1 = p2; Walaupun kita mendapatkan nilai 20 untuk *p1, namun yang kita lakukan sebenarny a adalah membuat p1 menunjuk ke lokasi yang sama dengan yang ditunjuk p2 yaitu k e x2 sehingga jika kita bermaksud mengubah nilai x1 dengan p1 : *p1 = 2; maka kita tidak akan mengubah nilai x1, namun x2 ! Ilustrasi untuk pointer assignment (p1 = p2) dapat dilihat pada gambar berikut :

Inisialisasi Pointer Operator & dalam inisialisasi ini berarti mengambil alamat dari operand dalam ha l ini alamat dari variabel n. Inisialisasi ini sangat penting karena pointer seb elum digunakan harus menunjuk ke lokasi memori yang valid kalau tidak maka progr am kita dapat melakukan kesalahan yang fatal yang biasa dikenal dengan access vi olation error. Misalnya : int *pn; *pn = 12; // fatal error !! C juga mendeklarasikan konstanta untuk menyatakan sebuah pointer tidak valid ata u tidak menunjuk ke manapun yaitu konstanta NULL yang perlu digunakan untuk inis ialisasi pointer jika tidak segera digunakan. Agar program menjadi tangguh, kita harus sedapat mungkin memeriksa pointer agar ti dak NULL sebelum digunakan : int *pn = NULL; if (pn != NULL) { /* aman menggunakan pn */ } else { /* pointer NULL */ } Melewatkan parameter dengan pointer Pada bab sebelumnya kita menjelaskan tentang fungsi dalam C. Dalam bab ini kita akan menggunakan fungsi untuk menukar nilai dua buah variabel yang dilewatkan ke fungsi yang biasanya disebut swap. Berikut adalah contoh program untuk mengilus trasikan prosesnya :

LISTING 6.1. Swap1.C #include <stdio.h> /* prototipe fungsi swap */ void swap(int,int); int main(void) {

int a = 10,b = 5; printf(Before swap a : %d b : %d\n,a,b); swap(a,b); printf(After swap a : %d b : %d\n,a,b); return 0; } void swap(int v1,int v2) { int tmp = v1; v1 = v2; v2 = tmp; } Setelah dijalankan, program menghasilkan : Before swap a : 10 b : 5 After swap a : 10 b : 5 yang tidak sesuai dengan tujuan program kita. Hal itu disebabkan karena fungsi swap() melewatkan variabel ke dalam fungsi deng an nilai (by value) jadi pada saat kita melewatkan a dan b, fungsi akan meng-cop y nilai-nilai itu sehingga pada saat kita berubah nilainya, nilai pada variabel diluarnya tetap. Agar kita dapat mengubah atau memodifikasi nilai di luar fungsi maka kita harus menggunakan pointer yang akan melewatkan alamat dari variabel di luar fungsi. De ngan mekanisme ini, kita dapat melewatkan apa saja ke dalam fungsi secara efisie n karena ukuran pointer selalu sama untuk masing-masing sistem operasi. Kembali ke program swap, kita harus memodifikasi fungsi swap() dengan menggunaka n pointer untuk melewatkan nilai ke dalam fungsi. Program setelah dimodifikasi m enjadi : LISTING 6.2. Swap2.C #include <stdio.h> /* prototipe fungsi swap */ void swap(int*,int*); int main(void) { int a = 10,b = 5; printf(Before swap a : %d b : %d\n,a,b); swap(&a,&b); /* Perhatikan tanda & untuk mengambil alamat variabel */ printf(After swap a : %d b : %d\n,a,b); return 0; } void swap(int *v1,int *v2) { int tmp = *v1; *v1 = *v2; *v2 = tmp; } Dengan program kali ini kita dapat menukar nilai a dan b yang menghasilkan : Before swap a : 10 b : 5 After swap a : 5 b : 10

Pointer ke data konstan Pada fungsi print_data() juga menggunakan kata kunci const untuk mengawali tipe data dalam parameternya. const di sini berfungsi untuk mencegah data yang dilewa tkan dalam fungsi dimodifikasi atau diubah. Dengan const ini, jika kita secara t idak sengaja mengubah nilai parameter dalam fungsi maka compiler akan mengindika sikan sebagai kesalahan (compiler error) void print_data(const double *data) { /* *data = 100; compiler error !!!*/ printf(Data : %lf\n,data); } Fasilitas ini sangat penting untuk mengisolasi suatu proses yang dilakukan oleh sebuah fungsi dengan pemanggil jika kita tidak menghendaki modifikasi data. Namu n jika kita memang menghendaki fungsi dapat memodifikasi data luar seperti fungs i swap(), maka kita harus menghilangkan kata kunci const dalam paramaternya. Pointer ke pointer C mengijinkan kita membuat pointer ke tipe apa saja termasuk bentuk yang aneh se perti : int **pp; yang mendeklarasikan pp sebagai pointer ke pointer ke integer. Bentuk ini pada dasarnya adalah jika kita hendak memodifikasi isi dari sebuah pointer dengan mel ewatkannya ke dalam fungsi. Kita juga dapat mendeklarasikan sekaligus menginisialisasi. int x = 12; int *p = &x; int **pp = &x;

Jika digambarkan akan nampak sebagai :

Kalau anda masih bertanya-tanya di mana anda akan menggunakan bentuk yang satu i ni, maka kami yakinkan anda seiring dengan pengalaman anda membuat program dan m enyelesaikan banyak permasalahan-permasalahan anda akan mengetahui sendiri kapan bentuk ini tidak nampak aneh lagi namun menjadi suatu kebutuhan bagi anda. Sebagai satu informasi bagi anda yang penasaran, bentuk ini sangat sering diguna kan dalam pemrograman COM yang berguna untuk melakukan binding (koneksi antara a ntarmuka atau interface dengan implementasinya), dimana yang dilewatkan adalah a lamat dari pointer ke suatu interface sehingga isi dari pointer itu sendiri yang

akan diubah, perhatikan penggalan berikut : ISuatuInterface* pi; pOtherInterface->QueryInterface(SOME_ID,&pi); Dengan asumsi pOtherInterface sudah valid dan QueryInterface() berhasil maka pi akan menunjuk ke lokasi implementasi interface dengan identitas SOME_ID. Pada bagian struktur data dinamis dengan linked list akan diilustrasikan bagaima na penggunaan tipe ** ini. Pointer ke fungsi (function pointer) Selain tipe data yang telah disebutkan sebelumnya, kit juga dapat mendeklarasika n pointer ke sebuah fungsi dengan prototipe tertentu : int (*pf)(const int); Bentuk ini mendeklarasikan pf sebagai pointer ke fungsi yang memiliki parameter konstanta dengan tipe integer dan memberikan nilai balik integer. Perhatikan tanda dereference * sebelum pf, jika ditulis tanpa tanda kurung maka akan menjadi : int *pf(const int); yang berarti fungsi biasa dengan parameter konstanta integer dan nilai balik poi nter ke integer. Jadi tanda kurung itu adalah keharusan untuk membedakannya deng an deklarasi fungsi reguler. Sebelum menggunakan pointer ke fungsi ini, terlebih dahulu harus diinisialisasi dengan alamat fungsi yang sesuai. LISTING 6.3. FuncPtr.C #include<stdio.h> /* prototipe */ int myfunc(const int d); int main(void) { int (*pf)(const int) = myfunc; /* deklarasi sekaligus inisialisasi */ (*pf)(12); /* penggunaan pointer ke fungsi */ return 0; } int myfunc(const int d) { return d*2; } Kalau bentuk pointer ke fungsi yang kompleks, kita dapat menggunakan typedef unt uk memudahkan penulisan : typedef int (*PF)(const int); Penggunaannya menjadi lebih mudah : PF pf = myfunc; (*pf)(12); Hal yang menarik dari pointer ke fungsi ini adalah kita dapat membuat array dari

pointer ke fungsi dengan bentuk : Dan selanjutnya digunakan dengan cara : int (*pf[5])(const int); pf[0] = myfunc; for (i = 0; i < 5;i++) (*pf[i])(i); Dengan memahami pointer yang satu ini, kita dapat membuat program yang dinamis d an table-driven dengan mendeklarasikan beberapa pointer ke fungsi dalam sebuah t abel atau array dan selanjutnya dipanggil dengan bentuk seperti penggunaan point er. Pointer ke fungsi ini sering digunakan untuk sistem dengan callback function yai tu sebuah fungsi akan dipanggil oleh fungsi yang lain tanpa perlu mengetahui imp lementasinya. Jika kita ingin mengubah perilaku sistemnya kita tinggal memodifik asi fungsi yang dipanggil saja. Contoh berikut mengilustrasikan hal itu : LISTING 6.4. Callback.C #include<stdio.h> typedef int (*FP)(const int); void display_numbers(int start,int stop,FP); int filter(const int num); int main(void) { display_numbers(0,20,filter); return 0; } void display_numbers(int start,int stop,FP fp) { int i; for (i = start;i <= stop;i++) { if (fp == NULL) printf("%i\n",i); else else if ((*fp)(i)) printf("%i\n",i); } } int filter(const int num) { return (num % 3 == 0); } Program ini mendeklarasikan pointer ke fungsi : typedef int (*FP)(const int);

Fungsi display_numbers() akan menampilkan bilangan integer mulai dari nilai yang dilewatkan dalam parameter start sampai stop. Dan parameter ke tiga adalah sebu ah callback function yang akan dipanggil untuk memberikan sebuah keputusan apaka h sebuah bilangan dicetak atau tidak. Pada contoh ini bilangan nol dan kelipatan tiga saja yang dicetak sesuai dengan fungsi callback (filter()) : return (num % 3 == 0); Fungsi display_numbers() dipanggil dalam main(): display_numbers(0,20,filter); yang akan mencetak bilangan nol dan semua bilangan kelipatan 3 mulai antara 0 sa mpai dengan 20. Dari program ini dapat dilihat bahwa pembandingan dilakukan dengan callback func tion, sehingga jika kita ingin menampilkan bilangan yang lain kita hanya perlu m emodifikasi fungsi filter() saja. Pointer ke fungsi ini secara umum digunakan untuk mengisolasi antara tugas-tugas atau menyediakan sebuah coupling antara dua buah implementasi sistem yang memud ahkan untuk memodifikasi masing-masing sistem tanpa perlu mengubah bentuk penggu naannya.

7. ARRAY Program sering ditulis untuk memanipulasi kumpulan data dengan tipe yang sama mi salnya dalam perhitungan statistik dan matrik. Dalam bahasa C kumpulan data itu disebut array. Deklarasi array Array dideklarasikan dengan menggunakan [ ] int prices[5]; Dengan deklarasi itu, prices akan menunjuk ke kumpulan data dengan 5 item yang s emuanya bertipe integer (int). Beberapa hal yang perlu diperhatikan tentang array : Nama array adalah pointer yang konstan (tidak dapat di-reassign) yang menyimpan alamat awal dari suatu kumpulan data. Item-item atau elemen-elemen dalam array harus mempunyai tipe data yang sama. Lokasi penyimpanan data di memori adalah kontinyu, jadi item pertama akan diikut i oleh item kedua dan seterusnya. Ukuran array adalah tetap dan tidak bisa diubah setelah deklarasi. Inisialisasi array Deklarasi array dapat diikuti dengan inisialisasi misalnya : int prices[5] = {100,200,300,400,500}; double factors[] = {0.2,0.3,0.4}; unsigned int data[20] = {0}; long data[5] = {1,2}; prices mendeklarasikan array dari 5 tipe data integer dan diikuti dengan inisial isasi. factors adalah deklarasi dengan tidak menentukan jumlah elemen yaitu dengan tand a [ ]. Jumlah elemen dalam inisialisasi array itu yang menentukan ukuran array. data adalah bentuk ringkas dari deklarasi yang disertai dengan inisialisasi. Den

gan bentuk ini semua elemen dalam array akan diisi dengan nol.Bentuk ini adalah cara singkat untuk menginisialisasi semua item menjadi nol dan hanya berlaku unt uk inisialisasi dengan nol saja. data mendeklarasikan array dari 5 long dan dua elemen pertama diinisialisasi den gan nilai 1 dan 2 sedangkan yang lain dengan nol. Mengakses elemen array Masing-masing elemen dalam array dapat diakses dengan menggunakan bilangan posit if mulai dari 0. Contoh : int a[5] = {1,2,3,4,5}; printf(Data ke 1 : %d\n,a[0]); Perhatikan kembali bahwa index array dalam C selalu mulai dari nol, jadi elemen pertama adalah elemen dengan index nol. Dan yang perlu diperhatikan adalah bahwa C tidak akan melakukan bound-checking atau pengujian terhadap index yang ditera pkan apakah termasuk dalam jangkauan array atau tidak sehingga kita harus berhat i-hati dalam mengakses elemen dalam array. Mengakses elemen array dengan index adalah salah satu cara yang bisa dilakukan. Seperti telah disebutkan bahwa nama array adalah pointer ke elemen pertama atau elemen dengan index nol, jadi kita juga mempunyai alternatif untuk mengakses ele men dalam array : int a[5] = {1,2,3,4,5}; int *p; p = a; printf(%d\n,*p ); ++p; printf(%d\n,*p ); Deklarasi itu dapat dijelaskan dengan gambar : p = a;

Selanjutnya ++p;

Jadi dengan pointer kita dapat mengakses elemen dalam array dengan bantuan opera tor ++ atau --. Namun nilai pertambahan dari operator ++ atau adalah sesuai deng an tipe data yang ditunjuk oleh pointer. Dalam hal ini tipe data yang ditunjuk a dalah int jadi besar perpindahan setiap pemanggilan operator ++ adalah sebesar u kuran integer. Operasi ini biasa disebut dengan pointer arithmetic. Yang perlu diperhatikan lagi adalah array tidak dapat di-assign dengan operator = : int a[5]; int b[5];

Deklarasi ini menyebabkan compiler error karena a dan b adalah pointer yang kons tan. Array sebagai paramater fungsi Karena array pada dasarnya adalah pointer, maka array juga dapat digunakan sebag ai parameter fungsi dan dapat juga ditukar dengan bentuk pointer. LISTING 7.1. ArrArgs.C #include<stdio.h> /* prototipe */ void print_array(int[],int); int main(void) { int a[5] = {1,2,3,4,5}; print_array(a,sizeof(a)/sizeof(s[0])); return 0; } void print_array(int data[],int size) { int i; for (i = 0;i < size;i++) printf(Elemen ke %d : %d\n,i,data[i]); } Program ini akan mencetak ke layar semua elemen. Pemanggilan fungsi print_array() disertai dengan sizeof(a)/sizeof(a[0]) ini adalah untuk menjamin fungsi tidak mengakses di luar jangkauan atau kapasita s array yaitu ukuran total yang dibutuhkan array dibagi dengan ukuran satu eleme n. Ini adalah salah satu cara yang portable. Program ini juga dapat dimodifikasi dengan menggunakan pointer. Kita hanya perlu mengubah prototipe dan header dari fungsi print_array() dengan mengganti array dengan pointer : Pada prototipe : void print_array(int*,int); Pada implementasinya : void print_array(int *data,int size) { } Selanjutnya program dapat dijalankan seperti semula. Array Multidimensional C tidak menyediakan array dimensional, namun kita dapat membuat array dari array yang nampak seperti array multidimensi. Contoh :

int a[5][5]; int i,j; for (i = 0; i< 5; i++) for (j = 0;j < 5; j++) { a[i][j] = i * j; } a dideklarasikan sebagai array dari 5 array 5 integer dan pada baris selanjutnya diinisialisasi dengan nilai tertentu dalam sebuah iterasi. Dapat dilihat pengaksesan array dari array juga sangat konsisten dengan array bi asanya yaitu dengan memandang setiap array memiliki index yang dimulai dari nol, jadi jika int a[5] maka a mempunyai elemen sebanyak 5 dan index untuk mengakses elemennya mulai dari 0 sampai dengan 4. 8. STRING C tidak mempunyai tipe data string seperti bahasa Pascal atau Basic, namun C men ggunakan array dengan tipe char sebagai gantinya. C menggunakan karakter khusus untuk menandai akhir dari string yaitu karakter nol (\0). Deklarasi Beberapa bentuk deklarasi dari array tipe char : char char char char data1[6] = {H,e,l,l ,o,\0}; data2[6] = There; data3[] = Learn C; data4[7] = No NULL;

data1 adalah deklarasi string yang mengharuskan kita menambahkan karakter \0 pada akhir array. Kalau kita tidak menyertakan karakter null, maka data1 bukan merupa kan string tetapi array tipe char. data2 adalah deklarasi string dengan maksimum jumlah karakter adalah 5 sedangkan karakter ke 6 secara otomatis diisi dengan karakter null (\0) oleh compiler. data3 adalah deklarasi string dengan tidak menentukan panjangnya. Dalam hal ini compiler juga akan menambahkan karakter null. data4 bukan string karena ukuran array adalah 7 dan semua terisi dengan karakter non null, sehingga akan menjadi array tipe char. Mencetak String Fungsi-fungsi standar seperti printf() dapat digunakan untuk mencetak string ke layar dengan menggunakan format %s. char str[6] = Hello; printf(%s,str); Kita juga dapat mencetak string dengan mengakses setiap karakter dan mencetak sa tu persatu ke layar dengan spesifikasi format %c : int i; char str[6] = Hello; while(str[i] != \0) { printf(%c,str[i++]); } String Assignment

String tidak dapat di-assignment atau dikopi dengan operator = karena nama strin g adalah seperti array yang merupakan pointer konstan. C menyediakan fungsi standar untuk memudahkan meng-kopi dari satu string ke string yang lain. char * strcpy(char * dest,const char * src); Fungsi ini dapat meng-kopi string dari parameter yang dinamai src ke parameter y ang dinamai dest. strcpy() melakukan pengkopian string tanpa memeriksa ukuran array dest, jadi kem ungkinan akan overflow jika ukuran dest kurang mencukupi. char buffer[10]; strcpy(buffer,Hello);/* OK */ strcpy(buffer,Hello there, how are you ?);/* overflow not OK */ char * strncpy(char * dest,const char * src,size_t count); Fungsi ini lebih aman dari strcpy() karena juga memperhitungkan jumlah maksimal karakter yang dikopi. Fungsi ini akan terus melakukan pengkopian karakter sampai ditemukan karakter null atau sebanyak maksimum karakter yang ditentukan. Jika s trncpy() lebih dulu mencapai jumlah maksimum, maka karakter null tidak akan dise rtakan. Untuk itu kita harus menambahkannya secara manual. char buffer[10]; strncpy(buffer,Hello,9);/* OK */ strncpy(buffer,Hello there, how are you ?,9);/* maksimal 10 karakter*/ buffer[9] = \0; /* karakter ke 9 diganti dengan null \0 */ Manipulasi string Kita dapat melakukan banyak hal dengan string jang suatu string, mencari karakter tertentu, a mencari substring. Fungsi-fungsi ini dideklarasikan dalam header size_t strlen(const char* str); Fungsi ini digunakan untuk menentukan panjang ter null. Contoh : strlen(Hello);/* menghasilkan 5 */ char * strrev(char * str); Fungsi ini berguna untuk membalik semua urutan karakter dalam string str kecuali karakter null. Contoh : char buffer[20] = Hello; strrev(buffer); /* buffer menjadi = olleH */ char *strcat(char * dest, const char * src); Fungsi ini digunakan untuk menambahkan string ke dalam buffer string yang lain. Contoh : char buffer[80 = Hello ; strcat(buffer, C!); /* menghasilkan Hello C! */ char * strchr(const char* str,int c); Fungsi ini digunakan untuk mencari sebuah karakter pertama dalam string yang sam a dengan karakter dalam parameter c dan memberikan nilai balik berupa pointer ke karakter yang ditemukan. Contoh : misalnya kita dapat mengetahui pan membandingkan dua buah string,sert file string.h sebuah string tanpa termasuk karak

char buffer[80] = C Programming Language; printf(%s,strchr(buffer,L)); /* menampilkan Language */ Untuk mencari karakter terakhir, dapat menggunakan strrchr(). int strcmp(const char* str1,const char* str2); Dalam C kita tidak dapat membandingkan dua buah string dengan menggunakan operat or == karena dengan cara itu yang kita bandingkan sebenarnya adalah lokasi memor i atau alamat dari variabel itu. C standard memiliki fungsi untuk membandingkan dua buah string str1 dan str2 den gan memperhitungkan huruf kecil atau besar (case sensitive) sesuai dengan urutan nya dalam abjad yang akan menghasilkan nilai balik: Negatif jika str1 < str2 menurut abjad. Nol jika str1 = str2. Positif jika str1 > str2 menurut abjad. Contoh : strcmp(Crash,Course); /* Hasilnya positif */ Untuk membandingkan dua buah string tanpa memandang case atau case insensitive, dapat menggunakan fungsi stricmp() dengan paramater yang sama. char *strstr(const char * str,const char * sub); Fungsi ini berguna untuk mencari substring dalam sebuah string dan jika berhasil memberikan pointer ke awal substring dan null jika gagal. Pembandingan yang dilakukan adalah case sensitive. Contoh : char buffer[80] = This is my first time to learn C; char * psub; psub = strstr(buffer,time); if (psub != NULL) { printf(Substring : %s\n,p); } akan mencetak hasil : time to learn C size_t strspn(const char * str,const char * cset); Fungsi ini berguna untuk menentukan lokasi atau index karakter pertama dalam str yang tidak terdapat dalam cset. Contoh : char cset = 1234567890; char str[20] = 123456h56; size_t pos; pos = strspn(str,cset); printf(Not match at : %c,pos); akan mencetak nilai 6 yaitu posisi karakter h. char *strtok(char * str,const char * delim); Fungsi ini berguna untuk mengekstrak substring-substring dalam string yang dipis ahkan oleh karakter-karakter dalam parameter delim. Fungsi ini dapat digunakan sebagai tokenizer dalam pembuatan compiler. Penggunaan fungsi ini adalah dengan melewatkan pointer ke suatu buffer yang meng andung string str dan parameter delim yang sudah diinisialisasi dengan karakterkarakter pemisah antara substring. Pada pemanggilan berikutnya, lewatkan NULL ke

parameter str, maka akan diperoleh substring-substring berikutnya sampai member ikan nilai balik NULL. Contoh : char delim = \t\n; /* pemisah : spasi, tab atau karakter 13 */ char buffer[80] = This is my first time to learn C; char * token; token = strtok(buffer,delim); while(token != NULL) { printf(%s\n,token); token = strtok(NULL,delim); } Akan menghasilkan : This is my first time to learn C Untuk fungsi-fungsi manipulasi string yang lain dapat dilihat pada referensi sta ndar C atau anda juga dapat menggunakan yang diserta oleh pembuat compiler (comp iler vendor) yang biasanya jumlahnya sangat banyak serta dengan dokumentasi yang jelas. 9. STRUKTUR Pada bab sebelumnya kita telah membahas bagaimana array dapat menyimpan kumpulan data dengan tipe yang sama. C juga memiliki bentuk khusus yang memungkinkan kit a mengelompokkan beberapa data dengan berbagai tipe data ke dalam satu unit data yang disebut struktur (struct). Bentuk struct ini biasa juga disebut user-defin ed type karena terserah pada pemrogram untuk menentukan jenis data apa saja yang ingin disimpan dalam sebuah struct. C bahkan mengijinkan untuk membuat struktur dalam struktur. Deklarasi struct tagStruct { tipe member; }; Misalnya : struct People { int nAge; char name[20]; }; yang mendeklarasikan tipe data People dengan isi atau member berupa data int dan array char.

Penggunaan struktur Deklarasi struktur atau struct itu biasanya disebut template atau blue print yang berguna bagi compiler untuk membuat bentuk nyatanya yang disebut instance yang s ecara harfiah diartikan sebagai contoh. Berawal dari kata instance itu selanjutnya dalam literatur-literatur komputer banyak menggunakan bentuk kata kerja dari in stance yang menjelaskan proses membuat instance dari template yaitu instantiate. Dalam bab ini kita akan menggunakan apa adanya karena kami belum menemukan kata yang sepadan adalam bahasa kita tanpa menimbulkan kebingungan. Sebelum dapat digunakan, struktur harus di-instantiate misalnya dengan mendeklar asikan variabel seperti biasanya dengan menambahkan kata struct di depan variabe l yang bersangkutan misalnya : struct People worker; struct People student = {20,Devi}; Notasi dot (.) dapat digunakan untuk mengakses member dalam struktur : worker.nAge = 30; strcpy(worker.name,David); Struktur dalam struktur Struktur juga dapat nested yaitu struktur yang lain terdapat dalam suatu struktu r, misalnya contoh sebelumnya kita kembangkan dengan menambahkan alamat sebagai sebuah struktur dalam struktur People : struct Location { char phone[16]; char city[20]; }; struct People { int nAge; char name[20]; struct Location address; }; Untuk mengakses member-membernya dapat dilakukan dengan cara yang sama seperti s ebelumnya dengan notasi dot misalnya : People worker; strcpy(worker.address.city,Malang); Mengakses struktur dengan pointer Seperti tipe data lainnya, struktur juga bisa dimanipulasi dengan menggunakan po inter misalnya : People worker; People * pw = &worker; (*pw).nAge = 20; Perhatikan bentuk (*pw).nAge, bentuk ini digunakan untuk mengakses member nAge d engan menggunakan pointer. C menyediakan cara yang lebih ringkas yaitu: pw->nAge = 20; Bentuk ini selain ringkas juga sangat desktriptif karena berbentuk tanda panah y

ang dapat segera dipahami sebagai menunjuk ke suatu tempat. Assignment antara struktur Kita telah membahas bagaimana isi array tidak dapat ditransfer atau diassign den gan operator =. Berbeda dengan array, struktur dapat menggunakan operator = untu k assignment.Jika struktur tersebut mengandung array maka isi array itu juga aka n dikopi misalnya. People worker1,worker2; worker1 = worker2; /* isi worker 1 menjadi sama dengan worker2 */ Melewatkan parameter non-primitive data Seperti telah disebutkan bahwa pointer adalah tipe data yang menyimpan alamat va riabel yang lain dan ukuran pointer adalah sama. Dengan mengetahui hal itu, kita dapat menggunakan pointer untuk menyimpan alamat data selain data primitive (int, float, double, dan sebagainya) atau melewatkan ke dalam sebuah fungsi. Misalnya : LISTING 9.1. Struct.C #include <stdio.h> typedef struct _mydata { int data1; double data2; }; /* prototipe */ void print_data(const _mydata*); int main(void) { _mydata data = {12,10.5}; print_data(&data); return 0; } void print_data(const _mydata *data) { printf(Integer data : %d, Double data : %lf\n,data->data1,data->data2); } Variabel data yang bertipe _mydata dideklarasikan disertai inisialisasi. Kemudia n dilewatkan ke fungsi print_data() dengan pointer yang selanjutnya akan menceta knya ke layar. 10. OPERASI FILE C mewarisi banyak model UNIX dalam menangani file, tentu saja karena UNIX dan C dapat dikatakan tumbuh bersama. Dalam UNIX semua operasi Input Output (I/O) sela lu dilakukan pada file, dan file dipandang sebagai kumpulan bytes. Dalam C, sebelum bekerja dengan file harus diasosiasikan dengan stream. Stream a

dalah struktur data yang berfungsi sebagai buffer atau penampung sementara yang berada antara program dan file. Ini berguna untuk mengatasi masalah pengaksesan file yang berada di perangkat penyimpanan yang lebih lambat dari memori misalnya disk. Stream Dalam C ada struktur yang bernama FILE yang berguna untuk menyimpan informasi te ntang stream bagi file yang sedang diakses. Programmer tidak perlu mengetahui is i dari FILE ini untuk melakukan operasi file, kita cukup menganggapnya sebagai b lack box saja dan melewatkannya ke fungsi-fungsi yang menangani file IO. Setiap program C menyediakan stream yang telah didefinisikan yaitu stdaux, stder r, stdin, stdout dan stdprn. stdout berhubungan dengan penampilan ke layar, stdi n berkenaan dengan masukan keyboard, stdaux berkenaan dengan perangkat misalnya Com1 port, stderr juga berkenaan dengan perangkat display untuk menampilkan pesa n kesalahan. Dan stdprn adalah koneksi dengan pencetak atau printer. File teks (text file) File text disimpan dengan berpedoman pada karakter ASCII yang menyimpan data ber dasarkan karakter yang masing-masing berukuran satu byte dan diakhiri dengan kar akter khusus yang disebut dengan end of file (EOF). File text dengan mudah dapat dimodifikasi dan dibaca. File dibuka dengan menggunakan fungsi FILE * fopen(const char * name,consth char * mode); Contoh : LISTING 10.1. TextFile.C #include<stdio.h> int main(void) { FILE* in = fopen("c:\\autoexec.bat","r"); FILE* out= fopen("c:\\autoexec.old","w"); int ch; while((ch = fgetc(in)) != EOF) { fputc(ch,stdout); fputc(ch,out); } fclose(out); fclose(in); return 0; } Program ini akan membuka file autoexec.bat dengan asumsi berada pada direktori c :\. Setelah program dibuka dan diasosiasikan dengan stream yang diwakili dengan variabel in dengan pointer ke tipe FILE. Disamping itu juga dibuka sebuah file u ntuk ditulisi untuk menduplikat file autoexec.bat menjadi file autoexec.old. Sem ua proses pembacaan dan penulisan dilakukan dalam sebuah iterasi dengan mengguna kan while yang mengecek karakter yang dibaca dengan fungsi fgetc() tidak sama de ngan karakter end of file (EOF) yang akan menyebabkan loop berhenti. Setiap karakter yang dibaca akan ditampilkan ke layar dan sekaligus ditulis ke f ile autoexec.old dengan fungsi fputc() dengan parameter kedua masing-masing stdo ut untuk ke layar dan out untuk ke file. Sebelum program keluar, semua file ditutup dengan fungsi fclose(). Fungsi fgetc() akan membaca setiap karakter dari stream dan pindah ke posisi kar

akter berikutnya dalam stream. fopen() memerlukan string sebagai parameter dengan nama mode yang ditentukan ses uai dengan tabel. Mode r w a r+ w+ Deskripsi

a+ Membuka file untuk dibaca saja dan file harus sudah ada. Membuka file baru, jika file sudah ada maka akan direset. Menambahkan data pada akhir file yang sudah ada. Membuka file untuk dibaca dan ditulisi dan file harus sudah ada. Membuka file baru untuk dibaca dan ditulisi, jika file sudah ada maka akan dires et (dikosongkan). Membuka file yang sudah ada untuk dibaca dan ditulis. Disamping mode diatas, ada juga mode opsional yaitu t dan b yang dapat ditambahkan p ada mode dalam tabel yang berarti text dan binary. Kalau kita tidak menyertakan b dala m fopen(), maka akan dianggap sebagai t karena itu adalah nilai defaultnya. Penanganan kesalahan (error handling) File yang dibuka dengan fungsi fopen() dapat menyebabkan kesalahan (error) yang dapat diperiksa dengan mengecek hasil keluarannya. LISTING 10.2. FOpen.C #include <stdio.h> int main(void) { FILE * in = fopen(test.txt,r+); if (in == NULL) { fprintf(stderr,fopen failed !\n); perror(Error : ); return 1; } fclose(in); return 0; } Fungsi perror() berfungsi untuk menampilkan pesan kesalahan operasi file dengan menambahkan string pada awal pesan pada parameternya. Yang perlu diperhatikan dalam penulisan nama file terutama yang mengandung direk tori misalnya : C:\mydata\test.txt jika kita melewatkannya dalam parameter fopen() : in = fopen(C:\mydata\test.txt,r);

maka kita akan mendapatkan bahwa in bernilai NULL yang berarti terjadi kesalahan pada fopen(), padahal kita sudah yakin bahwa file : C:\mydata\test.txt sudah ad a sebelum pemanggilan. Kesalahan ini sering terjadi karena kita lupa bahwa C mempunyai escape sequence yang diawali dengan karakter \, jadi jika compiler menemukan karakter \, maka sebuah karakter yang mengikutinya akan dianggap sebagai satu unit seperti \n, \t, sehingga penulisan C:\mydata\test.txt akan membingungkan karena C memiliki karakter khus us untuk menampilkan karakter \ yaitu dengan \\, sehingga penulisan yang benar adala h : in = fopen(C:\\mydata\\test.txt,r);

File biner (binary file) Berbeda dengan file text yang menyimpan data dalam bentuk karakter ASCII, file b iner tidak melakukan translasi karakter, jadi misalnya bilangan 12.3 tidak akan disimpan dalam empat karakter (1,2,. dan 3), tetapi dalam bytes yang mewakili bilanga tu sehingga menjadi efisien dan menghemat tempat. File biner juga memungkinkan kita melakukan pengaksesan secara acak dalam file d engan lebih mudah. Untuk bekeja dengan file biner, kita dapat menggunakan fungsi sebelumnya untuk m embuka file dengan menambahkan karakter b pada parameter mode. LISTING 10.3. WBinFile.C #include<stdio.h> int main(void) { double pi = 3.14; FILE * out = fopen(test.bin,wb); if (out == NULL) { perror(Error : ); return 1; } fwrite(&pi,sizeof(double),1,out); fclose(out); return 0; } Jika fopen() gagal, maka program sebaiknya keluar dan menampilkan pesan kesalaha n yang terjadi dengan fungsi perror(). Jika fopen() berhasil fwrite() digunakan untuk menuliskan sebuah data dengan tip e double dengan fungsi fwrite() yang mempunya prototipe seperti : size_t fwrite(void * p,size_t size,size_t n,FILE * stream); p adalah pointer ke data yang ingin ditulis ke file. size adalah ukuran dari data itu. n adalah jumlah dari data yang ingin ditulis. stream adalah stream untuk file yang bersangkutan. Untuk membaca data dari sebuah file biner, kita dapat melakukannya dengan fungsi fread() Contoh : LISTING 10.4. RBinFile.C #include<stdio.h>

int main(void) { double dd = 0; FILE * in = fopen(test.bin,rb); if (out == NULL) { perror(Error : ); return 1; } fread(&pi,sizeof(double),1,in); fclose(in); return 0; } Parameter-parameter dari fungsi fread() sama dengan fwrite(). Pencarian dalam file biner (binary file) Kita dapat melakukan pencarian data tertentu dalam sebuah file biner dengan memi ndahkan file pointer ke lokasi tertentu dalam file dan kemudian membacanya. Fung si-fungsi yang dapat digunakan antara lain fseek(), ftell(), frewind(), fsetpos dan fgetpos(). Untuk mengilustrasikan penggunaan fungsi-fungsi ini kita akan membuat sebuah pro gram sederhana untuk menyimpan nama-nama orang dengan alamat-masing-masing. Pada saat program dijalankan akan menampilkan tiga pilihan yaitu : 1. Memasukkan data 2. Mencari data berdasarkan identitas 3. Keluar program LISTING 10.5. SBinFile.C #include<stdio.h> typedef struct _data_orang { unsigned int id; char nama[20]; char alamat[20]; unsigned int umur; }; /* prototipe */ int tampilkan_pilihan(); void tampilkan_data(const _data_orang * data); int cari_data(FILE * stream,int id); void masukan_data(FILE * stream); int main(void) { int pilihan,id; FILE* stream = fopen("friend.dat","a+b"); if (stream == NULL) { perror("Error : "); return 1; } while ((pilihan = tampilkan_pilihan()) != 3) { switch(pilihan)

{ case 1 : masukan_data(stream); break; case 2 : printf("Masukkan ID : "); scanf("%i",&id); fflush(stdin); if (!cari_data(stream,id)) { printf("Data tidak ditemukan \n"); } break; } } fclose(stream); return 0; } int tampilkan_pilihan() { int pilihan; printf("\nMenu\n"); printf("1. Memasukan Data\n"); printf("2. Mencari Data\n"); printf("3. Keluar\n"); printf("Pilih[1-3] : "); scanf("%i",&pilihan); printf("\n"); fflush(stdin); return pilihan; } void tampilkan_data(const _data_orang * data) { printf("\nData sudah ada... \n"); printf("ID\t: %d\n",data->id); printf("Nama\t: %s\n",data->nama); printf("Alamat\t: %s\n",data->alamat); printf("Umur\t: %i\n",data->umur); } void masukan_data(FILE * stream) { _data_orang data; printf("ID : "); scanf("%i",&data.id); fflush(stdin); if (!cari_data(stream,data.id)) { printf("Nama : "); gets(data.nama); fflush(stdin); printf("Alamat : "); gets(data.alamat); fflush(stdin); printf("Umur : "); scanf("%i",&data.umur);

fflush(stdin); fwrite(&data,sizeof(_data_orang),1,stream); } } int cari_data(FILE * stream,int id) { int i,size,found = 0; _data_orang data; fseek(stream,0,SEEK_END); size = ftell(stream); rewind(stream); for (i = 0;i < size/sizeof(_data_orang);i++) { fread(&data,sizeof(_data_orang),1,stream); found = data.id == id; if (found) break; } if (found) tampilkan_data(&data); fseek(stream,0,SEEK_END); return found; } Program ini sangat sederhana yang terdiri dari empat fungsi pembantu int tampilkan_pilihan(); Fungsi ini berfungsi untuk menampilkan pilihan atau menu tentang proses yang aka n dijalankan. void tampilkan_data(const _data_orang * data); Fungsi ini berfungsi untuk mencetak data struktur dengan tipe _data_orang ke lay ar. int cari_data(FILE * stream,int id); Fungsi ini berfungsi untuk mencari suatu data dengan id tertentu dan akan menhas ilkan nilai balik bukan nol jika salah salah satu data ditemukan dan nol jika ti dak. void masukan_data(FILE * stream); Fungsi ini akan meminta kita memasukkan data-data id, nama,alamat dan umur yang jika belum ada maka akan ditambahkan ke dalam file. Pada program utama (main()), sebuah stream dibuka dengan fopen() dengan mode a+b y ang berarti mode untuk menambah file jika file itu sudah ada dan membuat file ba ru jika belum ada serta jenis file yang dibuat adalah jenis biner. Nampak dalam setiap selesai pemanggilan fungsi untuk menerima masukkan seperti s canf() atau gets() diikuti dengan fflush(). Hal ini perlu dilakukan untuk berjag a-jaga kalau kita salah memasukkan bentuk data tertentu misalnya kesalahan memas ukkan bilangan. Karena semua yang diketikkan akan diletakkan dalam buffer yang a kan dibaca oleh pemanggilan berikutnya. Tentuk saja hal ini tidak diinginkan, un tuk itu perlu dipanggil fflush() untuk segera me-reset stream yang bersangkutan yang dalam hal ini adalah stdin. Cobalah untuk menjalankan program ini, dan coba kembangkan baik dalam penanganan kesalahan atau dalam tampilannya. 11. MEMORI DINAMIS Pada bagian-bagian sebelumnya kita selalu mengandaikan bahwa jumlah variabel yan g kita butuhkan dalam program selalu kita ketahui jumlahnya dengan pasti. Pada k enyataannya kita jarang sekali dapat menyelesaikan suatu permasalahan dengan asu msi itu. Misalnya kita tidak akan membatalkan program reservasi tiket kita hanya

karena program kita dapat melayani jumlah tertentu. C menyediakan fasilitas unt uk menentukan jumlah alokasi data atau memori yang dinamis yaitu yang dapat kita tentukan pada saat program sedang berjalan (run time). Dengan kemampuan ini, pr ogram kita akan menjadi fleksibel untuk mengantisipasi kebutuhan data dan juga p rogram tidak harus mengalokasikan jumlah memori yang statis sebelum program dija lankan yang akan menjadi kurang efisien kalau pada saat berjalan hanya beberapa bagian data saja yang benar-benar digunakan. Pointer dan Memori Dinamis Telah kita ketahui bahwa pointer menyimpan alamat dari suatu lokasi data yang la in. Dengan menggunakan pointer ini kita dapat menyimpan alamat awal dari blok me mori yang kita buat dengan pemanggilan fungsi untuk pengalokasian memori dinamis standar yaitu malloc(), calloc(), realloc() dan free() yang dideklarasikan dala m header file malloc.h. void * malloc(size_t n); Fungsi ini berfungsi untuk mengalokasikan blok memori sebanyak n bytes. Memori y ang dialokasikan dengan malloc() tidak diinisialisasi, jadi akan berisi nilai-ni lai acak. Contoh : double * pd = malloc(10*sizeof(double)); Jika malloc() berhasil (dengan memeriksa nilai keluarannya dengan NULL) maka pd akan menunjuk ke awal lokasi memori yang dapat menyimpan 10 tipe data double. Untuk menggunakan pd kita dapat menggunakan pointer arithmetic atau dengan bentu k seperti mengakses elemen array. Contoh : LISTING 11.1. Malloc.C #include<stdio.h> #include<malloc.h> int main(void) { double * p; unsigned int i,n; printf(Jumlah array : ); scanf(%u,&n); /* Pengecekan NULL */ if ((p = malloc(n*sizeof(double))) == NULL) { fprintf(stderr,Error alokasi memori dengan malloc!\n); return 1; } /* akses lokasi memori seperti array */ for (i = 0;i < n;i++) { p[i] = i*i; } /* cetak isi memori */ for (i = 0;i < n;i++) {

printf(Data %u : %lf\n,p[i]); } /* Memori harus dibebaskan */ free(p); return 0; } void * calloc(size_t nelem, size_t elemsize); Pada dasarnya calloc() sama dengan malloc() hanya berbeda sedikit dalam bentuk p emanggilan dan dengan calloc() akan menginisialisasi blok memori dengan nol untu k tipe numerik dan karakter null jika tipe data string. Contoh pada malloc() dapat diganti dengan menggunakan calloc() hanya dengan meng ganti perintah p = malloc(n* sizeof(double)) dengan p = calloc(n,sizeof(double)) akan mendapatkan hasil yang sama. void * realloc(void * ptr, size_t n); Fungsi ini berfungsi untuk mengalokasikan kembali memori yang sudah dialokasikan sehingga ukurannya berubah. Misalnya sebuah array dinamis (memori dinamis) yang mengandung 10 double dan sua tu saat kita ingin mengubahnya menjadi 20 dengan tetap mempertahankan 10 double yang sudah ada dalam memori.

LISTING 11.2. Realloc.C #include<stdio.h> #include<malloc.h> int main(void) { double * p,*p_new; unsigned int i; p = calloc(10,sizeof(double)); if (p == NULL) { fprintf(stderr,Error calloc !\n); return 1; } /* re-alokasi */ p_new = realloc(p,20*sizeof(double)); if (p_new != NULL) p = p_new; else { fprintf(stderr,Error re-alokasi !\n); free(p);// p masih valid } free(p);

return 0; } Perhatikan baris : p_new = realloc(p,20*sizeof(double)); if (p_new != NULL) p = p_new; else { fprintf(stderr,Error re-alokasi !\n); free(p); } Bentuk ini bisa juga diganti : p = realloc(p,20*sizeof(double)); Bentuk pertama lebih aman karena jika realloc() gagal mengalokasikan memori baru yang mencukupi maka akan memberikan nilai balik NULL yang akan di-assign ke p_n ew, namun p tetap tidak berubah, atau blok memori sebelumnya yang alamatnya disi mpan dalam p tetap ada. Jika realloc() berhasil kita dengan aman dapat meng-assi gn p dengan p_new. Hal ini akan berbeda dengan bentuk kedua dimana jika gagal maka NULL akan disimp an langsung dalam p sehingga data sebelumnya akan hilang. void free(void * ptr); Fungsi ini berfungsi untuk mendealokasikan kembali memori yang sudah dialokasika n dengan malloc() atau calloc(). Penggunaannya dapat dilihat pada contoh-contoh malloc() dan calloc(). Lebih lanjut tentang realloc() Beberapa hal menarik dari realloc() adalah dapat menggantikan tugas-tugas yang d ilakukan oleh fungsi malloc() dan free() p = malloc(n*sizeof(double)); dapat dilakukan juga dengan p = realloc(NULL,n*sizeof(double)); Dan bentuk free(p); dapat diganti dengan realloc(p,0); Fungsi realloc() jika dipanggil dengan NULL sebagai parameter pertamanya akan me ngalokasikan memori baru sehingga dapat berfungsi seperti malloc(). Sedangkan jika parameter pertama dilewatkan variabel pointer ke suatu blok memor i yang sudah dialokasikan sebelumnya dan parameter kedua dibuat nol, maka memori akan didealokasikan sehingga berperan seperti free(). Struktur data dinamis Pengalokasian memori dinamis dapat digunakan untuk membuat struktur data yang di namis seperti linked list yang dapat menyimpan data dengan masing-masing elemen berupa struktur yang mempunyai member dengan tipe pointer yang merujuk ke strukt ur yang lain seperti gambar.

Dengan struktur data dinamis ini kita dapat mengalokasikan data secara bertahap tanpa mengalokasikan memori dalam jumlah besar dan tanpa memindahkan data. Conto h berikut menggambarkan singly linked list yaitu setiap elemen dalam list hanya menyimpan pointer ke elemen berikutnya saja. Jika anda memahami singly linked li st, kami yakin anda dapat dengan mudah mengembangkannya menjadi doubly linked li st. LISTING 11.3. SLList.C #include<stdio.h> #include<malloc.h> typedef struct _node { double data; _node* next; }node; /* prototipe */ node* new_item(double data); void insert_item(node** p,double data); void print_list(node* p); void free_list(node** head); int main(void) { node* head = NULL; double data; while (1) { printf("Masukkan data double : "); if ((scanf("%lf",&data) > 0)) { fflush(stdin); insert_item(&head,data); } else break; } printf("\nPrinting list...\n"); print_list(head); printf("\nFreeing items...\n"); free_list(&head); return 0; } node* new_item(double data) { node* tmp = (node*)malloc(sizeof(node)); tmp->data = data; tmp->next = NULL;

return tmp; } void insert_item(node** p,double data) { node* tmp = NULL; if (p == NULL) *p = new_item(data); else { if (data <= (*p)->data) { tmp = *p; *p = new_item(data); (*p)->next = tmp; } else insert_item(&(*p)->next,data); } } void print_list(node* p) { if (p == NULL) return; printf("Data : %lf\n",p->data); if (p->next != NULL) print_list(p->next); } void free_list(node** head) { static int i = 0; node* next = (*head)->next; // hanya satu item if (next == NULL && *head != NULL) { printf("Item %i\n",++i); free(*head); } while(next != NULL) { printf("Item %i\n",++i); next = (*head)->next; free(*head); *head = next; } } Fungsi new_item() berfungsi untuk membuat sebuah tipe data node dengan fungsi ma lloc() dan sekaligus mengisi member data dengan nilai pada parameter dan next de ngan NULL. Fungsi insert_item() memiliki parameter dengan pointer ke pointer tipe node (nod e**) yaitu p. Ini berguna untuk memodifikasi isi pointer dari dalam fungsi. Fung si ini juga akan mengurutkan data yang dimasukkan dengan membandingkan dengan da ta yang dimiliki oleh parameter p. Jika lebih kecil atau sama maka item (tipe no de) baru akan disisipkan sebelum data yang dirujuk oleh p. Jika lebih kecil maka akan dilakukan pemanggilan rekursif untuk menambahkan data baru pada bagian akh ir list. Algoritma itu dapat dipahami dari baris program : if (p == NULL)

*p = new_item(data); Baris ini pula sebagai kriteria berhenti (termination condition) dari fungsi yan g rekursif ini. Fungsi print_list() berfungsi untuk mencetak semua data dalam linked list juga d engan teknik rekursif. Pertama-tama fungsi ini akan mengecek pointer yang dilewa tkan. Jika NULL maka fungsi akan keluar. Jika tidak maka data akan dicetak denga n printf(). Selanjutnya member next akan diperiksa, jika tidak NULL pemanggilan rekursif akan dilakukan. Fungsi free_list() berguna untuk mendealokasikan semua memori yang digunakan ole h masing-masing item (node). Pointer untuk node yang pertama (head) dilewatkan d engan double indirection pointer (node**), agar kita dapat memodifikasi isi poin ter diluar fungsi (head). Pointer next dari head akan disimpan sementara dalam v ariabel lokal next : node* next = (*head)->next; Selanjutnya loop while akan memeriksa apakah next bernilai NULL, jika tidak maka pendealokasian memori akan dilakukan mulai dari ujung depan (head) dengan : while(next != NULL) { printf("Item %i\n",++i); next = (*head)->next; free(*head); *head = next; } Setelah pendealokasian (dengan pemanggilan free()), pointer head akan diperbahar ui dengan nilai yang yang telah disimpan sebelumnya. Sebagai tambahan untuk memeriksa data yang dialokasikan sama dengan yang didealo kasikan, kita tambahkan pemanggilan fungsi printf() untuk mencetak informasi pen dealokasian masing-masing item atau node. Perhatikan bentuk : next = (*head)->next; tanda () diperlukan karena kalau tidak maka compiler akan menginformasikan kesal ahan karena (*head) dan (*head)->next sama-sama menghasilkan tipe node* sedangk an tanpa () akan menjadi *head->next yang tidak menghasilkan tipe node*. Pada saat program dijalankan anda terus akan diminta memasukkan data tipe double sampai anda mengetikkan sesuatu yang tidak mewakili bilangan. Selanjutnya semua data dalam list yang sudah diurutkan akan dicetak dan pada akhirnya semua node akan dibersihkan atau didealokasikan. 12. TANGGAL DAN WAKTU Standard C menyediakan fungsi-fungsi untuk memanipulasi tanggal dan waktu. Dalam perhitungan tanggal dan waktu, fungsi dengan nama time() digunakan untuk m engambil waktu dan tanggal sekarang dalam bentuk tipe data yang dideklarasikan s ebagai time_t pada header time.h. Metode yang digunakan oleh fungsi time() ini berbeda-beda sesuai dengan implemen tasi oleh pihak yang memproduksinya (compiler vendor). Misalnya ada yang menggun akan perhitungan jumlah detik yang lewat sejak tengah malam GMT 1 Januari 1970, namun ada juga yang menghitung mulai tengah malam 31 Desember 1899. Walaupun implementasinya berbeda-beda, kita dapat menggunakannya dengan konsiste

n lewat pemanggilan fungsi time(). Fungsi-fungsi untuk penanganan tanggal dan waktu dituliskan dalam tabel : Fungsi Deskripsi asctime clock ctime difftime gmtime localtime mktime time Konversi tanggal dan waktu dari struktur tm ke bentuk string. Memeberikan waktu prosesor yang berlalu dalam jumlah tick. Konversi tanggal dan waktu dari tipe time_t ke bentuk string Menghitung perbedaan antara dua tipe data time_t Konversi waktu dalam time_t ke dalam struktur tm yang sesuai dengan UTC Konversi waktu dan tanggal dalam time_t menjadi struktur tm. Konversi waktu dalam struktur tm menjadi time_t dan melakukan penyesuaian. Memberikan waktu dan tanggal sekarang dalam time_t Contoh : LISTING 12.1. Time.C #include<stdio.h> #include<time.h> int main(void) { time_t sekarang; time(&sekarang); printf(Waktu sekarang : %s\n,ctime(&sekarang)); return 0; } Deklarasi struktur tm adalah sebagai berikut : struct tm { int tm_sec; // detik int tm_min; // menit int tm_hour; // jam int tm_mday; // hari dalam bulan 1-31 int tm_mon; // bulan 0 - 11 int tm_year; // tahun sejak 1900 int tm_wday; // hari sejak minggu 0-6 int tm_yday; // hari sejak januari 1-365 int tm_isdst; }; Sekarang kita akan membuat program yang cukup panjang untuk menampilkan kalender dengan mengetikkan dari command line: cldr januari 2004 dan akan menampilkan kalender dalam format yang umum di indonesia: Januari 2004

S S R K J S M -------------------------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 Program ini menggunakan fungsi-fungsi yang ada dalam header file time.h yaitu mk time() dan struktur tm. LISTING 12.2. Cldr.C #include<stdio.h> #include<stdlib.h> #include<time.h> #include<string.h> /* prototipe */ int get_wday(struct tm* ptm); int main(int argc,char ** argv) { static char * days[] = {"S","S","R", "K","J","S","M"}; static char * months[] = {"Januari","Februari","Maret", "April","Mei","Juni", "Juli","Agustus","September", "Oktober","Nopember","Desember"}; int mon = 2,year = 2003,row = 0; int firsttime = 1,firstwday = 0; int cal[6][7]; tm t; int i,j,day = 0; if (argc < 3) { printf("Penggunaan : cldr bulan tahun\n"); return 1; } for (i = 0;i < 12;i++) { if (strnicmp(argv[1],months[i],strlen(argv[1])) == 0) break; } if (i > 11) { printf("Tidak ada bulan dengan nama %s\n",argv[1]); return 1; } mon = i; year = atoi(argv[2])-1900; memset(cal,0,sizeof(cal));

for (i = 1;i < 32;i++) { memset(&t,0,sizeof(t)); t.tm_mon = mon; t.tm_year= year; t.tm_mday= i; if (get_wday(&t) != -1) { if (firsttime) { firsttime = 0; firstwday = t.tm_wday; /* agar minggu tampil terakhir */ day = (firstwday == 0)?6:firstwday-1; row = 0; } day = (t.tm_wday == 0)?6:t.tm_wday-1; cal[row][day] = i; if (++day > 6) { ++row; } } else break; } /* cetak kalender */ printf("\n\t%s %d\n\n",months[mon],year + 1900); for (i = 0;i < 7;i++) printf("%3s ",days[i]); printf("\n --------------------------"); for (i = 0;i < 6;i++) { printf("\n"); for (j = 0;j < 7;j++) { if (cal[i][j] == 0) printf(" "); else printf("%3d ",cal[i][j]); } } return 0; } int get_wday(struct tm* ptm) { int mon,year,mday; mon = ptm->tm_mon; year = ptm->tm_year; mday = ptm->tm_mday; if (mktime(ptm)== -1) return -1; if ((year == ptm->tm_year) && (mon == ptm->tm_mon) && (mday == ptm->tm_mday) && (ptm->tm_wday <= 6)) return ptm->tm_wday; else

return -1; } Simpanlah program ini dengan nama cldr.c dan compile menjadi cldr.exe. Cobalah untuk memahami program ini dengan memperhatikan baris demi baris dan mer ujuk ke referensi yang lain misalnya dalam dokumentasi compiler yang digunakan t entang fungsi-fungsi untuk manipulasi waktu. 13. UNION, TIPE ENUMERASI DAN PREPROCESSOR Union Selain tipe data struktur dengan kata kunci struct, C juga dapat membuat tipe da ta yang mana masing-masing membernya dapat menempati lokasi memori yang sama yan g disebut dengan union. Contoh : typedef union bilangan { char c; short s; int i; double d; }; bilangan b; b.c = a; b.s = 1200; b.i = 50000; b.d = 20.006; Ukuran dari sebuah union adalah sama dengan ukuran tipe data terbesar yang dikan dungnya dalam hal ini adalah sebesar double. Ini tentunya sangat berbeda dengan tipe struct yang kalau mengandung data-data seperti contoh union ini akan merupa kan jumlah dari ukuran masing-masing data membernya. Enumerasi Pada saat tertentu kita ingin menginginkan konstanta yang mewakili suatu angka t ertentu. Kita dapat menggunakan definisi dengan preprocessor : #define #define #define #define #define #define #define int h = minggu; atau kita dapat menggunakan tipe enumerasi ; enum hari {minggu,senen,selasa,rabu,kamis,jumat,sabtu}; enum hari h = minggu; Dengan enum compiler akan menjamin semua nilai akan berbeda. Jika kita tidak mem minggu senen selasa rabu kamis jumat sabtu 0 1 2 3 4 5 6

berikan nilai tertentu pada masing-masing item maka compiler akan menganggap nil ai mulai dari nol dan item berikutnya akan ditambah satu dan seterusnya. Jika kita memberikan nilai tertentu pada sebuah item maka nilai untuk item-item yang mengikutinya akan terus ditambah satu. Contoh : enum arah {utara = 1,timur,selatan,barat}; nilai timur = 2, selatan = 3 dan barat = 4. Atau kita juga bisa memberi nilai yang berbeda untuk masing-masing item enum arah {utara = 0,timur = 90,selatan = 180,barat = 270}; Preprocessor (front end processor) Seperti pernah disinggung bahwa compiler akan memroses hasil dari preprocessor. Jadi preprocessor akan melakukan tugasnya terlebih dahulu sebelum dilewatkan ke compiler. Dengan mekanisme ini kita dapat melakukan beberapa hal diantaranya : Menyertakan file Mendeklarasikan konstanta Mendefinisikan makro Debugging Menyertakan file Kita sudah sering menggunakan fungsi-fungsi standar yang dideklarasikan dalam he ader file yang kita sertakan pada awal penulisan program misalnya: #include <stdio.h> #include <malloc.h> Dengan deklarasi ini memerintahkan preprocessor untuk memroses isi file-file yan g diawali dengan #include dan berada dalam < >. Preprocessor tahu dimana harus m enemukan file-file ini dengan berpedoman pada apa yang disebut environment varia bles yang dalam MS-DOS didefinisikan dalam autoexec.bat misalnya compiler C tert entu menggunakan nama INCLUDE dan diikuti dengan direktori-direktori dimana prep rocessor akan mencari header-header file ini. Mendeklarasikan Konstanta Konstanta dengan preprocessor dideklarasikan seperti pada penjelasan tipe enumer asi. Deklarasi ini menyebabkan preprocessor akan melakukan substitusi setiap kal i menemukan konstanta dalam listing program. Konstanta dengan preprocessor juga dapat dideklarasikan secara kondisional misal nya : #if !defined(TEST_VALUE) #define TEST_VALUE 0 #endif Kondisional ditulis di antara #if dan #endif. Mendefinisikan makro Makro juga melakukan substitusi dengan parameter. #define MAX(a,b) (a) > (b) ? (a) : (b) MAX akan menentukan nilai yang paling besar antara a dan b dengan menggunakan op erator kondisional seperti yang telah dijelaskan sebelumnya. Tanda () diperlukan untuk setiap parameter dalam operasionalnya. Jika tanpa () d an kita menggunakan MAX untuk menyelesaikan pernyataan berikut :

mx = MAX(12 + 3,10); Preprocessor akan menjabarkan sebagai : mx = 12 + 3 > 10 ? 12 + 3 : 10; Yang tentu saja akan membingunkan compiler. Namun bentuk dengan tanda () dapat memperjelas bentuk menjadi : mx = (12 + 3) > (10) ? (12 + 3) : (10); Debugging Preprocessor juga dapat digunakan untuk membantuk melacak alur program yang sang at berguna untuk menemukan letak kesalahan dalam program. Dengan bantuan konstan ta yang dimengerti oleh preprocessor seperti __LINE__ untuk menentukan baris pro gram dalam integer dan __FILE__ untuk menentukan nama file yang sedang diproses. Contoh : #if defined(_MY_DEBUG) #define TRACE_LINE printf(Baris no : %i File : %s\n,__LINE__,__FILE__); #else #define TRACE_LINE #endif Makro ini selanjutnya digunakan seperti menggunakan fungsi : #define _MY_DEBUG TRACE_LINE yang akan menampilkan nomor baris dan nama file. Kalau kita mendefinisikan _MY_DEBUG, maka TRACE_LINE tidak melakukan apa-apa. Dengan fasilitas ini kita dapat menyisipkan makro-makro kita dalam program untuk mencetak nilai-nilai variabel tertentu untuk melihat kerja program sehingga mem udahkan untuk memperbaiki kesalahan.

APPENDIX ANSI C Escape Sequences and Trigraph Dalam C kita dapat memasukkan karakter yang tidak tercetak (non-printable) denga n menggunakan escape sequence yang diawali dengan karakter \. Tabel berikut adalah escape sequences dalam C Sequence \a \b \f \n \r \t \v \\ \ \ \? Alert Backspace Form Feed Newline Nama Interpretasi

Carriage return Horizontal Tab Vertical Tab Backslash Single Quote Double Quote Question Marks Bunyi seperti bell Pindah satu karakter ke kiri Pindah kursor ke awal baris Pindah ke baris berikutnya Pindah ke awal baris Pindah ke posisi tab horizontal berikutnya Pindah ke posisi tab vertikal berikutnya \ ? C juga mengenalkan konsep yang disebut trigraph yang mengijinkan programmer untu k mengetikkan kombinasi karakter-karakter tertentu pada keyboard untuk mewakili karakter tertentu yang tidak tersedia langsung di keyboarnya. Misalnya keyboard non-english tidak bisa mencetak secara langsung beberapa karakter dalam bahasa i nggeris. Masing-masing trigraph diawali dengan ?? diikuti dengan karakter ketiga. Beberap trigraph dituliskan dalam tabel : Trigraph ??( ??/ ??) ?? ??< ??! ??> ????= [ \ ] ^ { | } ~ # Translasi

ANSI Library Header Files ANSI C library menentukan semua aspek bahasa C secara keseluruhan walaupun telah melalui standarisasi. Fungsi-fungsi dalam library Standard C ditampilkan dalam tabel untuk memudahkan mempelajari berdasarkan header file yang perlu diikutkan dalam program. Header file assert.h ctype.h errno.h float.h limits.h locale.h Kegunaannya

math.h setjmp.h signal.h stdarg.h stddef.h stdio.h stdlib.h string.h time.h Mendeklarsikan makro untuk keperluan diagnostik. Mendeklarasikan fungsi-fungsi untuk konversi karakter. Mendeklarasikan makro untuk kondisi error dan juga variabel errno dimana fungsifungsi dalam library mendeposit kode error. Mendefinisikan jangkauan tipe data floating-point. Mendefinisikan jangkauan tipe data integer Mendeklarasikan struktur lconv dan fungsi-fungsi untuk keperluan customize progr am C dalam regional tertentu. Mendeklarasikan fungsi-fungsi yang berkaitan dengan matematika Mendeklarasikan fungsi setjmp() dan longjmp() yang berguna untuk mentransfer kon trol antara fungsi tanpa tergantung pemanggilan fungsi secara normal. File ini j uga mendeklarasikan tipe jmp_buf. Mendeklarasikan fungsi-fungsi untuk penanganan eksepsi. Mendefinisikan makro untuk keperluan parameter fungsi dengan jumlah yang variabe l. Mendefinisikan tipe-tipe data standar seperti size_t,wchar_t dan juga simbol NUL L dan juga makro offsetof. Mendeklarasikan fungsi-fungsi untuk operasi input output seperti printf() dan sc anf(). Juga mendefinisikan makro SEEK_SET,SEEK_CUR dan SEEK_END. Mendeklarasikan fungsi-fungsi utilitas seperti konversi string, alokasi memori, pembangkit bilangan acak dan beberapa fungsi untuk proses seperti abort, exit da n system. Mendeklarasikan fungsi-fungsi untuk manipulasi string. Mendeklarasikan fungsi-fungsi untuk memanipulasi tanggal dan waktu. Fungsi-fungsi untuk konversi Berikut ini adalah beberapa fungsi yang berguna untuk konversi dari string ke nu merik yang dideklarasikan dalam stdlib.h. Untuk konversi dari numerik ke string dapat menggunakan fungsi sprintf(). double atof(const char* str); Untuk konversi dari string ke tipe double. Fungsi ini akan melakukan konversi sampai ditemukan karakter yang tidak dapat di tanganinya sebagai numerik. Contoh double d; d = atof(2100.45 rupiah); d akan menjadi 2100.45 int atoi(const char * str); int atol(const char * str); Fungsi-fungsi ini menkonversi string menjadi int dan long sampai ditemukan karak ter yang tidak sesuai sebagai bilangan integer.

Contoh : int n = atoi(100 halaman);// n menjadi 100 long l = atol(12000000 orang); // l menjadi 12000000 Fungsi-fungsi untuk konversi karakter dari huruf kecil ke huruf besar dan sebali knya. Dideklarasikan dalam ctype.h. int tolower(int c); c adalah karakter yang ingin dikonversi. Fungsi ini menghasilkan nilai balik ber upa nilai karakter yang sudah dikonversi. Contoh : int c = tolower(A);// c menjadi a int toupper(int c); Melakukan konversi sebaliknya dari tolower(). Fungsi-fungsi untuk menguji apakah sebuah karakter termasuk dalam abjad atau buk an. Dideklarasikan dalam ctype.h. int isalnum(int c); Fungsi ini menguji apakah c termasuk karakter alphanumneric yaitu salah satu di antara 0-9,a-z atau A-Z. int isalpha(int c); Fungsi ini menguji apakah c termasuk karakter huruf yaitu karakter antara a-z da n A-Z. Untuk konversi dari numerik ke string dapat menggunakan fungsi sprintf() yang di deklarasikan dalam stdio.h. int sprintf(char * str, const char * fmt,); Fungsi ini menerima masukan variabel (dengan ) dengan format tertentu sesuai deng an parameter fmt yang sama dengan printf(). Hasil konversi yang berupa string ak an disimpan dalam str. Contoh : char buffer[80]; sprintf(buffer,Bilangan ini adalah %.2f,12.3);

Anda mungkin juga menyukai