You are on page 1of 63

Chuỗi Ký Tự

(String)

Trịnh Tấn Đạt


Khoa CNTT - Đại Học Sài Gòn
Email: trinhtandat@sgu.edu.vn
Website: https://sites.google.com/site/ttdat88/
Nội dung
▪ Khái niệm chuỗi ký tự (string)
▪ Chuỗi ký tự trong C
o Khai báo
o Nhập/xuất chuỗi ký tự
o Con trỏ và chuỗi ký tự
o Các thao tác trên chuỗi ký tự
o String và FILE
o Ví dụ
▪ Câu hỏi và Bài Tập
▪ Chuỗi ký tự trong C++ (option)
Ký tự (character)
▪ Kiểu char:
o Ký tự “in được” gồm: 26 chữ thường (a..z), 26 chữ hoa (A..Z), 10 chữ số (0..9), khoảng trắng,
các ký tự: ! “ # $ % & ‘ ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ { | } ~
o Các ký tự “không in được”: tab, lert (bell), newline, …

▪ Các ký tự “in được” đặc biệt: ‘\\’, ‘\’’, ‘\”’

▪ Các ký tự “không in được” đặc biệt:


\n new line
\a bell
\0 null character
\b backspace
\t horizontal tab
Ký tự (character)
▪ Nhập xuất ký tự

Trong C :

char ch;
scanf("%c", &ch);
printf("ky tu la : %c", ch);

Trong C++ :

char c;
cin>> c;
cout<<"ky tu la:" << c;
Chuỗi ký tự trong C
▪ Chuỗi ký tự là mảng một chiều, có mỗi thành phần là một ký tự (hoặc có thể xem là số nguyên),
được kết thúc bởi ký tự đặc biệt \0
▪ Ký tự kết thúc (\0) ở cuối chuỗi ký tự thường được gọi là ký tự null (không giống con trỏ NULL).
▪ Được khai báo và truyền tham số như mảng một chiều • Lưu ý:
- Ký tự đặt trong dấu nháy đơn
Ví dụ: char s[100]; // chuỗi s chứa tối đa 100 ký tự - Chuỗi ký tự đặt trong dấu nháy kép
char first_name[5] = { 'J', 'o', 'h', 'n', '\0' }; Ví dụ: In ra màn hình chuỗi other:
char last_name[6] = "Minor"; Dùng C: printf("%s",other);
char other[] = "Tony Blurt";
Dùng C++: cout<<other;
char characters[8] = "No null";

first_name 'J' 'o' 'h' 'n' \0 Chuỗi first_name có chiều dài là 4 (không tính ký tự \0)

other 'T' 'o' 'n' 'y' 32 'B' 'l' 'u' 'r' 't' '\0'

Chuỗi other có chiều dài là 10 (không tính ký tự \0)


Chuỗi ký tự trong C
❖ Nhập/ xuât chuỗi ký tự
▪ Có thể dùng scanf() hoặc cin>> để nhập chuỗi ký tự (không bao gồm khoảng trắng)
o toán tử >> với cin để nhập một chuỗi ký tự đến khi gặp một khoảng trống thì dừng.
▪ Ví dụ: #pragma warning(disable:4996)
#include <iostream> Nhập chuỗi có khoảng trắng, nếu không dùng fflush(stdin)
#include <stdlib.h> → kết quả là gi?
#include <string.h>
using namespace std;
int main()
{ char s[100], t[100];
cout <<"nhap chuoi:";
scanf("%s",&s);
printf("%s\n",s);
fflush(stdin); // xoa vung dem
cout <<"nhap chuoi:";
cin >> t ;
cout << t << endl;
return 0;
}
Chuỗi ký tự trong C
❖ Nhập/ xuât chuỗi ký tự
▪ Nhập chuỗi có khoảng trắng dùng hàm gets()
▪ Lưu ý không thể dùng hàm gets() trong visual studio version 15 trở đi.
Trước khi ra đời chuẩn C++11, chúng ta thường sử dụng hàm gets để nhập dữ liệu cho mảng kí tự.
Nhưng Visual studio 2015 áp dụng chuẩn C++11 trở lên, nên hàm gets() bây giờ đổi tên thành
gets_s().
#include <iostream>
▪ Ví dụ: #include <stdlib.h>
#include <string.h>
using namespace std;
int main()
{
char name[100];
cout<<"Nhap mot chuoi ky tu: ";
gets(name);
cout <<"chuoi la:" << name <endl;
return 0;
}
String
▪ Có thể dùng hàm puts() để in chuỗi ký tự ra màn hình

Ví dụ: #include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main() {
char A[255],B[255];
cout<<"Nhap chuoi: ";
gets(A);
int Dodai = strlen(A); // tìm độ dài của chuỗi
cout<<"Co do_dai: " << Dodai;
strcpy(B,A); // copy chuỗi A sang chuỗi B
cout<<"Output: ";
puts(B);
return 0;
}
String
▪ Lưu ý: kết thúc chuỗi

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{
char other[] = "Tony Blurt";
cout << other << endl;
other[4] = '\0'; "Blurt" sẽ không được in ra
cout << other << endl;
return 0;
}
other 'T' 'o' 'n' 'y' 32 'B' 'l' 'u' 'r' 't' '\0'
String trong C
❖ Lưu ý : Lỗi khi tạo một chuỗi
▪ Đối với chuỗi ký tự trong C . Chú ý: không có phép gán trong kiểu dữ liệu chuỗi như thế này là
sai
char ten[10];
ten = “hoahong”;

