02. Program C++ pertama — Pembahasan PR

Berkas .cpp jawabannya ada di exercises/02/homework/solutions/.

Halaman ini dibuka sesudah mencoba sendiri. Cara memakainya: bandingkan jalan pikiranmu dengan bagian Cara berpikir, bukan membandingkan kodenya baris per baris. Dua kode yang berbeda bentuk bisa sama-sama benar, dan yang perlu kamu tiru adalah cara sampai ke sana.

Menjalankan salah satu jawabannya:

g++ -std=c++17 -O2 -o jawab exercises/02/homework/solutions/01-biodata.cpp
./jawab

Soal 1 — Biodata

Soal. Cetak empat baris keterangan diri, satu cout per baris.

Cara berpikir. Setiap baris keluaran adalah satu pernyataan cout yang diakhiri endl. Tidak ada variabel, tidak ada logika — tujuannya membiasakan tangan dengan bentuk cout << ... << endl; dan titik koma.

Pembahasan.

#include <iostream>
using namespace std;

int main() {
    cout << "Nama: Budi Santoso" << endl;
    cout << "Kelas: 9A" << endl;
    cout << "Sekolah: SMP Negeri 1 Bandung" << endl;
    cout << "Saya ingin ikut OSN karena senang memecahkan teka-teki." << endl;
    return 0;
}

Uji. Program ini tidak membaca masukan; keluarannya harus empat baris, masing-masing berisi satu keterangan. Periksa satu hal yang mudah terlewat: tidak ada baris kosong di antaranya, dan tidak ada spasi di akhir baris.

endl dipakai di bab ini karena baru itu yang dikenalkan. Mulai Bagian 3 buku ini beralih ke "\n" yang lebih cepat. Untuk soal sekecil ini keduanya sama saja — yang penting konsisten dalam satu program.

Kesalahan umum.

  • Lupa titik koma di akhir salah satu baris.
  • Menulis cout << "Nama: Budi" << endl tanpa tanda kutip penutup, sehingga compiler mengeluh missing terminating " character.

Soal 2 — Kartu nama

Soal. Cetak kotak dari +, -, dan | dengan nama di tengah.

Cara berpikir. Gambarnya tiga baris, jadi kodenya tiga cout. Yang penting: panjang baris atas, tengah, dan bawah harus sama, kalau tidak kotaknya miring. Hitung dulu lebar isinya (di sini 16 karakter), baru tulis +, 16 tanda -, lalu +.

Pembahasan.

cout << "+----------------+" << endl;
cout << "|   Budi Santoso |" << endl;
cout << "+----------------+" << endl;

Uji. Hitung panjang ketiga barisnya dengan tangan — ketiganya harus sama persis:

Baris Panjang
+----------------+ 1 + 16 + 1 = 18
| Budi Santoso | 1 + 16 + 1 = 18
+----------------+ 1 + 16 + 1 = 18

Kalau namamu lebih panjang atau lebih pendek dari Budi Santoso, jumlah tanda - harus ikut disesuaikan. Inilah alasan soal ini melarang perulangan dulu: supaya terasa betapa merepotkannya menyamakan lebar dengan tangan, dan betapa mudahnya setelah Bab 05.

Kesalahan umum.

  • Jumlah - pada baris atas dan bawah berbeda.
  • Menghitung panjang baris tengah tanpa memperhitungkan spasi.

Soal 3 — Tabel dengan tab

Soal. Cetak tabel nama dan nilai tiga teman dengan pemisah \t.

Cara berpikir. \t melompat ke posisi tab berikutnya, bukan menambah jumlah spasi tetap. Karena itu kolom terlihat rapi selama nama-namanya sama panjang atau selisihnya tidak lebih dari satu lompatan tab.

Pembahasan.

cout << "Nama\tNilai\n";
cout << "Budi\t90\n";
cout << "Siti\t85\n";
cout << "Andi\t78\n";

Uji. Keluarannya:

Nama    Nilai
Budi    90
Siti    85
Andi    78

Posisi tab pada terminal biasanya kelipatan 8 karakter. Karena Nama, Budi, Siti, dan Andi semuanya empat huruf, satu \t cukup untuk melompat ke kolom yang sama. Coba ganti satu nama menjadi Muhammad dan lihat kolomnya bergeser satu lompatan.

Kesalahan umum.

  • Menulis \t di luar tanda kutip.
  • Memakai nama yang panjangnya jauh berbeda (Muhammad Rizki dan Ani), lalu heran kolomnya tidak sejajar. Untuk kasus itu dibutuhkan setw dari <iomanip>, yang belum dipakai di bab ini.

Soal 4 — Perbaiki error

Soal. File sengaja rusak dengan tiga kesalahan.

Cara berpikir. Perbaiki satu kesalahan paling atas, lalu compile lagi. Satu kesalahan sering memunculkan banyak baris pesan, jadi memperbaiki semuanya sekaligus berdasarkan tebakan biasanya malah menambah masalah.

Tiga kesalahannya:

  1. using namespace std tanpa titik koma.
  2. Cout seharusnya cout — C++ membedakan huruf besar dan kecil.
  3. Tidak ada titik koma setelah endl.

Compile pertama memberikan dua pesan sekaligus:

04-perbaiki-error.cpp:11:20: error: expected ';' before 'int'
   11 | using namespace std
      |                    ^
      |                    ;
04-perbaiki-error.cpp: In function 'int main()':
04-perbaiki-error.cpp:14:5: error: 'Cout' was not declared in this scope
   14 |     Cout << "Semua error sudah diperbaiki." << endl
      |     ^~~~

Perhatikan kesalahan ketiga belum muncul sama sekali. Compiler berhenti memahami isi main begitu menemui Cout yang tidak dikenal, jadi ia belum sampai memeriksa titik koma sesudah endl. Setelah dua kesalahan pertama diperbaiki dan di-compile lagi, barulah muncul:

