Anda di halaman 1dari 77

Modul Perkuliahan

PTE114 Dasar Komputer dan Pemrograman


Program Studi S1 Pendidikan Teknik Elektro

Oleh:
Djuniadi

JURUSAN TEKNIK ELEKTRO


FAKULTAS TEKNIK
UNNES
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 2
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 3
• 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 4
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 5
• 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 6
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 7
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 8
Outputnya :

Nilai (value) dari variabel j = 1


Alamat (address) dari variabel j = f7fffba4

Halaman 9
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 10
/ * 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 11
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 12
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 13
/ * Bermaksud mempertukarkan nilai dari dua variabel
tetapi tidak berhasil * /
void tukar (int p, int r)
{
int sementara ;
sementara = p ;
p = r;
r = sementara ;
}
Output :

3 5

/ * 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 ;
}

Halaman 14
Output :

5 3

• 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 [ ] ) ;

Halaman 15
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 16
• 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 17
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 Pass Pass Pass Pass Pass Pass Pass
awal ke 1 ke 2 ke 3 ke 4 ke 5 ke 6 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 18
for ( i = awal ; i < = akhir-1; i++)
Taruh unsur terkecil ke i dalam A [i]

Halaman 19
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 20
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 21
/*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 22
/*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 23
• 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 :

#include < stdio . h >


main ( )
{
int c :
c = getchar ( ) ;
while ( c != EOF ) {
putchar ( c ) ;
c = getchar ( ) ;
}
return 0 ;
}

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 ;
}

Halaman 24
/*
* 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 25
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 26
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 27
Program C

Stream

File

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.

Halaman 28
/ * 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


-3 11
file keluaran . txt
-3 + 11 = 8

• 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 )

Halaman 29
• 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 30
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 31
• 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 32
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
-N
1/X 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 33
Berapakah pangkat (4.0 , -2) ?

pangkat (4.0 , 0)
return 1.0

1.0

pangkat (4.0 , 2)
return (4.0 * pangkat (4.0 , 0) )
4.0

pangkat (4.0 , 2)
return (4.0 * pangkat (4.0 , 1) )

16.0

pangkat (4.0 , 2)
return (4.0 * pangkat (4.0 , 2) )

0.0625

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

Halaman 34
/ * 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 35
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 36
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 37
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 38
Output :

Unyil 129400000 12 1
Unyil 129400000 12 1
Unyil 129400000 12 1
Melani 129300000 12 2

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” ;

Halaman 39
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 40
• 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
s1 s2

100 275

Halaman 41
Outputnya :
s1.data = 100
s2.data = 275
psim->data = 100
psim->next->data = 275

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.

Halaman 42
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 43
Output :
psim ->data = 100
psim ->next ->data = 275
psim1 ->data = 275
Setelah psim1=psim, psim ->data = 100

Halaman 44
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 45
Menyisipkan suatu unsur di posisi setelah unsur tertentu

Sebelum : . . . ‘A’ ‘C’ ...

P
Q ‘B’

Sesudah : . . . ‘A’ ‘C’ ...

P Q : next
Q ‘B’

Q ->next = P ->next;
P ->next = Q

Menyisipkan suatu unsur antara dua unsur tertentu yang berurutan

Sebelum : . . . ‘A ‘C’ ...

P R

‘B’
Q

‘A’ ‘C’
Sesudah : . . . ...

P R

Q ‘B’

P->next = Q
Q ->next = R

Halaman 46
Menghapus unsur di posisi setelah unsur tertentu

Sebelum :
... ‘A’ ‘B’ ‘C’ ...

P Q

Sesudah :
... ‘A’ ‘B’ ‘C’ ...

P Q

P ->next = P ->next ->next;


Free (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

Halaman 47
#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 48
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 49
/*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 50
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 51
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.

27 23 30 36 19 12 34

bagi

27 23 30 19 12 34
bagi bagi
27 23 30 36 19 12 34

bagi bagi bagi


27 23 30 36 19 12
merge merge merge

23 27 30 36 12 19

merge merge

23 27 30 36 12 19 34
merge

12 19 23 27 30 34 36
Pemanggilan Pemanggilan
rekursif rekursif

Halaman 52
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 53
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 54
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 55
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 56
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 57
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 58
/ * 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 59
Output :

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

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 ) ) ;
?

Halaman 60
• 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 61
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 62
• 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 63
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 64
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 65
MODUL 15
OPERASI FILE

Mengingat operasi File


• Suatu file dapat dibuka pakai fungsi fopen dalam berbagai modus :
Modus Arti
“r” text file for reading
“w” text file for writing
“a” text file for appending
“rb” binary file for reading
“wb” binary file for writing
“ab” binary file for appending
“r+” text file for reading and writing
“w+” text file for writing and reading
“a+” text file for appending and reading
“rb+” binary file for reading and writing
“wb+” binary file for writing and reading
“ab+” 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 66
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 67
/ * 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 68
/ * 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 69
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 70
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 :

Nomor Nama Mahasiswa Alamat Mahasiswa Nilai


12 Melani Menteng 63
45 Unyil Depok 78
69 Ogah Tebet 71

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.

Halaman 71
#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 72
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 73
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 74
#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 75
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 76
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

Halaman 77

Anda mungkin juga menyukai