P07 | Konstanta, Makro, Struktur, dan Kelas Modul Praktikum FI2283 Pemrograman dan Simulasi Fisika Versi 2013.10.22
Catatan. Dalam praktikum ini akan dipelajari mengenai konstanta, makro, struktur, operator overloading, kelas, dan mencantumkannya dalam berkas pustaka sendiri (*.h). 1 Konstanta
89
2 Makro
91
3 Lebih lanjut dengan makro
91
4 Makro multi baris
92
5 Penggunaan makro yang tidak dianjurkan
93
6 Struktur
94
7 Fungsi dengan masukan suatu struktur
96
8 Operator overloading
98
9 Kelas
100
10 Berkas header
104
1
Konstanta
Konstanta adalah suatu variabel yang nilainya dijaga tetap dalam program. Konstanta dapat berjenis variabel apa saja. Dalam mendefisikan suatu konstanta digunakan kata simpanan const sebelum jenis variabel digunakan, seperti 89
const int x = 100; di mana x merupakan suatu konstanta berjenis int yang bernilai 100. Jenis variabel lain seperti double, bool, dan char dapat juga didefinisikan sebagai suatu konstanta. Perhatikan kode berikut ini /* constant.cpp Learn about constant in C++ Sparisoma Viridi
20131022.1955 Compile: g++ constant.cpp -o constant Execute: ./constant */ #include using namespace std; int main(int argc, char *argv[]) { int a = 10; cout << "a = " << a << endl; a = 22; cout << "a = " << a << endl; const int b = 123; cout << "b = " << b << endl; b = 1000; cout << "b = " << b << endl; return 0; } Tugas 1. Salin kode di atas dengan nama berkas constant.cpp, kompilasi, dan jalankan. Jelaskan apa yang terjadi dan mengapa hasil tersebut diperoleh. Laporkan dalam berkas laporan.txt. Bila terdapat pesan kesalahan tunjukkan pada baris mana dan mengapa.
90
2
Makro
Makro adalah frasa yang diwakili oleh suatu identifier, yang saat program dikompilasi akan disisipkan dalam program menggantikan identifier tersebut. Sebagai contoh perhatikan potongan kode berikut ini #define HELLO "Hello world!" yang berarti, apabila terdapat identifier HELLO dalam bagian manapun dalam program akan digantikan dengan frasa ”Hello world!”. Perhatikan kode berikut ini /* macro1.cpp Learn about macro in C++ Sparisoma Viridi 20131022.2022 Compile: g++ macro1.cpp -o macro1 Execute: ./macro1 */ #include using namespace std; #define HELLO "Hello world!" int main(int argc, char *argv[]) { cout << HELLO << endl; return 0; } Tugas 2. Salin kode di atas dengan nama berkas macro1.cpp, kompilasi, dan jalankan. Jelaskan apa yang terjadi dan laporkan dalam berkas laporan.txt.
3
Lebih lanjut dengan makro
Dalam contoh sebelumnya, makro Hello digantikan oleh suatu frasa yang ditampilkan dalam konsol. Apakah perintah C++ juga dapat dimasukkan dalam makro sebagai bagian dari frasa? Jawabnya adalah ya. Untuk itu perhatikan kode berikut ini 91
/* macro2.cpp Learn more about macro in C++ Sparisoma Viridi 20131022.2133 Compile: g++ macro2.cpp -o macro2 Execute: ./macro2 */ #include using namespace std; #define HELLO "Hello world!" << endl; int main(int argc, char *argv[]) { cout << HELLO return 0; } Tugas 3. Salin kode di atas dengan nama berkas macro2.cpp. Sebelum melakukan kompilasi perkirakan apa yang akan diperoleh saat kompilasi dengan menuliskannya dalam laporan.txt. Kemudian lakukan kompilasi dan jalankan program tersebut. Jelaskan lebih lanjut apa yang terjadi dan laporkan dalam berkas laporan.txt. Apakah telah dapat mengerti fungsi dari makro?
4
Makro multi baris
Suatu makro akan digantikan oleh frasa sampai akhir baris tersebut atau bila terdapat karakter ’\’ akan diikuti sampai baris berikutnya, sampai tidak lagi terdapat karakter tersebut. Untuk jelasnya perhatikan potongan kode berikut ini. /* macro3.cpp Learn more about macro in C++ Sparisoma Viridi 20131022.2133 Compile: g++ macro3.cpp -o macro3 Execute: ./macro3 92
*/ #include using namespace std; #define HELLO "Hello world!" << endl; \ cout << "This is the other line" << endl; int main(int argc, char *argv[]) { cout << HELLO return 0; } Tugas 4. Salin kode di atas dengan nama berkas macro3.cpp. Sebelum melakukan kompilasi perkirakan apa yang akan diperoleh saat kompilasi dengan menuliskannya dalam laporan.txt. Kemudian lakukan kompilasi dan jalankan program tersebut. Jelaskan lebih lanjut apa yang terjadi dan laporkan dalam berkas laporan.txt. Apakah telah dapat mendefinisikan makro multi baris?
5
Penggunaan makro yang tidak dianjurkan
Perhatikan potongan kode berikut ini /* macro4.cpp Learn more about macro in C++ Sparisoma Viridi 20131022.2150 Compile: g++ macro4.cpp -o macro4 Execute: ./macro3 */ #include using namespace std; #define NOT_RECOMMENDED_USE_OF_MACRO \ int main(int argc, char *argv[]) { \ \ cout << "Hello world" << endl;\ 93
\ return 0;\ } NOT_RECOMMENDED_USE_OF_MACRO
Tugas 5. Salin kode di atas dengan nama berkas macro4.cpp. Sebelum melakukan kompilasi perkirakan apa yang akan diperoleh saat kompilasi dengan menuliskannya dalam laporan.txt. Kemudian lakukan kompilasi dan jalankan program tersebut. Jelaskan lebih lanjut apa yang terjadi dan laporkan dalam berkas laporan.txt. Walaupun program di atas dapat bekerja, akan tetapi cara pemanfaatan makro seperti di atas tidak dianjurkan.
6
Struktur
Terdapat suatu kondisi di mana variabel yang dimanipulasi memerlukan struktur yang dapat menjelaskan makna dari variabel tersebut, misalnya saja besaran vektor ˆ ~r = xˆi + yˆj + z k,
(1)
di mana x, y, dan z merupakan bagian dari r. C dan C++ memperbolehkan suatu variabel memiliki anggota. Jenis variabel ini disebut sebagai struktur yang didefinisikan menggunakan kata simpanan struct. Untuk vektor dalam Persamaan (1) dapat dibuat suatu sruktur dengan cara struct vect3 { double x; double y; double z; }; Perhatikan kode berikut ini, yang menggunakan struktur vect3 di atas /* structure1.cpp Learn about structure in C++ Sparisoma Viridi 20131023.0527 Compile: g++ structure1.cpp -o structure1 Execute: ./structure1 94
*/ #include #include <sstream> #include <math.h> using namespace std; struct vect3 { double x; double y; double z; }; int main(int argc, char *argv[]) { // Declare a variable with type of vect3 vect3 r1; r1.x = -3.2; r1.y = 4.3; r1.z = 1001.9; // Display the variabel value cout << "r1 = (" << r1.x << ", "; cout << r1.y << ", " << r1.z; cout << ")" << endl; // Declare a variable with type of vect3 vect3 r2 = {1.0, -3.5, 100.01}; // Display the variabel value cout << "r2 = (" << r2.x << ", "; cout << r2.y << ", " << r2.z; cout << ")" << endl; return 0; } Tugas 6. Salin kode di atas dengan nama berkas structure1.cpp. Sebelum melakukan kompilasi perkirakan apa yang akan diperoleh saat kompilasi dengan menuliskannya dalam laporan.txt. Kemudian lakukan kompilasi dan jalankan program tersebut. Jelaskan lebih lanjut apa yang terjadi dan laporkan dalam berkas laporan.txt.
95
7
Fungsi dengan masukan suatu struktur
Sebagaimana telah dibahas dalam praktikum sebelumnya, bahwa sebuah fungsi dapat menerima parameter masukan berupa jenis variabel apa saja, termasuk struktur. Pada contoh dalam bagian ini diberikan fungsi yang menerima parameter berupa struktur, untuk kemudian menampilkannya. Hal ini dimaksudkan pula sebagai ilustrasi dari peran suatu fungsi, yaitu melakukan pekerjaan sederhana yang berulang-ulang. Pekerjaan yang dimaksud dalam hal ini adalah // Display the variabel value cout << "r1 = (" << r1.x << ", "; cout << r1.y << ", " << r1.z; cout << ")" << endl; yang dapat disederhanakan menjadi // Display the variabel value cout << "r1 = "; disp(r1); Untuk mendapatkan pemahaman yang lebih teknis, perhatikan kode berikut ini /* structure2.cpp Learn about structure in C++ Sparisoma Viridi 20131023.0525 Compile: g++ structure2.cpp -o structure2 Execute: ./structure2 */ #include #include <sstream> #include <math.h> using namespace std; struct vect3 { double x; double y; double z; }; void disp(vect3); 96
int main(int argc, char *argv[]) { // Declare a variable with type of vect3 vect3 r1 = {1.0, 0.0, 100.01}; // Display value of a vect3 type variable cout << "r1 = "; disp(r1); return 0; } void disp(vect3 r) { // Get x component double x = r.x; stringstream comp_x; if(x != 0) { comp_x << x; } // Get y component double y = r.y; stringstream comp_y; if(y < 0) { comp_y << " - " << fabs(y); } else if(y > 0) { comp_y << " + " << y; } // Get z component double z = r.z; stringstream comp_z; if(z < 0) { comp_z << " - " << fabs(z); } else if(z > 0) { comp_z << " + " << z; } // Merge all components stringstream all_comps; if(x != 0) all_comps << comp_x.str() << " |i>"; if(y != 0) all_comps << comp_y.str() << " |j>"; if(z != 0) all_comps << comp_z.str() << " |k>"; // Display merged result 97
cout << all_comps.str() << endl; }
Tugas 7. Salin kode di atas dengan nama berkas structure2.cpp. Lakukan kompilasi dan jalankan program tersebut. Jelaskan bagaimana fungsi di atas dapat membuat tanda negatif suatu komponen tidak lagi dekat dengan bilangannya dan dapat tidak menampilkan komponen yang bernilai nol. Tuliskan penjelasan Anda dalam berkas laporan.txt.
8
Operator overloading
Bila vektor dibicarakan, terikut pula bagaimana vektor tersebut dioperasikan. Salah satunya adalah operasi penjumlahan. Apakah potongan kode berikut ini dapat bekerja? vect3 a = {1, 2, 3}; vect3 b = {4, 5, 6}; vect3 c = a + b; Jawabnya ya. Akan tetapi hal ini memerlukan pendefinisian baru dari operator penjumlahan ’+’ yang semula tidak bekerja untuk struktur yang baru dibuat ini, yaitu vect3. Pendefinisian baru bagaimana suatu operator yang telah ada dapat melakukan fungsi lain untuk suatu jenis variabel disebut sebagai operator overloading. Dalam kode berikut ini akan disajikan bagaimana penjumlahan vektor dapat dilakukan dengan menggunakan fungsi dan vektor. /* operator1.cpp Learn about overloading operator in C++ Sparisoma Viridi 20131023.0557 Compile: g++ operator1.cpp -o operator1 Execute: ./operator1 */ #include #include <sstream> #include <math.h> using namespace std; 98
struct vect3 { double x; double y; double z; }; string str(vect3); vect3 add(vect3, vect3); vect3 operator+(vect3, vect3); int main(int argc, char *argv[]) { vect3 p1 = {1, 1, 1}; vect3 p2 = {1, -1, -2}; vect3 p3 = add(p1, p2); cout << str(p1) << " + "; cout << str(p2) << " = "; cout << str(p3) << endl; vect3 p4 = p1 + cout << str(p1) cout << str(p2) cout << str(p4)
p2; << " + "; << " = "; << endl;
return 0; } // Add two vect3 using a function vect3 add(vect3 r1, vect3 r2) { vect3 r3; r3.x = r1.x + r2.x; r3.y = r1.y + r2.y; r3.z = r1.z + r2.z; return r3; } // Add two vect3 using an operator vect3 operator+(vect3 r1, vect3 r2) { vect3 r3; r3.x = r1.x + r2.x; r3.y = r1.y + r2.y; r3.z = r1.z + r2.z; return r3; } 99
// Convert a vect3 to a string representation string str(vect3 r) { stringstream all_comps; all_comps << "("; all_comps << r.x << ", "; all_comps << r.y << ", "; all_comps << r.z << ")"; return all_comps.str(); } Tugas 8. Salin kode di atas dengan nama berkas operator1.cpp. Lakukan kompilasi dan jalankan program tersebut. Modifikasi program tersebut sehingga dapat menghitung pengurangan dua buah vektor, jelaskan modifikasi yang dilakukan dalam dalam berkas laporan.txt dan simpan hasil modifikasi dalam berkas operator2.cpp.
9
Kelas
Penggabungan struktur dan fungsi yang khusus hanya bekerja pada struktur tersebut disebut sebagai kelas. Dalam kelas pun dapat didefinisikan suatu operator untuk struktur tersebut. Dengan menggunakan kelas, keberlakukan suatu fungsi dapat dibatasi hanya berlaku untuk kelas tersebut. Dalam suatu kelas, anggotanya yang dapat berubah jenis variabel ataupun fungsi dapat dibedakan menjadi tiga macam, yaitu public, protected, dan private, yang bergantung dengan variabel mana yang boleh mengaksesnya. Yang pertama dapat diakses oleh variabel manapun, yang kedua hanya dapat diakses oleh variabel dari jenis kelas yang sama, dan yang terakhir hanya dapat diakes oleh variabel itu sendiri. Dalam bahasan ini hanya yang pertama yang akan dicontohkan. Perhatikan contoh berikut ini /* class1.cpp Learn about class in C++ Sparisoma Viridi 20131023.1100 Compile: g++ class1.cpp -o class1 Execute: ./class1 */ #include 100
#include <sstream> #include <math.h> using namespace std; class vect3 { public: double x; double y; double z; vect3(void); vect3(double, double, double); vect3(vect3&); ~vect3(void); string str(void); vect3 operator+(vect3); vect3 operator-(vect3); vect3 operator*(double); friend vect3 operator*(double, vect3); protected: private: }; vect3::vect3(void) { x = 0.0; y = 0.0; z = 0.0; } vect3::vect3(double x_, double y_, double z_) { x = x_; y = y_; z = z_; } vect3::vect3(vect3 &r) { x = r.x; y = r.y; z = r.z; } vect3::~vect3(void) { x = 0.0; y = 0.0; 101
z = 0.0; } string vect3::str(void) { stringstream all_comps; all_comps << "("; all_comps << x << ", "; all_comps << y << ", "; all_comps << z << ")"; return all_comps.str(); } vect3 vect3::operator+(vect3 r) { vect3 s; s.x = x + r.x; s.y = y + r.y; s.z = z + r.z; return s; } vect3 vect3::operator-(vect3 r) { vect3 s; s.x = x - r.x; s.y = y - r.y; s.z = z - r.z; return s; } vect3 vect3::operator*(double a) { vect3 s; s.x = a * x; s.y = a * y; s.z = a * z; return s; } vect3 operator*(double a, vect3 r) { vect3 s; s = r * a; return s; } int main(int argc, char *argv[]) { // Declare without initialization vect3 r1; cout << "Constructor vect3() is used" << endl; 102
cout << r1.str() << endl; cout << endl; // Declare with initialization with double vect3 r2(1.0, 2.0, -3.0); cout << "Constructor vect3(double, double, double) "; cout << "is used" << endl; cout << r2.str() << endl; cout << endl; // Declare with initialization from other vect3 vect3 r3; r3.x = -1.0; r3.y = 7.0; r3.z = 4.0; vect3 r4(r3); cout << "Constructor vect3(vect3) "; cout << "is used" << endl; cout << r4.str() << endl; cout << endl; // Add two variables of type vect3 vect3 r5; r5 = r2 + r4; cout << "Add two variables of type vect3" << endl; cout << r2.str() << " + " << r4.str() << " = "; cout << r5.str() << endl; cout << endl; // Substract two variables of type vect3 vect3 r6; r6 = r2 - r4; cout << "Substract two variables of type vect3" << endl; cout << r2.str() << " - " << r4.str() << " = "; cout << r6.str() << endl; cout << endl; // Multiply vect3 with scalar vect3 r7; double a = 2.0; r7 = r2 * a; cout << "Multiply vect3 with scalar" << endl; cout << r2.str() << " * " << a << " = "; cout << r7.str() << endl; cout << endl;
103
// Multiply scalar with vect3 vect3 r8; double b = 3.0; r8 = b * r2; cout << "Multiply scalar with vect3" << endl; cout << b << " * " << r2.str() << " = "; cout << r8.str() << endl; return 0; }
Tugas 9. Salin kode di atas dengan nama berkas class1.cpp. Lakukan kompilasi dan jalankan program tersebut. Modifikasi program tersebut sehingga dapat menghitung perkalian silang dan perkalian titik dua buah vektor, jelaskan modifikasi yang dilakukan dalam dalam berkas laporan.txt dan simpan hasil modifikasi dalam berkas class2.cpp.
10
Berkas header
Apabila makro, struktur, fungsi, kelas, dan konstanta yang dibuat sering digunakan, tidaklah efesien apabila entitas-entitas tersebut ditulis berulang-ulang dalam setiap berkas program yang dibuat. Untuk itulah terdapat fasilitas untuk membuat berkas header yang dapat dipanggil dengan cara #include "berkas_header.h" Dalam bagian ini, kelas vect3 yang telah dibuat akan disimpan dalam berkas header dengan nama berkas vect3.h. Perhatikan isi dari berkas tersebut /* vect3.h Vector 3-d definition Sparisoma Viridi 20131023.1109 Include: #include "vect3.h" */ #ifndef VECT3_H #define VECT3_H class vect3 { 104
public: double x; double y; double z; vect3(void); vect3(double, double, double); vect3(vect3&); ~vect3(void); string str(void); vect3 operator+(vect3); vect3 operator-(vect3); vect3 operator*(double); friend vect3 operator*(double, vect3); protected: private: }; vect3::vect3(void) { x = 0.0; y = 0.0; z = 0.0; } vect3::vect3(double x_, double y_, double z_) { x = x_; y = y_; z = z_; } vect3::vect3(vect3 &r) { x = r.x; y = r.y; z = r.z; } vect3::~vect3(void) { x = 0.0; y = 0.0; z = 0.0; } string vect3::str(void) { stringstream all_comps; all_comps << "("; 105
all_comps << x << ", "; all_comps << y << ", "; all_comps << z << ")"; return all_comps.str(); } vect3 vect3::operator+(vect3 r) { vect3 s; s.x = x + r.x; s.y = y + r.y; s.z = z + r.z; return s; } vect3 vect3::operator-(vect3 r) { vect3 s; s.x = x - r.x; s.y = y - r.y; s.z = z - r.z; return s; } vect3 vect3::operator*(double a) { vect3 s; s.x = a * x; s.y = a * y; s.z = a * z; return s; } vect3 operator*(double a, vect3 r) { vect3 s; s = r * a; return s; } #endif
di mana berkas header tersebut dipanggil oleh program di bawah ini /* class3.cpp Learn about class and header file in C++ Sparisoma Viridi 20131023.1151 106
Compile: g++ class3.cpp -o class3 Execute: ./class3 */ #define PI 3.141529 const double fx = 1.0; const double fy = 2.0; const double A = 1.0; #include #include #include #include
<sstream> <math.h>
using namespace std; #include "vect3.h" // Define function of acceleration vect3 acc(double t); int main(int argc, char *argv[]) { double T = max(1.0/fx, 1.0/fy); double tmin = 0.0; double tmax = 2.0 * T; double N = 1000; double dt = (tmax - tmin) / N; char ofn[] = "data.txt"; ofstream fout; fout.open(ofn); double t = tmin; fout << "#t\tx\ty\tz" << endl; while(t < tmax + dt) { vect3 a; a = acc(t); fout fout fout fout
<< << << <<
t << "\t"; a.x << "\t"; a.y << "\t"; a.z << endl;
t += dt; } 107
fout.close(); return 0; } vect3 acc(double t) { // Acceleration in x and y direction double ax = A * sin(2 * PI * fx * t); double ay = A * sin(2 * PI * fy * t); double az = 0.0; vect3 buf(ax, ay, az); return buf; }
Tugas 10. Salin kode di atas dengan nama berkas class3.cpp. Lakukan kompilasi dan jalankan program tersebut. Modifikasi program tersebut sehingga dapat menghasilkan pola-pola Lissajous yang lain. Buat empat macam pola dan terangkan bagaimana pola terkait dengan nilai fx /fy . Laporkan hasil pengamatan Anda dalam berkas class2.cpp. Untuk mendapatkan gambar dalam format EPS gunakan script di bawah ini bila perlu, sebagaimana ditampilkan hasil dari class3.cpp pada Gambar 1. # # # # # # #
plot-xy.gps Sparisoma Viridi 20131023.1157 Execute: gnuplot plot-xy.gps
set output "data.eps" set size 0.8, 1.1 set term post eps enhanced color font 24 set xlabel "{/Italics a_x}" set xtics 0.25 set xrange [-1.1:1.1] set ylabel "{/Italics a_y}" set ytics 0.25 set yrange [-1.1:1.1] set grid 108
1 0.75 0.5
ay
0.25 0 -0.25 -0.5 -0.75 -1 -1 -0.75-0.5-0.25 0 0.25 0.5 0.75 1 ax Gambar 1: Lissajous dengan fx /fy = 2.
plot "data.txt" u 2:3 every 5 title "" ps 2 pt 4
Keluaran praktikum 1. constant.cpp, macro1.cpp, macro2.cpp, macro3.cpp, macro4.cpp, structure1.cpp, structure2.cpp, operator1.cpp, operator2.cpp, class1.cpp, class2.cpp, class3.cpp, vect3.h, dan data.txt. 2. laporan.txt yang berisikan jawaban dari Tugas 1-10.
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. 1 1 Sparisoma
Viridi , .., 2013
109
.
110