▪ Đối với chuỗi ký tự trong C . Không : sử dụng toán tử gán = để chép nội dung của một chuỗi sang
chuỗi khác.
char a[4]=“hi”;
char b[4];
b = a; //???

▪ Đối với chuỗi ký tự trong C . Không: dùng toán tử ==, <, >, <=, >= để so sánh nội dung hai chuỗi
char a[] = “hi”;
char b[] = “there”;
if(a==b) //???
{}
* Khắc phục: sử dụng các hàm trong thư viện <string.h>
Con trỏ và String
❖ Khai báo chuỗi ký tự như một con trỏ : char *p;
▪ Cấp phát động cho con trỏ: p = new char [30];
▪ Xin cấp phát số lượng ký tự, giống mảng các ký tự

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{
char *p = new char[50];
cout <<"nhap chuoi:";
gets(p);
cout << "chuoi vua nhap:"<< p << endl;
return 0;
}
Con trỏ và String
❑ Lưu ý :
▪ Với một chuỗi ký tự char *s, cú pháp s+k sẽ trả về chuỗi tính từ ký tự thứ k trở về cuối chuỗi s.

'T' 'o' 'n' 'y' 32 'B' 'l' 'u' 'r' 't' '\0'

s
s+3 // k =3

▪ Với một chuỗi ký tự char *s, cú pháp s[k]= '\0' sẽ trả về chuỗi s trong đó s kết thúc tại vị trí k.

'T' 'o' 'n' '\0' 32 'B' 'l' 'u' 'r' 't' '\0'

s[3]= '\0'
Khi đó: s là "Ton"
Con trỏ và String
▪ Xét ví dụ khởi tạo bằng một hằng chuỗi kí tự như sau:
char s[] = "Lap Trinh";
s[1] = 'A'; //=> "LAp Trinh“
▪ Chuỗi kí tự "Lap Trinh" được xem như là một chuỗi hằng kí tự, nó có địa chỉ cụ thể trên bộ nhớ ảo, nó được lưu trên bộ
nhớ ảo.
▪ Khi sử dụng chuỗi hằng kí tự "Lap Trinh" để khởi tạo cho mảng s, mảng s không được khai báo là kiểu chuỗi hằng kí tự
(const char []) nên các kí tự trong mảng s hoàn toàn có thể bị thay đổi.
▪ Điều này chứng tỏ mảng s được cấp phát bộ nhớ tại địa chỉ khác chuỗi hằng kí tự "Lap Trinh“, việc khởi tạo mảng kí tự
bằng một chuỗi hằng kí tự chỉ đơn giản là copy từng kí tự của chuỗi "Lap Trinh" và đưa vào mảng.
▪ Do đó, con trỏ kiểu char (char *) trỏ đến mảng s và trỏ đến vùng nhớ của chuỗi hằng kí tự "Lap Trinh" là 2 trường hợp
khác nhau.
char s[] = "Lap Trinh";
cout << s << endl;
cout << &s << endl;
char *p_s = s;
p_s[1] = 'A'; //=> "LAp Trinh"
cout << p_s << endl;
cout << &p_s << endl;
cout << s << endl;
cout << &s << endl;
Con trỏ và String
▪ Câu hỏi: cho biết kết quả in ra màn hình

