You are on page 1of 27

CHUỖI TRONG C++

I) Khái niệm

Chuỗi trong C++ được xem là một Mảng các ký tự. Do đó khi bạn có một biến kiểu chuỗi thì
bạn có thể thao tác với nó như làm việc với một mảng.
Ví dụ;
string s = “acbd”;
Thì s lúc này chính là một mảng các ký tự trong đó s[0]= ‘a’; s[1]=’c’, s[2] = ‘b’ và s[3] = ‘d’;
Hoặc String c = “132465”
Thì c[3] chính là ký tự ‘4’, c[0] là ký tự ‘1’.
Với chuỗi thì chúng ta có 1 hàm chuyên dụng để lấy độ dài chuỗi là hàm size(), hàm này sẽ cho
biết chuỗi có bao nhiêu ký tự tất cả:
Ví dụ s= “accd” thì s.size() = 4;
C= “12234” thì C.size() = 5;
Ngoài ra có thể dung toán tử + để cộng 1 ký tự hoặc 1 chuỗi vào chuỗi.
Ví dụ
S = “abc”;
C= “12”
Thì S + C = “abc12” còn C+S = “12abc”
Hoặc s +’a’ = “abca”
‘a’ + s = “aabc”
Luyện tập :
1/ Khai báo một biến kiểu string s = “acbd” rồi tìm cách xuất ra màn hình thành abcd.
2/ nhập vào 1 chuỗi bất kỳ không có khoảng trắng có độ dài lớn hơn 4 rồi đổi chỗ vị trí của ký
tự đầu với ký tự cuối và ký tự kề đầu với ký tự kề cuối sau đó xuất ra màn hình:

Ví dụ:
Input
abccd
Ouput
dccba
3/ Nhập vào từ bàn phím 1 chuỗi bất kỳ không có khoảng trắng, sau đó dùng lệnh sắp xếp của
mảng để xuất ra màn hình chuỗi đã được sắp xếp theo thứ tự từ điển tăng dần:
Ví dụ:
Input :
bcaefhg
Output:
abcefgh
1) Nhập chuỗi :

Lưu ý “khoảng trắng” (‘ ‘) và dấu xuống dòng (‘\n’) cũng là một ký tự và nó sẽ có ảnh hưởng
nhất định đến lệnh nhập của chuỗi.
Thông thường khi nhập 1 chuỗi không có khoảng trắng, ta chỉ cần dùng lệnh cin là đủ ví dụ:
Ta muốn nhập từ “Tam” từ bàn phím và xuất ra ouput từ “Tam” thì chỉ cần viết lệnh như sau:

Tuy nhiên nếu ta muốn nhập từ “Tam Giac” và vẫn dùng lệnh cin để nhập thì kết quả sẽ như sau
:
Ở output lúc này chỉ xuất hiện từ “Tam” thay vì “Tam Giac”.
Lý do là vì lệnh cin sẽ dừng lại khi gặp khoảng trắng, do đó biến s chỉ nhận được chữ “Tam”
chứ không nhận được chữ “Giac”.
Do đó khi nhập chuỗi có khoảng trắng, chúng ta sẽ dùng lệnh getline(cin,<tên biến>);

Lưu ý lệnh getline sẽ dọn dẹp dấu xuống dòng nhưng cũng dừng khi thấy dấu này (‘\n’). Đây là
một thuận lợi và cũng là một điều rắc rối khi mà lệnh cin thường sẽ không tự dọn dẹp dấu
xuống dòng, điều này thường khiến lệnh getline bắt sai tín hiệu.
Ví dụ: ta khai báo hai biến s và c dạng string sau đó lần lượt nhập vào c và s:
ở dòng 1(hình dưới) ta thấy chuỗi không khoảng trắng nên ta chỉ cần dùng cin để nhập, tuy
nhiên lệnh cin lại không dọn dẹp dấu xuống dòng (giữa dòng 1 chứa từ “Hinh” và dòng 2 chứa
từ “Tam Giac” chứa 1 dấu xuống dòng (‘\n’) (dấu này vô hình với ta, nhưng máy thì đọc được))
do đó khi lệnh getline được gọi nó sẽ thấy một dấu xuống dòng (còn dư) và lệnh này sẽ dừng lại
ngay lập tức khi gặp dấu này, kết quả là s không lấy được giá trị nào cả, và chỉ là một chuỗi
rỗng. Do đó ở output chỉ thấy từ “Hinh” của chuỗi c.

