Friday, December 23, 2016

Bab 7. C++ Untuk Programer




Bab. 7 Masukan/Keluaran Aliran

Tujuan Instruksional
      ·         Header pustaka iostream.
      ·         Keluaran aliran.
      ·         Masukan aliran.
      ·         I/O tak-terformat read, write, dan gcount.
·         Pengenalan manipulator aliran.
·         Keadaan format aliran.
·         Keadaan error aliran.




7.1 Introduksi

Pustaka standard C++ menyediakan kapabilitas masukan/keluaran yang kaya. Bab ini akan mendiskusikan berbagai kapabilitas yang umumnya dipakai di dalam operasi I/O. Hampir semua fitur I/O yang akan didiskusikan berorientasi-objek. Hal ini akan memanfaatkan beberapa fitur C++ yang lain, seperti referensi, overloading fungsi dan overloading operator. Setiap operasi I/O dieksekusi dengan suatu cara yang sensitif terhadap tipe data. Jika suatu fungsi telah didefinisikan untuk menangani tipe data tertentu, maka fungsi anggota itu akan dipanggil untuk menangani tipe data tersebut.

Pengguna dapat menspesifikasi bagaimana melakukan operasi I/O untuk objek dengan tipe yang didefinisikan sendiri oleh pengguna. Hal ini dilakukan dengan mengoverload operator penyisipan aliran (<<) dan operator ekstraksi aliran (>>). Kemampuan ini merupakan salah satu fitur paling penting di dalam C++.

7.2 Aliran
I/O C++ terjadi di dalam aliran, yang merupakan runtun byte. Di dalam operasi masukan, byte-byte tersebut mengalir dari suatu divais (misalnya papanketik, disk drive, koneksi jaringan, dan lainnya) ke memori utam. Di dalam operasi keluaran, byte-byte mengalir dari memori utama ke suatu divais (misalnya layar, printer, disk drive, koneksi jaringan, dan lainnya).

Byte dapat merepresentasikan karakter, data mentah, citra, suara digital, video digital, atau informasi lain yang dibutuhkan oleh suatu aplikasi. Mekenisme I/O sistem harus memindahkan runtun byte dari divais ke memori utama (dan sebaliknya) secara konsisten dan handal. Pemindahan semacam itu seringkali melibatkan putaran mekanikal, seperti rotasi cakram atau tape. Waktu yang dibutuhkan pemindahan seperti ini secara umum jauh lebih besar daripada waktu yang diperlukan oleh processor untuk memanipulasi data secara internal.

C++ menyediakan kedua kapabilitas “level-rendah” dan “level-tinggi”. Kapabilitas I/O level-rendah (yaitu, I/O tak-terformat) menspesifikasi jumlah byte yang akan dipindahkan divais-ke-memori atau memori-ke-divais. Pada pemindahan semacam itu, byte secara individu merupakan fokus pekerjaan. Kapabilitas level-rendah mendukung pemindahan data berkecepatan tinggi.
Programer umumnya menyukai kapabilitas level-tinggi (I/O terformat), dimana byte-byte dikelompokkan menjadi unit-unit seperti integer, angka-pecahan, karakter, string, dan tipe yang didefinisikan pengguna. Kapabilitas berorientasi-tipe ini jauh lebih disukai di dalam operasi I/O dibandingkan dengan kapabilitas level-rendah.

7.2.1 Objek dan Kelas Aliran Masukan/Keluaran
Pustaka iostream menyediakan banyak template untuk menangani operasi-operasi I/O. Sebagai contoh, template kelas basic_istream mendukung operasi masukan-aliran, template kelas basic_ostream mendukung operasi aliran-keluaran, dan template kelas basic_iostream mendukung kedua aliran-masukan dan aliran-keluaran. Setiap template mempunya spesialisasi template terdefinisi yang memampukan operasi I/O char. Selain itu, pustaka iostream menyediakan sehimpunan typedef untuk memberikan nama-nama alias bagi spesialisasi template. Penspesifikasi typedef mendeklarasikan sinonim (nama alias) untuk tipe data tertentu. Anda akan sering melihat penggunaan typedef untuk menciptakan nama tipe data yang lebih mudah dibaca dan yang lebih pendek. Sebagai contoh, statemen

typedef Kartu *KartuPtr;

mendefinisikan nama alias, KartuPtr, sebagai sinonim untuk tipe Kartu *. Penciptaan nama alias menggunakan typedef tidak berarti menciptakan tipe data; typedef hanya menciptakan nama tipe. typedef istream merepresentasikan sebuah spesialisasi dari basic_istream yang memampukan masukan char. Dengan alur yang sama, typedef ostream merepresentasikan sebuah spesialisasi dari basic_ostream yang memampukan keluaran char. Begitu juga typedef iostream merepresentasikan sebuah spesialisasi basic_iostream yang memampukan kedua masukan dan keluaran char. Anda akan sering melihat penggunaan typedef pada bab ini.

Hirarki Template Aliran I/O dan Overloading Operator
Template basic_istream dan basic_ostream keduanya diderivasi melalui pewarisan tunggal dari template basis basic_ios1. Template basic_iostream diderivasi melalui pewarisan jamak dari template basic_istream dan basic_ostream. Diagram kelas UML pada Gambar 7.1 menyimpulkan relasi pewarisan ini.


Gambar 7.1 Hirarki pewarisan template aliran I/O


Overloading operator menyediakan notasi sederhana dalam melaksanakan operasi masukan/keluaran. Operator geser-kiri (<<) dioverload untuk melakukan operasi keluaran aliran dan dikenal dengan operator penyisipan aliran. Operator geser-kanan (>>) dioverload untuk melakukan operasi masukan aliran dan dikenal dengan operator ekstraksi aliran. Kedua operator tersebut digunakan bersama dengan objek aliran standard cin, cout, cerr, dan clog.

Objek Aliran Standard cin, cout, cerr, dan clog
Objek terdefinisi cin merupakan sebuah instans istream dan dikatakan “terkoneksi ke” divais masukan standard, yang biasanya adalah papanketik. Operator ekstraksi aliran (>>) yang dipakai di dalam statemen berikut menyebabkan suatu nilai untuk variabel integer skor (diasumsikan bahwa skor telah dideklarasikan sebagai sebuah variabel int) menjadi masukan dari cin ke memori:

cin >> skor; // data "mengalir" sesuai arah panah

Kompiler menentukan tipe data dari skor dan menyeleksi operator ekstraksi aliran teroverload yang sesuai dengan tipe data itu. Operator >> dioverload untuk memasukkan data bertipe fundamental, string, dan pointer.

Objek terdefinisi cout merupakan sebuah instans ostream dan dikatakan “terkoneksi ke” divais keluaran standard, yang biasanya adalah layar monitor. Operator penyisipan aliran (<<) yang dipakai di dalam statemen berikut menyebabkan suatu nilai untuk variabel integer skor (diasumsikan bahwa skor telah dideklarasikan sebagai sebuah variabel int) menjadi keluaran dari memori ke divais keluaran standard:

cout << skor; // data "mengalir" sesuai arah panah

Kompiler menentukan tipe data dari skor dan menyeleksi operator penyisipan aliran teroverload yang sesuai dengan tipe data itu. Operator << dioverload untuk memasukkan data bertipe fundamental, string, dan pointer.

Objek terdefinisi cerr merupakan sebuah instans ostream dan dikatakan “terkoneksi ke” divais keluaran standard, yang biasanya adalah layar monitor. Keluaran ke objek cerr tidak disangga, yang mengimplikasikan bahwa setiap penyisipan aliran ke cerr akan menyebabkan keluarannya ditampilkan segera. Hal ini untuk memberitahu pengguna tentang kejadian error pada program.

