C++: Bài 22. Chuỗi (String)

C++ cung cấp hai cách thức làm việc với chuỗi:

Một số khái niệm

Một chuỗi (string) là một tập hợp các ký tự kết thúc bằng ký tự ‘\0’ (NULL) có thứ tự ký tự trong bảng mã ASCII là 0. Một mảng ký tự một chiều và hai chiều lần lượt được coi là một chuỗi và một mảng chuỗi.

Một biến chuỗi được sử dụng để lưu trữ một dãy các ký tự, đó là hằng chuỗi.

Một hằng chuỗi là một dãy các ký tự và bắt buộc phải đặt trong cặp nháy kép. Giả sử ta có một chuỗi với có nội dung là “V1Study.com”, thì trong bộ nhớ nó được lưu trữ như sau:

‘V”1”S”t”u”d”y”.”c”o”m”\0’

Ký tự ‘\0’ được tự động thêm vào bởi trình dịch để đánh dấu điểm kết thúc của chuỗi. Vậy nên, ta nên khai báo một biến chuỗi với kích thước lớn hơn kích thước tối đa của chuỗi một đơn vị để có vị trí lưu trữ ký tự kết thúc.

Chuỗi ký tự theo phong cách lập trình C

Khai báo chuỗi

Bản chất của việc khai báo một chuỗi chính là khai báo một mảng ký tự một chiều. Vì thế, ta có cú pháp khai báo chuỗi như sau:

char tên_chuỗi[kích_thước];

, trong đó, tên_chuỗi do ta tự đặt tuân theo quy tắc đặt tên chung của ngôn ngữ C++, kích_thước là một số nguyên dương thể hiện số lượng ký tự tối đa của chuỗi.

Ví dụ, nếu bạn muốn khai báo một chuỗi có tên là str và có kích thước tối đa là 25 ký tự, ta có thể làm như sau: char str[26];

Dưới đây là một số ví dụ nữa về cách khai báo chuỗi:

//khai báo và gán từng ký tự cho chuỗi str1

char

str1[

4

] = {

'L'

,

'0'

,

'P'

}; /* ngôn ngữ C sẽ tự động ghi ký tự kết thúc là NULL, tức là ' \0' */

char

str2[

4

] =

"Lop"

; //không cần khai báo kích thước

char

str3[] =

"Study"

;

Xin lưu ý là bạn không thể làm như sau:

char

S[

5

]; S=

"abc"

; //sai, chương trình sẽ hiểu là gán mảng cho mảng vì chuỗi là mảng ký tự một chiều

Nhập liệu cho chuỗi

Sử dụng hàm gets() (thuộc thư viện <stdio.h>) được coi là cách thức đơn giản và phổ biến nhất để ta tiến hành nhập liệu cho chuỗi. Cú pháp sử dụng hàm này như sau: gets(Tên_chuỗi);

Ví dụ sau sẽ nhập liệu cho chuỗi a có kích thước tối đa là 30:

char

a[

30

]; cout<<

"Moi ban nhap mot chuoi: "

; cin>>a;

Ngoài ra, ta cũng có thể sử dụng hàm scanf() để nhập liệu cho chuỗi, khi đó ta sử dụng định dạng của chuỗi là %s. Lưu ý là scanf() không cho phép nhập chuỗi có dấu cách và do đó, khuyến nghị là không nên dùng hàm này để nhập chuỗi.

Chú ý: nếu trước khi nhập chuỗi ta đã nhập một số thì trong bộ đệm nhập liệu còn tồn tại ký tự Enter, khi đó ký tự này sẽ được đưa cho chuỗi dẫn đến không nhập liệu được. Để khắc phục điều này ta có thể sử dụng lệnh sau: cin.ignore(); . Ví dụ:

#include <

iostream

> using namespace std; main () {

char

a[

30

];

int

n; cout<<

"Moi nhap mot so: "

; cin>>n; cout<<

"Moi ban nhap mot chuoi: "

; cin.ignore(); //<= ta có thể sử dụng lệnh này // để đảm bảo bộ đệm nhập liệu không chứa // gì trước khi nhập chuỗi hoặc ký tự cin>>a;

return

0

; }

Ví dụ về xử lý chuỗi

Viết chương trình chuyển đổi một chuỗi ký tự thường thành HOA. Dưới đây trình bày hai cách xử lý yêu cầu này.

* Cách 1: Dùng hàm toupper(ch) (thuộc thư viện <ctype.h>) để chuyển ký tự thường thành ký tự HOA. Chương trình được viết như sau:

#include <

iostream

> #include<

stdio

.h> using namespace std; #define n

20

main() {

char

s[n]; cout<<

"Moi nhap 1 chuoi bat ky: "

;

for

(

int

i =

0

; i <

n

; i++) s[i]=toupper(getchar()); //nhập ký tự và đổi thành hoa rồi lưu vào mảng kết xuất chuỗi s cout<<

"Chuoi sau khi duoc chuyen doi thanh chuoi in hoa:"

<<endl;

for

(

int

i=

0

; i<

n

; i++) putchar(s[i]); //in từng ký tự ra màn hình

return

0

; }