Để tránh tình huống này chúng ta sẽ có 1 lệnh dọn dẹp dấu xuống dòng là lệnh cin.ignore(); ta
dùng như sau:
Lệnh cin.ignore() sẽ xóa một ký tự nó gặp đầu tiên từ input
Trong tường hợp này sau khi đã nhập chữ Hinh vào chuỗi c thì lệnh cin.ignore() sẽ xóa dấu
xuống dòng còn dư và khiến lệnh getline phía sau không còn bị ảnh hưởng. Kết quả là màn hình
xuất đúng.
Lưu ý : cin thì ko dọn dẹp dấu xuống dòng, getline thì có . Lệnh ignore() sẽ xóa bất cứ ký
tự đầu tiên nào nó gặp trong input.
Luyện tập
1/ Dùng lệnh getline nhập vào 3 biến a,b,c (dạng string) các chuỗi sau rồi xuất lại ra màn hình
output trên 3 dòng:
Nguyen Van Khanh
Do Van Nam
Le Ngoc Khe
2/ Dùng lệnh cin nhập vào hai biến string a,b, và lệnh getline để nhập vào biến c, rồi xuất ra
màn hình biến c(sau khi nhập):
Phong
Thang
Do Le Quyen
3/ cho 1 số n và sau đó là n chuỗi string khác nhau có khoảng trắng trên n dòng.
Sau đó lần lượt xuất các chuỗi theo thứ tự ngược lại.
Ví dụ
input :
3
Van Mai Huong
Le Van Tam
Do Ba Vinh
Output :
Do Ba Vinh
Le Van Tam
Van Mai Huong
4/ Lần lượt nhập tên và tuổi của 3 người, sau đó xuất ra theo tứ tự nghịch trên 1 dòng
Ví dụ
Input :
Le Van Loi
23
Bui Van Thanh
22
Chu Mai Huong
20
Ouput:
Chu Mai Huong 20
Bui Van Thanh 22
Le Van Loi 23
Bài làm
#include<iostream>
using namespace std;
int main(){
string s[100];
int x[100];
int n=0;
while(getline(cin,s[n]) && cin>>x[n]){
cin.ignore();
n++;
}
for(int i=n-1;i>=0;i--){
cout<<s[i]<<" "<<x[i]<<endl;
}
return 0;
}
2) Xử lý một số chuỗi cơ bản
a) Kiểu char (ký tự) và một số khái niệm cơ bản.
Giữa kiểu char và kiểu int có một mối liên hệ khá chặt chẽ, hai kiểu dữ liệu này có thể chuyển
đổi cho nhau một cách rất dễ dàng trong C++.
Ví dụ :
Ký tự ‘a’ mang một giá trị nguyên là 97, ‘b’ là 98 và tuần tự cho đến ‘z’ là 122
Chúng ta hoàn toàn có thể khai báo 1 biến số nguyên nhưng lại cho nó = với ký tự như sau:
Thay vì báo lỗi thì màn hình output sẽ hiện ra số 97.
Ngược lại ta cũng có thể cho kiểu ký tự bằng 1 số nguyên và sau đó thử xuất ra màn hình

Hoặc chúng ta cũng có thể ép kiểu 2 dạng dữ liệu này cho nhau như sau:
Thậm chí chúng ta có thể thao tác như sau

Với x ban đầu là kiểu char chứa ký tự ‘a’ nhưng ta hoàn toàn có thể cho x cộng với một số
nguyên là 3 vẫn là hợp lệ, x mới sau khi cộng sẽ biến thành ký tự ‘d’ vì ‘d’ mang trọng số 100,
còn ‘a’ là 97.

Điều này về sau giúp chúng ta thuận lợi trong việc xử lý từng ký tự trong một chuỗi.
Giả sử cho chuỗi s= “abcd”; hãy biến ký tự ‘b’ trong s thành ‘c’
Đầu tiên ta thấy rằng ký tự ‘b’ đang ở vị trí số 1 trong s. Ta chỉ cần thao tác cho s[1] = s[1]+1;
hoặc ++s[1]; đều sẽ được chuỗi s mới = “accd”;
Lưu ý : Chữ Hoa sẽ bắt đầu từ ký tự ‘A’ có giá trị nguyên là 65 và ‘Z’ có giá trị 90. Dễ nhận
thấy chữ hoa và chữ thường chênh lệch nhau 32 đơn vị (giá trị nguyên của chữ thường lớn hơn
97->122).Muốn chuyển đổi giữa chữ hoa và chữ thường, thì chúng ta chỉ cần +- cho 32 là được.
Ví dụ:
Cho chuỗi s = “duy”;
Để ký tự ‘d’ trong s biến thành chữ Hoa, ta chỉ cần thao tác như sau:
‘d’ là ký tự ở vị trí số 0 trong s, do đó ta chỉ cần cho s[0] = s[0]-32; hoặc s[0]-=32;
Kết quả sẽ được s =”Duy”;

