Ngôn ngữ lập trình c&c++ ( Phạm Hồng Thái) P7

Chia sẻ: Yukogaru | Ngày: | Loại File: PDF | Số trang:10

0
57
lượt xem
15
download

Ngôn ngữ lập trình c&c++ ( Phạm Hồng Thái) P7

Mô tả tài liệu
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

III. MẢNG DỮ LIỆU 1. Mảng một chiều a. Ý nghĩa Khi cần lưu trữ một dãy n phần tử dữ liệu chúng ta cần khai báo n biến tương ứng với n tên gọi khác nhau. Điều này sẽ rất khó khăn cho người lập trình để có thể nhớ và quản lý hết được tất cả các biến, đặc biệt khi n lớn. Trong thực tế, hiển nhiên chúng ta gặp rất nhiều dữ liệu có liên quan đến nhau về một mặt nào đó, ví dụ chúng có cùng kiểu và cùng thể hiện một đối tượng: như các...

Chủ đề:
Lưu

Nội dung Text: Ngôn ngữ lập trình c&c++ ( Phạm Hồng Thái) P7

  1. ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ Khoa Công nghệ Thông tin PHẠM HỒNG THÁI Bài giảng NGÔN NGỮ LẬP TRÌNH C/C++ i III. MẢNG DỮ LIỆU 1. Mảng một chiều a. Ý nghĩa Khi cần lưu trữ một dãy n phần tử dữ liệu chúng ta cần khai báo n biến tương ứng với n tên gọi khác nhau. Điều này sẽ rất khó khăn cho người lập trình để có thể nhớ và quản lý hết được tất cả các biến, đặc biệt khi n lớn. Trong thực tế, hiển nhiên chúng ta gặp rất nhiều dữ liệu có liên quan đến nhau về một mặt nào đó, ví dụ chúng có cùng kiểu và cùng thể hiện một đối tượng: như các toạ độ của một vectơ, các số hạng của một ma trận, các sinh viên của một lớp hoặc các dòng kí tự của một văn bản … Lợi dụng đặc điểm này toàn bộ dữ liệu (cùng kiểu và cùng mô tả một đối tượng) có thể chỉ cần chung một tên gọi để phân biệt với các đối tượng khác, và để phân biệt các dữ liệu trong cùng đối tượng ta sử dụng cách đánh số thứ tự cho chúng, từ đó việc quản lý biến sẽ dễ dàng hơn, chương trình sẽ gọn và có tính hệ thống hơn. Giả sử ta có 2 vectơ trong không gian ba chiều, mỗi vec tơ cần 3 biến để lưu 3 toạ độ, vì vậy để lưu toạ độ của 2 vectơ chúng ta phải dùng đến 6 biến, ví dụ x1, y1, z1 cho vectơ thứ nhất và x2, y2, z2 cho vectơ thứ hai. Một kiểu dữ liệu mới được gọi là mảng một chiều cho phép ta chỉ cần khai báo 2 biến v1 và v2 để chỉ 2 vectơ, trong đó mỗi v1
  2. Chương 3. Cấu trúc điều khiển và dữ liệu kiểu mảng hoặc v2 sẽ chứa 3 dữ liệu được đánh số thứ tự từ 0 đến 2, trong đó ta có thể ngầm định thành phần 0 biểu diễn toạ độ x, thành phần 1 biểu diễn toạ độ y và thành phần có số thứ tự 2 sẽ biểu diễn toạ độ z. Tóm lại, mảng là một dãy các thành phần có cùng kiểu được sắp kề nhau liên tục trong bộ nhớ. Tất cả các thành phần đều có cùng tên là tên của mảng. Để phân biệt các thành phần với nhau, các thành phần sẽ được đánh số thứ tự từ 0 cho đến hết mảng. Khi cần nói đến thành phần cụ thể nào của mảng ta sẽ dùng tên mảng và kèm theo số thứ tự của thành phần đó. Dưới đây là hình ảnh của một mảng gồm có 9 thành phần, các thành phần được đánh số từ 0 đến 8. 0 1 2 3 4 5 6 7 8 b. Khai báo [số thành phần] ; // không khởi tạo [số thành phần] = { dãy giá trị } ; // có khởi tạo [ ] = { dãy giá trị } ; // có khởi tạo − Tên kiểu là kiểu dữ liệu của các thành phần, các thành phần này có kiểu giống nhau. Thỉnh thoảng ta cũng gọi các thành phần là phần tử. − Cách khai báo trên giống như khai báo tên biến bình thường nhưng thêm số thành phần trong mảng giữa cặp dấu ngoặc vuông [] còn được gọi là kích thước của mảng. Mỗi tên mảng là một biến và để phân biệt với các biến thông thường ta còn gọi là biến mảng. − Một mảng dữ liệu được lưu trong bộ nhớ bởi dãy các ô liên tiếp nhau. Số lượng ô bằng với số thành phần của mảng và độ dài (byte) của mỗi ô đủ để chứa thông tin của mỗi thành phần. Ô đầu tiên được đánh thứ tự bởi 0, ô tiếp theo bởi 1, và tiếp tục cho đến hết. Như vậy nếu mảng có n thành phần thì ô cuối cùng trong mảng sẽ được đánh số là n - 1. − Dạng khai báo thứ 2 cho phép khởi tạo mảng bởi dãy giá trị trong cặp dấu {}, mỗi giá trị cách nhau bởi dấu phảy (,), các giá trị này sẽ được gán lần lượt cho các phần tử của mảng bắt đầu từ phần tử thứ 0 cho đến hết dãy. Số giá trị có thể bé hơn số phần tử. Các phần tử mảng chưa có giá trị sẽ không được xác định cho đến khi trong chương trình nó được gán một giá trị nào đó. − Dạng khai báo thứ 3 cho phép vắng mặt số phần tử, trường hợp này số phần tử được xác định bởi số giá trị của dãy khởi tạo. Do đó nếu vắng mặt cả dãy khởi 60
  3. Chương 3. Cấu trúc điều khiển và dữ liệu kiểu mảng tạo là không được phép (chẳng hạn khai báo int a[] là sai). Ví dụ: • Khai báo biến chứa 2 vectơ a, b trong không gian 3 chiều: float a[3] , b[3] ; • Khai báo 3 phân số a, b, c; trong đó a = 1/3 và b = 3/5: int a[2] = {1, 3} , b[2] = {3, 5} , c[2] ; ở đây ta ngầm qui ước thành phần đầu tiên (số thứ tự 0) là tử và thành phần thứ hai (số thứ tự 1) là mẫu của phân số. • Khai báo mảng L chứa được tối đa 100 số nguyên dài: long L[100] ; • Khai báo mảng dong (dòng), mỗi dòng chứa được tối đa 80 kí tự: char dong[80] ; • Khai báo dãy Data chứa được 5 số thực độ chính xác gấp đôi: double Data[] = { 0,0,0,0,0 }; // khởi tạo tạm thời bằng 0 c. Cách sử dụng i. Để chỉ thành phần thứ i (hay chỉ số i) của một mảng ta viết tên mảng kèm theo chỉ số trong cặp ngoặc vuông []. Ví dụ với các phân số trên a[0], b[0], c[0] để chỉ tử số và a[1], b[1], c[1] để chỉ mẫu số của 3 phân số a,b,c. ii. Tuy mỗi mảng biểu diễn một đối tượng nhưng chúng ta không thể áp dụng các thao tác lên toàn bộ mảng mà phải thực hiện thao tác thông qua từng thành phần của mảng. Ví dụ chúng ta không thể nhập dữ liệu cho mảng a[10] bằng câu lệnh: cin >> a ; // sai mà phải nhập cho từng phần tử từ a[0] đến a[9] của a. Dĩ nhiên trong trường hợp này chúng ta phải cần đến lệnh lặp for: int i ; for (i = 0 ; i < 10 ; i++) cin >> a[i] ; Tương tự, giả sử chúng ta cần cộng 2 phân số a, b và đặt kết quả vào c. Không thể viết: c=a+b; // sai mà cần phải tính từng phần tử của c: 61
  4. Chương 3. Cấu trúc điều khiển và dữ liệu kiểu mảng c[0] = a[0] * b[1] + a[1] * b[0] ; // tử số c[1] = a[1] * b[1] ; // mẫu số Để khắc phục nhược điểm này, trong các chương sau C++ cung cấp một kiểu dữ liệu mới gọi là lớp, và cho phép NSD có thể định nghĩa riêng phép cộng cho 2 mảng tuỳ ý, khi đó có thể viết một cách đơn giản và quen thuộc c = a + b để cộng 2 phân số. d. Ví dụ minh hoạ Ví dụ 1 : Tìm tổng, tích 2 phân số. void main() { int a[2], b[2], tong[2], tich[2] ; cout > a[0] ; cout > a[1] ; cout > b[0] ; cout > b[1] ; tong[0] = a[0]*b[1] + a[1]*b[0] ; tong[1] = a[1] * b[1] ; tich[0] = a[0]*b[0]; tich[1] = a[1] * b[1] ; cout
  5. Chương 3. Cấu trúc điều khiển và dữ liệu kiểu mảng cout
  6. Chương 3. Cấu trúc điều khiển và dữ liệu kiểu mảng for (i=0; i
  7. Chương 3. Cấu trúc điều khiển và dữ liệu kiểu mảng char monhoc[31] = "NNLT C++" ; xâu môn học chứa tối đa 30 kí tự, được khởi tạo với nội dung "NNLT C++" với độ dài thực sự là 10 kí tự (chiếm 11 ô đầu tiên trong mảng monhoc[31]). − Cách khai báo thứ 3 tự chương trình sẽ quyết định độ dài của mảng bởi xâu khởi tạo (bằng độ dài xâu + 1). Ví dụ: char thang[] = "Mười hai" ; // độ dài mảng = 9 b. Cách sử dụng Tương tự như các mảng dữ liệu khác, xâu kí tự có những đặc trưng như mảng, tuy nhiên chúng cũng có những điểm khác biệt. Dưới đây là các điểm giống và khác nhau đó. • Truy cập một kí tự trong xâu: cú pháp giống như mảng. Ví dụ: char s[50] = "I\'m a student" ; // chú ý kí tự ' phải được viết là \' cout > vẫn dùng được nhưng có nhiều hạn chế. Ví dụ char s[60] ; cin >> s ; cout > chỉ nhập "Tin" cho s (bỏ tất cả các kí tự đứng sau dấu trắng), vì vậy khi in ra trên màn hình chỉ có từ "Tin". Vì các phép toán không dùng được trực tiếp trên xâu nên các chương trình dịch đã viết sẵn các hàm thư viện được khai báo trong file nguyên mẫu string.h. Các hàm này giải quyết được hầu hết các công việc cần thao tác trên xâu. Nó cung cấp cho NSD phương tiện để thao tác trên xâu như gán, so sánh, sao chép, tính độ dài xâu, nhập, in, … Để sử dụng được các hàm này đầu chương trình cần có khai báo string.h. Phần lớn các hàm này sẽ được giới thiệu trong phần tiếp sau. 65
  8. Chương 3. Cấu trúc điều khiển và dữ liệu kiểu mảng c. Phương thức nhập xâu (#include ) Do toán tử nhập >> có hạn chế đối với xâu kí tự nên C++ đưa ra hàm riêng (còn gọi là phương thức) cin.getline(s,n) để nhập xâu kí tự. Hàm có 2 đối với s là xâu cần nhập nội dung và n-1 là số kí tự tối đa của xâu. Giống phương thức nhập kí tự cin.get(c), khi gặp hàm cin.getline(s,n) chương trình sẽ nhìn vào bộ đệm bàn phím lấy ra n-1 kí tự (nếu đủ hoặc lấy tất cả kí tự còn lại, trừ kí tự enter) và gán cho s. Nếu tại thời điểm đó bộ đệm đang rỗng, chương trình sẽ tạm dừng chờ NSD nhập dữ liệu (dãy kí tự) vào từ bàn phím. NSD có thể nhập vào dãy với độ dài bất kỳ cho đến khi nhấn Enter, chương trình sẽ lấy ra n-1 kí tự đầu tiên gán cho s, phần còn lại vẫn được lưu trong bộ đệm (kể cả kí tự Enter) để dùng cho lần nhập sau. Hiển nhiên, sau khi gán các kí tự cho s, chương trình sẽ tự động đặt kí tự kết thúc xâu vào ô tiếp theo của xâu s. Ví dụ 1 : Xét đoạn lệnh sau char s[10] ; cin.getline(s, 10) ; cout
  9. Chương 3. Cấu trúc điều khiển và dữ liệu kiểu mảng VN[6] = US[6]; VN[7] = US[7] ; // năm cout
  10. Chương 3. Cấu trúc điều khiển và dữ liệu kiểu mảng trình ngắn để thay thế một đoạn con bất kỳ nào đó trong s bởi một đoạn con bất kỳ (có độ dài tương đương) trong t. Ví dụ các dòng lệnh chuyển đổi ngày tháng trong ví dụ trước có thể viết lại bằng cách dùng hàm strncpy như sau: strncpy(VN+0, US+3, 2) ; // ngày strncpy(VN+3, US+0, 2) ; // tháng strncpy(VN+6, US+6, 2); // năm • strcat(s, t); Nối một bản sao của t vào sau s (thay cho phép +). Hiển nhiên hàm sẽ loại bỏ kí tự kết thúc xâu s trước khi nối thêm t. Việc nối sẽ đảm bảo lấy cả kí tự kết thúc của xâu t vào cho s (nếu s đủ chỗ) vì vậy NSD không cần thêm kí tự này vào cuối xâu. Tuy nhiên, hàm không kiểm tra xem liệu độ dài của s có đủ chỗ để nối thêm nội dung, việc kiểm tra này phải do NSD đảm nhiệm. Ví dụ: char a[100] = "Mẫn", b[4] = "tôi"; strcat(a, “ và ”); strcat(a, b); cout
Đồng bộ tài khoản