char ch = 'A';
Vì &ch trả về dữ liệu kiểu (char *) nên đối tượng cout xem nó
cout << ch << endl; như là C-style string nên in ra kí tự A và tiếp tục cho đến khi
gặp giá trị '\0'.
cout << &ch << endl;
Mảng các chuỗi
❖ Dùng con trỏ cấp 2 để biểu diễn mảng các chuỗi ký tự
▪ Ví dụ
char *sports[ ] = {“golf”, “hockey”, “football”, “cricket”, ”shooting”};
Hay:
char **sports;
Mảng các chuỗi
▪ Ví dụ: nhập vào 3 chuỗi và in ra màn hình dùng array of strings (pointers)
#include<iostream>
#include<stdio.h> Có thể dùng cấp phát tỉnh:
#include<string.h> char s[100][1024];
using namespace std;
int main()
{
char **s; // array of strings, cấp phát động // in cac chuoi ra man hinh
s = new char*[3]; for(int i=0;i<3;i++)
// cap phhat dong cho 3 chuoi {
// moi chuoi chua toi da 1024 ky tu cout << "chuoi " << i+1 << "la:";
for(int i=0;i<3;i++) cout << s[i] << endl;
s[i] = new char[1024]; }
// nhap cac chuoi trong array of strings // don dep vung nho
for(int i=0;i<3;i++) for(int i=0;i<3;i++)
{ cout << "nhap chuoi:"; delete[] s[i];
gets(s[i]); delete[] s;
} return 0;
}
Các hàm xử lý chuỗi trong C
▪ Các hàm xử lý chuỗi thông dụng: trong thư viện <string.h>
strlen();
toupper(); strupr(); strlwr();
strcpy(); strncpy();
strchr(); strstr();
stricmp();
memset();
atoi(); atof(); atol()
https://beta.wikiversity.org/wiki/Chu%E1%BB%97i_k%C3%BD_t%E1%BB%B1_trong_C
https://v1study.com/c-ham-xu-ly-chuoi-string-a56.html
https://oktot.net/huong-dan-su-dung-cac-ham-xu-ly-chuoi-trong-c/
http://cunglaptrinh.blogspot.com/2015/01/cac-ham-xu-ly-chuoi-trong-C.html
Các hàm xử lý chuỗi trong C
▪ Lấy độ dài chuỗi: strlen
▪ Độ dài của chuỗi kí tự được tính từ kí tự đầu tiên cho đến kí tự kết thúc chuỗi ( không đếm ký tự
'\0') size_t strlen ( const char * str );
Ví dụ:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{ char s[20] = "ABC def";
cout << strlen(s) <<endl; // ket qua la 7
char *p = new char[256];
cout << "nhap chuoi:" ;
gets(p);
int k = strlen(p);
cout << k <<endl;
delete[] p;
return 0;
}
String
▪ Đổi một ký tự thường thành ký tự hoa - Hàm toupper
Cú pháp: char toupper(char c)
▪ Đổi toàn bộ các ký tự của chuỗi thành IN HOA : strupr
Cú pháp: char* strupr(char *s)
▪ Đổi toàn bộ các ký tự của chuỗi thành in thường: strlwr
Cú pháp: char *strlwr(char *s) #include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{ char s[20] = "lap TrinH C";
char c ='a';
cout<< char(toupper(c))<<endl; // A
cout<< strupr(s) <<endl;
cout<< strlwr(s) <<endl;
return 0;
}
String
▪ Gán/sao chép nội dung chuỗi:
o Chép toàn bộ chuỗi source sang chuỗi destination: strcpy
Cú pháp: char* strcpy(char *Des, const char *Source)
Lưu ý: Mảng kí tự destination phải được cấp phát đủ bộ nhớ để lưu trữ chuỗi
kí tự được copy từ mảng kí tự source.
o Chép tối đa n ký tự đầu tiên từ source sang dest: strncpy
Cú pháp: char * strncpy(char *Des, const char *Source, size_t n)
Lưu ý: Visual studio áp dụng chuẩn C++11 trở lên, nên chúng ta cần sử dụng hàm
strncpy_s thay thế cho 2 hàm copy mảng kí tự trong thư viện cstring (string.h)
String
▪ Tạo chuỗi mới từ chuỗi đã có: strdup
char *strdup(const char *src);
▪ Khắc phục được vấn đề mảng kí tự destination phải được cấp phát đủ bộ nhớ để
lưu trữ chuỗi kí tự được copy từ mảng kí tự source.
▪ Khi dùng strdup, chuỗi destination đầu tiên được cấp phát bộ nhớ cùng kích thước
với chuỗi source, sau đó sẽ tiến hành sao chép nội dung từ source sang destination.
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{ char s1[255], s2[255], s3[255];
cout<<"nhap chuoi:";
gets(s1);
cout<<"chuoi s1:"<<s1<<endl;
strcpy(s2,s1); // copy s1 to s2
cout<<"chuoi s2:"<<s2<<endl;
strncpy(s3,s1, int (strlen(s1) / 2)); // copy 1/2 so luong ky tu cua s1 to s3
s3[int (strlen(s1) / 2)] = '\0'; // whyyyyy????
cout<<"chuoi s3:"<< s3 <<endl;
char *s4 = strdup(s1);
cout<<"chuoi s4:"<< s4 <<endl;
return 0;
}
String
▪ Đảo ngược chuỗi: strrev
char *strrev(const char *s);
▪ Đảo ngược thứ tự các ký tự trong chuỗi (trừ ký tự kết thúc chuỗi)
▪ Trả về địa chỉ của chuỗi kết quả.
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{ char s[] = "Tin hoc co so A";
char *p = strrev(s);
cout<<p; // A os oc coh niT
return 0;
}
String
❖ So sánh chuỗi - so sánh theo thứ tự từ điển : strcmp
▪ Phân biệt IN HOA – in thường:
int strcmp(const char *s1, const char *s2);
Có 3 TH xảy ra :
o strcmp(s1,s2) == 0: hai chuỗi kí tự này hoàn toàn giống nhau
char str1[] = "This is a string"; char str2[] = "This is a string";
o strcmp(s1,s2) < 0: chuỗi s1 nhỏ hơn chuỗi s2. Điều này có nghĩa tại vị trí phát hiện cặp kí tự
không tương xứng giữa str1 và str2.
char str1[] = "abcDEF"; char str2[] = "abcdef";
o strcmp(s1,s2) > 0: chuỗi s1 lớn hơn chuỗi s2.
char str1[] = "abcDEF"; char str2[] = “Abcdef";
▪ Không phân biệt IN HOA – in thường: stricmp
int stricmp(const char *s1, const char *s2);
#include<iostream> // Sap xep cac word trong s theo thu tu tang dan
#include<stdio.h> for(int i = 0; i < 3; i++)
for(int j = i+1; j < 4; j++)
#include<string.h>
{
using namespace std; if (strcmp(s[i],s[j])>0)
int main() {
{ char **s = new char*[5]; strcpy(temp,s[i]);
for(int i = 0; i < 4; i++) strcpy(s[i],s[j]);
s[i]= new char[255]; strcpy(s[j],temp);
char *temp = new char[255]; }
strcpy(s[0],"Banana"); }
strcpy(s[1],"Lemon"); cout <<"\nSau khi sap xep" << endl;
for(int i = 0; i < 4; i++)
strcpy(s[2],"Peach");
cout<< s[i] << " ";
strcpy(s[3],"Apple");
for(int i = 0; i < 4; i++) return 0;
cout<< s[i] << " "; }
String
▪ Nối chuỗi: strcat
Cú pháp: char * strcat ( char * destination, const char * source );
Ý nghĩa của hàm này là nối vào sau chuỗi destination một bản copy của chuỗi kí tự
source.
Lưu ý: Mảng kí tự destination phải có đủ bộ nhớ để chứa được thêm chuỗi mới được
nối vào.
▪ Tách chuỗi: strtok
Cú pháp : char *strtok(char *s, const char *sep);
Trả về địa chỉ của đoạn đầu tiên. Muốn tách đoạn kế tiếp tham số thứ nhất sẽ là NULL
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{
char s[255],t[255];
char c[255]= "Lap Trinh:C++";
cout<<"nhap s:"; gets(s);
cout<<"nhap t:"; gets(t);
strcat(s,t);
cout<<"noi chuoi = " << s <<endl;
//strtok // tach 2 chuoi boi dau :
cout<< strtok(c,":")<<endl;
//cat chuoi tu vi tri dung lai truoc do
cout<< strtok(NULL, ":")<<endl;
return 0;
}
String
▪ Tìm một ký tự trên chuỗi: strchr
Cú pháp: char *strchr(const char *s, int c);
o Tìm kiếm sự xuất hiện đầu tiên của ký tự c (một unsigned char) trong chuỗi được trỏ tới bởi tham
số s.
o Hàm này trả về một con trỏ tới sự xuất hiện đầu tiên của ký tự c trong chuỗi s, hoặc trả về NULL
nếu không tìm thấy ký tự đó.
▪ Tìm một ký tự trên chuỗi: strrchr
Cú pháp: char *strrchr(const char *str, int c)
o Tìm kiếm sự xuất hiện cuối cùng của ký tự c (một unsigned char) trong chuỗi được trỏ tới bởi
tham số str.
o Hàm này trả về một con trỏ tới sự xuất hiện cuối cùng của ký tự trong str. Nếu giá trị không được
tìm thấy, hàm trả về một con trỏ null.
▪ Tìm một đoạn ký tự trên chuỗi: strstr
Cú pháp: const char * strstr ( const char * text, const char * pattern );
Hàm này sẽ trả về địa chỉ của ô nhớ của mảng kí tự text mà hàm này tìm thấy sự trùng khớp giữa
chuỗi kí tự pattern với chuỗi kí tự text. Nếu không tìm thấy, hàm này trả về giá trị NULL.
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{
char text[] = "This is a simple string";
char pattern[] = "simple";
char c = 'e';
char *ret = strchr(text, c);
cout <<"ket qua:" << ret <<endl;
cout << "vi tri tim thay:" << (ret-text) / sizeof(char) << endl; // 15
char *p = strstr(text, pattern);
if (p == NULL) {
cout << "khong tim thay" << endl;
}
else {

int match_index = (p - text) / sizeof(char); // 10


cout <<"ket qua:" << p <<endl;
cout << "vi tri tim thay: " << match_index << endl;
}
cout<< strrchr(text, ' ')+1; // ' ‘ khoang trang-> in ra gi???
return 0;
}
simple aaaa
String
❖ Đổi chuỗi ký tự sang số : atoi(), atof(), atol():
▪ Cú pháp:
int atoi(const char *s): chuyển chuỗi thành số nguyên
long atol(const char *s): chuyển chuỗi thành số nguyên dài
float atof(const char *s): chuyển chuỗi thành số thực

