Operator >> dan << yang selama ini kita pakai di layar ternyata tidak terikat pada layar — mereka adalah bagian dari abstraksi stream yang bekerja pada sumber dan tujuan apa pun, termasuk teks biasa di memori. Header <sstream> menyediakan kelas-kelas untuk tujuan itu: std::istringstream membaca dari string, std::ostringstream menulis ke string, dan std::stringstream bisa dua arah. Kombinasi ini menyelesaikan dua kebutuhan yang sangat umum: memecah teks menjadi nilai bertipe, dan merangkai banyak potongan data menjadi satu string yang rapi. Pada Chapter ini kita memakai keduanya, memindahkan keterampilan parsing dari Chapter Input Validation ke medan tanpa keyboard.

Tiga Kelas Stream Berbasis String #

Struktur ketiganya persis seperti keluarga file yang akan kita pelajari pada Chapter berikutnya — hanya “sumbernya” yang berbeda, yaitu std::string di memori:

KelasArahKonstruktor menerimaPemakaian lazim
std::istringstreamString → programstring sumberParsing teks, split kata
std::ostringstreamProgram → string(mulai kosong)Membangun laporan bertahap
std::stringstreamDua arahstring awal (opsional)Konversi bolak-balik

Semua operator dan state yang sudah kita kuasai berlaku di sini: >> memakai num_get yang sama (lengkap dengan parsing parsial), flag galat bekerja persis, dan manipulator format juga berlaku per stream. Karena datanya sudah ada di memori, kegagalan parsing tidak berbahaya — kita cukup periksa state dan ulangi dengan data lain.

Parsing Teks Menjadi Nilai #

Kasus pertama: satu baris data "Budi 21 172.5" perlu dipecah menjadi nama, umur, dan tinggi badan. Dengan istringstream, kita memperlakukan string itu persis seperti input keyboard:

cpp
#include <iostream>
#include <sstream>
#include <string>

int main() {
    // 1. Parsing satu baris data menjadi beberapa tipe
    std::istringstream data("Budi 21 172.5");
    std::string nama;
    int umur = 0;
    double tinggi = 0.0;
    data >> nama >> umur >> tinggi;
    std::cout << "Nama   : " << nama << '\n';
    std::cout << "Umur   : " << umur << " tahun\n";
    std::cout << "Tinggi : " << tinggi << " cm\n";

    // 2. Memisah kalimat menjadi kata-kata
    std::istringstream kalimat("belajar pemrograman itu menyenangkan");
    std::string kata;
    int nomor = 1;
    while (kalimat >> kata) {
        std::cout << "Kata " << nomor << ": " << kata << '\n';
        ++nomor;
    }
    return 0;
}

Output yang Dihasilkan:

text
Nama   : Budi
Umur   : 21 tahun
Tinggi : 172.5 cm
Kata 1: belajar
Kata 2: pemrograman
Kata 3: itu
Kata 4: menyenangkan

Dua pola di layak dicatat:

  1. Baris 7-11 (parsing bertipe): data >> nama >> umur >> tinggi membaca tiga nilai bertipe berbeda dari satu string. Konversi otomatis terjadi — 21 menjadi int, 172.5 menjadi double — dengan aturan num_get yang sama persis seperti cin.
  2. Baris 18-22 (split kalimat): loop while (kalimat >> kata) memanfaatkan fakta bahwa >> memotong pada spasi. Stream berubah menjadi false saat habis (state failbit + eofbit), sehingga loop berhenti dengan sendirinya tanpa penghitung batas.

Pola split ini adalah jawaban idiomatik C++ untuk “memecah kalimat per kata” tanpa menulis pencarian spasi manual. Bila butuh pemisah lain seperti koma, kita gunakan std::getline(stream, field, ',') — teknik yang akan muncul lagi pada Chapter Serialization Pengantar saat membahas CSV.

Membangun String Bertahap #

Kasus kedua adalah kebalikannya: kita tidak tahu isi laporan akhir di awal — data datang per baris, per iterasi, per hasil perhitungan — tetapi semuanya harus menyatu dalam satu string yang terformat baik. Menyambung std::string dengan + bekerja, tetapi format angka (presisi, lebar kolom) tidak ikut rapi. ostringstream memberi kita seluruh kekuatan formatter stream:

cpp
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::ostringstream laporan;
    laporan << "LAPORAN PENJUALAN\n";
    laporan << "=================\n";

    std::string nama[] = {"Kopi", "Teh", "Gula"};
    int jumlah[] = {3, 5, 2};
    double harga[] = {25000.0, 7000.0, 15000.0};

    double total = 0.0;
    laporan << std::fixed << std::setprecision(2);
    for (int i = 0; i < 3; ++i) {
        double subtotal = jumlah[i] * harga[i];
        total += subtotal;
        laporan << nama[i] << " x" << jumlah[i] << " = Rp" << subtotal << '\n';
    }
    laporan << "Total : Rp" << total << '\n';

    // Hasil akhir diambil kapan saja lewat str()
    std::cout << laporan.str();
    std::cout << "Panjang laporan: " << laporan.str().size() << " karakter\n";
    return 0;
}

Output yang Dihasilkan:

text
LAPORAN PENJUALAN
=================
Kopi x3 = Rp75000.00
Teh x5 = Rp35000.00
Gula x2 = Rp30000.00
Total : Rp140000.00
Panjang laporan: 118 karakter
  1. Baris 8-10: laporan dimulai sebagai buffer kosong; dua baris pertama ditulis seperti ke cout.
  2. Baris 17 (std::fixed + setprecision(2)): format state terpasang pada stream laporan, bukan pada cout — setiap stream menyimpan formatnya sendiri. Itulah sebabnya nilai Rupiah tampil dua desimal sementara cout di baris terakhir bebas memilih gayanya.
  3. Baris 20-22 (loop): setiap iterasi menambah satu baris subtotal; tidak ada string yang disambung manual, cukup satu operator << berantai.
  4. Baris 25-26 (str()): hasil akhir diambil lewat str() yang mengembalikan salinan seluruh isi buffer — bisa dicetak, disimpan ke variabel, atau ditulis ke file.

Pola ini bernilai besar saat output perlu ditunda dulu: pesan galat yang baru dikirim bila kondisi terpenuhi, isi email yang dikomposisi sebelum dikirim, atau test yang membandingkan output fungsi dengan harapan.

Kapan stringstream Dipilih #

Dengan dua pola di atas, kita punya peta keputusan yang jelas:

  • Parsing: istringstream unggul bila datanya campur tipe atau bila ingin memakai getline dengan delimiter khusus. Untuk konversi tunggal string→angka, std::stoi/std::stod lebih ringkas dan melaporkan posisi sisa karakter.
  • Membangun: ostringstream unggul bila butuh formatting stream (lebar, presisi, manipulator) atau bila kode kita sudah menulis ke std::ostream& — fungsi dari Chapter Peta iostream bisa diarahkan ke buffer tanpa diubah satu baris pun. Untuk penyusunan format yang sudah final, std::format dari Chapter Formatting Output sama-sama layak.
  • Konversi dua arah: std::stringstream yang sama dipakai untuk string→angka lalu angka→string dalam satu objek, misalnya pada perintah pengolah data per baris.

Kita kini bisa membaca dari string dan menulis ke string dengan seluruh perangkat stream. Langkah berikutnya menempatkan perangkat itu pada tempat yang paling praktis: file di disk, lewat <fstream>.

Referensi #