* Cách 2: Dùng hàm strupr(str) thuộc thư viện <string.h> để chuyển chuỗi str thành chuỗi in HOA. Chương trình được viết như sau:

#include <

iostream

> #include<

string

.h> #include<

stdio

.h> using namespace std; main() {

char

str[

30

]; //khai báo một chuỗi có tối đa 30 ký tự

do

{ cout<<

"Moi ban nhap mot chuoi bat ky: "

; gets(str); }

while

(strlen(str)==

0

|| strlen(str)>

30

); //yêu cầu nhập lại chuỗi khi kích thước bằng không hoặc vượt quá 30 strupr(str); //chuyển str thành chuỗi in hoa cout<<

"Chuoi sau khi chuyen:

\"

"

<<str<<

"

\"

"

;

return

0

; }

Một ví dụ về kết quả chạy chương trình trên được thể hiện ở hình dưới đây:

Mảng chuỗi - demo hàm strupr()

Mảng chuỗi

Nếu bạn cần quản lý một số lượng chuỗi nào đó (ví dụ như quản lý quản lý sinh viên bao gồm có phần họ và tên, quê quán, …) thì trong ngôn ngữ C bạn cần phải dùng đến mảng chuỗi. Bản chất của mảng chuỗi là mảng ký tự hai chiều với số hàng và số cột tương ứng, trong đó số hàng chính là số chuỗi bạn muốn có, còn số cột là kích thước tối đa của mỗi chuỗi.

Ta có thể khai báo một mảng chuỗi theo cú pháp như sau:

char tên_mảng_chuỗi[số_chuỗi] [kích_thước_chuỗi];

Ví dụ sau đây khai báo mảng chuỗi có tên hoVaTen gồm 50 chuỗi, mỗi chuỗi có tối đa 30 ký tự.

char

hoVaTen[

50

][

30

];

Nhập liệu cho mảng chuỗi

Dưới đây là một ví dụ thể hiện cách nhập liệu cho mảng chuỗi, trong đó vòng lặp for luôn là lựa chọn tốt nhất cho các thao tác với chuỗi:

#include <

iostream

> #include<

string

.h> #include<

stdio

