Tài liệu Kỹ thuật lập trình - Bài 4: Chuỗi ký tự - Ngô Hữu Dũng: Kỹ thuật lập trình
Bài 4 – Chuỗi ký tự
Ngô Hữu Dũng
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-201791
Khái niệm
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-201792
 Mảng kiểu ký tự
 char word [] = {'H','e','l','l','o','!'};
 Chuỗi ký tự
 char word [] = {'H','e','l','l','o','!','\0'};
 char word [] = "Hello!";
 Chuỗi ký tự bao gồm một ký tự đặc biệt nằm cuối chuỗi
 Báo hiệu kết thúc chuỗi
 Được hiểu là ký tự NULL, có thể viết là '\0'
 Một chuỗi, ví dụ "Hello!", đã bao hàm ký tự kết thúc, tức char[7]
 Kiểu liệt kê, ví dụ {'H','e','l','l','o','!','\0'}, tức char[7]
Khai báo
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-201793
 Cú pháp char [] = ;
 Cần xác định kích cỡ của chuỗi
 Khai báo 
 Khởi tạo một giá trị cho biến
 cần đủ lớn để chứa 
 có thể lớn hơn chiều dài của 
 bao gồm các ký tự và ký tự NULL (\0)
 Nếu không khai báo (để trống)
 Cần khởi tạo chuỗi ban đầu cho biến
 Kích cỡ của biến chính là chiều dài của ...
                
              
                                            
                                
            
 
            
                 30 trang
30 trang | 
Chia sẻ: putihuynh11 | Lượt xem: 774 | Lượt tải: 0 
              
            Bạn đang xem trước 20 trang mẫu tài liệu Kỹ thuật lập trình - Bài 4: Chuỗi ký tự - Ngô Hữu Dũng, để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
Kỹ thuật lập trình
Bài 4 – Chuỗi ký tự
Ngô Hữu Dũng
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-201791
Khái niệm
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-201792
 Mảng kiểu ký tự
 char word [] = {'H','e','l','l','o','!'};
 Chuỗi ký tự
 char word [] = {'H','e','l','l','o','!','\0'};
 char word [] = "Hello!";
 Chuỗi ký tự bao gồm một ký tự đặc biệt nằm cuối chuỗi
 Báo hiệu kết thúc chuỗi
 Được hiểu là ký tự NULL, có thể viết là '\0'
 Một chuỗi, ví dụ "Hello!", đã bao hàm ký tự kết thúc, tức char[7]
 Kiểu liệt kê, ví dụ {'H','e','l','l','o','!','\0'}, tức char[7]
Khai báo
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-201793
 Cú pháp char [] = ;
 Cần xác định kích cỡ của chuỗi
 Khai báo 
 Khởi tạo một giá trị cho biến
 cần đủ lớn để chứa 
 có thể lớn hơn chiều dài của 
 bao gồm các ký tự và ký tự NULL (\0)
 Nếu không khai báo (để trống)
 Cần khởi tạo chuỗi ban đầu cho biến
 Kích cỡ của biến chính là chiều dài của chuỗi (gồm ký tự NULL)
 khởi tạo hợp lệ?
 nằm giữa dấu hai nháy “”
 liệt kê {} các ký tự bao gồm ký tự NULL, ‘\0’, ở cuối cùng
Ví dụ khai báo
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-201794
1. char hello[] = "Hello!"; // char[7]
2. char hi[] = {'H','i','!','\0'}; // char[4]
3. char name[10];
4. char classname[20] = " Lop tin hoc ";
5. char city[20] = "TP. HCM";
6. char empty[] = "";
7. char empty1[10] = "";
8. char country[] = {'V','N'};// Array, not string!
9. char gender[2] = "male"; // Error!? Overflow
10. char classroom = "V10.4"; // Error!? Char vs string
11. char university[] = 'IUH'; // Error!? Char vs string
12. char a[]; // Error!? unknown size
Khởi tạo giá trị
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-201795
 Một khởi tạo giá trị: char hello[] = "Hello!";
 Tương đương với
 char hello[] = {'H','e','l','l','o','!','\0'};
 char hello[7] = {'H','e','l','l','o','!','\0'};
 char hello[7] = "Hello!";
 Một khởi tạo giá trị: char empty[] = "";
 Tương đương với
 char empty[] = {'\0'}; 
 char empty[1] = {'\0'};
 char empty[1] = "";
