CHƯƠNG 9: HÀM ( FUNCTION) VÀ LÊNH GÔP ( MACRO)
Tác dụng khi sử dụng chương trình con:
1) Trong khi viết chương trình, chúng ta thường gặp những đoạn chương trình được lặp đi lặp lại nhiều lần ở những chỗ khác nhau. Để tránh rườm rà, ta thay thế các đoạn này bằng chương trình con tương ứng và khi cần, ta chỉ việc gọi chương trình con đó ra( với các tham số tương ứng cần thiết) mà không cần viết lại cả khúc chương trình đó.
2) Một vấn đề lớn và phức tạp sẽ tương ứng với một chương trình có thể rất lớn và rất dài. Việc nhìn tổng quan cả chương trình cũng như việc gỡ rối, hiệu chỉnh sẽ rất khó khăn. Ta có thể phân tách vấn đề phức tạp thành các vấn đề nhỏ hơn ( tương ứng với các chương trình con, những khối, những modun) để dễ kiểm tra, gỡ rối từng khối một và sau đó ghép lại thành chương trình lớn. Việc lại dựa trên nguyên tắc “ chia để trị, chia để dễ điều khiển”.
Overloading functions: tạo thêm phương án mới cho hàm
Một ví dụ:
int ham_cua_toi ( int, int);
int ham_cua_toi ( long, long);
int ham_cua_toi ( long);
overloaded function có thể dịch là đa dạng hóa hàm, là định nghĩa thêm chức năng cho hàm. Overloaded function được hiểu là hàm nhiều phương án thực hiện, nhiều phương án tác chiến, để phân biệt với hàm đơn chỉ có duy nhất một tình huống thực hiện. Mỗi khi gọi đến tên hàm có nhiều phương án, chương trình dịch sẽ tìm đến phương án thực hiện thích hợp nhờ sự khác nhau giữa các dãy tham số.
Dùng hàm ( function ) hay macro?
Bên cạnh hàm, C/C++ còn có một loại giúp ta tránh khỏi sự rườm rà khi viết chương trình và tiết kiệm thời gian. Đó là macro.
Macro là tập hợp các lệnh và biểu thức được đại diện bằng 1 tên nào đó. Khi dịch, nếu C/C++ gặp các Macro này nó sẽ thay thế tên bằng tập hợp lệnh của nó.
#define tên_macro dãy _văn_ bản
Như vậy #define là chỉ dẫn đặt tên của C/C++
Điểm giống giữa macro và hàm:
Chỉ cần dùng tên hàm và tên macro là đã làm được nhiều việc. Do đó vừa tiết kiệm được thời gian, vừa tránh được sai sót , lại làm cho chương trình sáng sủa, dễ đọc, dễ nhìn…
Điểm khác:
1) Chương trình viết với macro sẽ dài hơn vì tên của macro là cả một tập hợp các lệnh. Gọi n lần thì cần n lần bộ nhớ của tập hợp các lệnh của macro. Trong khi đó dùng hàm thì chương trình sẽ bé hơn. Dùng n lần gọi hàm thì bộ nhớ cũng chỉ tương đương xấp xỉ 1 lần.
2) Chương trình chạy với macro sẽ chạy nhanh hơn một chút vì không phải mất thủ tục gọi hàm. Song đây không phải là ưu điểm mà bạn cần để ý.
3) Chỉ nên dùng macro với các cụm lệnh đơn giản. Nếu cụm lệnh macro dài quá thì kém tác dụng.
4) Macro được viết ra với sự thích nghi của các kiểu dữ liệu. Song macro không có tính đệ qui, không có tính modun hóa như hàm.
Một số hàm thông dụng:
Hàm tạo số ngẫu nhiên:
Hàm random ( num)
Là hàm tạo các số ngẫu nhiên nằm trong khoảng từ 0 tới num-1
Hàm rand() tạo số ngẫu nhiên nằm trong khoảng 0 đến 32767
Hàm randomize() tạo điểm xuất phát ngẫu nhiên cho các hàm rand() và random() nói trên.
//Example 9.18.cpp
#include<stdlib.h>
#include<iostream>
#include<time.h>
using namespace std;
// Output numbers random from 0 to 99
int main()
{
srand(time(0));
cout<<"Random number is from 0 to 99 : " << rand()%100
;
cout<< endl;
system("pause");
return 0;
}
Vấn đề sinh số ngẫu nhiên trong C++
I. Các thư viện liên quan đến vấn đề sinh số ngẫu nhiên
1. Thư viện stdlib.h
Thư viện này bao gồm các chức năng liên quan đến việc cấp phát, giải phóng bộ nhớ; Chuyển đổi các kiểu dữ liệu; Điều khiển tiến trình; Sắp xếp và tìm kiếm dữ liệu; Một số phép tính toán học.
Trong bài viết này, ta chỉ làm việc với 2 hàm rand() và srand() cùng với hằng số RAND_MAX trong thư viện stdlib.h
2. Thư viện time.h
Thư viện này cung cấp các hàm làm việc với thời gian.
Trong bài viết này, ta chỉ làm việc với 2 hàm time() và kiểu dữ liệu time_t trong thư viện time.h
II. Các hàm, hằng số và kiểu dữ liệu liên quan đến vấn đề sinh số ngẫu nhiên
1. Hằng số RAND_MAX (nằm trong thư viện stdlib.h)
Hằng số RAND_MAX là một hằng số nguyên, nó đại diện cho giá trị lớn nhất mà có thể được trả về từ hàm rand(). Giá trị của RAND_MAX = 7FFFH = 32767D
Để biết giá trị của RAND_MAX ta có thể sử dụng đoạn chương trình sau:
#include <stdlib.h>
#include <iostream.h>
void main()
{
cout << "Gia tri cua RAND_MAX la: " << RAND_MAX << endl;
}
2. Hàm rand() (nằm trong thư viện stdlib.h)
Cú pháp:
int rand();
Hàm rand() được sử dụng để sinh ra một số nguyên ngẫu nhiên nằm trong khoảng từ 0 đến RAND_MAX.
Ta sử dụng đoạn chương trình sau để sinh ra một số nguyên ngẫu nhiên nằm trong khoảng từ 0 đến RAND_MAX.
#include <stdlib.h>
#include <iostream.h>
int main()
{
int so_nguyen_ngau_nhien = rand();
cout << so_nguyen_ngau_nhien << endl;
}
Nhận xét: Ta nhận thấy là mỗi khi chạy lại chương trình ta đều nhận được một số nguyên giống nhau nằm trong khoảng từ 0 đến RAND_MAX. Để giải quyết vấn đề này ra sẽ phải sử dụng hàm srand() khi bắt đầu chạy chương trình (ta sẽ tìm hiểu hàm srand() ở phần dưới)
3. Kiểu dữ liệu time_t (nằm trong thư viện time.h)
Kiểu dữ liệu time_t được khai báo trong time.h như sau:
typedef long time_t;
Ta thấy rằng time_t là một số nguyên kiểu long và nó mô tả số giây đã trôi qua được tính từ điểm mốc là 0 giờ 0 phút 0 giây ngày mùng 1 tháng 1 năm 1970.
Ta sử dụng đoạn mã sau để biết khoảng thời gian từ 00:00:00 ngày 01/01/1970 đến thời điểm hiện tại là bao nhiêu giây:
#include <time.h>
#include <iostream.h>
void main()
{
time_t seconds;
time(&seconds);
cout << seconds << endl;
}
4. Hàm time() (nằm trong thư viện time.h)
Cú pháp:
time_t time (time_t *timer);
Hàm time() được sử dụng để lấy số giây tính từ 0 giờ 0 phút 0 giây ngày 1 tháng 1 năm 1970 cho đến thời điểm hiện tại.
Chú ý:
- Nếu con trỏ timer bằng NULL thì số giây sẽ được trả về cho hàm.
- Nếu con trỏ timer khác NULL thì số giây sẽ được trả về cho cả tham số là con trỏ timer và cả cho hàm.
Ta thấy đoạn mã dưới hai biến seconds, my_seconds và return_seconds đều có giá trị như nhau và giá trị đó thể hiện khoảng thời gian từ 00:00:00 ngày 01/01/1970 đến thời điểm hiện tại là bao nhiêu giây:
#include <time.h>
#include <iostream.h>
void main()
{
time_t seconds;
time_t my_seconds;
time_t return_seconds;
seconds = time(&my_seconds);
return_seconds = time(NULL);
cout << seconds << endl;
cout << my_seconds << endl;
cout << return_seconds << endl;
}
5. Hàm srand() (nằm trong thư viện stdlib.h)
Cú pháp:
void srand (unsigned int seed);
Hàm này được sử dụng để đặt điểm bắt đầu cho việc sinh số ngẫu nhiên của hàm rand(). Tham số seed chính là điểm bắt đầu để sinh số ngẫu nhiên.
Ta thấy rằng nếu dùng hàm rand() mà không sử dụng hàm srand() để đặt điểm bắt đầu thì mỗi lần chạy chương trình hàm rand() sẽ sinh ra các con số tương tự nhau. Để giải quyết vấn đề này ta sẽ đặt hàm srand() phía trên hàm rand() và thay đổi giá trị của tham số seed trong hàm srand() mỗi khi bắt đầu chạy chương trình. Việc thay đổi này, ta sẽ sử dụng giá trị trả về của hàm time() để làm giá trị cho seed bởi tại mỗi thời điểm thì giá trị trả về của hàm time() là khác nhau. Cách viết cụ thể như sau: srand ( (unsigned) time(NULL) );
Chú ý:
- Nếu seed = 1 thì kết quả số ngẫu nhiên do rand() sinh ra tương tự như không có hàm srand() ở phía trên.
- Nếu seed là một hằng số nguyên không đổi thì mỗi khi chạy chương trình, mặc dù có hàm srand() ở phía trên hàm rand() thì số ngẫu nhiên được sinh ra vẫn là một con số giống nhau (Điều này được giải thích bởi điểm bắt đầu vào chương trình do hàm srand() xác định là như nhau)
Đoạn chương trình sau sẽ sinh ra một số ngẫu nhiên trong khoảng từ 0 đến RAND_MAX và mỗi lần chạy lại thì chương trình sẽ không sinh ra các số giống nhau nữa.
#include <stdlib.h>
#include <time.h>
#include <iostream.h>
void main()
{
srand((unsigned)time(NULL)); //unsigned để xác định là số không dấu
int random_integer = rand();
cout << random_integer << endl;
}
III. Sinh số ngẫu nhiên trong một khoảng xác định trước
1. Sinh số nằm trong khoảng từ 0 cho đến n (với n <= RAND_MAX)
#include <stdlib.h>
#include <time.h>
#include <iostream.h>
void main()
{
int random_integer;
int n;
cout << "Nhap so n voi n nho hon RAND_MAX: "; cin >> n;
srand((unsigned)time(NULL));
for(int index=0; index<20; index++)
{
random_integer = (rand() % n)+1;
cout << random_integer << endl;
}
}
2. Sinh số nằm trong khoảng [a, b] (với 0 <= a <= b <= RAND_MAX)
#include <stdlib.h>
#include <time.h>
#include <iostream.h>
void main()
{
srand((unsigned)time(0));
int random_integer;
int a, b;
cout << "Nhap vao khoang [a, b]: "; cin >> a >> b;
int range=(b-a)+1;
for(int index=0; index<20; index++)
{
random_integer = a + int(range*rand()/(RAND_MAX + 1.0));
cout << random_integer << endl;
}
}
Các hàm thời gian
Đó là những hàm xác lập và đọc thời gian, xác lập và đọc ngày- tháng. Các hàm này nằm trong tệp <DOS.h>.
Ngày – tháng và thời gian được lưu trữ và vận hành nhờ một hệ thống đồng hồ và bộ nhớ thường trực trong máy. Vì vậy bạn có thể dùng nó như là một đồng hồ làm việc hàng ngày.
Tham khảo:
Ngôn ngữ lập trình C++ ( Quách Tuấn Ngọc)
Nguồn Internet: http://my.opera.com/laptrinhc/blog/sinh-sng-u-nhi-n
0 comments:
Post a Comment