Objek terdefinisi clog merupakan sebuah instans ostream dan dikatakan “terkoneksi ke” divais keluaran standard, yang biasanya adalah layar monitor. Keluaran ke objek clog disangga, yang mengimplikasikan bahwa setiap penyisipan aliran ke clog akan ditampung di dalam suatu penyangga (area memori). Penyanggaan merupakan suatu teknik peningakatan kinerja I/O yang dipelajari di dalam matakuliah Sistem Operasi.


Gambar 7.2 Hirarki pewarisan template aliran I/O untuk pemrosesan file


Template Pemrosesan File
Pemrosesan file di dalam C++ menggunakan template kelas basic_ifstream (untuk masukan file), basic_ofstream (untuk keluaran file), dan basic_fstream (untuk masukan dan keluaran file). Setiap template kelas memiliki spesialisasi template terdefinisi yang memampukan I/O char. C++ menyediakan sehimpunan typedef untuk nama alias bagi spesialisasi template yang ada. Misalnya, typedef ifstream merepresentasikan sebuah spesialisasi dari basic_ifstream untuk memampukan masukan char dari suatu file. Dengan alur yang sama, typedef ofstream merepresentasikan sebuah spesialisasi dari basic_ofstream untuk memampukan keluaran char ke suatu file. Dan juga, typedef fstream merepresentasikan sebuah spesialisasi dari basic_fstream untuk memampukan masukan char dari dan keluaran char ke suatu file. Template basic_ifsteam mewarisi dari basic_istream, basic_ofstream mewarisi dari basic_ostream, dan basic_fstream mewarisi dari basic_iostream. Diagram kelas UML pada Gambar 7.2 menyimpulkan sebagian dari hirarki pewarisan I/O.

7.3 Keluaran Aliran
Kapabilitas keluaran terformat dan tak-terformat disediakan oleh ostream. Kapabilitas ini mencakup keluaran dari tipe data standard dengan operator penyisipan aliran (<<); keluaran dari karakter melalui fungsi anggota put; keluaran tak-terformat melalui fungsi anggota write; keluaran dari integer dari format desimal, oktal, dan heksadesimal; keluaran dari nilai pecahan dengan berbagai kepresisian; keluaran dari data dengan lebar bidang tertentu; dan lainnya.

7.3.1 Keluaran dari Variabel char *
C++ menentukan tipe data secara otomatis, kelebihan dari C. Misalnya, diinginkan untuk menampilkan alamat yang disimpan di dalam suatu pointer char *. Operator << telah dioverload sehingga bisa menampilkan char * sebagai string yang diterminasi oleh null. Untuk menampilkan alamat, Anda bisa meng-cast char * menjadi void * (hal ini bisa dilakukan kepada sembarang variabel pointer). Gambar 7.3 mendemonstrasikan program yang bisa menampilkan variabel char * dalam format string dan format alamat. Alamat yang ditampilkan di sini dalam basis 16 (heksadesimal).

Gambar 7.1 Menggunakan Spesialisasi Template Fungsi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Gambar 7.3: gambar7_03.cpp
// Printing the address stored in a char * variable.
#include <iostream>
using namespace std;

int main()
{
  const char *const kata = "cinta";
  // menampilkan nilai dari char *, kemudian menampilkan nilai dari
  // static_cast to void *
  cout << "Nilai dari kata adalah: " << kata << endl
    << "Nilai dari static_cast< void * >( kata ) adalah: "
    << static_cast< void * >( kata ) << endl;
} // akhir dari main

Nilai dari kata adalah: cinta
Nilai dari static_cast< void * >( kata ) adalah: 00428300

7.3.2 Keluaran Karakter Menggunakan Fungsi Anggota put
Anda dapat menggunakan fungsi anggota put untuk menampilkan karakter. Sebagai contoh, statemen

cout.put( 'A' );

menampilkan karakter tunggal A. Pemanggilan terhadap put dapat dibuat bertingkat, seperti di dalam statemen

cout.put( 'A' ).put( '\n' );

7.4 Masukan Aliran
Sekarang akan didiskusikan tentang masukan aliran. Kapabilitas masukan terformat dan tak-terformat disediakan oleh istream. Operator ekstraksi aliran (>>) normalnya melompati karakter spasi putih (seperti spasi, tab, dan garis-baru) di dalam aliran masukan; nanti akan didiskusikan bagaimana mengubah watak ini. Setelah tiap masukan, operator ekstraksi aliran memberikan nilai balik berupa sebuah referensi yang menunjuk ke objek aliran yang menerima pesan ekstraksi (objek aliran adalah cin di dalam ekspresi cin>>skor). Jika referensi itu digunakan sebagai kondisi (misalnya di dalam kondisi kontinuasi loop statemen while), maka fungsi operator cast teroverload void * secara implisit dipanggil untuk mengkonversi referensi menjadi sebuah nilai pointer tak-null atau pointer null tergantung dari sukeses tidaknya operasi masukan terakhir. Sebuah pointer tak-null mengkonversi referensi tersebut menjadi nilai bool, true, untuk mengindikasikan kesuksesan dan pointer null mengkonversinya menjadi nilai bool, false, untuk mengindikasikan kegagalan. Ketika pembaacaan dilakukan melewati ujung akhir suatu aliran, maka operator cast teroverload void * menghasilkan pointer null untuk mengindikasikan end-of-file.

Setiap objek aliran memuat beberapa bit keadaan yang digunakan untuk mengendalikan keadaan aliran (misalnya untuk pemformatan, penetapan keadaan error, dan lainnya). Bit-bit tersebut digunakan oleh operator cast teroverload void * untuk menentukan apakah menghasilkan nilai balik sebuah pointer tak-null atau pointer null. Ekstraksi aliran menyebabkan failbit ditetapkan 1 jika dibaca tipe data yang salah dan menyebabkan badbit ditetapkan 1 jika operasi masukan mengalami kegagalan.

7.4.1 Fungsi Anggota get dan getline
Fungsi anggota get tanpa argumen membaca satu karakter dari aliran (termasuk karakter spasi putih dan karakter non-grafik, seperti runtun kunci yang merepresentasikan end-of-file) dan menjadikan karakter tersebut sebagai nilai balik dari pemanggilan fungsi. Fungsi get menghasilkan nilai balik EOF ketika end-of-file ditemukan di dalam aliran.

Fungsi Anggota eof, get, dan put
Gambar 7.4 mendemonstrasikan fungsi anggota eof dan get pada aliran masukan cin dan fungsi anggota put pada aliran keluaran cout. Program terlebih dahulu menampilkan nilai dari cin.eof(), dimana false (0 pada keluaran) untuk menunjukkan bahwa end-of-file tidak terjadi pada cin. Pengguna kemudian memasukkan sebaris teks dan menekan ENTER yang diikuti dengan end-of-file (<Ctrl>-z pada Windows, <Ctrl>-d pada UNIX dan Macintosh). Baris 15 membaca setiap karakter, dimana baris 16 mengirim keluaran ke cout menggunakan fungsi anggota put.  Ketika end-of-file dijumpai, statemen while berhenti, dan baris 20 menampilkan nilai cin.eof(), yang sekarang bernilai true (1 pada keluaran), untuk menunjukkan bahwa end-of-file telah dijumpai pada cin. Program ini menggunakan fungsi anggota get tanpa-argumen dan menghasilkan nilai balik berupa karakter yang sedang dibaca (baris 15). Fungsi eof menghasilkan nilai balik true hanya jika program mencoba membaca melewati karakter terakhir di dalam aliran.

Fungsi anggota get dengan satu argumen referensi-karakter membaca karakter selanjutnya dari aliran masukan (meski jika yang dibaca adalah karakter spasi putih) dan menyimpannya di dalam argumen karakter. Versi fungsi get ini menghasilkan nilai balik berupa referensi yang menunjuk ke objek istream.