Nếu chuyển đổi không thành công, kết quả trả về của các hàm là 0.

Ví dụ
float f;
char *str = "12345.67";
f = atof(str);
printf("string = %s float = %f\n", str, f);
String
❖ The less commonly-used string functions
▪ memset(), memcpy(), memcmp(), memmove()
▪ strerror()
▪ …

https://en.wikibooks.org/wiki/C_Programming/String_manipulation
String và FILE
▪ Hàm fputs() – ghi một chuỗi ký tự vào file. Hàm fputs() trong C được sử dụng để
ghi một chuỗi ký tự vào file.
Cú pháp : int fputs(const char * s, FILE *file)
Trong đó: #include <stdio.h>
#include <string.h>
- s là con trỏ trỏ tới địa chỉ của một chuỗi #include<iostream>
using namespace std;
- file: con trỏ tới một file cần ghi
int main()
{
FILE *fp;
// open file
fp = fopen("file2.txt", "wt");
// write string into file
fputs("hello c programming!", fp);
// close file
fclose(fp);
return 0;
}
String và FILE
File: file2.txt
▪ Hàm fgets() – đọc một dòng ký tự từ file. Hàm fgets()
trong C được sử dụng để đọc một dòng ký tự từ một Ky thuat Lap Trinh
file đã cho.
Cú pháp : char* fgets(char *s, int n, FILE *file)
#pragma warning(disable:4996)
Trong đó:
#include <iostream>
- s là con trỏ kiểu char trỏ tới một vùng nhớ để lưu trữ chuỗi #include <stdlib.h>
đọc từ file using namespace std;
- n là độ dài tối đa cần đọc trên một dòng trong file int main()
- file: là con trỏ đến file cần đọc {
// mo file de doc
❑ Lưu ý: FILE* fi = fopen("F:\\input_4.txt", "rt");
▪ Hàm fgets đọc từ file ra (n - 1) kí tự, việc đọc dữ liệu sẽ char text[300];
bị dừng nếu đọc được kí tự new line '\n' hoặc EOF. if(fgets(text,200,fi)!= NULL)
▪ Chuỗi kí tự đọc được sẽ lưu vào vùng nhớ được quản lý cout << text << endl;
bởi con trỏ s, nếu đọc dữ liệu thành công thì trả về địa chỉ fclose(fi);
của s, ngược lại trả về NULL. return 0;
}
String và FILE
❖ Đọc file có nhiều dòng
▪ Mỗi dòng lưu trữ vào một chuỗi ký tự (mỗi chuỗi có ký tự xuống dòng)
▪ Chuỗi cuối file không có ký tự xuống dòng