Khởi tạo giá trị (2)
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-201796
 Một khởi tạo giá trị: 
 char hi[7] = "Hi!";
 char hi[7] = {'H','i','!','\0'};
 Khởi tạo một chuỗi rất dài, dùng dấu \ để xuống dòng
 char longstring[] = "Toi la sinh vien Cong nghe Thong \
 tin\nTruong Dai hoc Cong Nghiep TP. HCM.\n\
 Than chao cac ban!";
 char longstring[] = "Toi la sinh vien Cong nghe Thong "
 "tin\nTruong Dai hoc Cong Nghiep TP. HCM.\n"
 "Than chao cac ban!";
0 1 2 3 4 5 6
'H' 'i' '!' '\0'
Phép gán
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-201797
 Các phép gán trực tiếp cho chuỗi bị hạn chế
 Bởi trình biên dịch xử lý với chuỗi như mảng
 Một khởi tạo giá trị: char hello[] = "Hello!";
 Các phép gán trực tiếp sau đó bị trình biên dịch báo lỗi
 hello = "Good morning!"; // Error!
 “Good morning!” là const char[14] không gán được cho char[7]
 hello = "Hi!"; // Error!
 const char[4] không thể được gán cho char[7]
 hello = hi; // Error!
 char[4] không thể được gán cho char[7]
Phép gán (2)
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-201798
 Một khai báo char name[10];
 name = "Quang"; // Error!
 const char[6] không gán được cho char[10]
 name = hello; // Error!
 char[7] không gán được cho char[10]
 Làm thế nào để thay đổi giá trị của chuỗi?
 Dùng các hàm xử lý chuỗi như scanf
 Thay đổi từng phần tử
 Các hàm trong thư viện string.h
 Tự viết hàm xử lý chuỗi ký tự
Nhập chuỗi từ bàn phím
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-201799
 Dùng hàm scanf trong thư viện stdio.h
 scanf("%s",name);
 Nhập "My name is C", name = "My"
 scanf("%[^\n]s",name);
 Nhập "My name is C", name = "My name is C"
 scanf("%[^e]s",name);
 Nhập "My name is C", name = "My nam"
 scanf("%10s",name);
 Nhập "My_name_is_C", name = "My_name_is"
 scanf("%s %s",name1, name2);
 Nhập "My name is C", name1 = "My", name2 = "name"
 scanf tự động thêm ký tự NULL vào sau chuỗi nhận được từ bàn phím
Phần tử của chuỗi
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017100
 Phép khởi tạo char hello[] = "Hello!";
 hello[0] = 'H', hello[1] = 'e', hello[2] = 'l', hello[6] = '\0'
 Phép gán sau đó hello = "Hi!"; sẽ bị báo lỗi!
 Có thể thay thế phép gán trên bằng các lệnh:
 hello[0] = 'H';
 hello[1] = 'i';
 hello[2] = '!';
 hello[3] = '\0';
 Xuất chuỗi: printf("%s", hello);
 printf("%s", "e"); // "e"= {'e', '\0'}
 Xuất ký tự: printf("%c", hello[1]);
 printf("%c", 'e');
hello[0] hello[1] hello[2] hello[3] hello[4] hello[5] hello[6]
'H' 'e' 'l' 'l' 'o' '!' '\0'
Thư viện string.h
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017101
 size_t strlen(const char * str)
 Trả về chiều dài của chuỗi ký tự str
 strlen(“hello”) = 5, strlen(hello) = 6
 size_t: Unsigned integral type
 const char: Bởi hàm không thay đổi giá trị của str
 char * strcpy(char * destination, const char * source)
 Chép nội dung chuỗi source sang chuỗi destination bao gồm ký tự NULL
 Chuỗi destination phải đủ chứa chuỗi source (bao gồm ký tự NULL)
 Bản thân hàm trả về destination
 strcpy(hello, “Hi!”) trả về chuỗi “Hi!” và hello = “Hi!”
 char * destination: Hàm thay đổi giá trị của destination
 const char * source: Hàm không thay đổi giá trị của source
Thư viện string.h (2)
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017102
 char * strncpy(char * destination, const char * source, size_t num)
 Chép num phần tử đầu tiên của source sang destination
 Nếu num không đủ lớn để bao gồm ký tự NULL của source, 
 hàm không tự gán ký tự NULL vào destination
 strncpy(hello, “Hi!”, 3); // hello = “Hi!ol!”
 hello[3]=‘\0’; // hello = “Hi!”
 strncpy(hello, hi, strlen(hi)+1); // hello = “Hi!”
 char * strcat( char * destination, const char * source )
 Nối chuỗi source vào cuối chuỗi destination
 destination phải đủ chứa chuỗi kết quả (bao gồm ký tự NULL)
 char name[10]; strcpy(name, hello); strcat(name, hi); // name = “Hello!Hi!”