Versi ketiga fungsi get mengambil tiga argumen, yaitu sebuah array karakter, batas ukuran, dan sebuah pembatas (atau delimiter dengan nilai default ‘\n’). Versi ini membaca karakter dari aliran masukan. Ia membaca satu karakter lebih sedikit dari jumlah karakter maksimum yang dispesifikasi dan berhenti jika delimiter dibaca. Karakter null disisipkan untuk menghentikan string masukan di dalam array karakter yang digunakan sebagai penyangga oleh program. Delimiter tidak ditempatkan di dalam array karakter tetapi tetap berada di dalam aliran masukan (delimiter menjadi karakter pertama selanjutnya yang dibaca). Jadi, hasil dari pemanggilan kedua dari get adalah baris kosong, kecuali jika karakter delimiter dihapus dari aliran masukan (bisa juga dengan cin.ignore()).

Gambar 7.4 Menggunakan Fungsi Anggota get, put, dan eof

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Gambar 7.4: gambar7_04.cpp
// Menggunakan fungsi anggota get, put dan eof.
#include <iostream>
using namespace std;

int main()
{
  int karakter; // menggunakan int, karena char tidak bisa merepresentasikan EOF

  // meminta pengguna memasukkan sebaris teks
  cout << "Sebelum masukan, cin.eof() adalah " << cin.eof() << endl
    << "Masukkan sebaris teks diikuti dengan end-of-file:" << endl;

  // menggunakan get untuk membaca setiap karakter; menggunakan put untuk menampilkannya
  while( ( karakter = cin.get() ) != EOF )
    cout.put( karakter );

  // menampilkan karakter end-of-file
  cout << "\nEOF di dalam sistem ini adalah: " << karakter << endl;
  cout << "Setelah masukan EOF, cin.eof() adalah " << cin.eof() << endl;
} // akhir dari main

Sebelum masukan, cin.eof() adalah 0
Masukkan sebaris teks diikuti dengan end-of-file:
Menguji fungsi anggota get dan put
^Z

EOF di dalam sistem ini adalah: -1
Setelah masukan EOF, cin.eof() adalah 1

Membandingkan cin dan cin.get
Gambar 7.5 membandingkan masukan menggunakan ekstraksi aliran dengan cin (yang membaca karakter sampai karakter spasi-putih ditemukan) dan menggunakan cin.get. Pemanggilan terhadap cin.get (baris 22) tidak menspesifikasi sebuah delimiter, sehingga karakter default ‘\n’ digunakan.

Gambar 7.5 Membandingkan cin dan cin.get

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Gambar 7.5: gambar7_05.cpp
// Membandingkan cin dan cin.get.
#include <iostream>
using namespace std;

int main()
{
  // menciptakan dua array char, masing-masing dengan 80 elemen
  const int UKURAN = 80;
  char buffer1[ UKURAN ];
  char buffer2[ UKURAN ];

  // menggunakan cin membaca karakter ke buffer1
  cout << "Masukkan sebuah kalimat:" << endl;
  cin >> buffer1;

  // menampilkan isi buffer1
  cout << "\nString yang dibaca dengan cin adalah:" << endl
    << buffer1 << endl << endl;

  // menggunakan cin.get untuk membaca karakter ke buffer2
  cin.get( buffer2, UKURAN );

  // menampilkan isi buffer2
  cout << "String yang dibaca dengan cin.get adalah:" << endl
    << buffer2 << endl;
} // akhir dari main

Masukkan sebuah kalimat:
Membandingkan masukan string dengan cin dan cin.get

String yang dibaca dengan cin adalah:
Membandingkan

String yang dibaca dengan cin.get adalah:
 masukan string dengan cin dan cin.get

Menggunakan Fungsi Anggota getline
Fungsi anggota getline bekerja mirip dengan versi ketiga dari fungsi anggota get dan menyisipkan sebuah karakter null setelah baris teks di dalam array karakter. Fungsi getline membuang delimiter dari aliran, tetapi tidak menyimpannya di dalam array karakter. Program pada Gambar 7.6 mendemonstraskan penggunaan fungsi anggota getline pada sebaris teks (baris 13).

Gambar 7.6 Menggunakan Fungsi Anggota getline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Gambar 7.6: gambar7_06.cpp
// Membaca karakter menggunakan fungsi anggota geline.
#include <iostream>
using namespace std;

int main()
{
  const int UKURAN = 80;
  char buffer[ UKURAN ]; // menciptakan array yang memuat 80 karakter

  // memasukkan karakter ke dalam buffer via getline
  cout << "Masukkan sebuah kalimat:" << endl;
  cin.getline( buffer, UKURAN );

  // menampilkan isi buffer
  cout << "\nKalimat yang dimasukkan adalah:" << endl << buffer << endl;
} // akhir dari main

Masukkan sebuah kalimat:
Penggunaan fungsi anggota getline

Kalimat yang dibaca adalah:
Penggunaan fungsi anggota getline

7.4.2 Fungsi Anggota istream: peek, putback, dan ignore
Fungsi anggota ignore dari kelas istream membaca dan membuang sejumlah karakter (default satu karakter) atau berhenti bila menjumpai delimiter tertentu (default adalah EOF, yang menyebabkan ignore untuk melompat ke end-of-file ketika membaca dari suatu file). Fungsi anggota putback menempatkan kembali karakter sebelumnya yang didapatkan oleh get dari sebuah aliran masukan ke aliran tersebut. Fungsi anggota peek menjadikan nilai balik karakter selanjutnya dari sebuah aliran masukan tidak tidak membuang karakter tersebut dari aliran.

7.5 I/O Tak-Terformat Menggunakan read, write, dan gcount
Masukan/keluaran tak-terformat dilakukan menggunakan fungsi anggota read dan write dari kelas istream dan ostream. Fungsi anggota read membaca byte demi byte dari suatu array karakter. Byte-byte ini tidak terformat. Sebagai contoh,

char buffer[] = "SELAMAT ULANG TAHUN";
cout.write( buffer, 10 );

menampilkan 10 byte pertama dari buffer (termasuk karakter null, jika ada, yang akan menyebabkan keluaran dengan cout dan << untuk berhenti). Pemanggilan