▪ Xét ví dụ file sau đây chứa 3 chuỗi

File: file3.txt
C was originally developed at Bell Labs
by Dennis Ritchie between 1972 and
1973 to make utilities running on Unix
Later it was applied to re-implementing
the kernel of the Unix operating system
During the 1980s C gradually gained
popularity
#pragma warning(disable:4996)
#include <iostream> Có thể dùng mảng tỉnh :
#include <stdlib.h> char s[10][1024];
#include <string.h>
using namespace std; Câu hỏi : viết lại chương trình bằng cách chia thành
int main() các hàm đọc file và ghi file
{ // mo file de doc
void readFromFile(FILE *file , char **&s, int &k);
FILE* fi = fopen("F:\\input_4.txt", "rt");
char **s; // dung mang dong (con tro cap 2)
void writeToFile(FILE *file, char **s);
char *temp = new char[1024];
s = new char*[10];
for(int i=0;i<10;i++)
s[i] = new char[1024];
//…
int k =0;
FILE *fp; // ghi 3 chuoi len file
while(fgets(temp,1024,fi)!= NULL)
// open file
{
fp = fopen("F:\\output_4.txt", "wt");
strcpy(s[k],temp);
// write string into file
k++;
for(int i=0;i<k;i++) // ghi len file
}
fputs(s[i], fp);
for(int i=0;i<k;i++) // in 3 chuoi ra man hinh
puts(s[i]);
fclose(fp);
return 0;
fclose(fi);
}
// …
#include<iostream>
#include<stdio.h>
Ví dụ: #include<string.h>
using namespace std;
int main() {
▪ Nhập vào một chuỗi. Đếm số char s[150];
lượng nguyên âm, phụ âm trong int vowels, consonant, digit, space;
chuỗi (Count the Number of vowels = consonant = digit = space = 0;
Vowels, Consonants) gets(s);
for (int i = 0; s[i] != '\0'; ++i) {
Ví dụ: Input: “ Lap trinh C” if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' ||
Nguyên âm: 2 s[i] == 'o' || s[i] == 'u' || s[i] == 'A' ||
s[i] == 'E' || s[i] == 'I' || s[i] == 'O' ||
Phụ âm: 7 s[i] == 'U') {
++vowels;
}
else if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) {
++consonant;
}
cout<<"Vowels: " << vowels <<endl;
else if (s[i] >= '0' && s[i] <= '9') {
cout<<"Consonants: " << ++digit;
consonant<<endl; }
cout<<"Digits: " << digit<<endl; else if (s[i] == ' ') {
cout<<"White spaces: " << space<<endl; ++space;
return 0; }
} }
int countWords(char *str)
Ví dụ: {
bool inWord = false;
▪ Đếm số lượng từ trong chuỗi int c = 0; // word count
(Count words in a given int len = strlen(str);
string) // Scan all characters one by one
for(int i=0;i<len;i++)
Ví dụ: Input: “ Lap trinh C” . { if (str[i] == ' ' || str[i] == '\n' || str[i] == '\t')
Output: 3 inWord = false;
Câu hỏi: // If next character is not a separator and
- đếm từ bắt đầu bằng nguyên âm // inWord is False, then set the inWord as True and
- đếm từ bắt đầu bằng phụ âm // increment word count
else if (inWord == false)
{
#include<iostream> inWord = true;
#include<stdio.h>
#include<string.h>
c++;
using namespace std; }
int countWords(char *str) ; }
int main() return c;
{
char *s = new char[255]; }
gets(s);
cout <<"so luong tu:" <<countWords(s) << endl;
return 0;
}
#include<iostream>

