Upload
anto-sahabatnoah
View
45
Download
0
Embed Size (px)
Citation preview
Modul Perkuliahan
TIK127 Algoritma dan Pemrograman
TIK129 Praktek Algoritma dan Pemrograman
Program Studi S1 Pendidikan Teknik Informatika & Komputer
Jilid 2
Oleh:
Djuniadi
JURUSAN TEKNIK ELEKTRO
FAKULTAS TEKNIK
UNNES
Halaman 2
DAFTAR ISI
MODUL 1 …………………………………………………………………….. 3
MODUL 2 …………………………………………………………………….. 10
MODUL 3 …………………………………………………………………….. 16
MODUL 4 …………………………………………………………………….. 20
MODUL 5 …………………………………………………………………….. 26
MODUL 6 …………………………………………………………………….. 27
MODUL 7 …………………………………………………………………….. 31
MODUL 8 …………………………………………………………………….. 33
MODUL 9 …………………………………………………………………….. 37
MODUL 10 ..………………………………………………………………….. 40
MODUL 11 ..………………………………………………………………….. 45
MODUL 12 ..………………………………………………………………….. 52
MODUL 13 ..………………………………………………………………….. 56
MODUL 14 ..………………………………………………………………….. 64
MODUL 15 ..………………………………………………………………….. 66
MODUL 16 ..………………………………………………………………….. 74
Halaman 3
MODUL 1
STORAGE CLASS
Storage Class
• Setiap variabel dan fungsi dalam C mempunyai dua atribut : tipe dan storage-
class.
Ada 4 macam storage-class: automatic, eksternal, register dan static. Keyword-
nya masing-masing: auto, extern, register, static.
• Keyword auto dipakai untuk secara eksplisit menyatakan storage-class
automatic.
Contoh:
auto int a, b;
auto float f;
Variabel yang dideklarasikan dalam suatu block adalah automatic, secara
implicit. Jadi keyword auto jarang dipakai.
Makna storage-class auto
Apabila suatu block mulai dimasuki, memori dialokasikan untuk variabel-variabel
automatic. Variabel-variabel ini bersifat local dalam block. Pada waktu block itu
ditinggalkan (keluar dari block), memori yang dialokasikan untuk variabel-
variabel auto itu menjadi bebas lagi. Jadi nilai dari variabel-variabel auto ini
menjadi hilang. Jika block ini dimasuki lagi nanti, system mengalokasikan lagi
memori untuk variabel-variabel auto, tetapi nilai sebelumnya tidak diketahui.
Jadi masa hidup variabel auto adalh sejak block-nya dimasuki sampai saat
blocknya ditinggalkan.
Strorage-class extern
• Salah satu cara untuk menyalurkan informasi lintas block dan lintas fungsi
adalah dengan menggunakan variabel eksternal.
• Variabel yang dideklarasikan di luar fungsi mendapat alokasi memori secara
permanen (selama program aktif). Storage-classnya extern.
Halaman 4
• Variabel extern ini bersifat global, artinya bisa diakses oleh semua fungsi yang
dideklarasikan sesudahnya.
• Baris
int a=1, b=2, c=3;
Bisa ditulis lbih eksplisit:
extern int a=1, b=2, c=3;
Tetapi kata kunci extern dalam hal ini tidak diperlukan.
Kata kunci extern dipakai untuk menyuruh compiler untuk mencari definisi
dari variabel-variabel ybs ditempat lain, baik dalam file ini maupun dalam file
lainnya.
/*contoh variabel-variabel eksternal */
#include <stdio.h>
int a=1, b=2, c=3; /*variabel-variabel global */
int f (void)’ /*prototype fungsi */
main ( )
{
printf ( “%3d\n”,f( ) ); /*cetak 12 */
printf (“%3d%3d%3d\n”, a,b,c); /*cetak 4 2 3 */
return 0;
}
int f (void)
{
int b, c; /* b dan c ini bersifat local */
/* b dan c yang global tertutupi */
a = b = c = 4;
return (a+b+c);
}
Halaman 5
Contoh penggunaan kata kunci extern:
Program tadi bisa ditaruh dalam dua file;
dalam file prog1.c:
#include (stdio.h)
int a=1, b=2, c=3; /*variabel-variabel global */
int f (void) /*prototype fungsi */
main ( )
{
printf (“ %3d\n”, f ( ) );
printf (“ %3d%3d%3d\n”, a,b,c);
return 0;
}
Dan dalam file prog2.c:
int f (void)
{
extern int a; /*cari definisinya ditempat lain */
int b,c;
a= b = c = 4;
return (a+b+c) ;
}
• Bahwa suatu program dapat dipisahkan dalam beberapa file dan dapat di-
compile secara terpisah, sangat penting dalam pembuatan program yang besar.
• Cara kompilasi di UNIX, misalnya:
gcc -c prog1.c (menghasilkan prog1.0)
gcc -c prog2.c (menghasilkan prog2.0)
gcc prog1.0 prog2.0 - 0 prog
Atau
gcc prog1.c prog2.c -0 prog
Halaman 6
• Masa hidup variabel-variabel eksternal adalah selama program aktif. Tetapi
bisa saja tersembunyi (tertutupi) oleh variabel local.
• Semua fungsi mempunyai stroge-class eksternal.
Ini berarti kita bisa (kalau mau) pakai kata kunci extern di depan prototype
fungsi atau di depan definisi fungsi.
Contoh:
extern double sqrt ( double );
extern double sqrt ( double x )
{
}
• Penggunaan variabel eksternal sebagai alat komunikasi antar fungsi harus
dibatasi, karena dapat terjadi efek sampingan yang sulit dikontrol. Komunikasi
antar fungsi sebaiknya dilakukan lewat argument-argumwn fungsi.
Storage-class register
• Memberitahu compiler bahwa variabel ybs seharusnya disimpan dalam register
(storage berkecepatan sangat tinggi) jika keadaan memungkinkan. Jumlah
register yang tersedia sangat terbatas (biasanya hanya beberapa).
• Jika keadaan tidak memungkinkan, storage-class register dianggap menjadi
storage-class automatic.
• Biasanya storage-class register dipakai untuk variabel yang sangat sering
diakses, misalnya variabel pengontrol looping, agar program bisa lebih cepat.
Contoh:
{
register int I;
for (i=0; i<batas; i++) {
}
}
Halaman 7
Storage-class static
Memberikan dua macam pemakaian yang penting:
1. Membuat variabel local mempertahankan nilai sebelumnya, pada waktu
blocknya dimasuki lagi.
Contoh:
Fungsi berikut ini melakukan hal yang berbeda tergantung pada berapa kali ia
telah dipanggil.
void f (void)
{
static int kali = 0;
++kali;
if (kali <= 3)
printf (“ belum lebih dari 3 kali.|n”);
else
printf (“ sudah lebih dari 3 kali.\n”);
}
Waktu program mulai, variabel kali diberi nilai awal 0. Pertama kali fungsi f
dipanggil, kali bernilai 0. Pada pemanggilan berikutnya, kali tidak diinisialisasi
lagi, tetapi mempunyai nilai dari akhir pemanggilan sebelumnya.
Jadi variabel local yang berstorage-class static merupakan kepunyaan pribadi
fungsi ybs (alokasi memorinya permanen).
2. Variabel eksternal yang juga dideklarasikan static dibatasi scopenya, yaitu dari
tempat deklarasinya sampai dengan akhir dari file dimana variabel itu
dideklarasikan.
Pengunaan static sebagai storage-class untuk definisi fungsi dan prototype
fungsi mengakibatkan scope fungsi itu dibatasi pada file dimana fungsi itu
didefinisikan.
Halaman 8
Contoh:
void f (int a)
{
. . . /* g ( ) tersdia di sini, tetapi tidak di file lainnya */
}
static int g (void)
{
. . .
}
Menentukan alamat (address) dari suatu variabel
• Setiap variabel mempunyai suatu alamat yang unik yang menyatakan
lokasinya dalam memori.
• Seringkali sangat berguna untuk mengakses suatu variabel lewat alamatnya ,
tidak lewat namanya.
• Untuk mendapatkan alamat dari suatu variabel, kita pakai operator amperstand,
yaitu &.
Andaikan x adalah suatu variabel yang mendapat alokasi memori mulai dari
lokasi 1234 , maka ekspresi &x akan memberikan alamat dari x yaitu 1234.
• Untuk mencetak alamat dengan fungsi printf , pergunakan conversion-
specifier %p.
/ * Contoh pencarian alamat suatu variabel */
#include <stdio.h>
main ( )
{
int j = 1;
printf (“Nilai (value) dari variabel j = %d\n” , j);
printf (“Alamat (address) dari variabel j = %p\n” , &j);
return 0;
}
Halaman 9
Outputnya :
Nilai (value) dari variabel j = 1 Alamat (address) dari variabel j = f7fffba4
Halaman 10
MODUL 2
POINTER
Pointer (Petunjuk)
• Pointer adalah suatu variabel yang berisi alamat (address) dari suatu variabel.
• Ingat bahwa pada umunya memori suatu mesin komputer terdiri dari unit-unit
(cell-cell) yang berurutan (diberi alamat terurut) yang dapat dimanipulasi
secara individu ( per byte ) atau secara kelompok. Biasanya satu byte untuk
suatu char, dua byte berurutan untuk suatu int, empat byte berurutan untuk
suatu long, dsb.
Suatu pointer biasanya memerlukan dua byte (misalnya di PC) atau empat byte
(misalnya di SUN) untuk dapat menyimpan suatu alamat.
• Sebelum dipakai, pointer perlu diberi alokasi memori melalui suatu deklarasi
seperti variabel lainnya.
Untuk mendeklarasikan suatu variabel pointer, kita taruh tanda * di depan
nama pointer itu.
Contoh :
int *ip ;
mendeklarasikan bahwa variabel ip mempunyai tipe int * ( yaitu , bahwa ip
adalah suatu pointer ke int ). Jadi ip dapat berisi alamat dari suatu variabel
yang bertipe int.
• Perhatikan bahwa
int *ip , ipp ;
mendeklarasikan bahwa ip adalah suatu pointer ke int dan ipp adalah suatu
variabel bertipe int
Tetapi
int *ip, *ipp ;
mendeklarasikan bahwa ip dan ipp masing-masing adalah pointer ke int.
• Operator unary * (sebagai operator indirection atau dereferencing)
apabiladiterapkan pada suatu pointer, memberikan objek (variabel) yang
ditunjuk oleh pointer tersebut.
Halaman 11
/ * Contoh penggunaan operator unary * dan & */
#include <stdio.h>
main ( )
{
int a , *ip , b ;
a = 7 ;
ip = &a ;
printf (“Alamat variabel a = %p\n”
“Nilai (isi) dari pointer ip = %p\n\n”, &a , ip) ;
printf (“ Nilai variabel a = %d\n”
“Nilai dari *ip = %d\n\n”, a , *ip) ;
b = *ip ;
ip = 4 ;
printf (“Sekarang , nilai b = %d\n”
“nilai a = %d\n dan nilai *ip = %d\n, b , a , *ip) ;
return (0) ;
}
Outputnya :
Alamat variabel a = FFF4 Nilai (isi) dari pointer ip = FFF4 Nilai variabel a = 7 Nilai dari *ip = 7 Sekarang, nilai b = 7 nilai a = 4 dan nilai *ip = 4
Halaman 12
Penjelasan program :
• int a , *ip , b ;
menyatakan bahwa a adalah suatu variabel int, ip adalah suatu pointer ke int ,
dan b adalah suatu variabel int. Memori secukupnya dialokasikan untuk ketiga
variabel itu.
• ip = &a ;
Alamat dari variabel a diisikan ke pointer ip. Dikatakan ip menunjuk ke a.
• b = *ip ;
Variabel b diberi nilai dari variabel yang ditujukan oleh ip. Jadi b diberi nilai
dari a, yaitu 7.
• *ip = 4 ;
Variabel yang ditujukan oleh pointer ip diberinilai 4 . Jadi a diberi nilai 4 .
Apakah output dari program ini ?
#include <stdio.h>
main ( )
{
char *p , *q , ch1 , ch2 ;
ch1 = ‘a’ ;
ch2 = ‘b’ ;
p = &ch1 ;
q = &ch2 ;
printf (“%c%c%c%c\n” , ch1 , ch2 , *p , *q) ;
p = q ;
printf (“%c%c%c%c\n” , ch1 , ch2 , *p , *q) ;
q = &ch1 ;
p = *q;
printf (“%c%c%c%c\n” , ch1 , ch2 , *p , *q) ;
return 0 ;
}
Halaman 13
Pointer sebagai Argumen Fungsi
• Telah kita bahas sebelunya bahwa semua pemanggilan fungsi dalam bahas C
bersifat call-by-value. Variabel yang dipakai sebagai argumen aktual suatu
fungsi tidak dapat diubah oleh fungsi tersebut , karena berdasarkan mekanisme
call-by-value hanya salinan nilai variabel itu yang dipakai sebagai nilai awal
bagi argumen fungsi tersebut.
• Seringkali suatu fungsi perlu mengubah satu atau lebih variabel di luar fungsi
tersebut , misalnya fungsi untuk mempertukar nilai dari dua variabel.
• Suatu variabel dapat diubah oleh suatu fungsi apabila alamat dari variabel itu
disalurkan sebagai argumen aktual kepada fungsi tsb.
• Suatu fungsi dapat menerima alamat dari variabel sebagai argumen
aktualnya, apabila argumen formalnya merupakan pointer.
• Call-by-reference merupakan suatu cara untuk menyalurkan alamat (addresss /
reference) dari suatu variabel kepada suatu fungsi sehingga memungkinkan
fungsi tsb mengubah nilai dari variabel itu.
Jadi efek call-by-reference dapat diperoleh dalam bahasa C dengan
mempergunakan pointer dan operator address-of & , walaupun bahasa C
hanya mengenal call-by-value.
• Dua contoh program berikut ini memperlihatkan penggunaan pointer sebagai
argumen fungsi.
/ * Program ini memperlihatkan versi fungsi tukar
yang belum benar * /
#include <stdio.h>
void tukar (int p , int r) ;
main ( )
{
int i = 3 , j = 5 ;
tukar (i, j) ;
printf (“%d %d\n”, i, j) ;
return 0 ;
}
Halaman 14
/ * Bermaksud mempertukarkan nilai dari dua variabel
tetapi tidak berhasil * /
void tukar (int p, int r)
{
int sementara ;
sementara = p ;
p = r ;
r = sementara ;
}
Output :
/ * Program ini memperlihatkan suatu fungsi tukar
yang benar * /
#include <stdio.h>
void tukar (int *p , int *r) ;
main ( )
{
int i = 3 , j = 5 ;
tukar (&i, &j) ;
printf (“%d %d\n”, i, j) ;
return 0 ;
}
/ * Mempertukarkan nilai dari dua variabel * /
void tukar (int *p, int *r)
{
int sementara ;
sementara = *p ;
*p = *r ;
*r = sementara ;
}
3 5
Halaman 15
Output :
• Call-by-reference dapat dicapai secara tidak langsung dalam bahasa C dengan
jalan :
1) Deklarasikan parameter fungsi sebagai suatu pointer ;
2) Dereference pointer itu dengan operator * dalam body fungsi ;
3) Berikan alamat variabel sebagai argumen aktual pada waktu fungsi itu di
panggil.
Objek-objek Const
Katakunci const dipakai di depan nama variabel dalam deklarasi untuk
menyatakan bahwa nilai variabel itu tidak akan diubah.
• Apabila suatu variabel tidak perlu diubah atau seharusnya tidak diubah,
variabel itu sepatutnya dideklarasikan dengan memakai const agar dapat
dijamin tidak terjadi perubahan yang tidak disengaja.
Contoh :
const double e = 2.71828182845905 ;
const char pesan [ ] = “Peringatan : “ ;
int hexKeInt (const char bilhex [ ] ) ;
5 3
Halaman 16
MODUL 3
SORTING
Sorting (Pengurutan Data)
Sorting merupakan salah satu kegiatan komputasi yang sangat penting.
Aplikasinya banyak sekali, antara lain: pengurutan nilai ujian, pengurutan kata
dalam kamus, bagian dari algoritma yang lebih rumit, dll.
Input untuk algoritma sorting adalah suatu barisan unsur-unsur yang dapat diurut.
Outputnya adalah barisan unsur-unsur terurut berdasarkan kriteris tertentu.
Ada banyak algoritma sorting antara lain:
Bubble-sort
Selection-sort
Insertion-sort
Merge-sort
Quick-sort
dll
Untuk mengurutkan data dalam jumlah yang banyak, perlu perhatikan efisiensi.
Ada yang efisien (quick-sort, merge-sort). Ada yang tidak efisien (bubble-sort,
selection-sort, insertion-sort).
Bubble-sort
• Sederhana, tetapi tidak efisien.
Tidak baik untuk sorting data yang banyak.
• Intinya:
Periksa barisan unsure dari ujung ke ujung sepasang demi sepasang,
pertukarkan dua unsure berdampigan yang belum terurut. Ulangi samapai
semua unsur berada di tempat yang benar.
• Dalam satu kali jalan (satu pass), minimal satu unsure ditaruh ke tempatnya
yang benar. Jika ada N unsure, maka diperlukan maksimal N-1 pass. Dalam
pass yang pertama, diperlukan maksimal N-1 pertukaran. Dalam pass yang
kedua, diperlukan maksimal N-2 pertukaran. Dan seterusnya.
Halaman 17
• Unsur yang lebih kecil akan “bubble up” ke satu ujung sambil bertukaran
tempat dengan unsur-unsur yang lebih besar.
Lihat algoritme dalam program berikut.
/*Program ini mengurutkan nilai-nilai dalam suatu array menjadi terurut naik,
dengan algoritme sorting “bubble sort” */
#include <stdio.h>
void bubblesort (int arrayint [ ], const int ukuran);
main ( ) {
int i, ukuran, ar [ ] = {7,3,66,3,-5,22,-77,2};
ukuran = sizeof (ar) / sizeof (int) ;
printf (“data sebelum di-sort : \n”) ;
for (i=0; i<ukuran-1; 1++) printf (“%4d”, ar [i] );
printf (“\n”);
bubblesort (ar, ukuran);
printf (“setelah di-sort dalam urutan naik:\n”);
for (i=0; <ukuran-1; i++) printf (“%4d”, ar [i]) ;
printf (“\n”);
return 0;
}
void bubblesort (int arrayint [ ], const int ukuran)
{
int I, j;
void tukar (int *p1, int *p2);
for (I=0; I <= ukuran-2; ++I)
for (j = ukuran-1; j > I; - - j)
if (arrayint [j-1] > arrayint [ j ])
tukar (&arrayint [j-1], &arrayint [ j ]);
}
Halaman 18
void tukar (int *p1, int *p2)
{
int sementara;
sementara = *p1; *p1 = *p2; *p2 = sementara;
}
Output
Data sebelum di-sort :
7 3 66 3 -5 22 -77 2
Setelah di-sort dalam urutan naik :
-77 -5 2 3 3 7 22 66
Contoh bubble-sort
Data
awal
Pass
ke 1
Pass
ke 2
Pass
ke 3
Pass
ke 4
Pass
ke 5
Pass
ke 6
Pass
ke 7
ar [0] 7 -77 -77 -77 -77 -77 -77 -77
ar [1] 3 7 -5 -5 -5 -5 -5 --5
ar [2] 66 3 7 2 2 2 2 2
ar [3] 3 66 3 7 3 3 3 3
ar [4] -5 3 66 3 7 3 3 3
ar [5] 22 -5 3 66 3 7 7 7
ar [6] -77 22 2 3 66 22 22 22
ar [7] 2 2 22 22 22 66 66 66
Untuk data ini, 5 pass sudah cukup.
Selection-sort
• Mau menurut array
A [awal] A [awal + 1] . . . A [akhir]
Sehingga memenuhi kiteria
A [awal] < = A [awal + 1] < = . . . < = A [akhir]
• Ide algoritma ;
Halaman 19
for ( i = awal ; i < = akhir-1; i++)
Taruh unsur terkecil ke i dalam A [i]
Halaman 20
MODUL 4
ARITMATIKA POINTER
Aritmatika pada pointer
• Operasi-operasi tambah dan kurang dapat dilakukan pada pointer, tetapi
maknanya sangat berbeda dengan tambah dan kurang pada variabel biasa.
• Jika P adalah suatu pointer ke objek dengan tipe tertentu, maka ekspresi p+1
memberikan alamat untuk objek berikutnya.
Secara umum, p+1 memberikan alamat dari objek ke 1 setelah objek yang
sekarang ditunjuk oleh p.
(i adalah suatu integer)
Misalkan p adalah pointer ke variabel bertipe int dan satu int membutuhkan
memori 4 byte. Jika p berisi alamat 3000, maka :
P+1 memberikan alamat 3004
P+2 memberikan alamat 3008
. . .
P+i memberikan alamat 3000 + i*4
• Jika p dan q masing-masing menunjuk ke unsure-unsur suatu array dan p > q,
maka p-q menghasilkan suatu integer yang menyatakan banyaknya unsure
array antara p dan q.
/*contoh operasi tambah dan kurang pada pointer */ #include <stdio.h> main ( ) {
double a[10], *p, *q, *r; p = &a [0]; q = p + 1; r = p + 2; printf (“p:%p, q:%p, r: %p\n” , p, q, r); printf (“q-p: %d\n” , q-p) : printf (“r-p: %d\n” , r-p) : printf (“++p: %p\n” , ++p); return 0;
}
Halaman 21
Output di mesin PC (Borland C++) :
p: FFA4, q: FFAC, r: FFB4
q-p: 1
r-p: 2
++p: FFAC
Pointer dan Array
• Dalam bahasa C, pointer dan array sangat erat hubungannya.
• Nama dari suatu array merupakan suatu pointer konstan yang menunjuk ke
unsure pertama dari array itu.
• Pointer dapat digunakan untuk menggantikan array subscripting.
Dengan menggunakan pointer, komputasi biasanya berlangsung lebih cepat.
Contoh :
Andaikan diberikan deklarasi
int b [5] ;
int *p ;
Maka statement
p = b ;
ekivalen dengan
p = &b [0]
Dengan statement ini, keempat ekspresi berikut ini ekivalen satu sama lain :
b [3]
*(b + 3)
p [3]
*(p + 3)
Halaman 22
/*hubungan antara array dan pointer */ #include <stdio.h> main ( ) {
int i, offset, b [ ] = (1,2,3,4) ; int *pi = b; /* pi menunjuk ke unsure b [0] */ printf (“Array b dicetak dengan : \n” “Notasi nama-array/subscript\n”) ; for (i=0; i < = 3; i++) printf (“ b [%d] = %d\d” , i, b [i] ); printf (“\nNotasi nama-array/offset\n”); for (offset=0; offset < = 3; offset++) printf (“*(b + %d) = %d\n”, offset, *(b + offset) ); printf (“\nNotasi pointer/subscript \n”); for (i=0; I < = 3; i++) printf (“pi [%d] = %d\n”, i, pi [i] ); printf (“\nNotasi pointer/offset\n”): for (offset=0; offset < = 3; offset ++) printf (“*(pi + %d) = %d\n”, offset, *(pi + offset) ); return 0;
}
Output
Array b dicetak dengan : Notasi nama-array/subscript b [0] = 1 b [1] = 2 b [2] = 3 b [3] = 4 Notasi nama-array/offset * (b + 0) = 1 * (b + 1) = 2 * (b + 2) = 3 * (b + 3) = 4 Notasi pointer/subscript pi [0] = 1 pi [1] = 2 pi [2] = 3 pi [3] = 4 Notasi pointer/offset *(pi + 0) = 1 *(pi + 1) = 2 *(pi + 2) = 3 *(pi + 3) = 4
Halaman 23
/*menyalin string dengan notasi array dan notasi
pointer */
#include <stdio.h>
void salin1 (char *s2, const char *s1) ;
void salin2 (char *s2, const char *s1) ;
main ( )
{
char string 1 [10], *string 2 = ”Hello”,
String 3 [10], *string 4 [ ] = “Apa kabar?”;
salin1 (string1, string 2);
printf (“string1 = %s\n”, string 1);
salin2 (string3, string 4);
printf (“string3 = %s\n”, string3);
return 0;
}
/* salin string s1 ke s2, pakai notasi array */
void salin1 (char *s2, const char *s1)
{
int i;
for (i=0; s2 [1] = s1 [i]; i++)
; /* tidak kerja apa-apa disini */
}
/* salin string s1 ke s2, pakai notasi pointer */
void salin2 (char *s2, const char *s1)
{
for ( ; *s2 = *s1; s2++, s1++)
; /* tidak kerja apa-apa disini */
}
Output :
String1 = Hello String3 = Apa kabar?
Halaman 24
• Menyalin input ke output karakter per karakter :
baca satu karakter ;
while ( karakter bukan tanda EOF ) {
Outputkan karakter yang baru saja dibaca ;
Baca satu karakter ;
}
• Dalam C :
Dapat dipakai untuk menyalin dari satu file ke file lain dengan menggunakan
redirection dalam UNIX atau DOS.
Menyalin dari filel . txt ke file2. txt:
a.out < filel . txt > file2. Txt
/ * Menyalin dari standart – input ke standart – output karakter per karakter
versi 2 * /
# include < stdio . h >
main ( )
{
int c ;
while ( ( c = getchar ( ) ) ! = EOF )
putchar (c) :
return 0 ;
}
#include < stdio . h > main ( ) { int c : c = getchar ( ) ; while ( c != EOF ) { putchar ( c ) ; c = getchar ( ) ; } return 0 ;
}
Halaman 25
/ *
* Menyalin dari standart – input ke standart – output
* karakter per karakter , huruf besar dijadikan
* huruf kecil
* /
# include < stdio . h >
int jadiKecil ( int c ) ;
main ( )
{
int c ;
while ( (c = getchar ( ) ) ! = EOF )
putchar ( jadiKecil ( c ) )
return 0 ;
}
int jadiKecil ( int c )
{
return ( (c >= ‘A’&& c <= ‘Z’ ) ? ( c+’a’-‘A’ ) :c );
}
Halaman 26
MODUL 5
EKSPRESI KONDISIONAL
Ekspresi Kondisional
Ekspresil ? ekspresi 2 : ekspresi 3
• Operator ? : adalah suatu operator ternary ( perlu tiga operand )
• Semantiknya :
Pertama – tama ekspresi1 dievaluasi; jika nilai ekspresi1 itu tidak - nol (true),
maka ekspresi 2 dievaluasi dan nilai ekspresi 2 itu menjadi nilai dari seluruh
ekspresi kondisional; jika nilai ekspresi1 itu nol (false), maka ekspresi3
dievaluasi dan nilai ekspresi 3 itu menjadi nilai dari seluruh ekspresi
kondisional.
• Contoh :
z = (a > b) ? a : b;
sama maksudnya dengan
if (a > b)
z = a;
else
z= b;
/ * Menyalin dari standart – input ke standart – output
* karakter per karakter , huruf besar dijadikan
* huruf kecil dengan memakai fungsi tolower dari
* standart – library * /
# include < stdio . h >
# include < ctype . h >
main ( ) {
int c ;
while ( (c = getchar ( ) ) ! = EOF )
putchar ( tolower ( c ) ) ;
return 0 ;
}
Halaman 27
MODUL 6
PENGOLAHAN FILE
Berkas ( File ) dan I/O
• Penyimpanan data dalam variable dan array di memori primer bersifat
sementara ; semua data ini hilang ketika program berakhir.
• File dipakai untuk menyimpan data secara permanen pada alat penyimpanan
sekunder seperti disket.
• File :
- koleksi data menurut format tertentu dalam memori (alat penyimpanan)
sekunder
- mempunyai nama
• Program dapat menulis data ke file; program dapat membaca data dari file.
• C memandang file sebagai suatu barisan dari bytes yang berakhir dengan suatu
tanda end – of – file ( EOF ).
0 1 2 n – 1
. . . . . . . . . Tanda EOF
Suatu file dari n bytes dalam pandangan C
• Sebelum dapat dibaca atau ditulis , suatu file harus dibuka dulu dengan fungsi
fopen yang prototipenya:
FILE * fopen ( const char *nama, const char *modus ) ;
Argument pertama untuk fopen adalah suatu string yangmenyatakan nama
file. Argument kedua adalah suatu string yang menyatakan modus atau
bagaimana file itu akan digunakan.
Fungsi fopen mengembalikan suatu pointer ke FILE. Tipe FILE didefinisikan
dalam < stdio . h >. Pointer ke FILE itu dipakai untuk baca dari atau tulis ke
file .
• Waktu suatu file dibuka , file itu dikaitkan dengan suatu stream yang
merupakan saluran komunikasi antara program dengan file itu.
• Membaca data dari suatu file pada dasarnya adalah membaca data dari
streamnya . menulis data ke suatu file pada dasarnya adalah menulis data ke
streamnya .
Halaman 28
Program C
Stream : Arry of bytes
• Waktu program mulai eksekusi , tiga file secara otomatik dibuka :
1) Standart input , dengan file pointer stdin
2) Standart output , dengan file pointer stdout
3) Standart error , dengan file pointer stderr
Srdin biasanya terhubung ke keyboard, stdout dan srderr biasanya terhubung
ke layer monitor. Tetapi stdin dan stdout dapat dialihkan ( diredirect ) ke file
atau pipe dalam lingkungan system operasi UNIX dan DOS .
• Modus-modus untuk buka file , antara lain:
Read : “r”
Write : “w”
Append : “a”
• Jika suatu file yang belum ada dibuka untuk diwrite atau di-append ( ditulis
pada ujung ) , maka file itu akan dibuatkan / diciptakan .
• Membuka suatu file yang sudah ada untuk di-write akan menyebabkan isi
lamanya dibuang .
• Membuka suatu file yang sudah ada di-append tidak menyebabkan isi lamanya
dibuang; data baru akan ditambahkan di ujung .
• Mencoba buka suatu file yang tidak ada untuk di-read adalah suatu error . jika
terjadi error atau fopen tidak berhasil membuka suatu file , maka fopen akan
mengembalikan pointer NULL.
Stream
File
Halaman 29
/ * contoh baca dari file dan tulis ke file * / # include < stdio . h > main ( ) {
FILE * ifp, *ofp; int a, b; / * open file masukan. Txt untuk baca */ ifp = fopen ( “ masukan . txt “, “w” ) ; fscanf ( ifp, “%d %d” , &, &b ) ; fprintf ( ofp, “%d + %d = %d” , a, b, a+b ) ; / * tutup kedua file */ fclose (ifp); fclose (ofp); return 0 ;
} file masukan .txt
file keluaran . txt
• File yang sudah selesai diproses harus ditutup dengan memanggil fungsi
fclose . prototipenya :
Int fclose (FILE *filePointer);
fclose memutuskan hubungan antara file – pointer itu dengan file yang
bersangkutan yang dibuak dengan fopen dulu . file- pointer itu dapat dipakai
lagi untuk file lain.
• Untuk menulis data ke file , gunakan:
Int fprintf ( FILE * fp,const char * format, ...) ;
Int fputc ( int c , FILE * fp) :
printf ( format , argumenArgumenLain)
ekivalen dengan
fprintf (stdout,format, argumenArgumenLain)
putchar ( c )
Sama maksudnya dengan
fputc ( c , stdout )
-3 11
-3 + 11 = 8
Halaman 30
• Untuk membaca data dari file , gunakan:
int fcsanf (FILE * fp ,const char * format, …);
int fgetc (FILE * fp) ;
scanf (format, argumenArgumenLain);
ekivalen dengan
fscanf (stdin, format, argumenArgumenLain);
getchar ( )
sama maksudnya dengan
fgetc (stdin)
Halaman 31
MODUL 7
STRING
String
• String tertentu (konstanta string) ditulis dalam bentuk seperti “abc”
• Setiap string berakhir dengan karakter ‘\0’ (nilai ASCII 0).
• Dalam C , suatu string diperlakukan compiler sebagai suatu pointer ke karakter
pertamanya.
Tipe suatu string adalah char *
• Seperti untuk suatu array dari char , memori juga dialokasikan untuk
menyimpan suatu string. Sebagai contoh , string “abc” memerlukan memori 4
byte.
Argumen untuk fungsi main ( )
Dua argumen, yaitu argc dan argv, dapat dipakai oleh fungsi main untuk
berkomunikasi dengan operating-system.
Variabel argc memberikan jumlah argumen-argumen baris perintah (command
line arguments) yang terdiri dari nama program (yang executable) diikuti
argumen-argumen lainnya yang diperlukan.
Command-line diberikan kepada operating-system untuk menjalankan program.
Array ardv adalah suatu array dari pointer ke char , yaitu suatu array of strings.
String-string ini adalah kata-kata yang membentuk command-line itu.
argv [0] selalu mengandung nama program executable.
/ * Program ini mencetak command-linenya */ #include <stdio.h> main ( int argc , char *argv [ ] ) {
int i ; printf (“argc = %d\n” , argv); for (i = 0 ; i < argc ; i++) printf (“argv[%d] = %s\n” , I , argv [i] ) ; return 0 ;
}
Halaman 32
• Andaikan program di atas ini di-compile menjadi file executable bernama test
maka perintah berikut dalam UNIX .
test saya suka C
akan menhsailkan respons di layar :
argc = 4
argv [0] = coba
argv [1] = saya
argv [2] = suka
argv [3] = C
• Argv [argc] berisi pointer nol.
Halaman 33
MODUL 8
REKURSIF
Fungsi Rekursif
• Fungsi yang memanggil dirinya , secara langsung atau lewat fungsi lain ,
disebut fungsi rekursif.
Proses pemanggilan diri itu disebut rekursi (recursion).
• Contoh :
Kita mau membuat sebuah fungsi rekursif untuk memangkatkan suatu bilangan
real tak-nol dengan suatu pangkat berupa bilangan bulat.
1 jika N = 0
XN = X(XN-1) jika N > 0
1/X-N jika N < 0
/ * Menghiyung x pangkat N , untuk x = 0 */
double pangkat (double x , int N)
{
if (N = = 0 )
return 1.0 ;
else if (N > 0)
return ( x * pangkat (x, N-1) ) ;
else /* untuk N < 0 =/
return ( 1 / pangkat (x,-N) ) ;
}
Halaman 34
Berapakah pangkat (4.0 , -2) ?
Latihan
Buat sebuah fungsi rekursif untuk mengalikan dua bilangan bulat positif tanpa
menggunakan operator perkalian.
Jawab :
• Ciri masalah yang dapat diselesaikan secara rekursif adalah bahwa masalah itu
dapat direduksi menjadi satu atau lebih masalah-masalah serupa yang lebih
kecil
• Secara umum , suatu algoritme rekursif selalu mengandung dua macam kasus :
1) Satu atau lebih kasus yang pemecahan masalahnya dilakukan dengan
menyelesaikan masalah serupa yang lebih sederhana (yaitu menggunakan
recursive-calls) .
2) Satu atau lebih kasus yang pemecahan masalahnya dilakukan tanpa
menggunakan recursive-calls.
Kasus-kasus ini disebut kasus dasar atau kasus penyetop.
• Supaya tidak terjadi rekursi yang tak berhingga , setiap langkah rekursif
haruslah mengarah ke kasus penyetop
pangkat (4.0 , 0) return 1.0
pangkat (4.0 , 2) return (4.0 * pangkat (4.0 , 0) )
pangkat (4.0 , 2) return (4.0 * pangkat (4.0 , 1) )
pangkat (4.0 , 2) return (4.0 * pangkat (4.0 , 2) )
1.0
4.0
16.0
0.0625
Halaman 35
/ * Contoh solusi rekursif untuk problem Menara Hanoi * /
#include <stdio.h>
void tulislangkah (int, int, int, int);
main(int argc , char *argv[ ] ) {
int jumlah Cakram ;
if (argc ! = 2 || atoi (argv[1] ) < 1) {
fprint(stderr, “Contoh penggunaan : %s 3\n”’
argv[0] ) ;
exit (1) ;
}
jumlahCakram = atoi (argv[1] ) ;
printf (“\n*** Menara Hanoi ***\n”) ;
printf (“\nUntuk memindahkan %d cakram dari \npasak 1 “
“ke 2 , lakukan langkah-langkah ini : \n\n”,
jumlahCakram) ;
tulisLangkah (jumlahCakram, 1 , 2 , 3) ;
printf (“\n*** Selesai ***\n”) ;
return 0 ;
}
void tulisLangkah (int jumlahCakram , int awal , int akhir , int bantu)
{
if (jumlahCakram = = 1 )
printf (“Pindahkan sebuah cakram sari pasak %d ke “
“%d. \n” , awal , akhir ) ;
else {
tulisLangkah (jumlahCakram - 1 , awal , bantu , akhir ) ;
printf (“Pindahkan sebuah cakram dari pasak %d ke “
“%d. \n” , awal , akhir ) ;
tulisLangkah (jumlahCakram - 1 , bantu , akhir , awal ) ;
}
}
Halaman 36
Andaikan program itu di-compile menjadi file executable bernama Hanoi, maka
perintah
hanoi 4
akan memberikan output:
*** Menara Hanoi ***Untuk memindahkan 4 cakram dari pasak 1 ke 2 , lakukan langkah-langkah ini : Pindahkan sebuah cakram dari pasak 1 ke 3. Pindahkan sebuah cakram dari pasak 1 ke 2. Pindahkan sebuah cakram dari pasak 3 ke 2. Pindahkan sebuah cakram dari pasak 1 ke 3. Pindahkan sebuah cakram dari pasak 2 ke 1. Pindahkan sebuah cakram dari pasak 2 ke 3. Pindahkan sebuah cakram dari pasak 1 ke 3. Pindahkan sebuah cakram dari pasak 1 ke 2. Pindahkan sebuah cakram dari pasak 3 ke 2. Pindahkan sebuah cakram dari pasak 3 ke 1. Pindahkan sebuah cakram dari pasak 2 ke 1. Pindahkan sebuah cakram dari pasak 3 ke 2. Pindahkan sebuah cakram dari pasak 1 ke 3. Pindahkan sebuah cakram dari pasak 1 ke 2. Pindahkan sebuah cakram dari pasak 3 ke 2. *** Selesai ***
Halaman 37
MODUL 9
STRUCT
Structure
• Suatu structure adalah suatu koleksi dari satu atau lebih variabel yang bertipe
sama ataupun berbeda-beda , dan dapat diperlukan sebagai satu kesatuan.
Bandingkan dengan suatu array. Semua variabel (unsur) dalam suatu array
harus bertipe sama.
Contoh :
struct mahasiswa {
char *nama ;
int umur ;
int semester ;
char *NIM ;
};
mendeklarasikan suatu structure bernama mahasiswa yang terdiri dari 4
anggota (member).
• Struct adalah keyword bahasa C yang mengawali deklarasi suatu structure.
• Suatu deklarasi struct mendefinisikan suatu tipe data baru.
• Structure sering juga disebut record.
• Kombinasi antara pointer dan structure memungkinkan pembentukan struktur
data yang kompleks yang diperlukan untuk penanganan masalah-masalah dunia
nyata.
• Structure dapat berada di sebelah kiri maupun di sebelah kanan assignment ,
dapat disalurkan sebagai argumen ke fungsi dan dapat dikembalikan sebagai
nilai dari fungsi.
• Dua structure tidak dapat dibandingkan , karena mereka mungkin tidak
disimpan dalam byte-byte memori yang berurutan.
• Deklarasi
struct mahasiswa m1;
menyatakan bahwa m1 adalah suatu variabel bertipe struct mahasiswa dan
baginya disediakan memori secukupnya.
Halaman 38
Variabel m1 terdiri dari empat anggota dengan nama-nama : nama , umur ,
semester dan NIM.
Anggota suatu structure diakses dengan :
• menggunakan operator titik . dalam bentuk :
structure . anggota
atau
( * pointer-ke-structure) . anggota
• menggunakan operator panah - > dalam bentuk :
pointer-ke-structure - > anggota
/ * Contoh structure * / #include <stdio.h> / * definisi tipe baru : struct nahasiswa */ struct mahasiswa {
char *nama; int umur; int semester; char *NIM;
}; main ( ) {
struct mahasiswa mhs = {“Unyil” , 12 , 1 , “1294000001”} ; struct mahasiswa *pm = &mhs ; printf (“%-10s %11s %3d %2d\n”, mhs.nama, mhs.NIM, mhs.umur,
mhs.semester) ; printf (“%-10s %11s %3d %2d\n”,
(*pm) .nama , (*pm) . NIM , (*pm) . umur , (*pm) .semester ) ;
printf (“%-10s %11s %3d %2d\n”, pm - >nama , pm - >NIM , pm - >umur , pm - >semester ) ;
mhs.nama = “Melani” ; mhs.NIM = “1293000001” ; mhs.umur = mhs.umur - 1 ; mhs.semester++; printf (“%-10s %11s %3d %2d\n”, pm - >nama , pm - >NIM , pm - >umur , pm - >semester ) ; return 0 ;
}
Halaman 39
Output :
Typedef
• Kata kunci typedef dipakai untuk membuat nama (identifier) baru bagi suatu
tipe data.
Identifier lama tetap berlaku.
Nama yang dipilih dimaksudkan untuk memperjelas makna program , dan juga
seringkali untuk menyederhanakan penulisan.
Contoh :
typedef char * String ;
typedef int Bulat ;
typedef double Vektor[10] ;
typedef struct mahasiswa Mhs ;
typedef struct {
char *nama ;
char *alamat ;
int nomor ;
long gaji ;
} Karyawan;
Nama-nama baru ini menjadi sinonim dari nama-nama lama, dan dapat dipakai
untuk mendeklarasikan variabel.
Bulat i , array[5] ;
Karyawan kar ;
Vector v ; /* ekivalen dengan : double v [10] ; */
String s = “abc” ;
Unyil 129400000 12 1 Unyil 129400000 12 1 Unyil 129400000 12 1 Melani 129300000 12 2
Halaman 40
MODUL 10
STRUKTUR DATA DINAMIS
Struktur Data Dinamis
• Struktur data seperti array adalah struktur data statis . dikatakan statis karena
ukuran array dan alokasi memori untuk array sudah harus ditentukan sebelum
program mulai dieksekusi dan tidak dapat diubah selama program sedang
berjalan.
• Struktur data dinamis adalah struktur data yang ukuran dan alokasi
memorinya dapat ditambah atau dikurangi pada waktu program sedang
berjalan .
Struktur data yang dapat tumbuh dan menciut ini sangat banyak kegunaannya.
• Kita akan mempelajari satu struktur data dinamis yang sangat mendasar, yaitu
linked-list.
Penguasaan terhadap linked-list merupakan kunci untuk menguasai struktur
data dinamis lainnya.
• Untuk itu, kita mulai denagn mempelajari:
Self - Referential Structure
• Self - referential structure adalah suatu structure yang mengandung anggota
berupa pointer ke structure itu sendiri.
• Contoh :
struct node {
int data ;
struct node *next ;
};
mendefinisikan tipe struct node .
Structure yang bertipe struct node ini mempunyai dua anggota :
1) data, yang bertipe int
2) next, yang bertipe struct node *(dengan kata lain, next adalah pointer ke
struct node )
Halaman 41
• istilah * self-referential * berasal dari kenyataan bahwa pointer next itu
menunjuk ke structure dimana next merupakan anggota.
• Structure-structure self-referential dapat digandengkan bersama (di-link)
untuk membentuk struktur data seperti list, stack, queue dan tree.
/ * contoh linking dari structure-structure self-referential
# include < stdio . h>
struct node {
int data;
struct node * next;
};
typedef struct node SIMPUL ;
main ( )
{
SIMPUL s1, s2, *psim;
s1.data = 100;
s1.next = &s2;
s2.data = 275;
s2.next = NULL;
psim = &s1;
printf (“s1.data = %d\n” , s1.data ) ;
printf (“s2.data = %d\n” , s2.data ) ;
printf (“psim->data = %d\n” , psim->data ) ;
printf (“psim->next->data = %d\n” , psim->next->data ) ;
return 0 ;
}
psim
100 275
s1 s2
Halaman 42
Outputnya :
Alokasi Memori Dinamis
• Program dapat melakukan alokasi memori secara dinamis, yaitu pada waktu
eksekusi, untuk mendapatkan memori bagi suatubaviabel (biasanya structure
self-referential) dan untuk membebaskan memori yang sudah tidak dibutuhkan.
• Banyaknya memori yang dapat dialokasikan secara dinamis tentu saja
bergantung pada julah memori primer yang masih tersedia
• Alokasi memori dinamis biasanya melibatkan fungsi malloc, fungsi free dan
operator sizeof.
void *malloc (size_t size) :
Mengalokasikan ruang memori untuk suatu objek yang ukurannya size
byte. Block memori ini tidak diinisialisasi. Jika sukses, malloc
memberikan pointer ke blok memori itu; jika tidak, malloc memberikan
pointer NULL.
Size_t adalah tipe integer unsigned yang didefinisikan dalam stdlib.h dan
stddef.h. Nilai yang dihasilkan operator sizeof adalah bertipe size_t.
void free (void *ptr) :
Membebaskan blok memori yang ditunjuk oleh pointer ptr, yang tadinya
diperoleh melalui fungsi malloc. Blok memori yang dibebaskan ini dapat
dialokasikan lagi untuk keperluan lain.
Pointer ke void
• Suatu pointer dapat diberi nilai dari pointer lain yang setipe. Jika berlainan tipe,
perlu pakai operator cast.
s1.data = 100 s2.data = 275 psim->data = 100 psim->next->data = 275
Halaman 43
Perkecualiannya : pointer ke void (yaitu pointer yang bertipe void *)
merupakan pointer generic yang dapat menerima nilai dari pointer apa saja dan
pointer apa saja dapat diberi nilai dari pointer ke void, tanpa operator cast.
• Pointer ke void tidak dapat didereference, karena tipe objeknya tidak diketahui.
• Pointer dapat diinisialisasi atau diberi nilai berupa 0, NULL, atau suatu alamat.
Pointer dengan nilai NULL tidak menunjuk apa-apa. NULL adalah suatu
konstanta simbolik yang didefinisikan dlam stdio.h.
/*contoh penggunaan malloc dan free */ #include (stdio.h) #include (stdlib.h) void cetakpesan (void); struct node {
int data; struct node *next; }; typedef struct node SIMPUL ; main ( ) {
SIMPUL *psim, *psim1; psim = malloc (sizeof (SIMPUL) ); if (psim ! = NULL) { /* alokasi memori berhasil */ psim ->data = 100; } else { cetakpesan ( ); exit (1); } psim1 = malloc (sizeof (SIMPUL) ); if (psim) { /* ekivalen dengan : psim1 != NULL */ psim1 ->data = 275 psim1 ->next = NULL psim ->next = psim1 } else { cetakpesan ( ) : exit (1) } printf (“psim ->data = %d\n”, psim ->data); printf (“psim ->next ->data = %d\n”,
psim ->next ->data) ; printf (“psim1 ->data = %d\n”, psim1 ->data); psim1 = psim printf (“setelah psim1=psim, psim1 ->data = %d\n”
psim1 ->data) ; free (psim ->next) ; free (psim) ; return 0;
} Void cetakpesan (void) {
fprintf (stderr, “*** Malloc gagal dapatkan memori.\n”); }
Halaman 44
Output :
psim ->data = 100
psim ->next ->data = 275
psim1 ->data = 275
Setelah psim1=psim, psim ->data = 100
Halaman 45
MODUL 11
LINK LIST
Linked-List
• Adalah suatu barisan unsur/objek. Tiap objek merupakan suatu self-referential
structure (disebut juga node/simpul) yang mengandung alamat (pointer) untuk
objek berikutnya.
Satu objek di – linked (dihubungkan) dengan objek berikutnya oleh pointer tsb.
Pointer penghubung untuk unsure terakhir biasanya diberi nilai NULL.
• Contoh :
P
3 1 7
Ilustrasi ini menggambarkan suatau linked-list yang terdiri dari 3 unsur. Pointer
P menunjuk ke unsure pertama. Pointer P diperlukan agar unsure-unsur linked-
list itu bisa diakses.
• Linked-list kosong (empty) adalah linked-list yang tak punya unsure. Biasanya
dinyatakan dengan pointer yang bernilai NULL.
P
empty list
• Data disimpan dlam linked-list secara dinamis. Unsure/simpul dibuat pakai
fungsi malloc pada waktu diperlukan. Suatu simpul dapat mengandung data
dengan tipe apa saja (termasuk struct lain).
• Linked-list cocok untuk aplikasi dimana jumlah unsure data dapat berubah-
ubah atau tidak dapat diperkirakan pada awal proses.
• Operasi-operasi pada linked-list antara lain :
Menyisipkan (insert) unsur
Menghapus (delete) unsur
Mencari (search/look-up) unsur
Menentukan apakah suatu list itu kosong
Halaman 46
Menyisipkan suatu unsur di posisi setelah unsur tertentu
Sebelum : . . . . . .
P
Q
Sesudah : . . . . . .
P Q : next
Q
Menyisipkan suatu unsur antara dua unsur tertentu yang berurutan
Sebelum : . . . . . .
P R
Q
Sesudah : . . . . . .
P R
‘ A ’ ‘ C ’
‘ B ’
‘ A ’ ‘ C ’
‘ B ’
Q ->next = P ->next; P ->next = Q
‘ A ‘ C ’
‘A’ ‘ C ’
‘ B ’
‘ B ’
P->next = Q Q ->next = R
Q
Halaman 47
Menghapus unsur di posisi setelah unsur tertentu
Sebelum :
. . . . . .
P Q
Sesudah :
. . . . . .
P Q
Berikut ini kita akan membuat program untuk mengolah suatu list-of-characters,
dengan menu :
1. Sisip huruf ke list sehingga terurut menurut abjad
2. Hapus huruf dari list
Langkah-langkahnya:
1. Tampilkan menu
2. Baca pilihan dari unsur
3. Laksanakan pilihan
4. Ulangi langkah 2 dan langkah 3 sampai selesai
P ->next = P ->next ->next; Free (Q);
‘B’ ‘C’ ‘A’
‘B’ ‘C’‘A’
Halaman 48
#include (stdio.h) #include (stdlib.h) struct simpul { char data; struct simpul *next; }; typedef struct simpul SIMPUL; typedef SIMPUL *ptrKeSIMPUL; void cetakmenu (void); void sisip (PtrKe SIMPUL*, char); void cetaklist (PtrKeSIMPUL); int kosong (PtrKeSIMPUL); char hapus (PtrKeSIMPUL)*, char; main ( ) {
PtrKeSIMPUL list = NULL; /* pointer ke unsure pertama */ int pilihan; char ch, info, buangan [80]; cetakmenu ( ); printf (“? “); scanf (“%d”, &pilihan) ; gets (buangan); while (pilihan ! = 3 ) {
switch (pilihan) { case 1 :
printf (“ketik satu huruf: “); scanf (“%c”, &info) ; gets (buangan); sisip (&list, info); cetaklist (list); break ;
case 2 : if (! kosong (list) {
printf (“ketik satu huruf yang mau dihapus: “); scanf (“%c”, &info) ; gets (buangan); ch = hapus (&list, info); if (ch != ‘\0’) {
printf (“%c dihapus.\n”, info) : cetaklist (list); } else printf (“%c tidak ketemu.\n\n”, info);
} else printf (“List kosong.\n\n”); break :
default : printf (“pilihan tidak sah.\n\n”); cetakmenu ( ) ; break;
} /* switch */ printf (“? “) : scanf (“%d”, &pilihan) ; gets (buangan);
} /* while */ printf (“*** selesai ***\n”)’ return 0;
}
Halaman 49
void cetakmenu (void) { printf (“Pilihan Anda: \n” “ 1: Sisip satu unsure ke list.\n” “ 2: Hapus satu unsure dari list.\n” “ 3: Selesai.\n);
} /* sisip satu huruf dengan menjaga urutan menurut abjad */
void sisip (PtrKeSIMPUL *pList, char info) {
PtrKeSIMPUL baru, sebelum, kini;
baru = malloc (sizeof (SIMPUL) );
if (baru !=NULL) { /* memori tersedia */
baru ->data = info;
baru ->next = NULL;
sebelum = NULL;
kini = *pList;
/* cari posisi */
while (kini !=NULL && info > kini ->data) {
Sebelum = kini;
kini = kini ->next;
}
if (sebelum = = NULL) {
baru ->next = *plist;
*plist = baru;
} else {
sebelum ->next = baru;
baru ->next = kini;
}
} else {
printf (“%c tidak disisipkan. Kehabisan memori.\n”, info);
}
}
Halaman 50
/*cetak list mulai dari unsure yang ditunjuk oleh P */ void cetaklist (PtrKeSIMPUL) {
if (P = = NULL) printf (“NULL\n\n”); else { while (P ! = NULL) { printf (“%c - -> “, P ->data); P = P ->next; } printf (“NULL\n\n”);
} /* memberikan 1 jika list kosong; 0 jika tidak */ int kosong (PtrKeSIMPUL List) { return (list = = NULL); } /*hapus satu huruf dari list */ char hapus (PtrKeSIMPUL *plist, char info) { ptrKeSIMPUL sebelum, kini, sementara; if (info = = (*plist ->data) {
sementara = *plist; *plist = (*plist) ->next; free (sementara); return info;
} else { sebelum = *plist; kini = (*plist) ->next; while (kini != NULL && kini ->data !=info) { sebelum = kini; kini = kini ->next; } if (kini != NULL) { sementara = kini; sebelum ->next = kini ->next; free (sementara); return info; }
} return ‘\0’ ;
}
Halaman 51
Tampilan interaksi:
Pilihan Anda : 1 : Sisip satu unsur ke list, 2 : Hapus satu unsur dari list, 3 : Selesai.
? 1 Ketik satu huruf : B B - -> NULL ? 1 Ketik satu huruf : A A - -> B - -> NULL ? 1 Ketik satu huruf : C A - -> B - -> C - -> NULL ? 2 Ketik satu huruf yang mau dihapus : F F tidak ketemu. ? 2 Ketik satu huruf yang mau dihapus : B B dihapus. A - -> C - -> NULL ? 2 Ketik satu huruf yang mau dihapus : C C dihapus. A - -> NULL ? 2 Ketik satu huruf yang mau dihapus : A A dihapus. NULL ? 3 ***selesai ***
Halaman 52
MODUL 12
MERGE SORT
Merging :
proses menggabungkan dua barisan terurut menjadi satu barisan terurut.
contoh :
4 7 10 11
di –merger dengan
-2 1 5 8 9
Menghasilkan
-2 1 4 5 7 8 9 10 11
MERGE – SORT
1) Bagi barisan data menjadi 2 subbarisan.
2) Sort tiap subbarisan secara rekursif
3) Merge kedua subbarisan yang sudah terurut itu menjadi barisan terurut.
bagi
27
Pemanggilan rekursif
27 23 30 36 19 12 34
27 23 30
23 27 30 36
27 23 30 36
23 36 30
23 27 30 36
19 12 34
19 12 34
12 19 34
19 12
12 19
12 19 23 27 30 34 36
bagi
bagi
bagi
bagi bagi
merge
mergemerge
merge
merge
merge
Pemanggilan rekursif
Halaman 53
Selain fungsi malloc , standart-library denga header file stdlib.h juga
menyediakan fungsi calloc dan realloc untuk alokasi memori secara dinamis.
Prototipenya :
void *calloc (size_t nobj , size_t size) ;
void *realloc (void *ptr , size_t size) ;
Fungsi calloc mengembalikan pointer ke memori untuk suatu array yang
terdiri dari nobj unsur , masing-masing unsur berukuran size byte. Memori itu
diinisialisasi dengan nilai 0 .
Jika alokasi memori tidak berhasil, calloc mengembalikan pointer NULL.
calloc berguna untuk alokasi dynamic-array. (Bandingkan dengan array statis
yang dialokasikan pada waktu komplikasi , tanpa menggunakan calloc).
Ukuran dynamic-array belum diketahui pada waktu komplikasi.
Fungsi realloc berguna untuk mengubah ukuran objek yang ditunjuk oleh
pointer ptr menjadi size byte. Isi objek bagian yang lama tetap.
realloc mengembalikan pointer memori yang baru. Jika alokasi memori tidak
berhasil, realloc mengembalikan pointer NULL.
Pointer ke Fungsi
• Nama dari suatu fungsi adalah pointer ke fungsi itu.
• Seperti pointer ke variabel, pointer ke fungsi dapat diperlukan sebagai :
- argumen untuk fungsi
- unsur dalam array
- nilai yang dikembailkan fungsi
- dll
• Contoh : Deklarasi
double (*pf) (double) ;
Menyatakan bahwa pf adalah suatu pointer ke suatu fungsi yang memerlukan
satu argumen bertipe double dan mengembalikan nilai bertipe double.
Perhatikan bahwa deklarasi di atas berbeda dengan :
double *g (double) ;
Halaman 54
yang menyatakan bahwa g adalah suatu fungsi yang memerlukan satu
argument bertipe double dan mengembalikan nilai bertipe double * (pointer
ke double).
/ * Contoh penggunaan pointer-ke-fungsi */
#include <stdio.h>
#define N 5
int min(int * , int) ;
int jumlah (int * , int ) ;
main ( ) {
int a [N] = {5, 7, -5, 3, 6} ;
int (*pf) (int * , int) ;
pf = jumlah ;
printf (“%d = = %d \n” , (*pf) (a, N) , jumlah (a,N) ) ;
pf = min ;
printf (“%d = = %d \n” , min (a,N) , (*pf) (a,N) ) ;
return 0 ;
}
int min (int *a , int n) {
int i , m = a[0] ;
for (i = n-1 ; i > 0; i- -)
if (a[i] < m) m = a[i] ;
return m ;
}
int jumlah (int *a , int n) {
int i , j = a[0] ;
for (i = 1; i < n; i+ +) j + = a[i] ;
return j ;
}
Output :
16
16 = = 16 -5 = = -5
Halaman 55
Apabila ada deklarasi :
int *p ;
void quicksort (int * , int , int) ;
Apakah tipe dari p ?
int *
Apakah tipe dari quicksort ?
void (*) (int *, int , int)
• Contoh :
int (*uji[5] ) (void) ;
mendeklarasikan bahwa uji adalah suatu array yang terdiri dari 5 unsur. Tiap
unsure merupakan suatu pointer ke suatu fungsi yang tak memerlukan argumen
dan yang return-type-nya int.
Halaman 56
MODUL 13
BITWISE
Tipe-tipe dasar dalam bahasa C
Tipe-tipe integer:
char unsigned char signed char
short unsigned short
int unsigned
long unsigned long
Tipe-tipe floating:
float double long double
Operator-operator bitwise
• Operasi dilakukan per bit.
• Berlaku pada operand yang bertipe integral , dalam representasi sebagai
untaian bit (binary digit).
• Bergantung pada mesin computer, karena mesin computer yang satu dengan
yang lain bisa berbeda dalam hal merepresentasi suatu nilai sebagai untaian bit.
• Ada 6 operator bitwise:
~ bitwise complement
<< left shift
>> right shift
& bitwise and
^ bitwise xor ( exclusive or )
| bitwise or
Perhatikan precendence dan assosiativity mereka dalam table operator yang
telah kita bahas sebelumnya.
Halaman 57
Bitwise Complement
Operator ~ membalik setiap bit dari representasi biner argumennya. (D.k.l.,
operator ~ menghasilkan one’s complement dari argumennya. ) Bit 0 menjadi 1
dan bit 1 menjadi 0.
Contoh :
unsigned char bits = 0227 ;
1 0 0 1 0 1 1 1
bits = ~bits ;
0 1 1 0 1 0 0 0
Left – shift dan Right – shift
Operator left – shift << menggeser ke kiri bit-bit dari operand kirinya sebanyak
posisi yang dinyatakanoleh operand kanannya . bit yang digeser keluar menjadi
hilang, bit yang digeser masuk bernilai 0.
Contoh :
unsigned char bits = 0227 ;
1 0 0 1 0 1 1 1
bits = bits << 2 ;
0 1 0 1 1 1 0 0
Operator right - shift >> menggeser ke kanan bit - bit dari operand kirinya
sebanyak posisi yang dinyatakan oleh operand kanannya. Bit yang digeser keluar
menjadi hilang. jika operandnya unsigned, bit yang digeser masuk bernilai 0; jika
tidak, bit yang digeser masuk bisa bit 0 atau bit tanda tergantung pada mesin
komputer ybs.
Contoh :
unsigned char bits = 0227 ;
1 0 0 1 0 1 1 1
bits = bits << 3 ;
0 0 0 1 0 0 1 0
Halaman 58
Bitwise – AND, bitwise – XOR dan bitwise – OR
Operator-operator &, ^, dan | bekerja pada operandnya bit per bit.
bit1 bit2 bit1 & bit2 bit1 ^ bit2 bit1 | bit2
0 0 0 0 0
1 0 0 1 1
0 1 0 1 1
1 1 1 0 1
Contoh :
unsigned char hasil;
unsigned char b1 = 0145 ;
0 1 1 0 0 1 0 1
unsigned char b2 = 0257 ;
1 0 1 0 1 1 1 1
Hasil = b1 & b2 ;
0 0 1 0 0 1 0 1
Hasil = b1 ^ b2 ;
1 1 0 0 1 0 1 0
Hasil = b1 | b2 ;
1 1 1 0 1 1 1 1
Halaman 59
/ * Operator-operator bitwise * / #include < stdio . h > void cetakbit ( unsigned char c ) ; main ( ) {
unsigned char bits = 0227 ; /* bilangan oktal * / unsigned char b1 = 0145 ; unsigned char b2 = 0257 ; unsigned char hasil ; printf (*bits : %#4o “ , bits ) ; cetakbit (bits) ; printf (*~bits : %#4o “ , hasil = ~bits) ; cetakbit (hasil) ; printf (*bits << 2 : %#4o “ , hasil = bits<<2); cetakbit (hasil) ; printf (*bits >> 3 : %#4o “ , hasil = bits>>3); cetakbit (hasil) ; printf (“b1 : %#4o “ , b1); cetakbit (b1); printf (“b2 : %#4o “ , b2); cetakbit (b2); printf (“b1 & b2 : %#4o “ , hasil = b1&b2 ) ; cetakbit (hasil) ; printf (“b1 ^ b2 : %#4o “ , hasil = b1^b2 ) ; cetakbit (hasil) ; printf (“b1 | b2 : %#4o “ , hasil = b1|b2 ) ; cetakbit (hasil) ; return 0;
} void cetakbit (unsigned char c) { unsigned char i , mask = 1 << 7 ; / * 10000000 * / for ( i = 1 ; i <= 8 ; i++ ) { putchar ( (c & mask) ? ‘1’ : ‘0’ ); c = c << 1 ; } putchar ( ‘ \n’ ) ; }
Halaman 60
Output :
Perhatikan perbedaan antara operator – operator bitwise :
~ , & , |
Dengan operator – operator logical :
! , && , | |
Operator Koma ( , )
Operator biner, mempunyai precedence paling rendah. operand – operandnya
berupa ekspresi.
Ekspresi koma berbentuk :
ekspresi1 , ekspresi2
Pertama – tama ekspresi1 dievaluasi , kemudian ekspresi2 . nilai dan tipe dari
ekspresi koma itu secara keseluruhan sama dengan nilai dan tipe dari operand
kanannya.
Contoh :
Jika a bertipe char dan b bertipe int , maka ekspresi
a = 0 , b = 8
mempunyai nilai 8 dan bertipe int .
Apakah yang akan dicetak oleh
printf ( “%d” , (a = 8 , 3 ) ) ;
?
bits : 0227 - - > 10010111 ~bits : 0150 - - > 01101000 bits << 2 : 0134 - - > 01011100 bits >> 3 : 022 - - > 00010010 b1 : 0145 - - > 01100101 b2 : 0257 - - > 10101111 b1 & b2 : 045 - - > 00100101 b1 ^ b2 : 0312 - - > 11001010 b1 | b2 : 0357 - - > 11101111
Halaman 61
• Operator koma sering dipakai dalam for-loop untuk melakukan inisialisasi
ganda dan pemrosesan ganda terhadap indeks.
Contoh :
for (jumlah = 0 , i = 1 ; i <= n ; ++i)
jumlah + = i ;
dapat dipakai untk menghitung jumlah dari integer 1 s/d n . for-loop trs dapat
ditulis lebih singkat menjadi
for (jumlah = 0, i = 1 ; i< = n ; jumlah + = i, ++i
;
Bukan
for (jumlah = 0, i = 1 ; i <= n ; ++i , jumlah += i)
;
• Tidak semua tanda koma yang muncul dalam program menyatakan operator
koma. sebagai contoh, tanda koma yang dipakai untuk memisahkan argument
fungsi dan tanda koma yang muncul dalam barisan penginisialisasi arry
bukanlah operator koma.
Union
• Union mengikuti sintaks seperti untuk struct , tetapi anggota-anggotanya
menempati bagian memori yang sama.
• Keyword union dipakai untuk mendeklarasikan suatu tipe union yang baru.
Contoh :
union int_float {
int i ;
float f ;
} ;
mendeklarasikan bahwa tipe union int_float mempunyai anggota i dan f .
Setelah ada deklarasi tipe diatas , kita dapat mendeklarasikan variable-variabel
bertipe union int_float .
union int_float a , b;
Halaman 62
Deklarasi ini mengakibatkan memori dialokasikan untuk variable a dan b .
masing-masing variabel itu mendapat alokasi memori sebanyak yang
diperlukan untuk menyimpan anggota yang terbesar.
/ * contoh tentang union * /
#include < stdio . h >
union int_float {
int i ;
float f ;
} ;
typedef union int_float BILANGAN ;
main ( )
{
BILANGAN b ;
printf ( “ sizeof (BILANGAN) = %d\n” , sizeof (BILANGAN) ) ;
printf ( “sizeof (int) = %d\n” , sizeof (int)) ;
printf ( “sizeof (float) = %d\n” , sizeof (float)) ;
b.i = 1234 ;
printf ( “i : %10d f : %16 . 10e\n” , b.i, b.f ) ;
b.f = 1234 . ;
printf ( “i : %10d f : %16 . 10e\n” , b.i, b.f ) ;
return 0 ;
}
Output di PC:
sizeof (BILANGAN) = 4 sizeof (int) = 2 sizeof (float) = 4 i: 1234 f: 7.8522980213e-01 i: 16384 f: 1.2340000000e+03
Halaman 63
• Union dipakai :
a) apabila diperlukan interpretasi ganda untuk satu bagian memori tertentu ,
atau
b) untuk menghemat memori , dengan membolehkan bagian memori yang
sama dipakai untuk tipe-tipe yang berlainan.
• Programmer bertanggung jawab penuh tentang interpretasi mana yang harus
dipakai pada keadaan tertentu .
Halaman 64
MODUL 14
SEARCH
Pelacakan Linier (Linear Search) Dan Pelacakan Biner (Binary Search)
• Untuk melacat suatu nilai tertentu dalam sebuah array yang belum di-sort , kita
dapat gunakan pelacakan linier.
• Jika sudah di-sort, ada cara yang secara umum lebih efisien, yaitu pelacakan
biner.
Contoh implementasi pelacakan linier :
/ * lacaklinier : mengembalikan indeks I s.s.
* N = = a [ I ] jika N ada dalam array
* a [awal] . . . a[akhir] ; mengembalikan -1 jika tidak.
* /
int lacaklinier (int N, int a[ ] , int awal , int akhir )
{
int I ;
enum {tidak , ya} ketemu ;
ketemu = tidak ;
I = awal ;
while (I < = akhir && !ketemu)
if (N = = a[I] ) ketemu = ya ;
else I++;
if (ketemu) return I ;
else return -1 ;
}
Halaman 65
Contoh implementasi pelacakan biner :
/ * lacakbiner : mengembalikan indeks I s.s.
* N = = a [ I ] jika N ada dalam array
* a [awal] . . . a[akhir] yang sudah terurut ;
* mengembalikan -1 jika tidak ketemu.
* /
int lacakbiner (int N, int a[ ] , int awal , int akhir )
{
int rendah , tengah , tinggi
enum {tidak , ya} ketemu ;
rendah = awal ;
tinggi = akhir ;
ketemu = tidak ;
while (rendah < = tinggi && !ketemu ) {
tengah = (rendah + tinggi ) / 2;
if (N = = a[tengah] ) ketemu = ya;
else if (N < a[tengah] ) tinggi = tengah - 1;
else rendah = tengah + 1;
}
if (ketemu ) return tengah ;
else return -1 ;
}
Halaman 66
MODUL 15
OPERASI FILE
Mengingat operasi File
• Suatu file dapat dibuka pakai fungsi fopen dalam berbagai modus :
Modus Arti “r” “w” “a” “rb” “wb” “ab” “r+” “w+” “a+” “rb+” “wb+” “ab+”
text file for reading text file for writing text file for appending binary file for reading binary file for writing binary file for appending text file for reading and writing text file for writing and reading text file for appending and reading binary file for reading and writing binary file for writing and reading binary file for appending and reading
• Text-file :
diinterpretasikan sebagai suatu sequence dari karakter-karakter teks.
Binary-file :
diinterpretasikan sebagai suatu sequence dari byte.
Text-file lebih portable , tetapi binary-file lebih cepat untuk diproses.
• UNIX tidak membedakan text-file dan binary-file.
MS-DOS membedakan.
• Untuk file yang dibuka dengan modus yang mengandung + , antara operasi
baca dan tulis perlu diselingi dengan call ke salah satu fungsi-fungsi berikut :
fflush, fseek, fsetpo, rewind.
• Suatu file yang sedang diproses dikaitkan dengan suatu variabel (indikator
posisi file) yang berisi file-offset , yaitu suatu nilai yang menyatakan posisi
byte yang sedang dibaca atau ditulis terhadap posisi awal file.
• Biasanya suatu file diproses dari awal file ke akhir file secara sekuensial.
Tetapi file dapat juga diakses secara random. Caranya : indikator posisi file
itu diberi nilai yang sesuai, dengan memakai fungsi-fungsi :
int fseek(FILE *fp, long offset, int patokan) ;
Halaman 67
long ftell(FILE *fp) ;
void rewind (FILE *fp) ;
int fgetpos (FILE *fp, fpos_t *pos) ;
int fsetpos (FILE *fp, const fpos_t *pos) ;
• Fungsi fscanf dan fprintf dipakai untuk memproses file (melakukan I/O)
menurut format tertentu. Untuk memproses file secara mentah (unformatted
I/O) , kita dapat gunakan fungsi fread dan fwrite.
size_t fread (void *ptr,
size_t ukuran,
size_t jumlah,
FILE *fp ) ;
Fungsi fread membaca maksimum jumlah * ukuran byte dari file yang
ditunjuk oleh fp dan menyimpannya dalam array yang ditunjuk oleh ptr. Nilai
yang dikembalikkan adalah jumlah unsur yang berhasil ditransfer (bias kurang
dari jumlah , jika end-of-file muncul) . jika end-of-file dijumpai , maka indikator
end-of-file dibuat on. Jika ukuran atau jumlah bernilai nol, maka fread tidak
melakukan apa-apa kecuali mengembalikan nilai nol.
size_t fwrite (conts void *ptr,
size_t ukuran,
size_t jumlah,
FILE *fp ) ;
Fungsi fwrite melakukan kebalikan dari fread. Jika nilai yang dikembalikan
kurang dari jumlah , berarti ada error. Jika ukuran atau jumlah bernilai nol ,
maka fwrite tidak melakukan apa-apa kecuali mengembalikan nilai nol.
Halaman 68
/ * membuat suatu file untuk diakses secara random
* /
#include <stdio.h>
#include <stdio.h>
#define JMLrecord 100
typedef struct {
int nomor ;
char nama[20] ;
char alamat [25] ;
int nilai
} MHS ;
main ( )
{
int i ;
MHS blankrecord = {0 , “ “ , “ “ , 0) ;
FILE *fp ;
fp = fopen (“mhs.dat”, “wb”) ;
if (fp = = NULL) {
fprintf (stderr , “Tidak berhasil buka file,\n) ;
exit (EXIT_FAILURE) ;
}
for (i = 1 ; i < = JMLrecord; i++)
fwrite (&blankrecord, sizeof (MHS) , 1 , fp) ;
fclose (fp) ;
printf (“*** Selesai***\n”) ;
return 0 ;
}
Halaman 69
/ * menulis ke file yang dibuat pakai program sebelum ini * / #include <stdio.h> #include <stdio.h> #define JMLrecord 100 typedef struct {
int nomor ; char nama[20] ; char alamat [25] ; int nilai
} MHS ; main ( ) {
MHS mahasiswa ; FILE *fp ; fp = fopen (“mhs.dat”, “rb+”) ; if (fp = = NULL) {
fprintf (stderr , “Tidak berhasil buka file,\n) ; exit (EXIT_FAILURE) ;
} printf (“Ketika nomor mahasiswa” “ (1 s / d %d, 0 untuk berhenti) \n? “, JMLrecord); scanf (“%d”, &mahasiswa.nomor) ; while (mahiswa.nomor ! = 0) {
printf (“Ketik nama , alamat , nilai\n? “) ; scanf (“%s%s%d”, mahasiswa.nama, mahasiswa.alamat, &mahasiswa.nilai) ; fseek (fp, (mahasiswa.nomor - 1) * sizeof(MHS), SEEK_SET) ; fwrite (&mahasiswa, sizeof (MHS) , 1, fp) ; printf (“Ketikan nomor mahasiswa\n? “) ; scanf (“%d”, &mahasiswa.nomor) ;
} fclose (fp) ; return 0 ;
}
Halaman 70
Tampilan program:
Ketik nomor mahasiswa (1 s / d 100, 0 untuk berhenti) ? 45 Ketik nama , alamat , nilai ? Unyil Depok 78 Ketik nomor mahasiswa ? 12 Ketik nama , alamat , nilai ? Melani Menteng 63 Ketik nomor mahasiswa ? 69 Ketik nama , alamat , nilai ? Ogah Tebet 71 Ketik nomor mahasiswa ? 0
/ * membaca file yang diisi pakai program sebelum ini * /
#include <stdio.h>
#include <stdio.h>
#define JMLrecord 100
typedef struct {
int nomor ;
char nama[20] ;
char alamat [25] ;
int nilai
} MHS ;
main ( )
{
MHS mahasiswa ;
FILE *fp ;
fp = fopen (“mhs.dat”, “rb+”) ;
if (fp = = NULL) {
fprintf (stderr , “Tidak berhasil buka file,\n) ;
Halaman 71
exit (EXIT_FAILURE) ;
}
printf (“%-6s%-21s%-26s%7s\n” , “Nomor” ,
“Nama mahasiswa” , “Alamat Mahasiswa” ,
“Nilai”) ;
fread (&mahasiswa, sizeof (MHS) , 1 , fp) ;
while (!feof (fp) ) {
if (mahasiswa.nomor != 0)
printf (“%-6d%-21s%-26s%7d\n” ,
mahasiswa.nomor , mahasiswa.nama,
mahasiswa.alamat , mahasiswa.nilai ) ;
fread (&mahasiswa, sizeof (MHS) , 1 , fp) ;
}
fclose (fp) ;
return 0 ;
}
Contoh output :
Dalam standard-library stdio tersedia fungsi tmpfile yang membuka suatu file
sementara dalam modus “wb+” . File sementara ini akan dihapus secara otomatis
pada akhir eksekusi program. File ini juga akan dihapus apabila ia ditutup dengan
fclose.
Program berikut ini memperlihatkan contoh penggunaan fungsi tmpfile.
Nomor Nama Mahasiswa Alamat Mahasiswa Nilai 12 Melani Menteng 63 45 Unyil Depok 78 69 Ogah Tebet 71
Halaman 72
#include <stdio.h>
main ( )
{
FILE *pf , *pfsem ;
char nama[15] ;
int c , bil1 , bil2 ;
printf (“Ketikkan nama file yang berisi \n”
“pasangan-pasangan bilangan bulat : \n” ) ;
scanf (“%s” , nama ) ;
pf = fopen (nama , “r+”) ;
if (pf = = NULL) {
printf (“Tidak berhasil buka file %s.\n” ,
nama ) ;
exit (EXIT_FAILURE) ;
}
pfsem = tmpfile ( ) ; /* buka file sementara * /
if (pfsem = = NULL) {
printf (“Tidak bias buka file sementara.\n”) ;
exit (EXIT_FAILURE) ;
}
fscanf (pf , “%d%d” , &bil1 , &bil2 ) ;
while (!feof (pf) ) {
fprintf (pfsem ,“%d + %d = %d\n” , bil1 , bil2, bil1 + bil2 ) ;
fscanf(pf , %d%d” , &bil1 , &bil2 ) ;
}
rewind (pf) ; rewind (pfsem) ; /* balik ke awal * /
while ( (c = fgetc(pfsem) ) ! = EOF ) {
fputc (c , pf) ;
}
fclose (pf) ; fclose (pfsem) ;
return 0 ;
}
Halaman 73
Jika file masukan berisi :
-8 102
36 69
225 -25
maka pelaksanaan program tsb dengan file masukan akan mengubah isi file
masukan menjadi :
-8 + 102 = 94
36 + 69 = 105
225 + -25 = 200
Halaman 74
MODUL 16
PREPROSESSOR
Preprocessor
Ada satu tahap yang dilalui oleh suatu program C sebelum ia dikompilasi
menurut tata bahasa C, yaitu tahap preprocessing yang dilakukan oleh
preprocessor C. Preprocessing ini mengolah baris-baris program yang dimulai
dengan tanda # .
# mengawali suatu preprocessor directive .
Kita sudah sering menggunakan preprocessor-directive :
#include <namafile>
atau
#include “namafile”
Directive #include menyuruh preprocessor menaruh salinan dari suatu file
ditempat directive tsb
Jika nama file diapit tanda < > , maka preprocessor akan mencari file itu dalam
directory-directory baku tertentu menurut system , misalnya /user/include dalam
UNIX.
Jika nama file diapit tanda “ “ , maka preprocessor akan mencari file itu dalam
directory dimana file yang sedang dikompilasi itu berada.
• Contoh :
#include < stdio . h >
#include “msort . h”
#include “abc . c”
• Directive #include sangat berguna untuk program besar yang terdiri dari
berbagai .h file dan .c file.
• Direvtive dengan #define dapat muncul dalam 2 bentuk :
#define identifier tekspengganti
Halaman 75
#define identifier ( identifier , . . . . ., identifier) tekspengganti
Untuk setiap directive #define bentuk pertama ,
Preprocessor mengganti setiap keberadaan identifier setelah directive itu
dengan tekspengganti sebelum program dikompilasi .
Contoh :
#define PI 3.14
Menyuruh preprocessor mengganti setiap konstanta simbolik PI yang muncul
setelah directive tsb dengan 3.14 sebelum program dikompilasi.
Mekanisme ini berguna untuk memperjelas program dan mempermudah
perubahan konstanta . tetapi hati-hati, semua teks yang muncul setelah
identifier pertama akan dianggap sebagai teksPengganti .
• Directive #define bentuk kedua berguna untuk membuat macro.
Macro adalah suatu nama (bias punya argumen) yang diasosiasikan dengan
suatu teks pengganti. Teks pengganti ini dapat menyatakan suatu operasi.
Macro tanpa argumen berlaku sebagai konstanta simbolik.
Untuk macro yang berargumen , argument-argumennya disubstitusikan dalam
eks pengganti pada waktu macro itu di-expand oleh preprocessor.
(di-expand, maksudnya, identifier dan argument-argumennya digantikan oleh
teks pengganti dalam program .)
Contoh:
#define kuadrat ( x ) ( ( x ) * ( x ) )
Setelah itu dalam program dapat ditulis
x = kuadat ( a + b );
yang akan di-expand menjadi
x = ( ( a + b ) * ( a + b ) );
Halaman 76
Perhatian definisi-definisi berikut mengandung masalah:
#define kuadrat ( x ) x*x
#define kuadrat ( x ) ( ( x ) * ( x ) )
#define kuadrat ( x ) ( x ) *( x )
#define kuadrat ( x ) ( ( x ) * ( x ) );
• Macro sering dipakai untuk menggantikan pemanggilan fungsi dengan inline –
code. inline – code lebih efisien karena tidak perlu melalui proses pemanggilan
fungsi yang cukup memakan waktu.
Fungsi-fungsi dari standard-library sering didefinisikan sebagai macro,
misalnya getchar dalam stdio. h didefinisikan sebagai berikut:
#define getchar ( ) getc (stdin)
Contoh lagi:
#define min ( x,y ) ( ( ( x ) < ( y ) ? ( x ) : ( y )
membuat macro yang dapat dipakai untuk mencari minimum dari dua nilai.
• Definisi dari suatu macro dapat dihapus dengan directive:
ss
#undef identifier
• Perhatian ekspresi dengan efek sampingan jangan dipakai sebagai argumen
bagi macro,karena argument macro mungkin dievaluasi lebih dari satu kali.
Contoh:
min (i++,j++) /* tidak benar! */
Halaman 77
DAFTAR PUSTAKA 1. H.M. Deitel & P.J. Deitel. C: How to program. 2nd edition. Prentice Hall 2. Brian W Kernighan and Dennis M Ritche. The C Programming Language,
Prentice Hall, Second edition 3. Paul M Embree and Bruce Kimble, C Language Algorithms for Digital Signal
Processing, Printice Hall 4. Catatan Kuliah Konsep Pemrograman