.h> using namespace std; main() {

char

hoVaTen[

50

][

30

];

int

sochuoi;

do

{ cout<<

"Moi ban nhap so chuoi muon thao tac: "

; //trước tiên yêu cầu nhập số chuỗi muốn thao tác cin>>sochuoi; }

while

(!(sochuoi>

0

&& sochuoi<=

50

)); //số chuỗi phải nằm trong đoạn [1,50] cin.ignore(); //sau đó cần phải tiến hành khử dữ liệu trong bộ đệm bàn phím vì còn tàn dư ký tự '\n' , hàm này thuộc thư viện <stdio.h> cout<<

"Moi ban nhap cac chuoi:"

<<endl;

for

(

int

i=

0

; i<

sochuoi

; i++){ //rồi tiến hành

do

{ cout<<

"Chuoi thu "

<<i+

1

<<

": "

; gets(hoVaTen[i]); //nhập từng chuỗi một. }

while

(strlen(hoVaTen[i])>

30

);//cần đảm bảo mỗi chuỗi nhập vào có kích thước không >30 } cout<<

"Sau khi nhap, ta duoc cac chuoi nhu sau:

\n

"

;

for

(

int

i=

0

; i<

sochuoi

; i++){ puts(hoVaTen[i]); }

return

0

; }

Tìm chuỗi có độ dài lớn nhất, nhỏ nhất của mảng chuỗi

Dưới đây là ví dụ hoàn chỉnh thể hiện một cách tìm độ dài Max, Min trong mảng chuỗi:

#include <

iostream

> #include<

string

.h> #include<

stdio

.h> using namespace std; main() {

char

hoVaTen[

50

][

30

];

int

sochuoi;//biến sochuoi để lưu số lượng chuỗi thực tế muốn thao tác

int

Max, Min; //khai báo hai biến này để lưu trữ độ dài lớn nhất, nhỏ nhất

do

{ cout<<

"Moi ban nhap so chuoi muon thao tac: "

; cin>>sochuoi; }

while

(!(sochuoi>

0

&& sochuoi<=

50

)); cin.ignore(); cout<<

"Moi ban nhap cac chuoi:"

<<endl;

for

(

int

i=

0

; i<

sochuoi

; i++){

do

{ cout<<

"Chuoi thu "

<<i+

1

<<

": "

; gets(hoVaTen[i]); }

while

(strlen(hoVaTen[i])>

30

); } Max = Min = strlen(hoVaTen[

0

]);

for

(

int

i=

1

; i<

sochuoi

; i++) { //lấy từng chuỗi sau đó để so sánh //tìm độ dài Max

if

(Max<

strlen

(hoVaTen[i])) //nếu độ dài lớn hơn Max Max = strlen(hoVaTen[i]); //thì lưu vào Max (chu trình lặp lại với các chuỗi tiếp theo) //tìm độ dài Min

if

(Min>strlen(hoVaTen[i])) //nếu độ dài nhỏ hơn Min Min = strlen(hoVaTen[i]); //thì lưu vào Min } //in ra giá trị độ dài lớn nhất và nhỏ nhất trong biến Max và Min sau chu trình lặp cout<<

"Do dai lon nhat va nho nhat trong cac chuoi la Max = "

<<Max<<

", Min = "

<<Min;

return

0

; }

Một kết quả demo cho chương trình:

Mảng chuỗi - Tìm độ dài max min trong mảng chuỗi

Lớp string theo chuẩn C++

Chuẩn C++ cung cấp lớp string (nằm trong namespace std) có thể hỗ trợ tất cả các hoạt động như đã trình bày ở trên và các hoạt động khác nữa.

Ví dụ 1: Khai báo các chuỗi, gán chuỗi, nối chuỗi

#include <

iostream

> using namespace std; main () { string str1 =

"Hello"

; string str2 =

"World"

; string str3;

int

len; // copy str1 vào str3 str3 = str1; cout <<

"str3 : "

<< str3 << endl; // nối str1 với str2 str3 = str1 + str2; cout <<

"str1 + str2 : "

<< str3 << endl; // độ dài của str3 sau khi ghép nối len = str3.size(); cout <<

"str3.size() : "

<< len << endl;

return

0

; }

Khi thực thi ví dụ trên thì ta được kết quả sau:

str3 : Hello
str1 + str2 : HelloWorld
str3.size() :  10

Ví dụ 2: Chuyển chuỗi nhập vào thành chuỗi in HOA

#include<

bits

/stdc++.h> using namespace std; main() { string str;

do

{ cout<<

"Moi ban nhap mot chuoi bat ky: "

; getline(cin,str); }

while

(str.size()==

0

|| str.size()>

30

); transform(str.begin(),str.end(),str.begin(),::toupper); //chuyển str thành chuỗi in hoa cout<<

"Chuoi sau khi chuyen:

\"

"

<<str<<

"

\"

"

;

return

0

; }

Ví dụ 3: Nhập liệu và hiển thị mảng chuỗi

#include <

iostream

> using namespace std; main() { string hoVaTen[

50

];

int

sochuoi;

do

{ cout<<

"Moi ban nhap so chuoi muon thao tac: "

; cin>>sochuoi; }

while

(!(sochuoi>

0

&& sochuoi<=

50

)); cin.ignore(); cout<<

"Moi ban nhap cac chuoi:"

<<endl;

for

(

int

i=

0

; i<

sochuoi

; i++){

do

{ cout<<

"Chuoi thu "

<<i+

1

<<

": "

; getline(cin,hoVaTen[i]); }

while

(hoVaTen[i].size()>

30

); } cout<<

"Sau khi nhap, ta duoc cac chuoi nhu sau:

\n

"

;

for

(

int

i=

0

; i<

sochuoi

; i++){ cout<<hoVaTen[i]<<endl; }

return

0

; }

Tìm độ dài chuỗi lớn nhất và nhỏ nhất trong mảng chuỗi

#include <

iostream

> using namespace std; main() { string hoVaTen[

50

];

int

sochuoi;//biến sochuoi để lưu số lượng chuỗi thực tế muốn thao tác

int

Max, Min; //khai báo hai biến này để lưu trữ độ dài lớn nhất, nhỏ nhất

do

{ cout<<

"Moi ban nhap so chuoi muon thao tac: "

; cin>>sochuoi; }

while

(!(sochuoi>

0

&& sochuoi<=

50

)); cin.ignore(); cout<<

"Moi ban nhap cac chuoi:"

<<endl;

for

(

int

i=

0

; i<

sochuoi

; i++){

do

{ cout<<

"Chuoi thu "

<<i+

1

<<

": "

; getline(cin,hoVaTen[i]); }

while

(hoVaTen[i].size()>

30

); } Max = Min = hoVaTen[

0

].size();

for

(

int

i=

1

; i<

sochuoi

; i++) { //lấy từng chuỗi sau đó để so sánh //tìm độ dài Max

if

(Max<

hoVaTen

[i].size()) //nếu độ dài lớn hơn Max Max = hoVaTen[i].size(); //thì lưu vào Max (chu trình lặp lại với các chuỗi tiếp theo) //tìm độ dài Min

if

(Min>hoVaTen[i].size()) //nếu độ dài nhỏ hơn Min Min = hoVaTen[i].size(); //thì lưu vào Min } //in ra giá trị độ dài lớn nhất và nhỏ nhất trong biến Max và Min sau chu trình lặp cout<<

"Do dai lon nhat va nho nhat trong cac chuoi la Max = "

<<Max<<

", Min = "

<<Min;

return

0

; }