Biến toàn cục và biến địa phương

Một phần của tài liệu Giáo trình lập trình căn bản (nghề kỹ thuật sửa chữa, lắp ráp máy tính) (Trang 57)

Biến toàn cục là những biến được sử dụng mọi nơi trong chương trình. Còn biến

địa phương chỉ có giá trị trong thời gian hoạt động, sau khi hàm kết thúc thì những biến

khai báo bên trong hàm đó cũng như các tham số của nó cũng kết thúc.

5.1. Biến toàn cc

Ví dụ:

Dòng File Edit Search Run Compile Debug Project Option Window Help

1 2 3 4 5 6 7 8 9 10 11 #include <stdio.h> #include <conio.h> // khai báo prototype void oddeven(); void negative();

//khai báo biến toàn cục int inum;

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 {

printf("Nhap vao 1 so nguyen : "); scanf("%d", &inum); oddeven(); negative(); getch(); } // hàm kiểm tra chẳn lẻ void oddeven() { if (inum % 2)

printf("%d la so le.\n", inum); else

printf("%d la sochan.\n", inum); }

//Hàm kiểm tra số âm void negative()

{

if (inum < 0)

printf("%d la so am.\n", inum); else

printf("%d la so duong.\n", inum); }

F1 Help Alt-F8 Next Msg Alt-F7Prev Msg Alt - F9 Compile F9 Make F10 Menu

Kết quả in ra màn hình

Giải thích chương trình

Chương trình trên gồm 2 hàm oddeven và negative, 2 hàm này ta thấy không có tham sốđể truyền biến inum vào xửlý nhưng vẫn cho kết quả đúng. Do chương trình

trình mỗi khi gọi và sử dụng nó. Xét tình huống sau: Giả sử trong hàm negative ta khai báo biến inum có kiểu int như sau:

void negative() {

int inum;

….

}

Khi đó chương trình sẽ cho kết quả sai! Do các câu lệnh trong hàm negative sử

dụng biến inum sẽ sử dụng biến inum khai báo trong hàm negative và lúc này biến inum toàn cục không có tác dụng đối với các câu lệnh trong hàm này. Biến inum khai báo trong hàm negative chỉ có ảnh hưởng trong phạm vi hàm và chu trình sống của nó bắt

đầu từ lúc gọi hàm đến khi thực hiện xong.

5.2. Biến địa phương

Các biến trong hàm là biến địa phương. Biến địa phương chỉ tồn tại trong thời

gian hàm đó hoạt động.

Tầm tác dụng của biến địa phương chỉ hạn chếtrong hàm mà nó được khai báo. Các biến địa phương cũng sẽ không có mối liên hệ nào với biến toàn cục có cùng tên và cùng kiểu. Ví dụ int n; main() { int p; … } ham_thi_du() { int p int n; …. }

- Các biến địa phương không lưu trữ kết quả cho các lần sau. Lần nào biết lần

ấy, các biến địa phương được sinh ra rồi chết luôn khi ra khỏi hàm.

- Các tham sốcũng là biến địa phương. Nghĩa là cũng chỉ hoạt động khi hàm

BÀI TP

Lý thuyết

1. Hàm là gì? Tại sao phải sử dụng hàm? 2. Trình bày các thành phần của hàm.

3. Trình bày tóm tắt các cách truyền tham số? Phân biệt sự khác nhau giữa các cách này. Cho ví dụ minh họa.

Thực hành

4. Viết hàm nhập một số nguyên bất kỳ. Hãy đọc giá trị của sốnguyên đó nếu nó có giá trị từ0 đến 9, ngược lại thông báo không đọc được.

5. Viết hàm hập 3 số nguyên a, b và c từ bàn phím. Hãy tìm số có giá trị nhỏ nhất ( hoặc lớn nhất).

6. Viết hàm tính tiền đi taxi từ số km nhập vào. Biết: - 1 km đầu giá 15000đ

- Từ km thứ2 đến km thứ5 giá 13500đ

- Từ km thứ 6 trởđi giá 11000đ

- Nếu đi hơn 120 km sẽđược giảm 10% trên tổng số tiền. 7. Viết hàm nhập vào tháng, in ra tháng đó có bao nhiêu ngày.

Hướng dẫn: Nhập vào tháng

