Bài giảng Kỹ thuật lập trình - Bài 4: Chuỗi ký tự - Ngô Hữu Dũng

pdf 30 trang ngocly 2380
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng 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

Tài liệu đính kèm:

  • pdfbai_giang_ky_thuat_lap_trinh_bai_4_chuoi_ky_tu_ngo_huu_dung.pdf

Nội dung text: Bài giảng Kỹ thuật lập trình - Bài 4: Chuỗi ký tự - Ngô Hữu Dũng

  1. Kỹ thuật lập trình Bài 4 – Chuỗi ký tự Ngô Hữu Dũng 91 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  2. Khái niệm  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] 92 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  3. Khai báo  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 93 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  4. Ví dụ khai báo 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 94 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  5. Khởi tạo giá trị  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] = ""; 95 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  6. Khởi tạo giá trị (2)  Một khởi tạo giá trị: 0 1 2 3 4 5 6  char hi[7] = "Hi!"; 'H' 'i' '!' '\0'  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!"; 96 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  7. Phép gán  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] 97 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  8. Phép gán (2)  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ự 98 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  9. Nhập chuỗi từ bàn phím  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 99 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  10. Phần tử của chuỗi  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[0] hello[1] hello[2] hello[3] hello[4] hello[5] hello[6] 'H' 'e' 'l' 'l' 'o' '!' '\0'  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'); 100 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  11. Thư viện string.h  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 101 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  12. Thư viện string.h (2)  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!” 102 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  13. Thư viện string.h (3)  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 103 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  14. Thư viện string.h (4)  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’ 104 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  15. Thư viện string.h (5)  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 105 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  16. Thư viện string.h (6)  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!” 106 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  17. Thư viện string.h (7)  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!” 107 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  18. Thư viện string.h (8)  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ớ 108 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  19. Chuyển đổi giữa chuỗi và số  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) 109 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  20. Chiều dài của chuỗi  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 110 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  21. Ví dụ tham khảo hàm tính chiều dài của chuỗi 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. } 111 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  22. Chép chuỗi  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) 112 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  23. Ví dụ tham khảo hàm chép chuỗi 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. } 113 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  24. Nối chuỗi  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 114 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  25. Ví dụ tham khảo hàm nối chuỗi 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. } 115 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  26. So sánh chuỗi  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  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 116 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  27. Ví dụ tham khảo về hàm so sánh chuỗi 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. }; 117 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  28. Tìm kiếm  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ả?  ?  ?  ?  ? 118 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  29. Ví dụ tham khảo về tìm kiếm chuỗi  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. } 119 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng
  30. Hết bài 4  Khái niệm chuỗi  Bài tập về nhà  Nhập vào họ và tên, đếm số ký tự alphabet  Khai báo, khởi tạo  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ữ  Phần tử của chuỗi  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  Thư viện string.h Van, tên An  Nhập vào một số, xuất ra chữ viết của số đó  Thư viện stdlib.h  Ví dụ: Nhập 456, xuất ra: Bon tram nam muoi sau  Một vài bài toán về chuỗi 120 Kỹ thuật lập trình | DHTH11C | HK1 | 2016-2017 Ngô Hữu Dũng