std::stringstream adalah stream yang sumber maupun tujuannya berupa std::string di memori, bukan berkas atau layar. Topik ini membahas std::istringstream untuk membaca dan mengurai string, std::ostringstream untuk menyusun string dari beberapa nilai, serta fungsi konversi angka seperti std::stoi dan std::to_string yang sering menyanding dengannya. Seluruh contoh bekerja tanpa berkas eksternal, sehingga mudah dicoba langsung.
Membaca string dengan istringstream#
std::istringstream memperlakukan string sebagai aliran data, sehingga operator >> dan std::getline bekerja di atasnya persis seperti di atas berkas. Keunggulan utamanya adalah kemudahan uji coba, karena data masukan dapat ditulis langsung di dalam kode. Operator >> mengonversi potongan teks sesuai tipe variabel sasarannya, dan perulangan di atasnya berhenti ketika data habis.
#include <iostream>
#include <sstream>
#include <string>
int main() {
// menjumlahkan angka yang tersimpan sebagai satu string
std::istringstream masuk("10 24 100");
int total = 0;
int nilai = 0;
while (masuk >> nilai) {
total += nilai;
}
std::cout << "total: " << total << "\n";
// mengambil angka dari depan teks dengan std::stoi
std::string teks = "42cm";
std::size_t sisa = 0;
int panjang = std::stoi(teks, &sisa);
std::cout << "angka: " << panjang << ", satuan: " << teks.substr(sisa) << "\n";
// menyusun string dari beberapa nilai dengan ostringstream
std::ostringstream keluar;
keluar << "Suhu rata-rata: " << 23.65 << " derajat";
std::cout << keluar.str() << "\n";
return 0;
}total: 134
angka: 42, satuan: cm
Suhu rata-rata: 23.65 derajatBagian kedua memperlihatkan std::stoi, yang mengubah awal string menjadi int dan melaporkan posisi berhentinya melalui argumen kedua bertipe std::size_t*. Informasi itu dipakai untuk mengambil satuan yang tersisa, yaitu cm, dengan substr. Bagian ketiga memakai std::ostringstream untuk menyusun kalimat laporan dari angka dan teks sekaligus, kemudian .str() mengambil hasilnya sebagai std::string.
Perulangan while (masuk >> nilai) bekerja karena operator >> melewati spasi yang memisahkan token, lalu mengonversi potongan berikutnya sesuai tipe variabel sasarannya. Setiap ekstraksi melanjutkan posisi baca dari titik berhenti sebelumnya, sehingga ketiga angka terkumpul dari satu aliran yang sama. Ketika data habis, ekstraksi gagal dan stream menjadi bernilai false, yang mengakhiri perulangan tanpa penghitung eksplisit. Mekanisme inilah alasan string stream disukai untuk pengujian, karena penguraian yang identik dengan penguraian berkas dapat dicoba menggunakan data yang tertulis di dalam kode.
Konversi angka tanpa exception#
std::stoi melempar exception ketika konversinya gagal, sedangkan dua mekanisme lain menandai kegagalan tanpa melempar apa pun. std::istringstream menandainya lewat bit keadaan yang dibahas pada topik keadaan stream, sedangkan std::from_chars dari C++17 melaporkan hasilnya lewat struct hasil kembalian. std::from_chars mengonversi deret karakter menjadi angka tanpa alokasi memori dan tanpa bergantung pada pengaturan locale, sehingga cocok untuk penguraian berfrekuensi tinggi.
#include <charconv>
#include <iostream>
#include <string_view>
void coba(std::string_view teks) {
int nilai = 0;
auto hasil = std::from_chars(teks.data(), teks.data() + teks.size(), nilai);
if (hasil.ec == std::errc{}) {
std::cout << "'" << teks << "' -> " << nilai
<< ", sisa " << teks.substr(hasil.ptr - teks.data()) << "\n";
} else if (hasil.ec == std::errc::result_out_of_range) {
std::cout << "'" << teks << "' -> melebihi jangkauan int\n";
} else {
std::cout << "'" << teks << "' -> gagal dikonversi\n";
}
}
int main() {
coba("24kg");
coba("berat");
coba("99999999999");
return 0;
}'24kg' -> 24, sisa kg
'berat' -> gagal dikonversi
'99999999999' -> melebihi jangkauan intHasil konversi diperiksa lewat hasil.ec, yang bernilai std::errc{} apabila berhasil, std::errc::result_out_of_range apabila angkanya melebihi jangkauan tipe sasaran, dan std::errc::invalid_argument apabila tidak ada angka di awal teks. Anggota hasil.ptr menunjuk karakter pertama yang tidak ikut dikonversi, sehingga perannya sama dengan parameter pos pada std::stoi. Ketiga cara konversi ini saling melengkapi, yaitu std::stoi untuk kode biasa yang tidak keberatan dengan exception, std::istringstream untuk penguraian bertahap, dan std::from_chars untuk jalur yang tidak boleh melempar.
Membagi baris menjadi kolom#
Banyak format data sederhana memisahkan kolom dengan satu karakter tertentu, misalnya titik koma. std::getline menerima argumen ketiga sebagai pemisah kustom sehingga baris dapat dipecah tanpa menulis pengurai sendiri. Hasil setiap potongan kemudian dikonversi dengan std::stoi apabila kolomnya berupa angka.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main() {
const std::string baris = "Citra;80;90;85";
std::istringstream masuk(baris);
std::string nama;
std::getline(masuk, nama, ';');
std::vector<int> nilai;
std::string kolom;
while (std::getline(masuk, kolom, ';')) {
nilai.push_back(std::stoi(kolom));
}
int total = 0;
for (int n : nilai) {
total += n;
}
std::cout << nama << ": " << nilai.size() << " nilai, "
<< "rata-rata " << total / static_cast<double>(nilai.size()) << "\n";
return 0;
}Citra: 3 nilai, rata-rata 85Potongan pertama diambil untuk nama, sedangkan perulangan while mengambil tiga kolom angka berikutnya. Pemanggilan std::getline berikutnya sesudah itu menemukan akhir data dan menggagalkan perulangan, sehingga vektor nilai tepat berjumlah tiga elemen tanpa potongan kosong. Pola ini cocok untuk data dengan jumlah kolom yang tetap, sedangkan data yang lebih bebas sebaiknya diperiksa jumlah kolomnya terlebih dahulu sebelum nilai-nilainya dipakai.
Menyusun string dengan ostringstream#
std::ostringstream merupakan kebalikan arahnya, yaitu menampung keluaran format ke dalam string. Semua operator << dan manipulator iostream tetap berlaku, sehingga angka dan teks dapat digabung tanpa konversi manual. Pendekatan ini menjadi cara idiomatik untuk membangun pesan error, laporan, atau baris data terstruktur sebelum dikirim ke tujuan akhirnya.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main() {
std::vector<std::string> nama = {"Ali", "Budi", "Citra"};
std::vector<double> rataRata = {78.5, 84.0, 91.25};
std::ostringstream laporan;
for (std::size_t i = 0; i < nama.size(); ++i) {
laporan << "- " << nama[i] << ": " << rataRata[i] << "\n";
}
std::cout << laporan.str();
return 0;
}- Ali: 78.5
- Budi: 84
- Citra: 91.25Seluruh baris laporan tersusun di memori terlebih dahulu, kemudian dicetak sekali lewat .str(). Apabila laporan perlu ditulis ke berkas, string yang sama dapat dikirim ke std::ofstream tanpa mengubah susunannya. Nilai yang dikembalikan .str() berupa salinan, sehingga penambahan isi stream sesudahnya tidak mengubah string yang sudah diambil. Tampilan double pada contoh mengikuti pengaturan bawaan iostream, dan pengaturan presisinya dibahas lebih lanjut pada topik pemformatan.
Kesalahan umum#
Kekeliruan berikut paling sering muncul saat string stream mulai dipakai.
- Memakai
std::stoipada masukan yang mungkin tidak valid. Fungsi ini melempar exceptionstd::invalid_argumentapabila tidak ada angka di awal string. Perbaikannya menggunakanstd::istringstreamdengan pemeriksaan kondisi, atau menangkap exception tersebut. - Mengira
std::stoimenandai konversi yang hanya berhasil sebagian. Teks12abcdikonversi menjadi 12 tanpa exception karena fungsi itu berhenti pada karakter pertama yang bukan angka. Perbaikannya memeriksa parameterpos, atau memakaistd::from_charsyang melaporkan posisi berhentinya secara bawaan. - Mengira operator
>>membaca sepanjang baris. Operator ini berhenti pada spasi sehingga teks yang mengandung spasi terpotong. Perbaikannya membaca baris denganstd::getlineterlebih dahulu. - Memakai ulang stream yang telah habis atau gagal tanpa pemulihan.
std::istringstreamyang mencapai akhir tetap berada di sana hingga keadaannya dipulihkan. Perbaikannya memanggilclear()untuk menghapus bit error, lalu mengganti isinya denganstr(). - Lupa memanggil
.str(). Isistd::ostringstreamtidak dapat dipakai sebagaistd::stringtanpa fungsi itu. Perbaikannya mengambil isinya lewat.str()sebelum dicetak atau disimpan.
Ringkasan#
std::istringstreammembaca string sebagaimanastd::ifstreammembaca berkas, lengkap dengan konversi melalui operator>>.std::getlinedengan argumen pemisah memecah baris menjadi kolom, danstd::stoimengonversi potongan angka sekaligus melaporkan posisi berhentinya.std::ostringstreammenyusun string dari beberapa nilai dengan<<, lalu.str()mengambil hasilnya.std::to_stringpraktis untuk satu nilai, tetapi formatnya tetap dan tidak dapat diatur.
Referensi#
- std::basic_stringstream — cppreference — Dokumentasi kelas stream yang bekerja atas string.
- std::basic_istringstream — cppreference — Dokumentasi stream masukan yang sumbernya string.
- std::basic_string::stol — cppreference — Dokumentasi stoi, stol, dan stoll beserta parameter posisinya.
- std::to_string — cppreference — Dokumentasi konversi angka ke string dengan format tetap.
- std::from_chars — cppreference — Dokumentasi konversi angka tanpa exception dari C++17 beserta hasil kembaliannya.
- Stream classes for strings — LearnCpp — Pembahasan istringstream dan ostringstream beserta contohnya.