Nếu là tháng 1, 3, 5, 7,8, 10, 12 thì có 30 ngày Nếu là tháng 4, 6, 9, 11 thì có 31 ngày

Nếu là tháng 2 và là năm nhuận thì có 29 ngày ngược lại 28 ngày

(Năm nhuận là năm chia chẵn cho 4)

8. Viết chương trình nhập vào 2 số x, y và 1 trong 4 toán tử +, -, *, /. Nếu là + thì in ra kết quả x + y, nếu là – thì in ra x – y, nếu là * thì in ra x * y, nếu là / thì in ra x / y (nếu

y = 0 thì thông báo không chia được)

9. Viết hàm nhận vào một sốnguyên dương n và thực hiện: a. Có phải là sốđối xứng? Là số nghịch đảo bằng chính nó. Ví dụ: 121, … b. Có phải là sốchính phương? Là số bằng bình phương số khác. Ví dụ: 4, 9, … c. Có phải là số nguyên tố? Là số lớn hơn 1 và chỉcó 2 ước số là 1 và nó. Ví dụ: 2, 3, 5, 7, 11, 13, … d. Chữ số lớn nhất và nhỏ nhất? Ví dụ: số 1706, nhỏ nhất 0 và lớn nhất 7 e. Các chữ sốcó tăng dần hay giảm dần không? Ví dụ: 12245, 156, 442, 941, …

10. Viết hàm nhận vào một sốnguyên dương n và thực hiện:

a. S = 1 + 2 + … + n b. S = 12 + 22 + … + n2

c. S = 1 + 1/2 + … + 1/n d. S = 1! + 2! + … + n!

11. Viết hàm trả về USCLN của 2 số nguyên. 12. Viết hàm in ra n phần tử của dãy Fibonacy

CHƯƠNG 5: DỮ LIU KIU MNG (ARRAY),

CHUI KÝ T (STRING) VÀ BN CHI (STRUCT)

Mục tiêu

− Trình bày được khái niệm mảng, chuỗi ký tự và bản ghi;

− Thực hiện cách khai báo, gán giá trị cho mảng, chuỗi ký tự và bản ghi; − Thực hiện các thao tác và truy xuất cho mảng, chuỗi ký tự và bản ghi; − Thực hiện các thao tác an toàn với máy tính.

Nội dung

1. Dữ liệu kiểu mảng

1.1. Khái nim

Mảng là một tổ chức kiểu dữ liệu có cấu trúc bao gồm một số cốđịnh các thành phần có cùng kiểu. Mỗi thành phần của mảng được truy xuất thông qua các chỉ số mô tả vị

trí của thành phần đó trong mảng.

1.2. Khai báo mng

2.2.1. Khai báo kiểu mảng

Cú pháp:

typedef <kiểu cơ sở> <tên kiểu mảng>[<số phần tử>];

Trong đó:

- <tên kiểu mảng>: tên kiểu mảng theo quy định đặt tên/định danh. - <kiểu cơ sở> : kiểu dữ liệu của các thành phần trong mảng. - <số phần tử> : sốlượng phần tử của mảng.

Ví dụ: khai báo kiểu dữ liệu mảng một chiều có tên MangInt (gồm 20 phần tử kiểu số

nguyên) và MangFloat (gồm 30 phần tử kiểu số thực).

typedef int MangInt[20]; typedef float MangFloat[30];

2.2.2. Khai báo biến mảng

Biến mảng được khai báo trực tiếp (tường minh) như sau:

Cú pháp:

<kiểu cơ sở> <tên biến mảng>[<số phần tử>];

2.2.3. Khởi tạo giá trị cho mảng khi khai báo

Ta có thể khởi tạo giá trị cho mảng một chiều thông qua các cách sau: - Khởi tạo giá trị cho mọi phần tử của mảng.

int a[4] = {2912, 1706, 1506, 1904};

Mảng a gồm 4 phần tử 2912, 1706, 1506, 1904

- Khởi tạo giá trị cho một số phần tửđầu tiên của mảng. Các phần tử còn lại sẽ có giá trị 0. int a[4] = {2912, 1706}; Mảng a gồm 4 phần tử 2912, 1706, 0, 0 - Khởi tạo giá trị 0 cho tất cả các phần tử của mảng, ta chỉ cần khởi tạo phần tử đầu bằng 0. int a[100] = {0};

