Mảng trong C – Mảng một chiều và mảng đa chiều
- 11-01-2023
- Toanngo92
- 0 Comments
Có thể khó lưu trữ một tập hợp các phần tử dữ liệu tương tự trong các biến khác nhau. Ví dụ, hãy xem xét rằng bài toánlưu trữ số áo của tất cả 11 cầu thủ của một đội bóng đá phải được ghi lại. Lưu trữ số áo của mỗi người chơi trong các biến có tên riêng chắc chắn sẽ mệt mỏi hơn là có một biến chung cho họ. Đây là lí do chúng ta cần tới khái niệm mảng. Một mảng (array) là một tập hợp các phần tử dữ liệu cùng kiểu. Mỗi phần tử của mảng có cùng kiểu dữ liệu, cùng lớp lưu trữ (storage class) và cùng đặc điểm. Mỗi phần tử được lưu trữ ở các vị trí liên tiếp trên vùng nhớ máy tính. Các phần tử này được gọi là phần tử/thành viên của mảng.
Mục lục
Định nghĩa mảng
Một mảng có một số đặc điểm cụ thể và phải được xác định bằng cách sử dụng chúng. Những đặc điểm này như sau:
- Lớp lưu trữ (storage class – tùy chọn)
- Kiểu dữ liệu của các phần tử trong mảng
- Tên mảng cho biết vị trí của phần tử đầu tiên của mảng
- Kích thước mảng, một hằng số là biểu thức số nguyên đánh giá giá trị dương
Một mảng được định nghĩa giống như cách định nghĩa một biến, ngoại trừ tên mảng được theo sau bởi một hoặc nhiều biểu thức, được đặt trong dấu ngoặc vuông, [], chỉ định kích thước mảng.
Quy tắc tạo tên mảng cũng giống như quy tắc tạo tên biến. Tên mảng và tên biến không được trùng nhau dễ dẫn đến dễ gây nhầm lẫn. Nếu một khai báo như vậy được đưa ra trong một chương trình, trình biên dịch sẽ hiển thị một thông báo lỗi.
Cú pháp tổng quát:
storage_class data_type array_name[size_expression]
Ví dụ:
int main(){
int danhsachcauthu[11];
return 0;
}
Lưu ý, khi xác định mảng, kích thước mảng sẽ là 11, mặc dù các chỉ số của các phần tử riêng lẻ trong mảng sẽ nằm trong khoảng từ 0 đến 10.
Các phần tử (array element) và chỉ mục/chỉ số (index/subscript) của mảng
Mỗi phần tử của một mảng được xác định bởi một Chỉ mục duy nhất hoặc chỉ số dưới được gán cho nó. Kích thước của một mảng được xác định bởi số lượng chỉ số cần thiết để xác định duy nhất từng phần tử. Chỉ số là một số nguyên dương đặt trong dấu ngoặc vuông [] được đặt ngay sau tên mảng, không có khoảng trắng ở giữa. Một chỉ mục giữ các giá trị số nguyên và bắt đầu bằng 0. Do đó, một mảng cầu thủ có 11 phần tử sẽ được biểu diễn dưới dạng: danhsachcauthu[11]. Và để truy vấn từng cầu thủ trong mảng, chúng ta dùng cú pháp truy vấn:
danhsachcauthu[0]
danhsachcauthu[1]
danhsachcauthu[2]
....
danhsachcauthu[10]
Phần tử mảng bắt đầu bằng danhsachcauthu[0], và vì vậy phần tử cuối cùng là danhsachcauthu[10] chứ không phải danhsachcauthu[11]. Điều này là do trong C, chỉ số mảng bắt đầu từ 0; và như vậy đối với một mảng n phần tử, phần tử cuối cùng có chỉ số là n-1. Giới hạn của các giá trị chỉ mục được phép được gọi là giới hạn của chỉ số mảng, Giới hạn dưới và Giới hạn trên. Một chỉ mục hợp lệ phải có một giá trị nguyên giữa các giới hạn hoặc bằng một trong số chúng. Thuật ngữ hợp lệ được sử dụng vì một lý do rất cụ thể. Trong C, nếu lập trình viên truy cập một phần tử bên ngoài phạm vi chỉ mục hợp pháp danhsachcauthu[11], nó sẽ không tạo ra lỗi khi có liên quan đến trình biên dịch C. Tuy nhiên, nó có thể truy cập một số giá trị có thể dẫn đến kết quả không thể đoán trước. Ngoài ra còn có nguy cơ ghi đè lên dữ liệu hoặc mã chương trình. Do đó, lập trình viên phải đảm bảo rằng tất cả các chỉ số đều nằm trong giới hạn hợp lệ.
Một số tiêu chuẩn khi sử dụng mảng
- Các phần tử của mảng có cùng kiểu. Điều này có nghĩa là nếu một mảng được khai báo kiểu int, thì nó không thể chứa các phần tử thuộc bất kỳ kiểu nào khác.
- Mỗi phần tử của mảng có thể được sử dụng bất cứ khi nào cần sử dụng bằng cách truy xuất vào index của phần tử đó
- Một phần tử của mảng có thể được gọi bằng một biến hoặc một biểu thức nguyên.
- Array có thể mang kiểu dữ liệu int, char, float hoặc double
Xử lý mảng trong C
Một mảng được xử lý khác với một biến trong C. Hai mảng, ngay cả khi chúng có cùng kiểu và kích thước, không thể so sánh bằng. Hơn nữa, không thể gán trực tiếp mảng này cho mảng khác.
Thay vào đó, mỗi phần tử mảng phải được gán riêng cho phần tử tương ứng của mảng khác.
Các giá trị không thể được gán cho toàn bộ một mảng, ngoại trừ tại thời điểm khởi tạo. Tuy nhiên, các phần tử riêng lẻ có thể được gán giá trị mà còn có thể được so sánh bình thường.
Ví dụ:
#include <stdio.h>
void examplearrcompare(){
int arr[2];
int arr_2[2];
arr[0] = 1;
arr[1] = 2;
arr_2[0] = 1;
arr_2[1] = 2;
if(arr == arr_2){
printf("bang nhau");
}else{
printf("khong so sanh dc");
}
}
void examplearrassign(){
int arr[2] = {1,2};
arr[0] = 1;
arr[1] = 2;
}
void examplearrassign2(){
int i = 0,num = 0;
printf("Nhap so phan tu mang:");
scanf("%d",&num);
int arr[num];
for(i = 0; i < num; i++){
printf("Nhap phan tu so %d cua mang:",i+1);
scanf("%d",&arr[i]);
}
for(i = 0 ; i < num; i++){
printf("\nPhan tu so %d cua mang la: %d",i+1,arr[i]);
}
}
int main()
{
examplearrcompare();
examplearrassign();
examplearrassign2();
return 0;
}
Các phần tử mảng không thể được khởi tạo, trừ khi mỗi phần tử được gán một giá trị riêng. Không nên sử dụng mảng nếu không có sự phân bổ thích hợp, vì kết quả trong những trường hợp như vậy là không thể đoán trước.
Điều này là do các vị trí lưu trữ được phân bổ được gán cho mảng không được khởi tạo tự động. Bất cứ khi nào các phần tử của một mảng như vậy được sử dụng trong các biểu thức số học, thì các giá trị đã tồn tại trước đó sẽ được sử dụng, các giá trị này không được đảm bảo là cùng loại với định nghĩa mảng, trừ khi mảng đó các yếu tố được khởi tạo rất rõ ràng. Điều này không chỉ đúng với mảng mà còn đúng với các biến thông thường.
Ví dụ:
#include <stdio.h>
void examplearrassign2(){
int i = 0,num = 0;
printf("Nhap so phan tu mang:");
scanf("%d",&num);
int arr[num];
for(i = 0; i < num; i++){
printf("Nhap phan tu so %d cua mang:",i+1);
scanf("%d",&arr[i]);
}
for(i = 0 ; i < num; i++){
printf("\nPhan tu so %d cua mang la: %d",i+1,arr[i]);
}
}
int main()
{
examplearrassign2();
return 0;
}
Ví dụ thuật toán tìm kiếm phần tử có giá trị lớn nhất trong mảng và tính giá trị trung bình của các phần tử trong mảng
#include <stdio.h>
void examplearray1(){
int ary[10];
int i, total, high;
for(i=0; i<10; i++)
{
printf("\n Enter value: %d : ", i+1);
scanf("%d",&ary[i]);
}
/* Displays highest of the entered values */
high = ary[0];
for(i=1; i<10; i++)
{
if(ary[i] > high)
high = ary[i];
}
printf("\nHighest value entered was %d", high);
/* prints average of values entered for ary[10] */
for(i=0,total=0; i<10; i++){
total = total + ary[i];
}
printf("\nThe average of the elements of ary is %d",total/i);
}
int main()
{
examplearray1();
return 0;
}
Ví dụ khai báo mảng ký tự và gán giá trị vào kí tự vào các phần tử bên trong mảng
#include <stdio.h>
void examplearray2(){
char alpha[26];
int i, j;
for(i=65,j=0; i<91; i++,j++)
{
alpha[j] = i;
printf("The character now assigned is %c - %d \n", alpha[j], alpha[j]);
}
// getchar();
}
int main()
{
examplearray2();
return 0;
}
Ngoài ra, chúng ta có thể khởi tạo giá trị các phần tử trong mảng bằng cách gán một danh sách các giá trị được phân tách bằng dấu phẩy và được đặt trong dấu ngoặc nhọn { } cho tên mảng. Các giá trị trong dấu ngoặc nhọn được gán cho các phần tử của mảng theo thứ tự xuất hiện của chúng, trừ mảng ký tự sẽ được nói ở phần tiếp theo.
Ví dụ:
int main(){
int arr1[3] = {3,2,4};
int str2[10] = "chuoi vi du";
float arr3[4] = {1,2.5,30,4.3};
return 0;
}
Trong trường hợp khởi tạo rõ ràng, storage class là extern hoặc static, các phần tử mảng được đảm bảo (không giống như class automatic) được khởi tạo bằng 0.
Trong tình huống sử dụng cách khởi tạo bằng {}, không cần thiết phải khai báo kích thước của mảng đang được khởi tạo. Nếu kích thước của mảng bị bỏ qua, trình biên dịch sẽ tính toán kích thước mảng bằng cách đếm các giá trị khởi tạo. Ví dụ, khai báo mảng bên ngoài sau đây sẽ đánh giá kích thước của mảng arr là 3 vì có 3 giá trị khởi tạo.
int main(){
int arr[] = {2,3,5};
return 0;
}
Mảng ký tự/chuỗi (character arrays/string)
Một chuỗi có thể được định nghĩa là một mảng kiểu ký tự, được kết thúc bằng ký tự NULL. Mỗi ký tự của chuỗi chiếm một byte và ký tự cuối cùng của chuỗi luôn là ký tự ‘\0’. ‘\0’ này được gọi là ký tự null. Nó là một chuỗi thoát như ‘\n’ và là viết tắt của một ký tự có giá trị 0 (không). Vì ‘\0’ luôn là ký tự cuối cùng của một chuỗi, nên các mảng ký tự phải dài hơn một ký tự so với chuỗi dài nhất mà chúng bắt buộc phải giữ. Ví dụ, một mảng arr, chứa 20 ký tự nên được khai báo là:
char arr[21];
Vị trí bổ sung được sử dụng để lưu trữ ký tự rỗng. Hãy nhớ rằng ký tự kết thúc (ký tự loại bỏ) rất quan trọng.
Các giá trị chuỗi có thể được nhập vào bằng hàm scanf(). Đối với chuỗi arr đã khai báo ở trên, câu lệnh nhận giá trị sẽ như sau:
scanf("%s" &arr);
// another input way can allow space in string
gets(arr);
// another input way can allow space in string
fgets(arr,100,stdin);
// refference https://stackoverflow.com/questions/20572105/why-cant-i-use-a-space-in-my-array-program
Ví dụ:
#include <stdio.h>
void examplestringaschararray(){
char ary[10];
int i;
printf("\n Enter string : ");
scanf("%s",&ary);
printf("\n The string is %s \n\n", ary);
for (i=0; i<10; i++)
printf("\t%d", ary[i]);
}
int main(){
examplestringaschararray();
return 0;
}
Xét chương trình chạy khi nhập liệu đủ 9 ký tự
Enter string : toan12345
The string is toan12345
116 111 97 110 49 50 51 52 53 0
Xét chương trình chạy khi nhập liệu chưa đủ 9 ký tự
Enter string : abcd
The string is abcd
97 98 99 100 0 -1 -1 -1 41 0
Trong ví dụ trên, khi chỉ có 4 ký tự được nhập thì ký tự thứ 5 là ký tự null. Điều này thực sự chỉ ra rằng chuỗi đã kết thúc. Các ký tự còn lại không thể đoán trước.
Trong trường hợp trên, tầm quan trọng của ký tự null trở nên rõ ràng. Ký tự null thực sự chỉ định phần cuối của chuỗi và là cách duy nhất mà các hàm làm việc với chuỗi sẽ biết vị trí của phần cuối của chuỗi.
Mặc dù C không có kiểu dữ liệu chuỗi nhưng nó cho phép các hằng chuỗi. Hằng chuỗi là một danh sách các ký tự được mã hóa trong dấu ngoặc kép(“”). Giống như bất kỳ hằng nào khác, nó không thể bị thay đổi trong chương trình. C hỗ trợ nhiều hàm chuỗi, được tìm thấy trong file header chuẩn string.h, sẽ được đề cập riêng ở bài chuỗi.
Mảng 2 chiều
Ở các phần trước, chúng ta đã thảo luận về mảng là mảng một chiều. Điều này có nghĩa là các mảng chỉ có một chỉ số index. Mảng có thể có nhiều hơn một chiều. Mảng đa chiều giúp biểu diễn các đối tượng đa chiều dễ dàng hơn, chẳng hạn như biểu đồ có hàng và cột. Mảng nhiều chiều được định nghĩa giống như mảng một chiều, ngoại trừ một cặp dấu ngoặc vuông [] riêng biệt, được yêu cầu trong trường hợp mảng hai chiều. Một mảng ba chiều sẽ có ba cặp dấu ngoặc vuông, v.v.
Cú pháp tổng quát:
storage_class data_type arr[expression1][expression2]...[expressionN]
trong đó ary là một mảng có lớp lưu trữ storage_class, kiểu dữ liệu data_type và exp1, exp2, expN là các biểu thức số nguyên dương cho biết số lượng phần tử mảng được liên kết với các index.
Dạng đơn giản nhất và thông dụng nhất của mảng đa chiều là mảng hai chiều. Mảng hai chiều có thể được coi là một mảng gồm hai mảng ‘một chiều’.Chúng ta có thể hình dung mảng 2 chiều tương tự một bảng bao gồm hàng và cột trong excel. Để định vị thông tin, hàng và cột bắt buộc được xác định và thông tin được đọc từ vị trí mà chúng (hàng và cột) giao nhau.
Vì vậy, ta coi mảng hai chiều là một lưới chứa các hàng và cột trong đó mỗi phần tử được chỉ định duy nhất bằng tọa độ hàng và cột của nó. Ví dụ định nghĩa một mảng 3 hàng và 2 cột như sau:
int arr[3][2];
Mảng này sẽ chứa 3 x 2 = (6) phần tử và chúng có thể được biểu diễn dưới dạng:
Cột | |||
0 | 1 | ||
Hàng | 0 | ptu1 | pt2 |
1 | pt3 | pt4 | |
2 | pt5 | pt6 |
Khởi tạo mảng đa chiều
Một định nghĩa mảng nhiều chiều có thể bao gồm việc gán các giá trị ban đầu. Phải cẩn thận về thứ tự mà các giá trị ban đầu được gán cho các phần tử mảng (chỉ có thể khởi tạo các mảng bên ngoài và mảng tĩnh). Các phần tử của hàng đầu tiên của mảng hai chiều sẽ được gán giá trị trước, sau đó là các phần tử của hàng thứ hai, v.v. Ví dụ:
int arr[3][4] = {3,2,1,4,5,4,2,3,1,4,7,8};
Dữ liệu sẽ được lưu trữ như sau:
arr[0][0]: 3 | arr[0][1]: 2 | arr[0][2]: 1 | arr[0][3]: 4 |
arr[1][0]: 5 | arr[1][1]: 4 | arr[1][2]: 2 | arr[1][1]: 3 |
arr[2][0]: 1 | arr[2][1]: 4 | arr[2][2]: 7 | arr[1][3]: 8 |
Ví dụ:
#include <stdio.h>
#include <string.h>
void testtwodimenarr(){
int ary[3][4] = {1,100,3,4,5,6,7,8,9,10,11,12};
int i,j;
for(i = 0; i < 3 ; i++){
for (j = 0; j < 4 ; j++){
printf("%d |", ary[i][j]);
}
printf("\n");
}
}
void main()
{
testtwodimenarr();
}
Mảng 2 chiều ký tự (chuỗi)
Ngoài ra, mảng 2 chiều có thể sử dụng trong tình huống danh sách chuỗi ( một danh sách mảng ký tự)
Một chuỗi có thể được biểu diễn dưới dạng một mảng ký tự một chiều. Mỗi ký tự trong chuỗi sẽ được lưu trữ trong một phần tử của mảng. Mảng chuỗi này có thể được tạo bằng cách sử dụng mảng ký tự hai chiều. Chỉ mục bên trái hoặc chỉ số dưới xác định số lượng chuỗi và chỉ mục bên phải chỉ định độ dài tối đa của mỗi chuỗi.
Ví dụ:
char arr[5][10];
Trong ví dụ trên, chúng ta định nghĩa ra mảng bao gồm 5 phần tử chuỗi (mảng ký tự), mỗi chuỗi có 9 phần tử ký tự (bao hồm ký tự null là đủ 10).
Ví dụ sử dụng mảng chuỗi:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
testtwodimenstrarr(){
int i, n = 0;
int item;
char x[10][12];
char temp[12];
printf("Enter each string on a separate line\n\n");
printf("Type 'END' when over \n\n");
/* read in the list of strings */
do
{
printf("String %d : ", n+1);
scanf("%s",x[n]);
} while (strcmp(x[n++], "END"));
/*reorder the list of strings */
n--;
printf("%d",n);
for(item=0; item<n-1; ++item)
{
/* find lowest of remaining strings */
for(i=item+1; i<n; ++i)
{
if(strcmp (x[item], x[i]) > 0)
{
/*interchange two stings */
strcpy (temp, x[item]);
strcpy (x[item], x[i]);
strcpy (x[i], temp);
}
}
}
/* Display the arranged list of strings */
printf("Recorded list of strings : \n");
for(i = 0; i < n ; ++i)
{
printf("\nString %d is %s", i+1, x[i]);
}
}
int main(){
testtwodimenstrarr();
return 0;
}
Phần 2 – Thực hành
Mảng
Các mảng có thể được phân loại thành hai loại dựa trên số chiều: Mảng một chiều hoặc Mảng đa chiều. Trong bài này, hãy tập trung vào cách tạo và sử dụng các mảng.
Sử dụng mảng một chiều
Một mảng một chiều có thể được sử dụng để lưu trữ một bộ giá trị duy nhất cùng kiểu dữ liệu. Hãy xem xét một tập hợp điểm của học sinh trong một môn học cụ thể. Hãy sắp xếp các điểm này theo thứ tự giảm dần.
Các bước để sắp xếp một mảng một chiều theo thứ tự giảm dần là:
Nhập tổng số điểm cần được nhập:
Khai báo một biến và giá trị cho nó phải được chấp nhận:
int n;
printf("\n Enter the total number of marks to be entered: ");
scanf("%d", &n);
Nhận tập hợp điểm:
Để chấp nhận một tập hợp giá trị cho một mảng, mảng cần phải được khai báo. Mã cho điều này như sau:
Hướng dẫn Thực Hành
Mảng (Thực Hành)
[2. Nhận bộ dữ liệu điểm số, ]
Để nhận bộ giá trị cho một mảng, mảng cần được khai báo. Mã nguồn tương tự như sau:
int num[100];
Số lượng phần tử trong mảng được xác định bằng giá trị được nhập cho biến n. Các phần tử của mảng cần được khởi tạo với giá trị, để chấp nhận n giá trị, cần sử dụng một vòng lặp. Cần phải khai báo một biến số nguyên làm chỉ mục cho mảng. Biến này giúp truy cập từng phần tử của mảng. Giá trị của các phần tử mảng sau đó được khởi tạo bằng cách chấp nhận giá trị từ người dùng. Mã nguồn cho việc này như sau:
for (i = 0; i < n; i++) {
printf("\n Nhập điểm của học sinh %d: ", i + 1);
scanf("%d", &num[i]);
}
Vì chỉ mục của mảng luôn bắt đầu từ 0 và chúng ta cần khởi tạo từ 1 đến n, mỗi khi vòng lặp for được thực thi, một giá trị nguyên được gán vào phần tử của mảng.
- Sao chép mảng
Trước khi sắp xếp mảng, việc bảo tồn mảng gốc là rất an toàn. Vì vậy, một mảng khác có thể được khai báo và các phần tử của mảng ban đầu có thể được sao chép vào mảng mới này. Mã nguồn dưới đây được sử dụng để thực hiện việc này:
int desnum[100];
for (i = 0; i < n; i++) {
desnum[i] = num[i];
}
- Sắp xếp mảng theo thứ tự giảm dần
Để sắp xếp mảng, các phần tử trong mảng cần phải được so sánh với nhau. Cách tốt nhất để sắp xếp mảng theo thứ tự giảm dần là chọn giá trị cao nhất trong mảng và hoán đổi nó với phần tử đầu tiên. Khi việc này được thực hiện, phần tử cao thứ hai từ các phần tử còn lại có thể được hoán đổi với phần tử thứ hai của mảng. Trong quá trình làm như vậy, phần tử đầu tiên của mảng có thể được bỏ qua vì nó là cao nhất. Tương tự, các phần tử của mảng có thể bị loại bỏ một cách từ từ cho đến khi phần tử cao thứ n được tìm thấy. Trong trường hợp cần phải sắp xếp mảng theo thứ tự tăng dần, giá trị cao nhất có thể được hoán đổi với phần tử cuối cùng của mảng.
Hãy xem xét một ví dụ số học để hiểu về mảng. Hình bên dưới đại diện cho một mảng các số nguyên cần được sắp xếp.
Mảng num với 6 phần tử. Để sắp xếp mảng này theo thứ tự giảm dần,
a. Chúng ta cần tìm phần tử lớn nhất và đặt nó ở vị trí đầu tiên. Điều này có thể được gọi là lần lặp đầu. Để đặt phần tử lớn nhất vào vị trí đầu tiên, chúng ta cần so sánh phần tử đầu tiên với phần còn lại. Trong trường hợp phần tử được so sánh lớn hơn phần tử đầu tiên, hai phần tử cần được đổi chỗ.
Để bắt đầu, trong lần lặp đầu tiên, phần tử ở vị trí đầu tiên được so sánh với phần tử ở vị trí thứ hai. Hình bên dưới đại diện cho việc đổi chỗ phần tử ở vị trí đầu tiên.
Tiếp theo, phần tử đầu tiên được so sánh với phần tử thứ ba. Hình bên dưới thể hiện việc đổi chỗ phần tử đầu tiên và phần tử thứ ba.
Quá trình này được lặp lại cho đến khi phần tử đầu tiên được so sánh với phần tử cuối cùng của mảng. Kết quả của mảng sau lần lặp đầu tiên sẽ như trong hình bên dưới.
b. Để lại phần tử đầu tiên không thay đổi, chúng ta cần tìm phần tử lớn thứ hai và đổi chỗ nó với phần tử thứ hai trong mảng. Hình bên dưới thể hiện mảng sau khi thực hiện việc này.
c. Phải đổi chỗ phần tử thứ ba với phần tử lớn thứ ba của mảng. Hình bên dưới thể hiện mảng sau khi đổi chỗ phần tử lớn thứ ba.
d. Phải đổi chỗ phần tử thứ tư với phần tử lớn thứ tư của mảng. Hình bên dưới thể hiện mảng sau khi đổi chỗ phần tử lớn thứ tư.
e. Hình bên trên thể hiện mảng đã được sắp xếp.
Để thực hiện điều này theo cách lập trình, chúng ta cần hai vòng lặp: một để tìm phần tử lớn nhất trong mảng và một để lặp lại quá trình n lần. Cụ thể, quá trình phải được lặp lại n-1 lần cho một mảng có n phần tử, vì phần tử cuối cùng sẽ không còn phần tử nào khác để so sánh. Do đó, chúng ta khai báo hai biến có tên i và j để làm việc thông qua hai vòng lặp for. Vòng lặp for với chỉ số i được sử dụng để lặp lại quá trình tìm phần tử lớn nhất trong phần còn lại của mảng. Vòng lặp for với chỉ số j được sử dụng để tìm phần tử lớn thứ tư trong mảng giữa phần tử thứ i+1 và phần tử cuối cùng của mảng. Do đó, phần tử lớn thứ tư trong phần còn lại của mảng sẽ được đưa vào vị trí thứ 4.
Để khai báo chỉ số và lặp lại mảng n-1 lần với chỉ số i là:
int i,j;
for (i = 0; i < n-1; i++)
{
Mã để lặp qua từ phần tử thứ 1 đến phần tử thứ n của mảng là:
for (j = i + 1; j < n; j++)
{
Để hoán đổi hai phần tử trong mảng, chúng ta cần sử dụng một biến tạm thời. Điều này là do khi chúng ta sao chép một phần tử của mảng sang một phần tử khác, giá trị trong phần tử thứ hai bị mất. Để tránh mất giá trị của phần tử thứ hai, giá trị cần phải được bảo tồn trong một biến tạm thời. Mã để hoán đổi phần tử thứ i với phần tử lớn nhất trong phần còn lại của mảng có thể là:
if (desnum[i] < desnum[j])
{
int temp = desnum[i];
desnum[i] = desnum[j];
desnum[j] = temp;
}
}
}
Vòng lặp for cần được đóng và do đó, hai dấu ngoặc đơn đóng thừa được sử dụng trong mã trước đó.
5. Hiển thị mảng đã được sắp xếp
“Chỉ số dưới giống nhau và có thể được sử dụng để hiển thị các giá trị của mảng như trong câu lệnh
dưới:
for (i = 0; i < n; i++)
{
printf("\n Phần tử tại [%d] là %d", i, desnum[i]);
}
‘Do đó, một mảng các phần tử có thể được sắp xếp. Chúng ta hãy xem chương trình hoàn chỉnh.
- Khởi chạy môi trường phát triển tích hợp NotBeans (có lẽ là NetBeans IDE) trong đó bạn có thể viết chương trình C.
- Tạo một dự án mới.
- Nhập mã sau vào trình soạn thảo (Source Editor) của tệp main.c:
#include <stdio.h>
int main() {
int n;
int desnum[100];
int i, j, temp;
printf("Nhập tổng số điểm cần nhập: ");
scanf("%d", &n);
for (i = 0; i < n; i++) {
printf("Nhập điểm của học sinh %d: ", i + 1);
scanf("%d", &desnum[i]);
}
// Sắp xếp mảng theo thứ tự giảm dần
for (i = 0; i < n - 1; i++) {
for (j = i + 1; j < n; j++) {
if (desnum[i] < desnum[j]) {
temp = desnum[i];
desnum[i] = desnum[j];
desnum[j] = temp;
}
}
}
for (i = 0; i < n; i++) {
printf("\n Điểm của học sinh [%d] là %d", i, desnum[i]);
}
return 0;
}
4. Kết nối và chạy ứng dụng.
Kết quả mẫu của chương trình trên được thể hiện trong hình
Nhập số điểm cần nhập: 5
Nhập điểm của học sinh 1: 90
Nhập điểm của học sinh 2: 85
Nhập điểm của học sinh 3: 70
Nhập điểm của học sinh 4: 95
Nhập điểm của học sinh 5: 88
Điểm của học sinh [0] là 95
Điểm của học sinh [1] là 90
Điểm của học sinh [2] là 88
Điểm của học sinh [3] là 85
Điểm của học sinh [4] là 70
Nhập số điểm cần nhập: 5
Nhập điểm của học sinh 1: 95
Nhập điểm của học sinh 2: 88
Nhập điểm của học sinh 3: 70
Nhập điểm của học sinh 4: 85
Nhập điểm của học sinh 5: 90
Điểm của học sinh [0] là 95
Điểm của học sinh [1] là 90
Điểm của học sinh [2] là 88
Điểm của học sinh [3] là 85
Điểm của học sinh [4] là 70
Phép cộng ma trận sử dụng mảng hai chiều
Mảng có thể có nhiều chiều. Một ví dụ điển hình về mảng hai chiều là ma trận. Một ma trận là một mẫu số hình chữ nhật được tạo bởi các hàng và cột. Giao điểm của mỗi hàng và cột có một giá trị. Hình 12.10 biểu thị một ma trận.
Số hàng và số cột trong một ma trận được biểu diễn dưới dạng (số hàng) x (số cột) được gọi là kích thước của ma trận. Kích thước của ma trận trong hình bên dưới.
Hãy xem xét ví dụ về phép cộng ma trận để hiểu cách sử dụng mảng hai chiều. Xem xét các ma trận A và B sau đây.
Tổng của hai ma trận này tạo ra một ma trận khác. Điều này được thực hiện bằng cách cộng giá trị từ mỗi hàng và cột tương ứng. Ví dụ, phần tử đầu tiên C(1,1) trong ma trận C sẽ là tổng của A(1,1) và B(1,1). Phần tử thứ hai C(1,2) sẽ là tổng của A(1,2) và B(1,2) và cứ tiếp tục như vậy.
Một quy tắc quan trọng khi cộng ma trận là rằng kích thước của các ma trận đang được cộng phải giống nhau. Nghĩa là, một ma trận 2×3 có thể được cộng với một ma trận khác có kích thước 2×3 duy nhất. Hình bên dưới biểu thị các ma trận A và C.
Để thực hiện điều này bằng cách lập trình:
- Khai báo ba mảng hai chiều. Mã cho việc này như sau:
int A[20][10], B[10][20], C[10][10];
2. Nhập kích thước của các ma trận. Mã cho việc này như sau:
int rows, cols;
printf("Nhập kích thước của ma trận: ");
scanf("%d %d", &rows, &cols);
3. Nhập giá trị của ma trận A và B.
Giá trị của ma trận được nhập theo từng hàng. Đầu tiên, giá trị của hàng đầu tiên được nhập. Sau đó, giá trị của hàng thứ hai được nhập và tiếp tục như vậy. Trong từng hàng, giá trị của từng cột được nhập tuần tự. Do đó, cần hai vòng lặp for để nhập giá trị của một ma trận. Vòng lặp for đầu tiên đi qua từng hàng một, trong khi vòng lặp for bên trong đi qua từng cột một.
Mã cho việc này như sau:
printf("Nhập giá trị của ma trận A và B:\n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("A[%d, %d], B[%d, %d] : ", i, j, i, j);
scanf("%d %d", &A[i][j], &B[i][j]);
}
}
4. Thêm hai ma trận. Hai ma trận có thể được cộng bằng mã sau:
C[i][j] = A[i][j] + B[i][j];
Lưu ý rằng dòng này cần nằm bên trong vòng lặp for bên trong của mã được cung cấp trước đó. Hoặc có thể viết lại hai vòng lặp for để thực hiện phép cộng ma trận.
5. Hiển thị ba ma trận. Mã cho việc này như sau:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("A[%d, %d] = %d, B[%d, %d] = %d, C[%d, %d] = %d\n", i, j, A[i][j], i, j, B[i][j], i, j, C[i][j]);
}
}
Hãy xem xét toàn bộ chương trình.
- Tạo một dự án mới.
- Nhập mã sau vào trình soạn thảo (Source Editor) của tệp main.c:
#include <stdio.h>
int main() {
int A[10][10], B[20][20], C[10][10];
int rows, cols;
printf("Nhập kích thước của ma trận: ");
scanf("%d %d", &rows, &cols);
printf("\nNhập giá trị của ma trận A và B:\n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("A[%d, %d], B[%d, %d] : ", i, j, i, j);
scanf("%d %d", &A[i][j], &B[i][j]);
}
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
C[i][j] = A[i][j] + B[i][j];
}
}
printf("\nBa ma trận A, B và C:\n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("A[%d, %d] = %d, B[%d, %d] = %d, C[%d, %d] = %d\n", i, j, A[i][j], i, j, B[i][j], i, j, C[i][j]);
}
}
return 0;
}
3. Xây dựng và chạy ứng dụng.
Kết quả mẫu của chương trình trên sẽ được hiển thị như trong hình
Bài tập
1. Viết chương trình nhập vào chuỗi đếm số ký tự nguyên âm của chuỗi
2. Viết chương trình nhập vào một mảng 5 phần tử và sắp xếp mảng theo chiều xuôi, và ngược
3. Viết chương trình đảo ngược mảng sau:
36 , 43, 53, 64, 80
4. Viết chương trình theo yêu cầu sau:
Có 2 mảng arr1 và arr2 có 5 phần tử.
Yêu cầu nhập liệu arr1.
1. Copy toàn bộ phần tử sang arr2
2. Copy toàn bộ phần tử sang arr2 nhưng theo chiều ngược lại
5. Viết chương trình C để tìm kiếm min và max trong 1 mảng ký tự.
6. Viết chương trình C để đếm số ký tự nguyên âm và phụ âm trong 1 từ.
7. Viết chương trình yêu cầu nhập vào 5 chuỗi, và sắp xếp chúng theo chiều xuôi, ngươc alphabet