cout.write( "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 10 );

menampilkan 10 karakter pertama. Fungsi anggota read membaca sejumlah karakter yang ditentukan ke dalam suatu array karakter. Jika  yang dibaca lebih sedikit dari jumlah karakter yang ditentukan, maka failbit ditetapkan 1. Fungsi gcount melaporkan jumlah karakter yang dibaca oleh operasi masukan terakhir.

Gambar 7.7 mendemonstrasikan fungsi anggota read dan gcount dari kelas istream, dan fungsi anggota write dari kelas ostream. Program membaca 20 karakter (dari runtun masukan yang lebih panjang) ke dalam array buffer dengan fungsi read (baris 13), menentukan jumlah karakter yang dibaca dengan gcount (baris 17) dan menampilkan karakter-karakter yang ada di dalam buffer dengan fungsi write (baris 17).


Gambar 7.7 I/O Tak-Terformat Menggunakan read, gcount, dan write

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Gambar 7.7: gambar7_07.cpp
// I/O tak-terformat menggunakan read, gcount dan write.
#include <iostream>
using namespace std;

int main()
{
  const int UKURAN = 80;
  char buffer[ UKURAN ]; // menciptakan array 80 karakter

  // menggunakan fungsi read untuk memasukkan karakter ke buffer
  cout << "Masukkan sebuah kalimat:" << endl;
  cin.read( buffer, 20 );

  // menggunakan fungsi write dan gcount untuk menampilkan isi buffer
  cout << endl << "Kalimat yang dimasukan adalah:" << endl;
  cout.write( buffer, cin.gcount() );
  cout << endl;
} // akhir dari main

Masukkan sebuah kalimat:
Menggunakan fungsi anggota read, write, dan gcount
Kalimat yang dimasukkan adalah:
Menggunakan fungsi a

7.6 Pengenalan Manipulator Aliran
C++ menyediakan berbagai manipulator aliran yang melakukan tugas pemformatan. Manipulator aliran menyediakan beberapa kapabilitas seperti menetapkan lebar bidang, menetapkan kepresisian, menetapkan dan tidak-menetapkan keadaan format, menetapkan karakter pengisi di dalam bidang, mengalirkan aliran, menyisipkan karakter garis-baru ke dalam aliran keluaran, menyisipkan karakter null ke dalam aliran keluaran, dan melompati spasi putih di dalam aliran masukan. Fitur-fitur ini akan dijelaskan sebentar lagi.

7.6.1 Basis Aliran Integral: dec, oct, hex, dan setbase
Integer diinterpretasikan sebagai nilai desimal (basis-10). Untuk mengubah basis dimana di dalamnya integer diinterpretasikan pada suatu aliran, sisipkan menipulator hex untuk menetapkan basis heksadesimal (basis-16) atau sisipkan manipulator oct untuk menetapkan basis oktal (baris-8). Anda bisa menyisipkan manipulator dec untuk menetapkan-ulang basis aliran menjadi desimal.

Basis aliran dapat diubah menggunakan manipulator aliran setbase, yang memerlukan sebuah argumen int (10, 8, atau 16) untuk menetapkan basis menjadi desimal, oktal, atau heksadesimal. Karena setbase memerlukan satu argumen, fungsi ini dikenal dengan manipulasi aliran terparameterisasi. Penggunaan setbase (atau sembarang manipulator terparameterisasi) memerlukan pencantuman header <iomanip>. Nilai basis aliran tetap sama sampai diubah secara eksplisit. Gambar 7.8 mendemonstrasikan manipulator aliran hex, oct, dec, dan setbase.

Gambar 7.8 Menggunakan manipulator aliran hex, oct, dec, dan setbase

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Gambar 7.8: gambar7_08.cpp
// Menggunakan manipulator aliran hex, oct, dec dan setbase.
#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
  int angka;

  cout << "Masukkan suatu angka desimal: ";
  cin >> angka; // memasukkan angka

  // menggunakan manipulator hex untuk menampilkan angka heksadesimal
  cout << angka << " dalam desimal adalah: " << hex
    << angka << endl;

  // menggunakan manipulator oct untuk menampilkan angka oktal
  cout << dec << angka << " dalam oktal adalah: "
    << oct << angka << endl;

  // menggunakan manipulator setbase untuk menampilkan angka desimal
  cout << setbase( 10 ) << angka << " dalam desimal adalah: "
    << angka << endl;
} // akhir dari main

Masukkan suatu angka desimal: 20
20 dalam heksadesimal adalah: 14
20 dalam oktal adalah: 24
20 dalam desimal adalah: 20

7.6.2 Kepresisian Pecahan: precision dan setprecision
Anda dapat mengendalikan kepresisian angka pecahan (jumlah digit di sebelah kanan titik desimal) menggunakan manipulator aliran setprecision atau fungsi anggota precision dari kelas ios_base. Pemanggilan terhadap fungsi anggota precision tanpa-argumen menghasilkan nilai balik berupa pengaturan kepresisian saat ini. Program pada Gambar 7.9 menggunakan fungsi precision (baris 22) dan manipulator setprecision (baris 31) untuk menampilkan sebuah tabel yang menampilkan akar kuadrat dari 2, dengan kepresisian bervariasi dari 0 sampai 9.

Gambar 7.9 Mengendalikan Kepresisian Nilai Pecahan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Gambar 7.9: gambar7_09.cpp
// Mengendalikan kepresisian atas nilai pecahan.
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

int main()
{
  double akar2 = sqrt( 2.0 ); // menghitung akar kuadrat dari 2
  int presisi; // kepresisian, bervariasi dari 0-9

  cout << "Akar kuadrat 2 dengan kepresisian 0-9." << endl
    << "Kepresisian ditetapkan menggunakan fungsi anggota "
    << "ios_base:" << endl;

  cout << fixed; // menggunakan notasi titik-tetap

  // menampilkan akar kuadrat menggunakan fungsi ios_base
  for ( presisi = 0; presisi <= 9; ++presisi )
  {
    cout.precision( presisi );
    cout << akar2 << endl;
  } // akhir dari for

  cout << "\nKepresisian ditetapkan menggunakan manipulator aliran "
    << "setprecision:" << endl;

  // menetapkan kepresisian untuk setiap dijit, kemudian menampilkan akar kuadrat
  for ( presisi = 0; presisi <= 9; ++presisi )
    cout << setprecision( presisi ) << akar2 << endl;
} // akhir dari main

Akar kuadrat 2 dengan kepresisian 0-9.
Kepresisian ditetapkan menggunakan fungsi anggota ios_base:
1
1.4
1.41
1.414
1.4142
1.41421
1.414214
1.4142136
1.41421356
1.414213562

Kepresisian ditetapkan menggunakan manipulator aliran setprecision:
1
1.4
1.41
1.414
1.4142
1.41421
1.414214
1.4142136
1.41421356
1.414213562

7.6.3 Lebar Bidang: width dan setw
Fungsi anggota width (dari kelas basis ios_base) menetapkan lebar bidang (jumlah posisi karakter dimana di dalamnya sebuah nilai ditampilkan atau jumlah karakter maksimum yang dibaca) dan memberikan nilai balik berupa lebar bidang sebelumnya. Jika nilai yang ditampilkan lebih sempit dari lebar bidang, maka karakter pengisi disisipkan sebagai pengganjal. Nilai yang lebih lebar dari lebar yang ditentukan akan dipotong. Fungsi width tanpa argumen menjadikan pengaturan saat ini sebagai nilai balik.

Gambar 7.10 mendemonstrasikan penggunaan fungsi anggota width pada masukan dan keluaran. Pada masukan yang dibaca ke dalam sebuah array char, jumlah maksimum karakter yang bisa dibaca adalah lebar bidang dikurangi satu. Hal ini karena karakter null akan ditempatkan di dalam string masukan. Ingat bahwa ekstraksi aliran berhenti ketika spasi putih dijumpai. Manipulator aliran setw juga dapat digunakan untuk menetapkan lebar bidang.

Gambar 7.10 Mendemonstrasikan Fungsi width

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Gambar 7.10: gambar7_10.cpp
// Mendemonstrasikan fungsi width.
#include <iostream>
using namespace std;

int main()
{
  int nilaiLebar = 4;
  char kalimat[ 10 ];

  cout << "Masukkan sebuah kalimat:" << endl;
  cin.width( 5 ); // memasukkan hanya 5 karakter dari kalimat

  // menetapkan lebar bidang, kemudian menampilkan karakter berdasarkan lebar tersebut
  while ( cin >> kalimat )
  {
    cout.width( nilaiLebar++ );
    cout << kalimat << endl;
    cin.width( 5 ); // memasukkan 5 karakter lagi dari kalimat
  } // akhir dari while
} // akhir dari main

Masukkan sebuah kalimat:
Ini adalah sebuah pengujian fungsi anggota width
Ini
adal
   ah
  sebu
     ah
    peng
     ujia
         n
       fung
          si
         angg
           ota
           widt
               h

7.6.4 Manipulator Aliran Keluaran yang Didefinisikan Pengguna
Anda dapat menciptakan manipulator aliran sendiri. Gambar 7.11 menampilkan penciptaan dan penggunaan manipulator aliran terparameterisasi baru bell (baris 8-11), carriageReturn (baris 14-17), tab (baris 20-23), dan endLine (baris 27-30). Untuk manipulator aliran keluaran, tipe nilai balik dan tipe parameter harus stream &. Ketika baris 35 menyisipkan manipulator endLine di dalam aliran keluaran, fungsi endLine dipanggil dan baris 29 menampilkan runtun escape \n dan manipulator flush kepada aliran keluaran standard cout. Begitu juga, ketika baris 35-44 menyisipkan manipulator tab, bell, dan carriageReturn di dalam aliran keluaran, fungsi tab (baris 20), bell (baris 8), dan carriageReturn (baris 14) dipanggil, yang pada gilirannya menampilkan berbagai runtun escape.