- Trình biên dịch tựxác định số phần tử của mảng thông qua danh sách khởi tạo nếu số phần tửkhông được chỉ rõ.

int a[] = {2912, 1706, 1506, 1904};

Mảng a sẽ gồm 4 phần tử 2912, 1706, 1506, 1904.

1.3. Gán giá tr cho mng

1.3.1. Truy xuất dữ liệu kiểu mảng

Truy xuất đến từng phần tử của mảng thông qua cú pháp sau:

Cú pháp:

<biến mảng>[<gt cs1>][<gt cs2>]…[<gt csn>]

Trong đó <gt cs1>, <gt cs1>, ..., <gt csn>: là các giá trị cụ thể của phần tử trong mảng muốn truy xuất.

Lưu ý, mảng a có n phần tử thì chỉ số của mảng sẽ từ0 đến n–1. Tức mà các phần tử của mảng là a[0], a[1], …, a[n-1].

Ví dụ, cho hai mảng sau:

int MangSo[100]; float DiemHK[100][2];

Lúc này, phần tử thứ 3 của mảng có chỉ sốlà 2: MangSo[2], điểm thi môn thứ

nhất của sinh viên thứ2: DiemHK[1, 0]…

Không thể nhập xuất trực tiếp biến kiểu mảng mà phải thông qua từng thành phần của mảng đó.

Ví dụ:

printf(“%d”, MangSo); // Sai

printf(“%d”, MangSo[2]); // Dung printf(“%f”, DiemHK); // Sai

printf(“%f”, DiemHK[1][0]); // Dung

Không thể dùng lệnh gán thông thường để gán dữ liệu giữa hai kiểu mảng cùng loại. Thay vào đó, ta sẽ gán dữ liệu trực tiếp giữa từng phần tửtương ứng.

Gán trực tiếp từng phần tử

<biến mảng đích>[<chỉ số thứ i>] =

<biến mảng nguồn>[<chỉ số thứ i>];

Ví dụ:

typedef int MangSo[3]; MangSo a, b = {1, 2, 3};

a = b; // Sai

for (int i=0; i<3; i++) // Dung a[i] = b[i];

1.3.2. Truyền mảng cho hàm

Tham số kiểu mảng trong khai báo hàm giống khai báo mảng.

void SapXepTang(int a[100]);

Tham số kiểu mảng được truyền cho hàm chính là địa chỉ của phần tửđầu tiên của mảng do đó sốlượng phần tử trong tham số mảng có thể bỏ trống hoặc ta khai báo dạng con trỏ.

void SapXepTang(int a[]); // Cach 1 void SapXepTang(int *a); // Cach 2

Do ta chỉ truyền địa chỉ của phần tửđầu tiên của mảng nên số thành phần thực sựđược sử dụng phải được truyền cho hàm thông qua một tham số khác.

// n la so phan tu thuc su duoc su dung void SapXepTang(int a[], int n);

void SapXepTang(int *a, int n);

Do biến mảng chính là địa chỉ của phần tửđầu tiên của mảng đó nên khi gọi hàm, ta chỉ việc truyền tên biến mảng cho hàm. Lưu ý, nội dung của mảng có thểthay đổi khi kết thúc hàm.

void NhapMang(int a[], &n); void SapXepTang(int a[], int n); void XuatMang(int a[], n);

void main(){

int a[100]; int n;

NhapMang(a, n); // Goi ham NhapMang SapXepTang(a, n); // Goi ham SapXepTang XuatMang(a, n); // Goi ham XuatMang }

1.4. Mt s bài toán trên mng

Mảng được xét là mảng các số nguyên và số phần tử tối đa của mảng là MAX = 100.

#define MAX 100

1.4.2. Nhập mảng

Yêu cầu

Viết thủ tục nhập mảng cho phép người sử dụng nhập sốlượng phần tử n thực tế

của mảng a và lần lượt nhập vào giá trị cho từng phần tử trong mảng này.

Ý tưởng

- Nhập sốlượng phần tử thực tế n của mảng.

- Lần lượt nhập giá trị cho n phần tử của mảng từ chỉ số0 đến chỉ số n – 1.

Cài đặt

Th tc nhp mng

Đầu vào : mảng a, sốlượng phần tử n (tham chiếu)

Đầu ra : không có

void NhapMang(int a[], int &n){

// Nhap so luong phan tu n cua mang

printf(“Nhap so phan tu n: ”); scanf(“%d”, &n);

// Nhap gia tri cho n phan tu cua mang for (int i = 0; i < n; i++){

printf(“Nhap phan phan tu thu %d: ”, i); scanf(“%d”, &a[i]);

} }