Ví dụ: #include<stdio.h>
#include<string.h>
using namespace std;
▪ Tách các từ trong chuỗi (Split int main()
string by space into words) {
char str[] = "ky thuat lap trinh";
char **newstr = new char*[20];
for(int i=0; i<20; i++)
newstr[i] = new char[255];
char delim[] = " "; // tach bang khoang trang
char *ptr = strtok(str, delim);
int n = 0;
while(ptr != NULL)
{
strcpy(newstr[n],ptr);
ptr = strtok(NULL, delim);
n++;
}
for(int k=0; k< n;k++)
cout<< newstr[k] <<endl;
Câu hỏi: cách tiếp cận khác không dùng strtok??? return 0;
}
Ví dụ:
▪ Viết chương trình đảo ngược thứ tự các từ có trong chuỗi (Reverse words in a given string)
Ví dụ: Nhập: lap trinh C ( giả sử mỗi từ cách nhau một khoảng trắng)
Xuất ra màn hình là: C trinh lap
#include<iostream>
#include<stdio.h> Câu hỏi: cách tiếp cận khác không dùng strcat ???
#include<string.h>
using namespace std;
void daothutu(char*s)
{ char c[255];
c[0]='\0';
for(int i=strlen(s)-1;i>=0;i--) int main()
if(s[i]==' ') {
{ char *s = new char[255];
strcat(strcat(c,s+i+1)," "); gets(s);
s[i]='\0'; cout <<"input:" <<s << endl;
} daothutu(s);
strcat(c,s); return 0;
puts(c); // in ra man hinh }
}
Bài Tập
1) Nhập vào một chuỗi s bao gồm các chữ cái in thường hoặc in hoa và khoảng trắng. Giả sử một từ là
một dãy liên tiếp các ký tự không chứa khoảng trắng.
Giả sử giữa các từ cách nhau duy nhất một khoảng trắng
Giả sử đầu và cuối chuỗi không chứa khoảng trắng.
Viết chương trình (hàm) thực hiện các yêu cầu sau :
a) Tách một từ bên phải/bên trái của chuỗi s
b) Đưa các ký tự đàu mỗi từ thành chữ in Hoa, còn lại chữ in thường
c) Đếm số lần xuất hiện của chuỗi con y trong s
d) Đếm số lần xuất hiện của các ký tự trong chuỗi s (26 ký tự latin từ a đến z)
e) Tạo chuỗi con được ghép từ từ đầu tiên và từ cuối cùng của chuỗi. Giữa 2 từ có một khoảng trắng.
f) Đảo các ký tự ngược lại trong mỗi từ.
g) Sắp xếp các từ trong chuỗi theo thứ tự tăng dần (theo thứ tự từ điển)
Bài tập
2. Nhập vào một chuỗi s bao gồm các chữ cái in thường hoặc in hoa và khoảng trắng. Giả sử một từ là
một dãy liên tiếp các ký tự không chứa khoảng trắng.
Giả sử giữa các từ cách nhau duy nhất một khoảng trắng
Giả sử đầu và cuối chuỗi không chứa khoảng trắng.
Viết chương trình (hàm) thực hiện các yêu cầu sau :
a) Đếm xem trong chuỗi s có bao nhiêu nguyên âm, phụ âm.
b) Kiểm tra xem chuỗi s có đối xứng hay không ? Ví dụ: chuỗi: “abc cba” là chuỗi đối xứng
c) Đếm xem chuỗi s có bao nhiêu từ?
d) Trong mỗi từ trong s, đếm xem có bao nhiêu ký tự. Tìm từ dài nhất (nhiều ký tự nhất)
e) Đếm số từ có k ký tự trong chuỗi s ( nhập vào k)
Bài tập
3) Sắp xếp các chuỗi theo thứ tự chữ cái ( dùng string compare). Đọc chuỗi từ file
input.txt, in kết quả đã sắp xếp ra file output.txt
Hint:
• Dùng array of string (2D pointer) để lưu trữ các chuỗi.
• Dùng hàm strcmp để so sánh hai chuỗi
Input.txt Output.txt
Hello Apple
Apple Candy
Cat Cat
Hi Hat
Hat Hello
Holiday Hi
Candy Holiday
Bài tập
4) Chuyển chuỗi sang số. Đọc một chuỗi từ file input (các chữ số cách nhau một
khoảng trắng). In kết quả ra màn hình

Input.txt Output: số nguyên


24510967 24510967
Bài tập
5) File input.txt chứa các chuỗi * File chua chuoi tieng Anh hoac Tieng Viet khong dau