Gambar 7.11 Menciptakan dan Menguji Manipulator Aliran Sendiri

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// Gambar 7.11: gambar7_11.cpp
// Menciptakan dan menguji manipulator aliran
// tak-terparameterisasi dan didefinisikan sendiri oleh pengguna
#include <iostream>
using namespace std;

// manipulator bell (menggunakan runtun escape \a)
ostream& bell( ostream& keluaran )
{
  return keluaran << '\a'; // mengeluarkan bunyi bip bip
} // akhir manipulator bell

// manipulator carriageReturn (menggunakan runtun \r)
ostream& carriageReturn( ostream& keluaran )
{
  return keluaran << '\r'; // mengeluarkan carriage return
} // akhir dari manipulator carriageReturn

// manipulator tab (menggunakan runtun escape \t)
ostream& tab( ostream& keluaran )
{
  return keluaran << '\t'; // mengeluarkan tab
} // akhir dari manipulator tab

// manipulator endLine (menggunakan runtun escape \n dan
// fungsi anggota flush)
ostream& endLine( ostream& keluaran )
{
  return keluaran << '\n' << flush; // mengeluarkan seperti end of line
} // akhir dari manipulator endLine

int main()
{
  // menggunakan manipulator tab dan endLine
  cout << "Menguji manipulator tab:" << endLine
    << 'a' << tab << 'b' << tab << 'c' << endLine;

  cout << "Menguji manipulator carriageReturn dan bell:"
    << endLine << "..........";

  cout << bell; // menggunakan manipulator bell

  // menggunakan manipulator carriageReturn dan endLine
  cout << carriageReturn << "-----" << endLine;
} // akhir dari main

Mengiji manipulator tab:
a       b       c
Menguji manipulator carriageReturn dan bell:
-----.....

7.7 Keadaan Format Aliran dan Manipulator Aliran
Berbagai manipulator aliran dapat digunakan untuk menspesifikasi jenis pemformatan yang akan dilakukan selama operasi aliran I/O. Manipulator aliran mengendalikan pengaturan format keluaran. Gambar 7.12 menjelaskan setiap manipulator aliran yang mengendalikan keadaan format aliran. Akan disajikan pula beberapa contoh pengendali format aliran pada beberapa bagian ke depan.

Gambar 7.12 Keadaan Format Aliran dari <iostream>

Manipulator
Penjelasan
skipsw


left


right


internal




boolalpha


dec


oct


hex


showbase



showpoint




uppercase




showpos


scientific

fixed

Melompati karakter spasi putih pada suatu aliran masukan. Pengaturan ini diatur-ulang dengan manipulator aliran noskipws.

Menyejajarkan keluaran ke kiri di dalam suatu bidang. Mengganjal karakter di sebelah kanan bila diperlukan.

Menyejajarkan keluaran ke kanan di dalam suatu bidang. Mengganjal karakter di sebelah kiri bila diperlukan.

Mengindikasikan bahwa tanda angka (positif atau negatif) harus disejajarkan ke kiri di dalam suatu bidang dan magnitudo angka harus disejajarkan ke kanan di dalam bidang yang sama (dengan cara mengganjal karakter antara tanda dan angka).

Menspesifikasi bahwa nilai bool harus ditampilkan sebagai kata true atau false. Manipulator nboolalpha menetapkan-ulang aliran untuk menampilkan nilai bool sebagai 1 (true) dan 0 (false).

Menspesifikasi bahwa integer harus diperlakukan sebagai nilai desimal (basis 10).

Menspesifikasi bahwa integer harus diperlakukan sebagai nilai oktal (basis 8).

Menspesifikasi bahwa integer harus diperlakukan sebagai nilai heksadesimal (basis 16).

Menspesifikasi bahwa basis suatu angka ditampilkan di depan angka tersebut ( 0 untuk oktal; 0x atau 0X untuk heksadesimal). Pengaturan ini diatur-ulang dengan manipulator aliran noshowbase.

Menspesifikasi bahaw angka pecahan harus ditampilkan dengan sebuah titik desimal. Ini biasanya dilakukan dengan fixed untuk menjamin bahwa  sejumlah dijit tertentu tetap ditampilkan di sebelah kanan titik desimal, meskipun terdari-dari dijit nol. Pengaturan ini diatur-ulang dengan manipulator noshowpoint.

Menspesifikasi bahwa huruf besar ( X dan A sampai F) harus digunakan di dalam sebuah integer heksadesimal dan bahwa huruf besar E harus digunakan ketika merepresentasikan sebuah nilai pecahan dalam notasi saintifik. Pengaturan ini diatur-ulang dengan manipulator aliran nonuppercase.

Menspesifikasi bahwa angka positif harus diawali dengan tanda +. Pengaturan ini diatur-ulang dengan manipulator aliran noshowpos.

Menspesifikasi keluaran dari nilai pecahan dalam notasi saintifik.

Menspesifikasi keluaran dari nilai pecahan dalam notasi titik-tetap dengan jumlah dijit tertentu di sebelah kanan titik desimal.


7.7.1 Ekor Nol dan Titik Desimal (showpoint)
Manipulator aliran showpoint memaksa suatu angka pecahan untuk ditampilkan dengan titik desimal dan ekor nol. Sebagai contoh, nilai pecahan 79.0 akan ditampilkan 79 apabila tanpa menggunakan showpoint dan ditampilkan 79.000000 (atau sebanyak mungkin ekor nol yang diinginkan) bila menggunakan showpoint. Untuk mereset atau mengatur-ulang pengaturan showpoint, gunakan manipulator aliran noshowpoint.

Program pada Gambar 7.13 menunjukkan bagaimana menggunakan ekor nol dan titik desimal untuk nilai pecahan. Ingat bahwa kepresisian default atas angka pecahan adalah 6. Ketika tidak ada manipulator aliran fixed atau scientific yang digunakan, maka kepresisian merepresentasikan jumlah dijit signifikan yang akan ditampilkan.


Gambar 7.13 Mengendalikan Penampilan Ekor Nol dan Titik Desimal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Gambar 7.13: gambar7_13.cpp
// Mengendalikan penampilan ekor nol dan
// titik desimal di dalam nilai pecahan.
#include <iostream>
using namespace std;

int main()
{
  // menampilkan nilai double dengan format aliran default
  cout << "Sebelum menggunakan showpoint" << endl
    << "9.9900 ditampilkan sebagai: " << 9.9900 << endl
    << "9.9000 ditampilkan sebagai: " << 9.9000 << endl
    << "9.0000 ditampilkan sebagai: " << 9.0000 << endl << endl;

  // menampilkan nilai double setelah showpoint
  cout << showpoint
    << "Setelah menggunakan showpoint" << endl
    << "9.9900 ditampilkan sebagai: " << 9.9900 << endl
    << "9.9000 ditampilkan sebagai: " << 9.9000 << endl
    << "9.0000 ditampilkan sebagai: " << 9.0000 << endl;
} // akhir dari main

Sebelum menggunakan showpoint
9.9900 ditampilkan sebagai: 9.99
9.9000 ditampilkan sebagai: 9.9
9.0000 ditampilkan sebagai: 9

Sesudah menggunakan showpoint
9.9900 ditampilkan sebagai: 9.99000
9.9000 ditampilkan sebagai: 9.90000
9.0000 ditampilkan sebagai: 9.00000