Lưu ý

- Tham số n (sốlượng phần tử) phải là tham chiếu (có dấu &) vì nội dung sẽ thay

đổi sau khi thực hàm.

- Vì sốlượng phần tử lớn nhất là MAX nên khi cần có thể kiểm tra xem n có vượt quá MAX hay không trước khi cho nhập mảng.

1.4.3. Xuất mảng

Yêu cầu

Viết thủ tục xuất mảng cho phép người sử dụng xuất nội dung mảng a cho trước với sốlượng phần tử là n.

Ý tưởng

Cài đặt

Th tc xut mng

Đầu vào : mảng a, sốlượng phần tử n

Đầu ra : không có

void XuatMang(int a[], int n){

// Xuat gia tri cua N phan tu trong mang

printf(“Noi dung cua mang la: ”);

for (int i = 0; i < n; i++)

printf(“%d ”, a[i]); printf(“\n”);

}

Lưu ý:

Tham số n không cần thiết phải là tham chiếu (không cần &) vì nội dung sẽ không thay

đổi sau khi thực hiện hàm.

1.5. Mng nhiu chiu

1.5.1. Khái niệm

1.5.2. Khai báo kiểu mảng 2 chiều

Cú pháp:

typedef <kiểu cơ sở> <tên kiểu>[<N1>][<N2>];

N1, N2: sốlượng phần tử mỗi chiều

Ví dụ:

typedef int MaTran[3][4];

Cú pháp (tường minh)

<kiểu cơ sở> <tên biến> [<N1>][<N2>];

Cú pháp (không tường minh – thông qua kiểu)

Typedef <kiểu cơ sở> <tên kiểu> [<N1>][<N2>]; <tên kiểu> <tên biến>;

<tên kiểu> <tên biến 1>, <tên biến 2>;

Ví dụ: (tường minh)

int a[10][20], b[10][20]; int c[5][10];

int d[10][20];

Ví dụ: (không tường minh – thông qua kiểu) typedef int MaTran10x20[10][20]; typedef int MaTran5x10[5][10]; MaTran10x20 a, b;

MaTran11x11 c; MaTran10x20 d;

1.5.3. Truy xuất đến một phần tử

Thông qua chỉ số

Ví dụ: Cho mảng 2 chiều như sau: int a[3][4];

Các truy xuất

Hợp lệ: a[0][0], a[0][1], ..., a[2][2], a[2][3]

Không hợp lệ: a[-1][0], a[2][4], a[3][3]

Gán dữ liệu kiểu mảng

Không được sử dụng phép gán thông thường mà phải gán trực tiếp giữa các phần tử.

<biến mảng đích> = <biến mảng nguồn>; // sai

<biến mảng đích>[<giá trị cs1>][<giá trị cơ sở 2>] = <giá trị>

Ví dụ: int a[5][10], b[5][10]; b = a; //sai int i, j; for (i = 0; i < 5; i++) for (j = 0; j< 10; j++ ) b[i][j] = a[i][j];

Truyền tham số cho hàm

- Tham số kiểu mảng trong khai báo hàm giống như khai báo biến mảng

void NhapMaTran(int a[50][100]);

- Tham số kiểu mảng truyền cho hàm chính là địa chỉ của phần tửđầu tiên của mảng.

• Có thể bỏ sốlượng phần tử chiều thứ 2 hoặc con trỏ.

• Mảng có thểthay đổi nội dung sau khi thực hiện hàm.

void NhapMaTran(int a[][100]); void NhapMaTran(int (*a)[100]);

Truyền mảng cho hàm

- Sốlượng phần tử thực sự truyền qua biến khác.

void XuatMaTran(int a[50][100], int m, int n); void XuatMaTran(int a[][100], int m, int n); void XuatMaTran(int (*a)[100], int m, int n);

- Lời gọi hàm

void XuatMaTran(int a[][100], int &m, int &n); void XuatMaTran(int a[][100], int m, int n); void main(){

int a[50][100], m, n; NhapMaTran(a, m , n); XuatMaTran(a, m, n); }