Thư viện string.h (3)
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017103
 char * strncat( char * destination, const char * source, size_t num ) 
 Nối num ký tự của chuỗi source vào cuối chuỗi destination
 Tự động thêm ký tự NULL và chuỗi kết quả (khác với strncpy)
 strcpy(name, hello); strncat(name, hi, 2); // name = “Hello!Hi”
 int strcmp( const char * str1, const char * str2 )
 So sánh chuỗi str1 với chuỗi str2, so sánh từng ký tự từ đầu đến khi phát hiện điểm
khác nhau hoặc đến cuối chuỗi (‘\0’)
 Giá trị trả về >0: str1 > str2
 Giá trị trả về =0: str1 = str2
 Giá trị trả về <0: str1 < str2
 int strcoll( const char * str1, const char * str2 )
 Tương tự strcmp
Thư viện string.h (4)
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017104
 int strncmp ( const char * str1, const char * str2, size_t num )
 So sánh num ký tự trong chuỗi str2 với chuỗi str1
 const char * strchr( const char * str, int character) 
 Trả về con trỏ (địa chỉ) của vị trí đầu tiên tìm được ký tự character trong chuỗi str
 printf("%d",strchr(hello,'o')-hello+1); // In ra số 5, tìm thấy ký tự ‘o’
 size_t strcspn( const char * str1, const char * str2)
 Trả về vị trí của phần tử trên str1 giống với ký tự bất kỳ trong str2
 printf("%d",strcspn(hello,"I got it!")+1); // In ra số 5, tìm thấy ký tự ‘o’
 const char * strpbrk( const char * str1, const char * str2)
 Giống strcspn nhưng trả về con trỏ (địa chỉ) của ký tự được tìm thấy hoặc NULL nếu
không tìm thấy
 printf("%d",strpbrk(hello,"I got it!")-hello+1); // In ra số 5, tìm thấy ký tự ‘o’
Thư viện string.h (5)
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017105
 const char * strrchr( const char * str, int character )
 Giống strchr nhưng tìm phần từ cuối cùng của chuỗi str
 printf("%d",strrchr(hello, 'l')-hello+1); // In ra số 4, tìm thấy ký tự ‘l’ sau
 size_t strspn( const char * str1, const char * str2): Trả về số ký tự đầu tiên
trong str1 trùng với bất kỳ ký tự nào trong str2
 strspn(hello,hi); // = 1, tìm được chữ ‘H’
 strspn(hello, “!olleH”); // = 6, tìm được các chữ H, e, l, l, o, !
 strspn(hello, “Heyo!”); // = 2, tìm được các chữ H, e, chữ o không được tính vì
không tìm được chữ ‘l’ theo thứ tự
 const char * strstr( const char * str1, const char * str2 ): Trả về con trỏ (địa
chỉ) của vị trí tìm thấy str2 trong str1
 printf("%d",strstr(hello,"lo")-hello+1); // = 4
Thư viện string.h (6)
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017106
 char * strtok( char * str, const char * delimiters): Chia chuỗi thành các chuỗi
con
 Char classname[20] = “ Lop tin:11”;
 printf("%s\n",strtok(classname," :")); // “Lop”
 printf("%s\n",strtok(NULL," :")); // “Tin”
 printf("%s\n",strtok(NULL," :")); // “11”
 void * memset( void * ptr, int value, size_t num): Điền giá trị value vào num
bytes ô nhớ đầu tiên của biến ptr
 memset(hello,'2',2); // hello = “22llo!”
 void * memcpy( void * destination, const void * source, size_t num ): Chép
num ô nhớ đầu tiên của biến source vào biến destination
 memcpy(hello,hi,3); // hello = “Hi!lo!”
Thư viện string.h (7)
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017107
 void * memmove( void * destination, const void * source, size_t num): Giống
memcpy nhưng cho phép chồng lấn
 memmove(hello,hi,3); // hello = “Hi!lo!”
 memcpy(hello,hello+3,3); // hello = “lo!lo!” trường hợp chồng lấn
 int memcmp( const void * ptr1, const void * ptr2, size_t num): So sánh ô nhớ
 const void * memchr( const void * ptr, int value, size_t num ): Tìm kiếm
 Ghi chú: Các lệnh về memory (mem) không phân biệt kiểu dữ liệu, chỉ thao tác