04-perbaiki-error.cpp:14:52: error: expected ';' before 'return'

Inilah bentuk kerja yang benar: perbaiki yang paling atas, compile lagi, baca pesan yang baru. Mencoba menebak ketiganya sekaligus dari pesan pertama tidak mungkin, karena pesan ketiganya memang belum ada.

Pembahasan.

#include <iostream>
using namespace std;

int main() {
    cout << "Semua error sudah diperbaiki." << endl;
    return 0;
}

Kesalahan umum.

  • Panik melihat pesan error yang panjang. Pesan pertama hampir selalu yang sebenarnya; sisanya akibat.
  • Menghapus baris yang error alih-alih memperbaikinya.

Tantangan — Kutipan berlapis

Soal. Cetak Guru berkata: "tulis \n untuk pindah baris" apa adanya.

Cara berpikir. Ada dua jenis karakter yang perlu di-escape: tanda kutip ganda menjadi \", dan garis miring terbalik menjadi \\. Yang menjebak adalah \n di dalam kalimat: kalau ditulis apa adanya, ia berubah menjadi pindah baris. Supaya muncul sebagai dua huruf \ dan n, tulis \\n.

Pembahasan.

cout << "Guru berkata: \"tulis \\n untuk pindah baris\"" << endl;

Uji. Keluarannya persis satu baris:

Guru berkata: "tulis \n untuk pindah baris"

Kalau keluaranmu terpecah menjadi dua baris, berarti \n di dalam kalimat masih dibaca sebagai perintah pindah baris, bukan sebagai dua huruf biasa.

Kesalahan umum.

  • Menulis \n alih-alih \\n, sehingga kalimat terpotong jadi dua baris.
  • Lupa \ pada tanda kutip, sehingga compiler mengira teksnya sudah selesai dan mengeluh expected ';'.

Latihan bergaya OSN — pembahasan

Berkas jawabannya ada di exercises/02/osn/solutions/.

Soal 1 — Papan Catur

Cara berpikir. Papan 8 × 8 hanya punya dua bentuk baris: #.#.#.#. dan .#.#.#.#. Keduanya berselang-seling, dimulai dari bentuk pertama. Tanpa perulangan, jawabannya adalah delapan pernyataan cout.

Pembahasan.

cout << "#.#.#.#.\n";
cout << ".#.#.#.#\n";
cout << "#.#.#.#.\n";
cout << ".#.#.#.#\n";
cout << "#.#.#.#.\n";
cout << ".#.#.#.#\n";
cout << "#.#.#.#.\n";
cout << ".#.#.#.#\n";

Uji. Jumlah barisnya harus tepat delapan dan setiap baris tepat delapan karakter. Cara cepat memeriksanya di terminal:

./catur | wc -l
./catur | awk '{ print length($0) }'

Perintah pertama harus mencetak 8, perintah kedua delapan angka 8.

Kesalahan umum.

  • Menukar urutan baris, sehingga pojok kiri atas menjadi ..
  • Menulis sembilan baris karena baris terakhir ditambahi endl berlebih.

Soal 2 — Tangga

Cara berpikir. Baris ke-i terdiri atas 5 - i spasi diikuti i tanda #, sehingga panjang setiap barisnya tetap lima. Menghitung spasinya lebih mudah dari bawah: baris terakhir tanpa spasi sama sekali.

Pembahasan.

cout << "    #\n";
cout << "   ##\n";
cout << "  ###\n";
cout << " ####\n";
cout << "#####\n";

Uji. Semua baris harus berpanjang lima:

./tangga | awk '{ print length($0) }'

Kalau ada angka selain 5, berarti jumlah spasinya salah — atau ada spasi yang terlanjur ikut di akhir baris.

Kesalahan umum.

  • Menulis tangga rata kiri (#, ##, ###) padahal soal meminta rata kanan.
  • Menambah spasi di akhir baris supaya "terlihat rapi" di editor.

Soal 3 — Struk Toko

Cara berpikir. Ketiga karakter yang menyulitkan punya bentuk escape masing-masing: \t untuk tab, \" untuk tanda kutip, \\ untuk satu garis miring terbalik. Jalur C:\struk\2026.txt berisi dua garis miring, jadi di dalam kode ditulis C:\\struk\\2026.txt.

Pembahasan.

cout << "Toko\t\"Sumber Rejeki\"\n";
cout << "Berkas\tC:\\struk\\2026.txt\n";
cout << "Pensil\t3\t6000\n";
cout << "Buku\t2\t14000\n";

Uji. Tab tidak terlihat di layar, jadi periksa dengan cat -A:

./struk | cat -A

Setiap tab muncul sebagai ^I dan setiap akhir baris sebagai $. Baris pertama harus terbaca Toko^I"Sumber Rejeki"$.

Kesalahan umum.

  • Mengganti tab dengan beberapa spasi karena di layar tampak sama.
  • Menulis C:\struk di dalam kode: \s bukan escape yang dikenal, dan compiler mengeluh unknown escape sequence.
  • Lupa satu \ pada tanda kutip penutup, sehingga seluruh baris sesudahnya dianggap bagian dari teks.

Kalau masih tersendat

  • Pesan error tidak terbaca → Bab 02, bagian Membaca pesan error.
  • Bingung kapan pakai endl dan kapan "\n" → Bab 02, bagian Mencetak dengan cout.
  • Tanda kutip dan garis miring membingungkan → Bab 02, tabel Karakter khusus.

Sebelum lanjut ke Bab 03, pastikan kamu bisa menulis kerangka program lengkap dari ingatan, tanpa menyalin, dalam waktu kurang dari satu menit.