1.5.4. Một sốbài toán cơ bản Một sốqui ước Kiểu dữ liệu: #define MAXD 50 #define MAXC 50 Nhập ma trận Yêu cu: Cho phép nhập mảng a, m dòng, n cột. Ý tưởng:

- Cho trước một mảng 2 chiều có dòng tối đa là MAXD, số cột tối đa là MAXC.

- Nhập sốlượng phần tử thực sự m, n của mỗi chiều. - Nhập từng phần tử từ[0][0] đến [m-1][n-1].

Hàm nhp ma trn

void NhapMaTran(int a[][MaxC], int &m, int &n){

printf(“Nhap so dong, so cot cua ma tran: ”); scanf(“%d%d”,&m, &n);

int i, j;

for (i = 0; i<m; i++)

for (j = 0; j<n; j++){

printf(“Nhap a[%d][%d]: ”,i,j); scanf(“%d”,&a[i][j]);

} }

Xuất ma trận

Yêu cu: cho phép nhập mảng a, m dòng, n cột.

Ý tưởng: xuất giá trị từng phần tử của mảng 2 chiều từ dòng có 0 đến dòng m -1, mỗi dòng xuất giá trị của cột 0 đến cột n-1 trên dòng đó.

Hàm xut ma trn:

void XuatMaTran(int a[][MAXC], int m, int n){ int i, j;

for (i = 0; i<m; i++){ for (j = 0; j<n; j++)

printf(“%d”,a[i][j]); printf(“\n”);

} }

2. Dữ liệu kiểu chuỗi ký tự

2.1. Khái nim

Chuỗi ký tự là một dãy gồm các ký tự hoặc một mảng các ký tự được kết thúc bằng ký tự '\0' (còn được gọi là ký tự NULL trong bảng mã Ascii).

Các hằng chuỗi ký tựđược đặt trong cặp dấu nháy kép "".

2.2. Khai báo chui

2.2.1. Khai báo theo mảng

Cú pháp:

char <Biến> [Chiều dài tối đa]

Ví dụ: Trong chương trình, ta có khai báo: char Ten[12];

Trong khai báo này, bộ nhớ sẽ cung cấp 12-1 bytes đểlưu trữ nội dung của chuỗi ký tự Ten; byte cuối cùng lưu trữ ký tự‘\0’ để chấm dứt chuỗi.

Ghi chú:

Chiều dài tối đa không nên khai báo thừa để tránh lãng phí bộ nhớ, nhưng cũng

không nên khai báo thiếu.

2.2.2. Khai báo theo con trỏ

Cú pháp:

char *<Biến>

Ví dụ: Trong chương trình, ta có khai báo: char *Ten;

Trong khai báo này, bộ nhớ sẽdành 2 byte đểlưu trữđịa chỉ của biến con trỏ Ten

đang chỉđến, chưa cung cấp nơi đểlưu trữ dữ liệu. Muốn có chỗđểlưu trữ dữ liệu, ta phải gọi đến hàm malloc() hoặc calloc() có trong “alloc.h”, sau đó mới gán dữ liệu cho biến.

2.2.3. Vừa khai báo vừa gán giá trị

Ví dụ:

#include<stdio.h> #include<conio.h> int main(){

char Chuoi[]="Mau nang hay la mau mat em" ; printf("Vua khai bao vua gan trị : %s",Chuoi) ; getch();

return 0; }

Ghi chú: Chuỗi được khai báo là một mảng các ký tự nên các thao tác trên mảng có thể

2.3. Các thao tác trên chui

Không thể gán giá trị hay sử dụng phép toán + (ghép chuỗi) và các phép toán so

sánh như: > (lớn hơn), < (nhỏhơn),… mà phải gọi các hàm thư viện trong <string.h>;

2.3.1. Cộng chuỗi - Hàm strcat()

Cú pháp:

char *strcat(char *des, const char *source)

Hàm này có tác dụng ghép chuỗi nguồn vào chuỗi đích.

Ví dụ: Nhập vào họ lót và tên của một người, sau đó in cả họ và tên của họ lên màn

Một phần của tài liệu Giáo trình lập trình căn bản (nghề kỹ thuật sửa chữa, lắp ráp máy tính) (Trang 57)