1. Stringstream và bài toán tách từ
Thông thường khi chuẩn hóa hay xử lý xâu ký tự thì bạn cần tách riêng lẻ các từ trong xâu theo dấu cách hoặc một ký tự khác ví dụ như dấu . , ! ...
stringstream nằm trong thư viện sstream, nó có chức năng biến xâu string của bạn thành luồng (tương tự như luồng vào từ bàn phím là cin). Từ đó bạn có thể đọc từng từ trong luồng stringstream ra và xử lý.
Ví dụ sau mình sẽ tách từng từ trong xâu ra, sau khi tách xong bạn có thể chuẩn hóa, đếm từ ... với từ bạn tách được.
Mã nguồn 1:
#include "iostream" #include "string" #include "sstream" using namespace std; int main(){ string s = "28tech hoc lap trinh"; //Khai báo stringstream ss và gán cho nó nội dung của s stringstream ss(s); string word; int dem = 0; while(ss >> word){ ++dem; cout << "Tu thu " << dem << " tach duoc : " << word << endl; } return 0; }
Output :
Tu thu 1 tach duoc : 28tech Tu thu 2 tach duoc : hoc Tu thu 3 tach duoc : lap Tu thu 4 tach duoc : trinh
Giải thích mã nguồn :
- Ban đầu bạn khai báo 1 biến stringstream và khởi tạo giá trị cho nó bằng nội dung xâu bạn muốn tách từ
- Dùng toán tử >> để nhập 1 từ trong luồng stringstream cho biến word, vòng lặp kia sẽ lặp cho tới khi luồng stringstream của bạn không còn từ nào nữa thì nó sẽ dừng lặp.
- Giữa các từ có nhiều dấu cách sẽ được bỏ qua hết, tương tự như bạn nhập cin từ bàn phím thì số lượng dấu cách giữa các từ không có ý nghĩa.
Trong trường hợp bạn muốn tách theo 1 ký tự khác, ví dụ như là dấu - thay vì dấu cách như mặc định bạn có thể sử dụng hàm getline(), hoặc bạn có thể thay cách dấu - thành dấu cách và xử lý như tách từ bằng dấu cách.
Mã nguồn 2:
#include "iostream" #include "string" #include "sstream" using namespace std; int main(){ string s = "28tech-hoc-lap-trinh"; //Khai báo stringstream ss và gán cho nó nội dung của s stringstream ss(s); string word; int dem = 0; while(getline(ss, word, '-')){ ++dem; cout << "Tu thu " << dem << " tach duoc : " << word << endl; } return 0; }
Output :
Tu thu 1 tach duoc : 28tech Tu thu 2 tach duoc : hoc Tu thu 3 tach duoc : lap Tu thu 4 tach duoc : trinh
2. Tách từ theo nhiều ký tự khác nhau
Giả sử bạn cần tách các xâu theo 1 loạt ký tự khác nhau (delimiter) thì bạn nên chuyển hết các ký tự này thành dấu cách rồi tách xâu bằng stringstream.
Ví dụ muốn tách xâu theo các ký tự : dấu chấm '.', dấu phẩy ',', dấu cách ' ', dấu hỏi chấm '?', và dấu chấm than '!' ta triển khai như sau
Mã nguồn :
#include "iostream" #include "string" #include "sstream" using namespace std; int main(){ string s = "28tech,hoc.lap!!trinh???C++ dsa"; //Thay hết delimiter bằng dấu cách for(int i = 0; i < s.size(); i++){ if(s[i] == '?' || s[i] == '!' || s[i] == '.' || s[i] == ','){ s[i] = ' '; } } //Khai báo stringstream ss và gán cho nó nội dung của s stringstream ss(s); string word; int dem = 0; while(ss >> word){ ++dem; cout << "Tu thu " << dem << " tach duoc : " << word << endl; } return 0; }
Output :
Tu thu 1 tach duoc : 28tech Tu thu 2 tach duoc : hoc Tu thu 3 tach duoc : lap Tu thu 4 tach duoc : trinh Tu thu 5 tach duoc : C++ Tu thu 6 tach duoc : dsa
3. Bài tập áp dụng stringstream
Bài tập 1 : Đếm số lượng từ trong xâu ký tự, giữa các từ có thể có nhiều dấu cách
Đối với bài toán này bạn có thể xử lý xâu bằng cách gặp ký tự khác dấu cách thì đếm 1 từ và xử lý nốt các ký tự còn lại của từ đó hoặc dùng stringtream
#include "iostream" #include "string" #include "sstream" using namespace std; int main(){ string s = "28tech 28tech com vn blog AI python"; stringstream ss(s); int cnt = 0; string word; while(ss >> word){ ++cnt; } cout << "So luong tu trong xau : " << cnt << endl; }
Output :
So luong tu trong xau : 7
Nếu bạn không muốn sử dụng stringstream thì có thể cài đặt như sau :
#include "iostream" #include "string" #include "sstream" using namespace std; int main(){ string s = "28tech 28tech com vn blog AI python"; int cnt = 0; for(int i = 0; i < s.size(); i++){ if(s[i] != ' '){ ++cnt; //duyet not cac ki tu cua tu bat dau tu chi so i while(i < s.size() && s[i] != ' '){ ++i; } --i; } } cout << "So luong tu trong xau : " << cnt << endl; }
Bài tập 2 : Chuẩn hóa từ và loại bỏ dấu cách thừa giữa các từ trong xâu, ví dụ " ngUYEN VaN tech28" thì chuẩn hóa thành "Nguyen Van Tech28"
Cách làm là bạn hãy tách các từ ra, chuẩn hóa từng từ rồi nối chung lại với nhau để tạo thành xâu chuẩn hóa.
Thay vì bạn cứ loay hoay xét từ và xóa dấu cách thừa thì việc tách ra, chuẩn hóa và gộp lại sẽ dễ và nhanh hơn nhiều.
#include "iostream" #include "string" #include "ctype.h" #include "sstream" using namespace std; int main(){ string s = " NgUYeN vAN tECH28 "; string res = ""; stringstream ss(s); string word; while(ss >> word){ //Ki tu dau tien cua tung tu thi viet hoa res += toupper(word[0]); //Cac ki tu con lai thi viet thuong for(int j = 1; j < word.size(); j++){ res += tolower(word[j]); } //Them dau cach giua cac tu res += " "; } //Loai bo ki tu dau cach thua sau tu cuoi cung res.pop_back(); cout << "Xau chuan hoa : " << res << endl; }
Output :
Xau chuan hoa : Nguyen Van Tech28Video String :