Luyện tập :
1/ Cho chuỗi s = “kHAnh”;
Hãy biến đổi s về thành “Khanh”.
int main(){
string s="kHAnh";
s[0]=s[0]-32;
s[1]=s[1]+32;
s[2]=s[2]+32;
cout<<s;
return 0;
2/ Nhập 1 chuỗi bất kỳ từ bàn phím chỉ gồm chữ thường và chữ hoa, hãy biến đổi tất cả các chữ
ở vị trí chẵn thành chữ thường và các vị trí còn lại sẽ là chữ hoa (lưu ý trong số mảng bắt đầu từ
0)
Ví dụ :
Input
mAbcEf
Output
mAbCeF
#include<iostream>
#include<string>
using namespace std;
int main(){
string s;
cin>>s;
for(int i=0;i<s.size();i++){
if(i%2==0){
if(s[i]>='A' && s[i]<='Z'){
s[i] +=32;
}
} else {
if(s[i]>='a' && s[i]<='z'){
s[i] -=32;
}
}
}
cout<<s;
return 0;
}
3/ cho chuỗi s = “3426”
int main(){
string s;
s="3426"; s[1]=s[1]+1; s[2]+=2;
cout<<s; return 0;
}
Tìm cách biến đổi chuỗi s thành “3546” bằng việc tăng giảm các ký tự riêng biệt trong chuỗi
ban đầu ( lưu ý ký tự ‘0’ có giá trị nguyên là 48 và ‘9’ có giá trị nguyên là ‘57’).
4/ Nhập một chuỗi có khoảng trắng sau đó biến tất cả các ký tự chữ thường thành chữ hoa và
ngược lại.
Input:
NguYen NhAt Nam
Output
nNGUyEN nHaT nAM
int main(){
string s;
getline(cin,s);
for(int i=0;i<s.size();i++)
if(s[i]>='A' && s[i]<='Z'){
s[i]+=32;
else if(s[i]>='a' && s[i]<='z'){
s[i]-=32;cout<<s;return 0;}
b) Một số bài toán xử lý chuỗi cơ bản
+ Đưa chuỗi về dạng Capitalize (kiểu viết tên, hoa chữ đầu và tất cả còn lại là thường).
Thông thường chúng ta sẽ được yêu cầu nhập 1 chuỗi có khoảng trắng sau đó biến đổi chuỗi
thành kiểu Capitalize:
Đại loại sẽ như sau:
Input :
nguyEN vAn mINh
ouput
Nguyen Van Minh
Đối với dạng bài này chúng ta cần tinh tế nhận diện điểm đặc trưng của các phần tử cần được in
hoa. Những phần tử cần đc viết hoa sẽ có 2 đặc điểm chính.
Thứ nhất là phần tử đầu tiên luôn được viết hoa.
Thứ hai là những phần tử nằm kề “khoảng trắng” về bên phải cũng sẽ được viết hoa.
Từ đó ta viết code như sau:
+ Xóa khoảng trắng dư thừa trong câu:
Đối với dạng bài này chúng ta sẽ làm quen với hàm erase
Cú pháp hàm này như sau :
s.erase(x,n);
với s là chuỗi chứa ký tự cần được xóa
x là vị trí bắt đầu xóa:
n là số lượng ký tự cần xóa (bắt đầu từ vị trí x)
Giả sử chuỗi s = “abcd”
Bạn muốn xóa ký tự ‘c’ khỏi s thì ta sẽ dung lệnh như sau:
s.erase(2,1);
trong đó 2 là vị trí của ký tự ‘c’;
1 là số ký tự cần xóa.
sau đó sẽ còn lại s=”abd”
nếu ta muốn xóa tiếp 2 ký tự ‘b’ và ‘d’ thì ta chỉ cần dùng tiếp lệnh:
s.erase(1,2);

Quay lại với bài toán xóa ký tự khoảng trắng dư thừa ban đầu :
Đầu tiên chúng ta sẽ dùng vòng while làm 2 thao tác, xóa hết ký tự trắng đầu dòng và cuối
dòng:
Sau đó sẽ chạy vòng for chạy tuần tự rồi dung while để kiểm tra có 2 khoảng trắng nào kế nhau
không, nếu có thì sẽ xóa bớt 1 trong hai, cho đến khi không còn hai khoảng trắng nào kế nhau.
#include<iostream>
#include<string>
using namespace std;
void capatilize(string s);
void erasespace(string s);
int main(){
string s;
getline(cin,s);
cout<<s<<endl;
erasespace(s);
cout<<endl;
capatilize(s);
return 0;
}
void capatilize(string s){
if(s[0]>='a' && s[0]<='z'){
s[0]-=32;
}
for(int i=1;i<s.size();i++){
if(s[i-1]==' '){
if(s[i]>='a' && s[i]<='z'){
s[i]-=32;
}
} else {
if(s[i]>='A' && s[i]<='Z'){
s[i]+=32;
}
}
}
cout<<s;
}
void erasespace(string s){
while(s[0]==' ') s.erase(0,1);
while(s[s.size()-1]==' ') s.erase(s.size()-1,1);
for(int i=1;i<s.size();i++){
while(s[i]==' ' && s[i-1]==' '){
s.erase(i,1);
}
}
cout<<s;
}
+ Đếm số chữ và số có trong chuỗi
Ở dạng bài tập này ta cần nắm rõ khoảng giá trị nguyên của chữ và số trong kiểu ký tự
số sẽ có giá trị từ 48 đến 57 (0->9), chữ thường (97->122), chữ hoa (65->90)
Ta sẽ cho chạy vòng for tuần tự từ đầu đến cuối chuỗi sau đó kiểm tra từng ký tự có thuộc vào
những khoảng kia hay ko rồi tăng biến đếm nều phù hợp.
#include<iostream>
#include<string>
using namespace std;
int main(){
string s;
int number=0;
int charac=0;
getline(cin,s);
for(int i=0;i<s.size();i++){
if(s[i]>=48 && s[i]<=57){
number++;
}
if((s[i]>=97 && s[i]<=122)||(s[i]>=65 && s[i]<=90)){
charac++;
}
}
cout<<number<<endl;
cout<<charac;
return 0;

}
Nếu không nhớ khoảng giá trị nguyên của chữ hay số thì có thể dung tạm cú pháp
(s[i]>=’a’&&s[i]<=’z’) hoặc (s[i]>=’A’&&s[i]<=’Z’) hoặc (s[i]>=’0’&&s[i]<=’9’)
Tuy nhiên không khuyến khích cách này, vì sau này muốn thao tác với những bài toán cụ thể
khác, các bạn sẽ gặp rắc rối.
+ Biến chuỗi thành số hoặc tách số từ chuỗi:
Trước hết ta làm quen với bài toán đơn giản hơn :
- Nhập 1 chuỗi chỉ chứa ký tự số, rồi biến chúng thành số.
Input
454
Output
454 (dưới dạng số nguyên)
Ta sẽ có 2 cách làm như sau:
1/ Đi từ sau lên
Với một số ta sẽ tách chúng ra từ đằng sau, tiếp đó ta sẽ nhân dần trọng số cao lên rồi cộng dồn
lại.
Giả sử một số a = 1342;
Ta sẽ tách thành : 2*1 + 4*10 + 3*100 + 1*1000;
Tương tự ở dạng chuỗi s = “1342”; chúng ta cũng làm như vậy tuy nhiên
Đầu tiên ta cần cho các ký tự trở về giá trị nguyên của chúng bằng cách cho chúng – 48;
Vì ký tự ‘0’ = 48, ‘1’ = 49, ‘2’ = 50…’9’ =57.
Khi đem các ký tự - 48 ta sẽ thu đc giá trị nguyên thực sự của chúng.
Code đại loại như sau
int t=0, k=1; // k chính là trọng số 1, 10,100….
for(int i=s.size()-1;i>=0;--i)
{
t+= (s[i]-48)*k ; //s[i]-48 là chuyển từ ký tự về dạng nguyên thực sự
k*=10;
}
cout<<t;
2/ Đi từ trc ra sau
Dạng này phức tạp hơn 1 chút.
Gải sử ta có 1 số bc có 2 chữ số:
Thì ab = a*10 +b
Nâng lên số có 3 chữ số:
abc = ab*10 + c
riêng ab lại = a*10 +b;
Từ đó ta có đoạn code sau:
int t=0;
for(int i=0;i<s.size();++i)
{
t = 10*t + (s[i]-48);
}
cout<<t;
Các bạn cần tự luyện tập code 2 đoạn này và thử xuất ra màn hình để hiểu rõ hơn.
3/ tách số từ chuỗi
Giả sử có một chuỗi lẫn lộn số, hãy tìm ra số lớn nhất trong các số đã cho và tổng các số trong
chuỗi đó.
Ví dụ:
Input
as12pk34k23p
output
34 // số lớn nhất
70 // tổng
Với dạng bài này, chúng ta sẽ chọn một trong 2 cách phía trên, đi từ sau lên hoặc đi từ trước.
Đoạn code phía dưới sẽ viết theo kiểu đi từ trước:
Các bạn thử luyện tập viết code cho bài này bằng cách đi từ sau lên nhé.

Bài Tập
1/ Nhập vào chuỗi bất kỳ :
Xuất ra các số xuất hiện trong chuỗi theo thứ tự tăng dần
Ví dụ :
Input : Gh12ju2juj67j22o
Output : 2 12 22 67
#include<iostream>
#include<string>
#include<sstream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
string s;
cin>>s;
for(int i=0;i<s.size();i++){
if(!(s[i]>='0' && s[i]<='9')){
s[i]=' ';
}
}
vector<int>v;
for(int i=0;i<s.size();i++){
if(s[i]>='0' && s[i]<='9'){
int so=0;
while(s[i]!=' ' && i<s.size()){
so=(so*10) +(s[i]-'0');
i++;
}
v.push_back(so);
}
}
sort(v.begin(),v.end());
for(int i=0;i<v.size();i++){
cout<<v[i]<<" ";
}
return 0;
}

2/
Nhập vào 1 chuỗi có khoảng trắng bất kỳ
Xóa hết các khoảng trắng thừa và xuất chuỗi mới cùng chữ cái in hoa có giá trị lớn nhất theo
thứ tự từ điển (không có xuất -1)
Ví dụ :
Input :
HoanG HOa Ung Van
Ouput
HoanG HOa Ung Van
V // ký tự hoa lớn nhất
3/ nhập vào 1 chuỗi có khoảng trắng sau đó xuất ngược với định dạng Capitalize
Ví dụ:
Input : NGuyEn VaN mANH
Output : Manh Van Nguyen
#include<iostream>
#include<vector>
#include<sstream>
using namespace std;
int main(){
string s;
getline(cin,s);
if(s[0]>=97 && s[0]<=122){
s[0]-=32;
}
for(int i=1;i<s.size();i++){
if(s[i-1]==' '){
if(s[i]>=97 && s[i]<=122){
s[i]-=32;
}
} else {
if(s[i]>=65 && s[i]<=90){
s[i]+=32;
}
}
}
vector<string>v;
stringstream ss(s);
string tmp;
while(ss>>tmp){
v.push_back(tmp);
}
for(int i=v.size()-1;i>=0;i--){
cout<<v[i]<<" ";
}

return 0;
}
4/ Nhập vào 2 chuỗi rồi tìm kiếm chuỗi 2 có tồn tại trong chuỗi 1 hay ko, nếu có xuất YES ko
thì xuất NO
Ví dụ
Input
LEEMINHO
MI
Ouput YES
Input :
LEEMINHO
LEEE
Output NO
5/ Nhập vào tên người theo định dạng Capital sau đó xuất tên (thường) và chữ cái đầu tiên của
họ và chữ lót.
Ví dụ
Input : Nguyen Van Luan
Output : luannv
Input : Le Hoang Viet Vu Thang
Output : thanglhvv
#include<iostream>
#include<vector>
#include<sstream>
using namespace std;
int main(){
string s;
getline(cin,s);
for(int i=0;i<s.size();i++){
s[i]=tolower(s[i]);
}
vector<string>v;
stringstream ss(s);
string tmp;
while(ss>>tmp){
v.push_back(tmp);
}
cout<<v[v.size()-1];
for(int i=0;i<v.size()-1;i++){
cout<<v[i][0];
}
return 0;
}
6/ Nhập 1 chuỗi s và hai số a<b <s.size(), kiểm tra chuỗi có phải là chuỗi đối xứng hay ko ?
Xuất YES nếu có và NO nếu ko ở dòng 1
Kiểm tra chuỗi con từ vị trí a đến b trong chuỗi s có đối xứng hay ko ? Nếu có xuất “CO” ở
dòng 2 không thì xuất “KHONG”
Ví dụ:
Input :
abcba
12
Output
YES
KHONG
Input
abccd
23
Output:
NO
CO

You might also like