với dữ liệu binary trong các ô nhớ
 void * memset( void * ptr, int value, size_t num): Điền giá trị value vào num
bytes ô nhớ đầu tiên của biến ptr
 memset(hello,'2',2); // hello = “22llo!”
Thư viện string.h (8)
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017108
 void * memcpy( void * destination, const void * source, size_t num )
 Chép num ô nhớ đầu tiên của biến source vào biến destination
 memcpy(hello,hi,3); // hello = “Hi!lo!”
 void * memmove( void * destination, const void * source, size_t num) 
 Giống memcpy nhưng cho phép chồng lấn
 memmove(hello,hi,3); // hello = “Hi!lo!”
 memcpy(hello,hello+3,3); // hello = “lo!lo!” trường hợp chồng lấn
 int memcmp( const void * ptr1, const void * ptr2, size_t num)
 So sánh num ô nhớ
 const void * memchr( const void * ptr, int value, size_t num )
 Tìm kiếm giá trị value
 Ghi chú: Các lệnh về memory (mem) không phân biệt kiểu dữ liệu, chỉ thao tác
với dữ liệu binary trong các ô nhớ
Chuyển đổi giữa chuỗi và số
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017109
 Thư viện chứa các hàm chuyển đổi giữa chuỗi và số
 int atoi (const char * str)
 Chuyển chuỗi str sang số nguyên và trả về giá trị số nguyên
 atoi("34.5 53") = 34
 double atof (const char* str)
 Chuyển đổi một chuỗi sang kiểu số thực và trả về số thực
 atof("34.5 53") = 34.5
 long int atol ( const char * str )
 Chuyển đổi chuỗi sang kiểu long int (4 bytes)
 long long int atoll ( const char * str )
 Chuyển đổi chuỗi sang kiểu long long int (8 bytes)
Chiều dài của chuỗi
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017110
 Chiều dài của chuỗi được xác định dựa vào ký tự NULL, kết thúc chuỗi
 Viết hàm tính chiều dài của chuỗi
 Hàm có kiểu nguyên, trả về chiều dài của chuỗi (output)
 Đối số của hàm là một chuỗi (input)
 Mã giả:
 Khai báo một biến đếm và khởi tạo giá trị 0
 Duyệt và đếm các phần tử của chuỗi
 Dừng đếm khi gặp ký tự ‘\0’
 Trả về chiều dài của chuỗi dựa vào giá trị của biến đếm
 Tương tự hàm strlen của thư viện string.h
Ví dụ tham khảo hàm tính chiều dài của chuỗi
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017111
1. int stringLength(const char str[])
2. {
3. int count = 0;
4. while (str[count] != '\0') 
5. count++;
6. return count;
7. }
8.
9. int main()
10. {
11. char hello[] = "Hello!"; 
printf("%d",stringLength(hello));
12. }
Chép chuỗi
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017112
 Viết hàm chép nội dung của một chuỗi nguồn vào một chuỗi đích
 Chuỗi đích sẽ mang giá trị của chuỗi nguồn (output)
 Đối số của hàm là hai chuỗi, nguồn và đích (input)
 Mã giả
 Khai báo một biến chạy và khởi gán giá trị ban đầu
 Duyệt từng phần tử của chuỗi nguồn
 Gán giá trị của từng phần tử ở chuỗi nguồn sang chuỗi đích
 Dừng sao chép khi gặp ký tự ‘\0’
 Gán ký tự ‘\0’ vào cuối chuỗi đích
 Tương tự lệnh strcpy của thư viện string.h
 Hàm có kiểu trả về là void
 Bạn có thể trả về chuỗi đích cho hàm nếu biết dùng con trỏ, pointer (sẽ học sau)