- Mỗi chuỗi trên một dòng , phân biệt bởi ký tự xuống dòng Input.txt
- Đầu và cuối chuỗi không có khoảng trắng C provides constructs that map efficiently to
- Giữ các từ có duy nhất một khoảng trắng typical machine instructions and has found
* In ra kết quả ra màn hình và ghi vào file output.txt lasting use in applications previously coded
in assembly language
Đọc chuỗi từ File text
Such applications include operating systems
a) Có bao nhiêu chuỗi chứa chuỗi con “and” ? and various application software for
b) Mỗi chuỗi có bao nhiêu từ có 3 ký tự. computers from supercomputers to
embedded systems
c) Tìm một chuỗi có nhiều từ nhất, Có tất cả bao nhiêu từ
C was originally developed at Bell Labs by
d) Sắp xếp các chuỗi tăng theo thứ tự là chiều dài của các chuỗi. Dennis Ritchie between 1972 and 1973 to
e) Đếm xem file Input.txt có tất cả bao nhiêu từ make utilities running on Unix
Later it was applied to re-implementing the
f) Tìm một từ dài nhất ứng với mỗi chuỗi.
kernel of the Unix operating system
g) Tìm chuỗi đảo ngược tương ứng. During the 1980s C gradually gained
h) Tìm các chuỗi con chứa các từ tại vị trí 2,3,4,5. popularity
(V í dụ chuôi đầu tiên có chuỗi con là “provides constructs that map ”)
Chuỗi ký tự trong C++ (option)
Chuỗi ký tự trong C++ (option)
▪ Các chương trình C++ có thể sử dụng chuỗi theo cách thức cũ của Ngôn ngữ C
(trong bài viết này gọi là C-String): mảng các ký tự kết thúc bởi ký tự mã ASCII là
0 (ký tự \0) cùng với các hàm thư viện khai báo trong <string.h>.
▪ Hạn chế:
o Người lập trình phải chủ động kiểm soát bộ nhớ cấp phát cho chuỗi ký tự.
o Không thể gán giá trị hay sử dụng phép toán + (ghép chuỗi) và các phép toán so
sánh như: > (lớn hơn), < (nhỏ hơn),... mà phải gọi các hàm thư viện trong
<string.h>
o Nếu dùng kỹ thuật cấp phát động thì phải quản lý việc cấp thêm bộ nhớ khi chuỗi
dãn ra (chẳng hạn do ghép chuỗi) và phải hủy bộ nhớ (khi không dùng nữa) để
tránh việc cạn kiệt bộ nhớ của máy tính
Chuỗi ký tự trong C++
▪ Kiểu chuỗi string trong thư viện STL của C++: Thư viện chuẩn STL (Standard
Template Library) cung cấp kiểu string (xâu ký tự)

#include <string>
using namespace std;

• Chuyển từ string sang C-String:


string s;
s.c_str();
• Chuyển từ C-String sang string:
char* s_old = "ABC";
string s(s_old);
Chuỗi ký tự trong C++
▪ Các phép toán và phương thức cơ bản:
o Các toán tử +, += dùng để ghép hai chuỗi và cũng để ghép một ký tự vào chuỗi;
o Các phép so sánh theo thứ tự từ điển: == (bằng nhau), != (khác nhau), > (lớn
hơn), >= (lớn hơn hay bằng), < (nhỏ hơn), <= (nhỏ hơn hay bằng);
o Hàm length() và phép lấy chỉ số [] để duyệt từng ký tự của chuỗi: nếu s là biến
kiểu string thì s[i] là ký tự thứ i của s với 0≤i<s.length();
o Phép gán = dùng để gán biến kiểu string bằng một chuỗi, hoặc bằng string khác,
chẳng hạn: string s="ABCDEF"; hay s1=s2; mà không cần copy xâu.
Chuỗi ký tự trong C++
Ví dụ: char st[]="ABCDEF";
string s;
s="XYZ";
cout << s << endl;
s=st;
cout << s.length() << " : " << s <<
endl;
toán tử >> với cin để nhập một chuỗi ký tự đến khi gặp một khoảng trống thì dừng.
Chuỗi ký tự trong C++
#include <iostream>
#include <conio.h>
Ví dụ: #include <string>
using namespace std;
int main()
{
string s = "Hello string"; // Khai báo biến kiểu string
cout << "Noi dung string: " << s << endl; // In nôi dung string ra màn hình
cout << "Chieu dai cua string: " << s.size() << endl;
// Chiều dài
cout << "Ky tu 0: " << s[0] << endl; // In ký tự đầu tiên của xâu
cout << "Ky tu 1: " << s[1] << endl; // In ký tự thứ 2
cout << "Ky tu 2: " << s[2] << endl; // In ký tự thứ 3
getchar();
return 0;
}
Chuỗi ký tự trong C++
▪ Nhập một string trên 1 dòng (chú ý cin sẽ chỉ đọc đến dấu cách hoặc xuống dòng đầu tiên):
istream& getline ( istream& in, string& str, char delimiter = ‘\n’);

istream in (có thể là file hay đối tượng chuẩn cin)


// getline with strings
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str;
short age;
cout << "Please enter full name and age"<< endl;
getline( cin, str) >> age;
cout << "Thank you " << str << "!\n";
return 0;
}
Chuỗi ký tự trong C++
▪ Các phương thức chèn, xóa, lấy chuỗi con:
Phương thức substr(int pos, int nchar) trích ra chuỗi con của một chuỗi cho trước,
Ví dụ str.substr(2,4) trả về chuỗi con gồm 4 ký tự của chuỗi str kể từ ký tự ở vị trí thứ 2 (ký tự đầu
tiên của chuỗi ở vị trí 0).
//get substring
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
int main ()
{
string s=“Hello World!!!!!!!!!";
cout << s.substr(2,4) << endl;
// cout << new string(str.begin()+2, str.begin()+2+4);
getchar();
return 0;
}
Chuỗi ký tự trong C++
▪ Phương thức insert() chèn thêm ký tự hay chuỗi vào một vị trí nào đó của chuỗi str
cho trước. Có nhiều cách dùng phương thức này:

