Lập trình C: Bài 9 – Mảng trong C
Nội dung
Trước khi tìm hiểu về mảng trong C, chúng ta thử làm ví dụ mở đầu.
1. Ví dụ mở đầu
Xét ví dụ nhập 5 số nguyên, xuất ra màn hình 5 số đó trên một dòng và tổng 5 số đó.
// e.g about array - code by nguyenvanquan7826 #include <stdio.h> int main() { int a, b, c, d, e; // 5 bien printf("Nhap a = "); scanf("%d", &a); printf("Nhap b = "); scanf("%d", &b); printf("Nhap c = "); scanf("%d", &c); printf("Nhap d = "); scanf("%d", &d); printf("Nhap e = "); scanf("%d", &e); int tong = a + b + c + d + e; printf("Tong cua %d + %d + %d + %d + %d = %d \n", a, b, c, d, e, tong); return 0; }
Kết quả:
Nhap a = 3
Nhap b = 5
Nhap c = 3
Nhap d = 6
Nhap e = 1
Tong cua 3 + 5 + 3 + 6 + 1 = 18
Như ví dụ ta thấy nhập hết 5 số và xuất chúng ta màn hình có vẻ rất vất vả và ta đã phải sử dụng quá nhiều biến, nếu số biến của chúng ta không phải là 5 mà là 50, 500,… thì việc này quả là rất khó khăn. Để khắc phục điều này chúng ta hãy sử dụng kiểu mảng.
Mảng Là tập hợp các phần tử có cùng kiểu dữ liệu. Mảng có mảng 1 chiều, 2 chiều,… và mỗi kiểu dữ liệu thì có 1 kiểu mảng tương ứng (mảng nguyên, mảng thực, mảng ký tự (chuỗi)),… Ta chủ yếu xét về mảng 1 chiều và mảng 2 chiều.
Bây giờ chúng ta sẽ giải quyết lại ví dụ trên bằng cách sử dụng mảng 1 chiều.
2. Mảng 1 chiều
2.1 Ví dụ tổng quan
Các bạn thử đọc và chạy chương trình này, sau đó hãy xem chi tiết ở dưới.
// e.g about array - code by nguyenvanquan7826 #include <stdio.h> int main() { // khai bao mang a co n phan tu int n = 5, i, s = 0; int a[n]; // thuc hien nhap tung phan tu mang for (i = 0; i < n; i++) { printf("Nhap a[%d] = ", i); scanf("%d", &a[i]); } // thuc hien in cac phan tu cua mang ra man hinh printf("\nMang da nhap \n"); for (i = 0; i < n; i++) { printf ("%d \t", a[i]); } // tinh tong cac so trong mang for (i = 0; i < n; i++) { s += a[i]; // s = s + a[i] } printf("\nTong cac so trong mang: %d\n", s); return 0; }
Nhap a[0] = 3
Nhap a[1] = 4
Nhap a[2] = 6
Nhap a[3] = 2
Nhap a[4] = 7
Mang da nhap
3 4 6 2 7
Tong cac so trong mang: 22
2.2 Cách khai báo mảng 1 chiều
KieuDuLieu TenMang [SoPhanTu];
VD: int a[10];
Mảng 1 chiều a gồm 10 phần tử thuộc kiểu nguyên. Sau khi khai báo ta có 1 mảng có dạng như sau:
2.3 Cách truy xuất đến các phần tử trong mảng
Sau khi mảng được khai báo, mỗi phần tử trong mảng đều có chỉ số để tham chiếu. Chỉ số bắt đầu từ 0 đến n-1 (với n là kích thước mảng). Trong ví dụ trên, ta khai báo mảng 10 phần tử thì chỉ số bắt đầu từ 0 đến 9.
Và ta truy xuất qua cú pháp: TenMang[ChiSo]
2.4 Cách nhập và xuất các phần tử của mảng
Để nhập dữ liệu cho các phần tử trong mảng ta cần duyệt tới từng phần tử trong mảng và tiến hành nhập bằng một vòng for
for (i = 0; i < n; i++) { printf("Nhap a[%d] = ", i); scanf("%d", &a[i]); }
Việc xuất các phần tử trong mảng cũng được tiến hành tương tự:
for (i = 0; i < n; i++) { printf ("%d \t", a[i]); }
2.5 Nhập xuất mảng sử dụng hàm
Trong nhiều bài toán, chúng ta phải nhập nhiều mảng, và xuất nhiều lần, khi đó hãy đưa nhập xuất vào hàm cho dễ dùng.
// e.g about array - code by nguyenvanquan7826 #include <stdio.h> void nhapMang(int a[], int n) { int i; // thuc hien nhap tung phan tu mang for (i = 0; i < n; i++) { printf("Nhap a[%d] = ", i); scanf("%d", &a[i]); } } void xuatMang(int a[], int n) { int i; for (i = 0; i < n; i++) { printf ("%d \t", a[i]); } } int main() { // khai bao mang a co n phan tu int n = 5; int a[n]; nhapMang(a, n); xuatMang(a, n); return 0; }
Lưu ý: Một mảng có mối quan hệ với 1 con trỏ, mảng có thế coi như 1 con trỏ nên khi truyền mảng vào hàm thì các phần tử của mảng sẽ bị ảnh hưởng nếu có sự thay đổi nào trong mảng.
2.6 Một vài lưu ý khác
Khởi tạo mảng: Chúng ta có thể khởi tạo mảng trong quá trình khai báo ngay. VD: float a [5] = {3.4, 5, 6, 7, 4,2}
Với cách khởi tạo này nếu ta khởi tạo vượt quá 5 phần tử máy sẽ báo lỗi, nếu thiếu phần tử nào thì phần tử đó nhận giá trị là 0.
VD: float a [5] = {3.4, 5, 7} => a[4] = 0
.
VD: float a [5] = {3.4, 5, 7, 1, 2, 3}
=> máy báo lỗi.
Ngoài ra chúng ta có cách khai báo và khởi tạo mảng chưa biết trước số lượng.
VD: int a[] = {3,6,2,5}
=> Mảng có 4 phần tử nhận giá trị tương ứng.
Hoặc: int a[];
=> Thường sử dụng khi dùng mảng làm tham số hình thức trong hàm.
3. Mảng 2 chiều
Chúng ta có thể coi nó như một ma trận. Các tính chất, cách khai báo, nhập xuất,… cũng tương tự như mảng 1 chiều.
KieuDuLieu TenMang [SoHang][SoCot];
VD khai báo: int a[5][10];
=> Mảng a gồm 5 hàng và 10 cột (mỗi hàng có 10 phần tử).
// e.g about array - code by nguyenvanquan7826 #include <stdio.h> #define MAX 10 // nhap mang n hang, m cot void nhapMang(int a[MAX][MAX], int n, int m) { int i, j; for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { printf("Nhap a[%d][%d] = ", i, j); scanf("%d", &a[i][j]); } } } // xuat mang n hang, m cot void xuatMang(int a[MAX][MAX], int n, int m) { int i, j; for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { printf ("%-3d", a[i][j]); } printf("\n"); // xuong dong khi het 1 dong } } int main() { // khai bao mang a co n phan tu int n = 2, m = 3; int a[MAX][MAX]; nhapMang(a, n, m); xuatMang(a, n, m); return 0; }
Chú ý: Thực chất trong bộ nhớ, các phần tử của mảng 2 chiều (và mảng nhiều chiều) được tổ chức như là nhiều mảng 1 chiều liên tiếp nhau, vì vậy ta có thể quy mảng 2 chiều thành mảng 1 chiều.
chap9-luu-tru-mang-2-chieu-trong-c.png
Bài tập
- Nhập vào một mảng, tìm số lớn nhất và nhỏ nhất trong mảng đã nhập.
- Nhập vào một dãy số, in ra các vị trí số lớn nhất (có thể có nhiều vị trí).
- Nhập vào một dãy số là lượng mưa của các tháng liên tiếp trong năm. Thông báo ra các tháng có lượng mưa lớn hơn lượng mưa trung bình của các tháng đó.
- Nhập vào một dãy số, sắp xếp và in ra dãy số theo chiều tăng dần.
- Nhập vào một ma trận (mảng 2 chiều). In ra tổng của mỗi hàng trong ma trận đó.
Anh ơi, anh cho em hỏi là void main và int main khác nhau chỗ nào vậy ạ, và cách dùng của void main và int main có gì khác nhau vậy ạ ?
Em cảm ơn anh.
void main thì hàm main không trả về giá trị nào
int main thì hàm main sẽ trả về giá trị kiểu nguyên. và ta phải trả về giá trị 0 (tức là không có lỗi) nếu trả về giá trị khác thì coi như chương trình lỗi (quy định chấm thi olympic).
Và đến thời điểm này quy định chuẩn là dùng int main nhé.
Nếu mình ko ghi return 0; thì liệu có vấn đề gì ko ạ ?
và bài nào mình cũng dùng int main được ạ ? (tại em thấy có đoạn anh dùng void main,có đoạn dùng int nên thắc mắc ạ )
Không return 0 cũng không sao, chương trình vẫn chạy. Chắc lúc dùng void là mình chưa biết luật.
Sau đi thi thì biết nên dùng int. 🙂
Anh ơi cho em hỏi là các phần tử của mảng được lưu ở đâu ạ ?(RAM,…)
Sao em khai báo long A[1000000000] thì biên dịch bình thường, còn khi chạy thì nó return 3 tỉ mấy ?
Cái này là do tràn bộ nhớ sao đó. Chứ a cũng chưa thử khai báo đến tỉ phần tử thế này. =))
Cho e hỏi là nhập n trong hàm nhập mảng khác nhập n ngoài hàm nhập mảng như nào ạ. Và khi nào thì nhập trong khi nào nhập ngoài ạ
Nhập trong là nhập trong, còn nhập ngoài là nhập ngoài. Khi nào cần truyền n từ ngoài vào thì dùng nhập ngoài.
anh ơi, sao em coppy ví dụ 2 nó báo lỗi ở nhapMang(a, n, m); là sao hả anh.
Lỗi cụ thể thế nào bạn?
31 21 C:\Users\TraMy-Dang\Documents\mang_hai_chieu.cpp [Error] cannot convert ‘int (*)[(((sizetype)(((ssizetype)m) + -1)) + 1)]’ to ‘int (*)[10]’ for argument ‘1’ to ‘void xuatMang(int (*)[10], int, int)’ đây ạ.
oh, Mình chạy vẫn ổn mà, ngon nữa…
đúng rồi anh ơi…nó báo lỗi ở đoạn nhập mảng anh .
Các bạn code trên phần mềm nào vậy? Mình chạy vẫn ổn mà.
em chay tren dev,visual deu bi loi ở chỗ đó anh ơi.
Cảm ơn các bạn, mình đã cập nhật lại nhé.
a có file pdf k ạ? nhà k có mạng, muốn tìm cũng khổ quá.
Mình không có file pdf. Khi nào bạn online thì có thể ấn Ctrl +S để lưu lại trang là được.
anh có thể chỉ em cách làm sao có thể nhập mảng bằng tệp được ko ạ
em thấy cách này cũng hay dùng,nhưng em chưa biết làm sao để mở đc ( vd như dung notepad để nhập v.v…)
Bạn tìm cách đọc file trong C/C++ nhé. Sau đó thì nhập số hay bất cứ thứ gì giống như từ bàn phím thôi.
anh ơi cho em hỏi printf (“%-3d”, a[i][j]); cái %-3d có nghĩa là gì vậy ạ.
%xd Xuất thông tin số nguyên và để x chỗ trống biểu diễn, dấu âm là để căn trái.
Xem chi tiết ở bài này nhé.
https://www.cachhoc.net/2014/12/04/lap-trinh-c-bai-2-kieu-du-lieu-va-nhap-xuat-trong-c/#2_Xuat_du_lieu_printf
em cảm ơn ạ
Em muốn nhờ anh chút ạ
Em có mảng 2 chiều ={xyDfdfgf
………….}
Làm thế nào để thay thế được kí tự x bằng kí tự y trong toàn mảng,còn nhiều hàng khác nữa và em muốn thay thế hai kí tự đầu mỗi hàng như x với y ấy ạ !
Thanks!
Bạn duyệt mảng và so sanha bình thường thôi …
Chào Quân,
Cảm ơn Q vì bài giảng trên.
MÌnh muốn hỏi là trong trường hợp mình muốn tạo 1 mảng để chứa 1 số nguyên có 100 chữ số thì làm thế nào hả Q ?
Cảm ơn Q nhiều.
Vậy bạn cứ tạo mảng 100 phần tử để chứa 100 chữ số. Tuy nhiên khi tính toán thì bạn cần tìm hiểu cách tính số lớn.
Cảm ơn Q nhé
#include
int main()
{
int n,i;
printf(“Nhap so so hang”);
scanf(“\t%d”,&n);
int a[n]=0;
while (i < n)
{
printf("nhap a[%d]\t",i);
scanf("%d", &a[i]);
}
printf("");
return 0;
}
Sao ct này e chạy bj lỗi z a
Bạn mô tả sai như thế nào, sai chỗ nào chứ. Hỏi thế sao mình biết được.
bạn nên để lệnh for thay while, còn như thế kia là sai do thiếu i++ trong {} rồi
cho e hỏi #define MAX 10 có nghĩa là sao ạ
Đó có nghĩa là khai báo hằng số MAX có giá trị là 10
Anh ơi làm sao để nhập vào một mảng mà nó in ra màn hình theo 1 hàng ngang ngay từ khi nhập ạ
Bạn nhập các số tách nhau bằng dấu cách là được 🙂
Bạn ơi cho mình hỏi cái. Mình điểu khiển UNO nháy LED.
for (i=0;i<n;i++) {digitalWrite(A[i],HIGH); digitalWrite(A[i-1],LOW); delay(200); };
Thì khi i =0. A[0] HIGH, nhưng mà i-1 = -1 <0 thì mảng không nhận giá trị hay nó chọn bất kì 1 phần tử trong mảng thế. Minhg cảm ơn
bạn cho i chạy từ 1 là được. hoặc giàng buộc điều kiện nếu i > 0 thì mới viết a[i-1]
Nếu i=1 thì con A[0] k đc nháy, lại phải viết ra riêng ý =]]. Cảm ơn bạn nhé,
#include
void input(int a[], int n)
{
int i;
printf(“Input Array:\n”);
for(i=0;i<n;i++)
{
printf("a[%d]=", i);
scanf("%d", &a[i]);
}
}
void output(int a[], int n)
{
int i;
printf("Output Array:\n");
for(i=0;i<n;i++)
{
printf("%-3d", a[i]);
}
}
int main()
{
int n, i, a[n];
printf("n="); scanf("%d", &n);
input(a, n);
output(a, n);
return 0;
}
Anh cho em hỏi code này sai chổ nào thế, khi nhập n=8 thì báo lỗi Segmetation fault ạ @@
Sai vì khai báo mảng a[n] trước khi n có giá trị.
cho e hỏi tại sao e nhâp mảng 1 chiều gồm 10 phân tử thì máy báo lỗi ko làm việc được ạ. Nhập xong là ko xuất ra hay làm gì được luôn ạ !
#include
void nhapmang(int a[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("nhap a[%d] ",i);scanf("%d",&a[i]);
}
}
int main()
{
int n,max=0,i=0;
printf("nhap n");scanf("%d",&n);
int a[n];
nhapmang(a,n);
for(i=0;i<n;i++)
{ if(max<a[i]) max=a[i];
}
printf("%d",max);
for(i=0;i<n;i++){
if(a[i]=max)printf("%i");
else printf("*");
}
}
anh ho em nhowfvoiws ạ.tại sao khi em chạy n im ra tất cả các vị trí vậy ah
So sánh bạn phải dùng == chứ không phải = nhé.
a oi phan 2.1 khai bao them i chi vay
Để dùng i trong vòng for đó.
#include
int main(){
int m[5],i,trungbinh=0;
for(i=0;i<5;i++){
printf("nhap m[%d]",i);
scanf("%d",&m[i]);
}for(i=0;i<5;i++){
trungbinh=(trungbinh+m[i])/5;
} printf("%d",trungbinh);
}
cho t hỏi vì sao khi t chay luon ra ket qua 0 vay
lưu trữ dữ liệu vào mảng 1 chiều, khi đã được tính toán tự động
vd: S1=2, s2=9,…….,Sn=n
lưu các giá trị đó vào mảng thì làm sao ạ..??
Mình cám ơn
Bạn gán các giá trị đó vào mảng là được.
namespace mangmotchieu
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void btnhap_Click(object sender, EventArgs e)
{
int n;
int[] A;
{
n = int.Parse(txtnhapn.Text);
A = new int[n + 1];
for (int i = 0; i < n; i++)
{
A[i] = int.Parse(Microsoft.VisualBasic.Interaction.InputBox("nhập phan tử thứ" + (i + 1).ToString()));
txtketqua.Text = txtketqua.Text + " " + A[i].ToString();
}
{
A = new int[n + 1];
for (int i = 0; i 0)
{
btnhap.Enabled = false;
txtketqua.Enabled = true;
}
else
{ MessageBox.Show(“n nhap phai la so nguyen duong”); }
{
txtnhapn.Text = “”;
txtnhapn.Focus();
}
}
mọi người làm ơn giúp em với.khi e viết chương trình kiểm tra số nguyen dương trong mảng thì khi chay chương trình phần button không hiện nhập
anh ơi nếu so sánh và sắp sếp các phần tử trong mảng thì sao ạ
Ý bạn là sao nhỉ? So sánh và sắp xếp thì cứ sắp xếp thôi, còn nếu chưa biết cách làm thì bạn có thể xem tại đây: https://vi.wikipedia.org/wiki/S%E1%BA%AFp_x%E1%BA%BFp_n%E1%BB%95i_b%E1%BB%8Dt#Vi%E1%BA%BFt_b%E1%BA%B1ng_C++
#include
int main()
{ int n;
int a[n];
int max;
printf(“Nhap may so: “);
scanf(“%d”,&n);
for(int i=1;ii)
{
max=a[i];
}
if(a[i]>i)
{
max=a[i];
}
}
printf(“%d”, max);
return 0;
}
ct tìm số lớn nhất đấy anh ơi, sao em làm mà cứ thấy sai sai, mà kết quả ra vẫn đúng, mong anh xem code và giải thích cho em ạ
sai bét tè lè nhè nhé. Nhập vào n số thì các số đó phải nhập từ bàn phím, bạn đã cho nhập từ bàn phím đâu. vào đây test thử. https://chamcode.net
#include
int main()
{ int n,i;
int a[20];
int max=0;
int min=1;
printf(“Nhap may so: “);
scanf(“%d”,&n);
for( i=1;i<=n;i++)
{ printf("Nhap so thu %d: ",i);
scanf("%d", &a[i]);
}
for(i=1;i<=n;i++)
{
if(max=a[i])
{
min=a[i];
}
}
printf(“%d %d”, max, min);
return 0;
}
mà thôi anh, xem bài này nè, bây giờ em nhập số âm vào thì nó cứ ra max là 0 miết anh ơi, chỉ em với, em khai báo max=0; còn nếu khai báo max= 1 số khác thì sai
Thì ban đầu max = 0 rồi, lại nhập toàn số âm thì làm gì có số nào lớn hơn max nữa. nên gán max = số đầu tiên sau khi nhập rồi hãy tìm.
bài viết của a rất dễ hiểu. xem xem trên youtube mà toàn khái niệm, xem xong chả hiểu gì.
a cho em hỏi 2 chỗ trong bài :
1.void nhapMang(int a[MAX][MAX], int n, int m) tại sao cái này phải là MAX MAX mà không để trống như void nhapMang(int a[], int n),MAX là cái gì ạ.
2.float a [5] = {3.4, 5, 7} => a[4] = a[5] = 0 Cái này a[4]=7 a[5]=0 chứ sao lại a[4]=a[5].
mảng 2 chiều thì cần có số lượng tối đa của mảng, MAX là số lượng tối đa. Mảng 1 chiều thì ko cần.
VD: float a [5] = {3.4, 5, 7} => a[4] = a[5] = 0. nghĩa là phần tử thứ 4 và thứ 5 =0 vì khai báo chỉ từ 0 đến 3 mà.
E vẫn chưa hiểu lắm ạ. Vậy là mảng a[5] phải có tới 6 phần tử vì tính từ 0 đến 5 ạ ( có tổng cộng 6 số trong ngoặc).
Nhưng sao em tưởng số phần tử phải bằng số lượng con số trong ngoặc như trên a ghi
VD: int a[] = {3,6,2,5} => Mảng có 4 phần tử nhận giá trị tương ứng.
Ah, xin lỗi bạn, có chút bug ở đây, tức chỉ có a[4] = 0 thôi, ko có a[5], chỉ có từ a[0] đến a[4] vì khai báo mảng có 5 phần tử, và khởi tạo ban đầu cho 4 cái thôi, cái cuối ko khởi tạo thì nó là 0.
#include
int main(){
int n;
printf(“\nNhap so luong phan tu n = “);
scanf(“%d”, &n);
int a[n];
for(int i = 0; i < n; i++){
printf("\nNhap a[%d] = ",i);
scanf("%d", &a[i]);
}
int tg;
int max;
max=n*(n-1)/2;
printf("max %d ",max);
for(int i=0 ;i<max;i++ ){
for(int j=i+1;j a[j]){
tg = a[i];
a[i] = a[j];
a[j] = tg;
}
}
}
printf(“\nMang da sap xep la: “);
for(int i = 0; i <n; i++){
printf("%5d", a[i]);
}
return 0;
}
thầy ơi em sắp xếp từ bé đến lớn, nhập n=1,2,3,4 vẫn ngon sao đến khi nhập 5 với mấy số lớn hơn lại sai ạ ?
cái vòng for này có vấn đề sao này.”for(int j=i+1;j a[j]){“
Anh ơi, chỗ khai báo mảng a[n] nó bị lỗi hoài a, e khai báo cho người dùng nhập cái nớ không được ạ!
Cho em hỏi có cách nào để cho người dùng nhập số phần tử trực tiếp cho mảng không a?
nhập xong rồi khai báo e.
Dạ cho em hỏi là giữa void main và int main dùng vào lúc nào ạ???
Dùng cái nào cũng đk nhé, nhưng giờ họ dùng int.
anh ơi cho em hỏi là trường em dạy mảng trước hàm mà em thấy các web đều dạy hàm trước mảng như thế có sao không ạ
Ko sao nhé.