Ví dụ tham khảo hàm chép chuỗi
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017113
1. void stringCopy(char str1[], const char str2[])
2. {
3. int i=-1;
4. do{
5. i++;
6. str1[i]=str2[i];
7. }while (str2[i]!='\0');
8. }
9. int main()
10. {
11. char hello[10];
12. stringCopy(hello,"Hello!");
13. printf("%s",hello);
14. }
Nối chuỗi
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017114
 Viết hàm nối một chuỗi nguồn vào cuối một chuỗi đích
 Chuỗi đích sẽ mang giá trị là kết quả của việc nối hai chuỗi
 Đối số của hàm gồm hai chuỗi
 Mã giả
 Khai báo hai biến chạy và khởi gán giá trị ban đầu
 Biến chạy cho chuỗi nguồn, bắt đầu từ đầu chuỗi nguồn
 Biến chạy cho chuỗi đích, bắt đầu từ cuối chuỗi đích
 Duyệt từng phần tử của chuỗi nguồn
 Gán giá trị của các phần tử của chuỗi nguồn vào chuỗi đích
 Dừng sao chép khi gặp ký tự NULL của chuỗi nguồn
 Gán ký tự NULL vào chuỗi đích
 Hàm tương tự như hàm strcpy trong thư viện string.h
Ví dụ tham khảo hàm nối chuỗi
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017115
1. void stringAppend(char dest[], const char src[])
2. {
3. int i = stringLength(dest)-1, j = -1;
4. do{
5. i++;j++;
6. dest[i]=src[j];
7. }while(src[j]!='\0');
8. }
9. int main()
10. {
11. char thanks[20] = "Thank";
12. stringAppend(thanks, " you!");
13. printf("%s",thanks);
14. }
So sánh chuỗi
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017116
 Viết hàm so sánh hai chuỗi ký tự str1 và str2
 Hàm trả về giá trị
 < 0 nếu str1 < str2
 = 0 nếu str1 = str2
 > 0 nếu str1 > str2
 Hàm có 2 đối số là hai chuỗi cần so sánh
 Mã giả
 Khai báo và khởi tạo cho một biến chạy
 Duyệt các phần tử cho đến khi
 Gặp phần tử khác nhau
 Hoặc kết thúc một trong hai chuỗi
 So sánh phần tử cuối cùng và trả về giá trị so sánh tương ứng
Ví dụ tham khảo về hàm so sánh chuỗi
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017117
1. int stringCompare(const char str1[], const char str2[])
2. {
3. int i = 0;
4. while(str1[i]==str2[i]&&str1[i]!='\0'&&str2[i]!='\0')
5. i++;
6. if(str1[i]>str2[i]) 
7. return 1;
8. else if (str1[i]<str2[i])
9. return -1;
10. else
11. return 0;
12. };
Tìm kiếm
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017118
 Viết hàm tìm kiếm vị trí của một chuỗi nguồn trong chuỗi đích
 Hàm trả về số nguyên là vị trí đầu tiên tìm thấy
 Hàm trả về số âm nếu không tìm thấy
 Đối số của hàm là hai chuỗi
 Mã giả?
 ?
 ?
 ?
 ?
Ví dụ tham khảo về tìm kiếm chuỗi
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017119
 Hoạt động??
1. int stringSearch(const char str1[], const char str2[])
2. {
3. int i=0, j=0;
4. while(str1[i]!='\0' && str2[j]!='\0')
5. {
6. if(str1[i+j]!=str2[j]) 
7. {
8. i++; j=0;
9. }
10. else
11. j++;
12. if (str2[j]=='\0') 
13. return i;
14. }
15. return -1;
16. }
Hết bài 4
Ngô Hữu DũngKỹ thuật lập trình | DHTH11C | HK1 | 2016-2017120
 Khái niệm chuỗi
 Khai báo, khởi tạo
 Phần tử của chuỗi
 Thư viện string.h
 Thư viện stdlib.h
 Một vài bài toán về chuỗi
 Bài tập về nhà
 Nhập vào họ và tên, đếm số ký tự alphabet
 Ví dụ: Nhập “Tran Van An ”, xuất ra có 9 ký tự
 Nhập vào một chuỗi, đếm số chữ
 Ví dụ: Nhập “Day la mot chuoi ky tu”, xuất ra có 6 chữ
 Nhập vào họ và tên, xuất ra họ, chữ đệm và tên
 Ví dụ: Nhập “Tran Van An”, xuất ra họ Tran, chữ đệm
Van, tên An
 Nhập vào một số, xuất ra chữ viết của số đó
 Ví dụ: Nhập 456, xuất ra: Bon tram nam muoi sau
            Các file đính kèm theo tài liệu này:
 bai_giang_ky_thuat_lap_trinh_ts_ngo_huu_dung_ky_thuat_lap_trinh_ngo_huu_dung_bai_04_9936_1985329.pdf bai_giang_ky_thuat_lap_trinh_ts_ngo_huu_dung_ky_thuat_lap_trinh_ngo_huu_dung_bai_04_9936_1985329.pdf