7.7.2 Penyejajaran (left, right, dan internal)
Manipulator left dan right memampukan Anda untuk menyejajarkan bidang ke kiri dengan mengganjal karakter di sebelah kanan atau untuk menyejajarkan bidang ke kanan dengan mengganjal karakter di sebelah kiri. Karakter pengganjal dispesifikasi oleh fungsi anggota fill atau manipulator aliran terparameterisasi setfill. Gambar 7.14 menggunakan manipulator setw, left, dan right untuk menyejajarkan ke kiri dan ke kanan suatu bidang data integer.

Gambar 7.14 Penyejajaran Kiri dan Kanan dengan left dan right

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Gambar 7.14: gambar7_14.cpp
// Penyejajaran kiri dan kanan dengan manipulator aliran left dan right.
#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
  int x = 12345;

  // menampilkan x disejajarkan ke kanan (default)
  cout << "Default adalah penyejajaran kanan:" << endl
    << setw( 10 ) << x;

  // menggunakan manipulator left untuk menampilkan x disejajarkan ke kiri
  cout << "\n\nMenggunakan std::left untuk menyejajarkan x ke kiri:\n"
   << left << setw( 10 ) << x;

  // menggunakan manipulator right untuk menampilkan x disejajarkan ke kanan
  cout << "\n\nMenggunakan std::right untuk menyejajarkan x ke kanan:\n"
    << right << setw( 10 ) << x << endl;
} // akhir dari main

Default adalah penyejajaran kanan:
        12345
Menggunakan std::left untuk menyejajarkan x ke kiri:
12345
Menggunakan std::right untuk menyejajarkan x ke kanan:
12345

Manipulator aliran internal mengindikasikan bahwa tanda suatu angka (atau basis ketika menggunakan manipulator aliran showbase) harus disejajarkan ke kiri di dalam sebuah bidang, bahwa magnitudo harus disejajarkan ke kanan, dan bahwa spasi di antara keduanya (antara tanda dan magnitudo) harus diganjal dengan karakter pengisi. Gambar 7.15 menampilkan manipulator aliran internal untuk menspesifikasi penspasian internal (baris 10). Perhatikan bahwa showpos memaksa tanda positif pada saat ditampilkan (baris 10). Untuk mengatur-ulang showpos, Anda bisa menggunakan manipulator aliran noshowpos.

Gambar 7.15 Menampilkan Integer dengan Penspasian Internal dan Tanda Positif

1
2
3
4
5
6
7
8
9
10
11
// Gambar 7.15: gambar7_15.cpp
// Menampilkan suatu integer dengan penspasian internal dan tanda positif.
#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
  // menampilkan nilai dengan penspasian internal dan tanda positif
  cout << internal << showpos << setw( 10 ) << 123 << endl;
} // akhir dari main

+       123

7.7.3 Pengganjalan (fill dan setfill)
Fungsi anggota fill menspesifikasi karakter pengisi untuk digunakan di dalam bidang penyejajaran; spasi secara default digunakan untuk pengganjalan. Fungsi ini menghasilkan nilai balik berupa karakter pengganjal yang dipakai sebelumnya. Manipulator setfill juga menetapkan karakter pengganjal. Gambar 7.16 mendemonstrasikan fungsi fill (baris 30) dan manipulator aliran setfill (baris 34 dan 37) untuk menetapkan karakter pengisi.

Gambar 7.16 Menggunakan fill dan setfill

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// Gambar 7.16: gambar7_16.cpp
// Menggunakan fungsi anggota fill dan manipulator aliran setfill
// untuk mengubah karakter pengisi.
#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
  int x = 10000;

  // menampilkan x
  cout << x << " ditampilkan sebagai int yang disejajarkan ke kiri dan ke kanan\n"
    << "dan sebagai heksadesimal dengan penyejajaran internal.\n"
    << "Menggunakan karakter pengganjal default (spasi):" << endl;

  // menampilkan x dengan basis
  cout << showbase << setw( 10 ) << x << endl;

  // menampilkan x dengan penyejajaran kiri
  cout << left << setw( 10 ) << x << endl;

  // menampilkan x sebagai heksadesimal dengan penyejajaran internal
  cout << internal << setw( 10 ) << hex << x << endl << endl;

  cout << "Menggunakan berbagai karakter pengganjal:" << endl;

  // menampilkan x dengan penyejajaran ke kanan
  cout << right;
  cout.fill( '*' );
  cout << setw( 10 ) << dec << x << endl;

  // menampilkan x dengan penyejajaran ke kiri
  cout << left << setw( 10 ) << setfill( '%' ) << x << endl;

  // menampilkan x dengan penyejajaran internal
  cout << internal << setw( 10 ) << setfill( '^' ) << hex
    << x << endl;
} // akhir dari main

10000 ditampilkan sebagai int yang disejajarkan ke kiri dan ke kanan
dan sebagai heksadesimal dengan penyejajaran internal.
Menggunakan karakter pengganjal default (spasi):
10000
10000
0x      2710

Menggunakan berbagai karakter pengganjal:
******10000
10000%%%%%%
0x^^^^^2710

7.7.4 Basis Aliran (dec, oct, hex, dan showbase)
C++ menyediakan manipulator aliran dec, hex, dan oct untuk menspesifikasi integer agar ditampilkan sebagai desimal, heksadesimal, dan oktal. Penyisipan aliran default adalah desimal jika tidak ada manipulator yang digunakan. Dengan ekstraksi aliran, integer yang diawali dengan 0 diperlakukan sebagai nilai oktal, integer yang diawali dengan 0x atau 0X diperlakukan sebagai heksadesimal, dan semua integer lainnya diperlakukan sebagai nilai desimal. Bagitu basis tertentu dispesifikasi untuk suatu aliran, semua integer pada aliran tersebut akan diproses menggunakan basis itu sampai basis berbeda dispesifikasi atau sampai program berhenti mengeksekusi.

Manipulator aliran showbase memaksa basis suatu integer untuk ditampilkan. Angka desimal ditampilkan secara default, angka oktal ditampilkan dengan 0 di bagian depan, dan angka heksadesimal ditampilkan dengan 0x atau 0X di bagian depan. Gambar 7.17 mendemonstrasikan kegunaan manipulator aliran showbase untuk memaksa suatu integer agar ditampilkan dalam format desimal, oktal, dan heksadesimal. Untuk mengatur-ulang pengaturan showbase, digunakan manipulator aliran noshowbase.

Gambar 7.17 Menggunakan showbase

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Gambar 7.17: gambar7_17.cpp
// Menggunakan manipulator aliran showbase.
#include <iostream>
using namespace std;

int main()
{
  int x = 100;

  // menggunakan showbase untuk menampilkan basis bilangan
  cout << "Menampilkan integer yang diawali dengan basisnya masing-masing:" << endl
    << showbase;

  cout << x << endl; // menampilkan nilai desimal
  cout << oct << x << endl; // menampilkan nilai oktal
  cout << hex << x << endl; // menampilkan nilai heksadesimal
} // akhir dari main

Menampilkan integer yang diawali dengan basisnya masing-masing:
100
0144
0x64

7.7.5 Notasi Angka Pecahan: scientific dan fixed
Manipulator aliran scientific dan fixed mengendalikan format keluaran angka pecahan. Manipulator scientific memaksa keluaran angka pecahan untuk ditampilkan dalam format saintifik. Manipulator aliran fixed memaksa angka pecahan untuk ditampilkan sebanyak sejumlah dijit (seperti dispesifikasi oleh fungsi anggota precision atau manipulator aliran setprecision) di sebelah kanan titik desimal. Gambar 7.18 mendemonstrasikan penampilan angka pecahan di dalam format tetap dan format saintifik menggunakan manipulator aliran scientific (18) dan fixed (22). Format eksponen di dalam notasi saintifik bisa berbeda pada kompiler yang tidak sama.