str.insert(int pos, char* s); chèn s (mảng ký tự kết thúc \0) vào vị trí pos của str;
str.insert(int pos, string s); chèn chuỗi s (kiểu string) vào vị trí pos của chuỗi str;
str.insert(int pos, int n, int ch); chèn n lần ký tự ch vào vị trí pos của chuỗi str;
Chuỗi ký tự trong C++
// inserting into a string
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
int main ()
{
string str="day la .. xau thu";
string istr = "them";
str.insert(8, istr);
cout << str << endl;
getchar();
return 0;
}
Chuỗi ký tự trong C++
▪ Phương thức str.erase(int pos, int n) xóa n ký tự của chuỗi str kể từ vị trí pos; nếu không quy định
giá trị n thì tất cả các ký tự của str từ vị trí pos trở đi sẽ bị xóa
// erase from a string
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
int main ()
{
string str="day cung la xau thu";
str.erase(0, 3); // " cung la xau thu"
cout << str << endl;
str.erase(6, 2);
cout << str << endl; // " cung xau thu"
getchar();
return 0;
}
Chuỗi ký tự trong C++
▪ So sánh: có thể đơn giản là sử dụng những toán tử quan hệ (==, !=, <, <=, >=) được
định nghĩa sẵn.
Tuy nhiên, nếu muốn so sánh một phần của một chuỗi thì sẽ cần sử dụng phương
thức compare()

int compare ( const string& str ) const;


int compare ( const char* s ) const;
int compare ( size_t pos1, size_t n1, const string& str ) const;
int compare ( size_t pos1, size_t n1, const char* s) const;
int compare ( size_t pos1, size_t n1, const string& str, size_t pos2, size_t n2 ) const;
int compare ( size_t pos1, size_t n1, const char* s, size_t n2) const;

Hàm trả về 0 khi hai chuỗi bằng nhau và lớn hơn hoặc nhỏ hơn 0 cho trường hợp khác
Chuỗi ký tự trong C++
// comparing apples with apples
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str1 ("green apple");
string str2 ("red apple");
if (str1.compare(str2) != 0)
cout << str1 << " is not " << str2 << "\n";
if (str1.compare(6,5,"apple") == 0)
cout << "still, " << str1 << " is an apple\n";
if (str2.compare(str2.size()-5,5,"apple") == 0)
cout << "and " << str2 << " is also an apple\n";
if (str1.compare(6,5,str2,4,5) == 0)
cout << "therefore, both are apples\n";
return 0;
}
Chuỗi ký tự trong C++
▪ Các phương thức tìm kiếm và thay thế
Phương thức find() tìm kiếm xem một ký tự hay một chuỗi nào đó có xuất hiện trong
một chuỗi str cho trước hay không

str.find(int ch, int pos = 0); tìm ký tự ch kể từ vị trí pos đến cuối chuỗi str
str.find(char *s, int pos = 0); tìm s (mảng ký tự kết thúc ‘\0’) kể từ vị trí pos đến cuối
str.find(string& s, int pos = 0); tìm chuỗi s kể từ vị trí pos đến cuối chuỗi.
Chuỗi ký tự trong C++
//find substring
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
int main ()
{
string str="Hello World ";
cout << str.find("World") << endl; // 6
cout << (int)str.find("hi") << endl; // -1
getchar();
return 0;
}
Chuỗi ký tự trong C++
▪ Phương thức replace() thay thế một đoạn con trong chuỗi str cho trước (đoạn con
kể từ một vị trí pos và đếm tới nchar ký tự ký tự về phía cuối chuỗi) bởi một chuỗi
s nào đó, hoặc bởi n ký tự ch nào đó.

str.replace(int pos, int nchar, char *s);


str.replace(int pos, int nchar, string s);
str.replace(int pos, int nchar, int n, int ch);

………………………………………………………..
string str="Hello World";
str.replace(0, 5, "Hi");
cout << str << endl;
getchar();
Chuỗi ký tự trong C++
▪ Tách xâu: stringstream
string S = "Xin chao tat ca cac ban"; // Khởi tạo giá trị của xâu
stringstream ss(S); // Khởi tạo stringstream từ xâu S

while (ss >> token) { // Đọc lần lượt các phần của xâu. Các phần tách nhau bởi dấu cách hoặc xuống dòng.
cout << token << endl;
}
Chuỗi ký tự trong C++
▪ Một số phương thức khác
Nhiều phương thức tiện ích khác như:
append()
rfind()
find_first_not_of()
find_last_not_of()
swap()

Cách dùng các hàm này đều được trình bày trong hệ thống hướng dẫn (help) của các
môi trường có hỗ trợ STL (trong VC++ là MSDN)

You might also like