Gambar 7.18 Menggunakan scientific dan fixed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Gambar 7.18: gambar7_18.cpp
// Menampilkan nilai pecahan pada defualt sistem,
// dalam format tetap dan format saintifik.
#include <iostream>
using namespace std;

int main()
{
  double x = 0.001234567;
  double y = 1.946e9;

  // menampilkan x dan y dalam format default
  cout << "Ditampilkan dalam format default:" << endl
    << x << '\t' << y << endl;

  // menampilkan x dan y dalam format saintifik
  cout << "\nDitampilkan dalam format saintifik:" << endl
  << scientific << x << '\t' << y << endl;

  // menampilkan x dan y dalam format tetap
  cout << "\nDitampilkan dalam format tetap:" << endl
    << fixed << x << '\t' << y << endl;
} // akhir dari main

Ditampilkan dalam format default:
0.001234567     1.946e+009

Ditampilkaan dalam format saintifik:
1.234567e-003   1.946000e+009

Ditampilkaan dalam format tetap:
0.0012345       1946000000.000000

7.7.6 Kendali Huruf Besar/Huruf Kecil
Manipulator aliran uppercase menampilkan huruf besar X atau E dengan nilai heksadesimal atau dengan notasi saintifik atas nilai pecahan (Gambar 7.19). Penggunaan manipulator aliran uppercase menyebabkan semua huruf di dalam suatu nilai heksadesimal menjadi huruf besar. Secara default, huruf untuk nilai heksadesimal dan eksponen di dalam notasi saintifik atas nilai pecahan selalu huruf kecil. Untuk mengatur-ulang pengaturan uppercase, Anda bisa menggunakan manipulator aliran nouppercase.

Gambar 7.19 Menggunakan scientific dan fixed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Gambar 7.19: gambar7_19.cpp
// Manipulator aliran uppercase.
#include <iostream>
using namespace std;

int main()
{
  cout << "Menampilkan huruf besardi dalam notasi" << endl
    << "saintifik dan nilai desimal:" << endl;

  // menggunakan std:uppercase untuk menampilkan huruf besar; menggunakan
  //  std::hex dan std::showbase untuk menampilkan nilai heksa dan basisnya
  cout << uppercase << 4.345e10 << endl
    << hex << showbase << 123456789 << endl;
} // akhir dari main

Menampilkan huruf besardi dalam notasi
saintifik dan nilai desimal:
4.345E+010
0X75BCD15

7.7.7 Kendali Huruf Besar/Huruf Kecil
C++ menyediakan tipe data bool, yang memiliki nilai true atau false, sebagai nilai alternatif bagi 0 dan 1 (tak-nol). Secara default, sebuah variabel bool menampilkan 0 atau 1. Namun, Anda bisa menggunakan manipulator aliran boolalpha untuk menetapkan aliran keluaran untuk menampilkan nilai bool sebagai string “true” atau “false”. Manipulator aliran noboolalpha dipakai untuk menetapkan aliran keluaran dalam menampilkan nilai bool sebagai integer (kembali ke pengaturan default). Program pada Gambar 7.20 mendemonstrasikan kedua manipulator aliran ini. Baris 11 menampilkan nilai bool, yang pada baris 8 ditetapkan true, sebagai suatu integer. Baris 15 menggunakan manipulator boolalpha untuk menampilkan nilai bool sebagai sebuah string. Baris 18-19 kemudian mengubah nilai bool kembali menjadi integer menggunakan manipulator noboolalpha.

Gambar 7.20 Mendemonstrasikan boolalpha dan noboolalpha

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Gambar 7.20: gambar7_20.cpp
// Mendemonstrasikan manipulator aliran boolalpha dan noboolalpha.
#include <iostream>
using namespace std;

int main()
{
  bool nilaiBoolean = true;

  // menampilkan default true booleanValue
  cout << "nilaiBoolean adalah " << nilaiBoolean << endl;

  // menampilkan nilaiBoolean setelah menggunakan boolalpha
  cout << "nilaiBoolean (setelah menggunakan boolalpha) adalah "
    << boolalpha << nilaiBoolean << endl << endl;

  cout << "menukar nilaiBoolean dan menggunakan noboolalpha" << endl;
  nilaiBoolean = false; // mengubah nilaiBoolean
  cout << noboolalpha << endl; // menggunakan noboolalpha

// menampilkan default false nilaiBoolean setelah menggunakan noboolalpha
 cout << "nilaiBoolean adalah " << nilaiBoolean << endl;

 // menampilkan booleanValue setelah menggunakan boolalpha kembali
 cout << "nilaiBoolean (setelah menggunakan boolalpha) adalah "
 << boolalpha << nilaiBoolean << endl;
} // akhir dari main

nilaiBoolean adalah 1
nilaiBoolean (setelah menggunakan boolalpha) adalah true

menukar nilaiBoolean dan menggunakan noboolalpha

nilaiBoolean adalah 0
nilaiBoolean (setelah menggunakan boolalpha) adalah false

7.7.8 Menetapkan Keadaan Format
Sekarang akan didiskusikan bagaimana menghasilkan nilai balik berupa format aliran. Fungsi anggota flags tanpa argumen menghasilkan nilai balik berupa pengaturan format sekarang sebagai tipe data fmtflags (dari kelas ios_base), yang merepresentasikan keadaan format. Fungsi anggota flags dengan satu argumen fmtflags menetapkan keadaan format seperti yang dispesifikasi oleh argumen dan menghasilkan nilai balik berupa pengaturan keadaan sebelumnya. Nilai pengaturan awal yang dijadikan nilai balik oleh flags bisa berbeda pada sistem yang tak sama. Program pada Gambar 7.21 menggunakan fungsi anggota flags untuk menyimpan keadaan format asli dari aliran (baris 17), dan kemudian mengembalikannya kembali ke pengaturan format asli pada baris 25.

Gambar 7.21 Mendemonstrasikan Fungsi Anggota flags

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Gambar 7.21: gambar7_21.cpp
// Mendemonstrasikan fungsi anggota flags.
#include <iostream>
using namespace std;

int main()
{
  int nilaiInteger = 1000;
  double nilaiDouble = 0.0947628;

  // menampilkan nilai flags, nilai int dan double (format asli)
  cout << "Nilai variabel flags yang direstorasi adalah: " << cout.flags()
    << "\nMenampilkan nilai dalam format asli:\n"
    << nilaiInteger << '\t' << nilaiDouble << endl << endl;

  // menggunakan fungsi cout flags untuk menyimpan format asli
  ios_base::fmtflags formasAsli = cout.flags();
  cout << showbase << oct << scientific; // mengubah format

  // menampilkan nilai flags, nilai int dan double (format baru)
  cout << "Nilai variabel flags yang direstorasi adalah: " <<
    << "\nMenampilkan nilai dalam format baru:\n"
    << nilaiInteger << '\t' << nilaiDouble << endl << endl;

  cout.flags( formatAsli ); // merestorasi format

  // menampilkan nilai flags, nilai int dan double (format asli)
  cout << "Nilai variabel flags yang direstorasi adalah: "
    << cout.flags()
    << "\nMenampilkan nilai dalam format asli kembali:\n"
    << nilaiInteger << '\t' << nilaiDouble << endl;
} // akhir dari main

nilaiBoolean adalah 1
nilaiBoolean (setelah menggunakan boolalpha) adalah true

menukar nilaiBoolean dan menggunakan noboolalpha

nilaiBoolean adalah 0
nilaiBoolean (setelah menggunakan boolalpha) adalah false

7.8 Keadaan Error Aliran
Keadaan suatu aliran diuji di dalam kelas ios_base. Akan didemonstrasikan bagaimana menguji keadaan error aliran pada Gamabr 7.22. eofbit dipakai untuk menetapkan aliran masukan setelah ditemukan end-of-file. Sebuah program dapat menggunakan fungsi anggota eof untuk menentukan apakah end-of-file telah ditemukan pada suatu aliran atau tidak. Pemanggilan

cin.eof()

menghasilkan nilai balik true jika end-of-file ditemukan pada cin dan false jika sebaliknya.

failbit dipakai untuk sebuah aliran ketika error format terjadi dan tidak ada karakter yang dimasukkan (yaitu, ketika Anda membaca sebuah angka dan pengguna pengguna mengentri sebuah string). Ketika error semacam itu terjadi, karakter tersebut tidak hilang. Fungsi anggota fail melaporkan apakah operasi aliran telah mengalami kegagal atau tidak.

Gambar 7.21 Mendemonstrasikan Fungsi Anggota flags

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Gambar 7.22: gambar7_22.cpp
// Menguji keadaan error.
#include <iostream>
using namespace std;

int main()
{
  int nilaiInteger;

  // menampilkan hasil dari fungsi-fungsi cin
  cout << "Sebelum operasi masukan buruk terjadi:"
    << "\ncin.rdstate(): " << cin.rdstate()
    << "\n cin.eof(): " << cin.eof()
    << "\n cin.fail(): " << cin.fail()
    << "\n cin.bad(): " << cin.bad()
    << "\n cin.good(): " << cin.good()
    << "\n\nMengharapkan suatu integer, tetapi dimasukkan sebuah karakter: ";

  cin >> nilaiInteger; // memasukkan nilai karakter
  cout << endl;

  // menampilkan hasil setelah masukan buruk
  cout << "Setelah operasi masukan buruk terjadi:"
    << "\ncin.rdstate(): " << cin.rdstate()
    << "\n cin.eof(): " << cin.eof()
    << "\n cin.fail(): " << cin.fail()
    << "\n cin.bad(): " << cin.bad()
    << "\n cin.good(): " << cin.good() << endl << endl;

  cin.clear(); // membersihkan aliran

  // menampilkan hasil setelah membersihkan aliran
  cout << "Setelah cin.clear()" << "\ncin.fail(): " <<
    << "\ncin.good(): " << cin.good() << endl;
} // akhir dari main

Sebelum operasi masukan buruk terjadi:
cin.rdstate(): 0
cin.eof(): 0
cin.fail(): 0
cin.bad(): 0
cin.good(): 1

Mengharapkan suatu integer, tetapi dimasukkan sebuah karakter:  A

Mengharapkan suatu integer, tetapi dimasukkan sebuah karakter:
cin.rdstate(): 2
cin.eof(): 0
cin.fail(): 1
cin.bad(): 0
cin.good(): 0

Setelah cin.clear()
cin.fail(): 0
cin.good(): 1

badbit ditetapkan untuk sebuah aliran ketika error yang terjadi menyebabkan data hilang. Fungsi anggota bad melaporkan apakah sebuah operasi aliran gagal atau tidak. Secara umum, kegagalan serius semacam ini tidak dapat diperbaiki.

goodbit ditetapkan untuk sebuah aliran jika tidak ada eofbit, failbit, dan badbit yang bernilai true. Fungsi anggota good menghasilkan true jika fungsi bad, fail, dan eof semuanya menghasilkan false. Operasi I/O seharusnya hanya dilakukan pada aliran “baik” saja.

Fungsi anggota rdstate menghasilkan nilai balik berupa keadaan error aliran. Pemanggilan cout.rdstate, misalnya, akan menghasilkan keadaan aliran, yang kemudian diuji oleh sebuah statemen switch yang memeriksa eofbit, badbit, dan goodbit.

Fungsi anggota clear dipakai untuk merestorasi keadaan aliran agar kembali “baik”, sehingga operasi I/O dapat dilaksanakan pada aliran tersebut. Argumen default untuk clear adalah goodbit, jadi statemen

cin.clear();

membersihkan cin dan menetapkan goodbit untuk aliran tersebut. Statemen

cin.clear( ios::failbit )

menetapkan failbit. Anda  bisa melakukan ini ketika melakukan operasi masukan pada cin dengan tipe yang terdefinisi oleh pengguna dan mengalami masalah. Nama clear mungkin tidak cocok untuk konteks ini, tetapi hal ini benar dalam konteks pemrograman.

Kesimpulan
*        I/O C++ terjadi di dalam aliran, yang merupakan runtun byte. Di dalam operasi masukan, byte-byte tersebut mengalir dari suatu divais (misalnya papanketik, disk drive, koneksi jaringan, dan lainnya) ke memori utam. Di dalam operasi keluaran, byte-byte mengalir dari memori utama ke suatu divais (misalnya layar, printer, disk drive, koneksi jaringan, dan lainnya).
*        Kapabilitas keluaran terformat dan tak-terformat disediakan oleh ostream. Kapabilitas ini mencakup keluaran dari tipe data standard dengan operator penyisipan aliran (<<); keluaran dari karakter melalui fungsi anggota put; keluaran tak-terformat melalui fungsi anggota write; keluaran dari integer dari format desimal, oktal, dan heksadesimal; keluaran dari nilai pecahan dengan berbagai kepresisian; keluaran dari data dengan lebar bidang tertentu; dan lainnya.
*        Operator ekstraksi aliran (>>) normalnya melompati karakter spasi putih (seperti spasi, tab, dan garis-baru) di dalam aliran masukan; nanti akan didiskusikan bagaimana mengubah watak ini. Setelah tiap masukan, operator ekstraksi aliran memberikan nilai balik berupa sebuah referensi yang menunjuk ke objek aliran yang menerima pesan ekstraksi (objek aliran adalah cin di dalam ekspresi cin>>skor). Jika referensi itu digunakan sebagai kondisi (misalnya di dalam kondisi kontinuasi loop statemen while), maka fungsi operator cast teroverload void * secara implisit dipanggil untuk mengkonversi referensi menjadi sebuah nilai pointer tak-null atau pointer null tergantung dari sukeses tidaknya operasi masukan terakhir. Sebuah pointer tak-null mengkonversi referensi tersebut menjadi nilai bool, true, untuk mengindikasikan kesuksesan dan pointer null mengkonversinya menjadi nilai bool, false, untuk mengindikasikan kegagalan. Ketika pembaacaan dilakukan melewati ujung akhir suatu aliran, maka operator cast teroverload void * menghasilkan pointer null untuk mengindikasikan end-of-file.
*        Masukan/keluaran tak-terformat dilakukan menggunakan fungsi anggota read dan write dari kelas istream dan ostream. Fungsi anggota read membaca byte demi byte dari suatu array karakter. Byte-byte ini tidak terformat.
*        Berbagai manipulator aliran dapat digunakan untuk menspesifikasi jenis pemformatan yang akan dilakukan selama operasi aliran I/O. Manipulator aliran mengendalikan pengaturan format keluaran.
Latihan
1)      Tulislah sebuah program yang menguji pemasukan nilai integer dalam format desimal, oktal, dan heksadesimal. Tampilkan setiap integer yang dibaca program dalam ketiga format tersebut. Uji program dengan data masukan beritu: 10, 010, 0x10.
2)      Tulislah sebuah program yang menampilkan nilai pointer, menggunakan casting kepada semua tipe data. Mana yang menghasilkan nilai yang aneh? Mana yang menyebabkan error terjadi?
3)      Tulislah sebuah program yang menguji hasil penampilan nilai integer 12345 dan nilai pecahan 1.2345 dalam bidang berbagai ukuran. Apa yang terjadi ketika nilai-nilai tersebut ditampilkan di dalam bidang yang memuat dijit lebih sedikit dibandingkan dengan nilai-nilai tersebut?
4)      Tulislah sebuah program yang memasukkan sebuah string dari papanketik dan menentukan panjang string tersebut. Tampilkan string di dalam suatu bidang yang memiliki lebar dua kali panjang string.




No comments:

Post a Comment