Bài tập tổng hợp Kỹ thuật lập trình C/C++ cơ bản dành cho sinh viên cao đẳng/đại học thuộc các khối trường về Công nghệ thông tin.
Đề bài:
Khi chạy chương trình, in ra menu như sau:
1) In ra n số chẵn đầu tiên.
2) In ra n số lẻ đầu tiên.
3) In ra n số nguyên tố đầu tiên.
4) In ra n số đầu tiên chia hết cho một số m bất kỳ (số m được nhập từ bàn phím).
5) Chuyển đổi số x dương thập phân sang nhị phân.
6) Nhập vào 2 số a và b. Tìm USCLN và BSCNN của 2 số đó.
7) Thoát chương trình.
▸Số nguyên tố là số chỉ chia hết cho 1 và chính nó (không bao gồm số 0 và số 1).
▸Số n được nhập từ bàn phím.
▸Người dùng nhập một số từ 1 đến 7 để thực hiện các chức năng của chương trình. Nếu nhập một số khác ngoài các số trong menu thì báo lỗi và yêu cầu người dùng nhập lại.
▸Sau khi thực hiện xong một chức năng thì in lại menu để người dùng chọn tiếp.
▸Khi chọn Thoát chương trình, hỏi lại người dùng có thực sự muốn thoát hay không, nếu người dùng bấm phím "Y" thì thoát chương trình, bấm phím "N" thì không thoát, in lại menu.
▸Mỗi chức năng là 1 hàm riêng biệt, với tham số nhận vào là n. Ví dụ: lietKeSoNguyenTo(int n).
Dạng bài tập này chính yếu là sẽ giúp cho các bạn có tư duy lập trình cơ bản về cách xử lý các luồng đi của chương trình và cách tổ chức, sử dụng hàm.
Demo các chức năng của chương trình
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
Bài giải
Để giải được bài này chúng ta cần phải xác định những việc quan trọng cần thực hiện như sau:
▸Menu người dùng. Menu sẽ được in ra khi người dùng lần đầu chạy chương trình, khi người dùng chạy xong một chức năng, hoặc khi người dùng chọn Thoát chương trình nhưng lại đổi ý. Dễ thấy việc in menu ở đây là một công việc lặp lại có điều kiện, vậy rõ ràng chúng ta cần sử dụng vòng lặp ở đây, cụ thể là vòng lặp do-while.
▸Tại sao lại là do-while mà không phải là while-do? Đó là bởi vì chúng ta sẽ cần in ra menu ít nhất 1 lần cho người dùng xem và chọn trước khi xét tới điều kiện để in tiếp. Vậy nên do-while là hợp lý hơn trong trường hợp này.
▸Do in menu là một công việc lặp lại, vậy nên chúng ta cần phải xây dưng riêng một hàm cho việc này. Hàm này không nhận vào tham số nào, nhưng sẽ trả về một số nguyên là chức năng mà người dùng chọn. Trong trường hợp người dùng cố tình nhập vào một số không có trong menu hoặc những ký tự không phải số, chúng ta sẽ luôn trả về -1.
▸Các hàm cụ thể cho mỗi chức năng. Ở đây chúng ta có 6 chức năng chính sẽ tương đương với 6 hàm khác nhau.
...
using namespace std;
...
int printMenu() {
// xoa man hinh
system("cls");
cout << "+-------------------+" << endl;
cout << "| Bai tap KTLT so 1 |" << endl;
cout << "+-------------------+" << endl;
cout << "1. In ra n so chan dau tien" << endl;
cout << "2. In ra n so le dau tien" << endl;
cout << "3. In ra n so nguyen to dau tien" << endl;
cout << "4. In ra n so dau tien chia het cho mot so m bat ky" << endl;
cout << "5. Chuyen doi so thap phan sang nhi phan" << endl;
cout << "6. Tim USCLN, BSCNN cua a va b" << endl;
cout << "7. Exit" << endl;
cout << "Chon chuc nang: ";
// make sure only input numbers
// hàm getInputNumber() là hàm tự viết
int myNumber = getInputNumber();
if (myNumber < 1 || myNumber > 7) {
return -1;
}
return myNumber;
}
int main(int argc, char** argv) {
int number = -1;
int a, b, m, n;
bool quit = false;
do {
number = printMenu();
if (number == -1) {
cout << "Ban da nhap vao mot so khong hop le!!!" << endl;
cin.get(); // tam dung chuong trinh
} else {
quit = true;
}
} while (!quit);
return 0;
}
▸Các bạn có thể copy toàn bộ đoạn mã trên và chạy thử trong Dev-C++ 5.11. Đoạn mã trên cơ bản đã giải quyết được vấn đề xử lý menu của chúng ta. Khi chạy, các bạn có thể thử nhập sai, khi đó menu sẽ được in lại liên tục cho đến khi nào bạn nhập đúng thì thôi. Lúc này chương trình sẽ thoát.
▸Như đã thấy trong hàm main(), chúng ta sử dụng biến number để đón nhận giá trị trả về khi người dùng nhập menu. Tiếp theo, chúng ta cần xử lý giá trị này để điều hướng người dùng tới những chức năng cụ thể. Với dạng điều hướng chức năng theo điều kiện như thế này, dễ thấy chúng ta sẽ sử dụng switch-case.
...
int main(int argc, char** argv) {
int number = -1;
int m, n;
bool quit = false;
do {
number = printMenu();
if (number == -1) {
cout << "Ban da nhap vao mot so khong hop le!!!" << endl;
cin.get(); // tam dung chuong trinh
}
system("cls");
switch(number) {
case 1:
// in n so chan
break;
case 2:
// in n so le
break;
case 3:
// in n so nguyen to dau tien
break;
case 4:
// in ra n so dau tien chia het cho mot so m bat ky
break;
case 5:
// chuyen so thap phan sang nhi phan
break;
case 6:
// uoc so chung lon nhat
// boi so chung nho nhat
break;
case 7:
cout << "Chao tam biet!!!";
quit = true;
break;
}
} while (!quit);
return 0;
}
...
▸Cách cài đặt switch-case về cơ bản là như trên. Đến lúc này thì phần xử lý các luồng chính của chương trình về cơ bản đã xong, chỉ cần tập trung vào việc xử lý logic cụ thể của từng chức năng là xong.
▸Tất nhiên, tôi sẽ không giải hết tất cả các bài tập nhỏ cho các bạn. Tôi sẽ chỉ giải ví dụ 2 bài in số chẵn, lẻ bên dưới mà thôi.
▸Để xem đầy đủ bài giải và mã nguồn, vui lòng kéo xuống cuối bài viết.
In ra n số chẵn, lẻ đầu tiên:
▸Ví dụ chúng ta nhập vào n = 7 thì sẽ in ra màn hình "2 4 6 8 10 12 14".
▸Cái này thì quá dễ rồi, khỏi phải giải thích nhé:
...
// in n so chan
void printEvenNumbers(int n) {
cout << "In ra " << n << " so chan dau tien" << endl;
int count = 0;
int i = 0;
do {
if (i % 2 == 0) {
cout << i << " ";
count++;
}
i++;
} while (count < n);
}
// in n so le
void printOddNumbers(int n) {
cout << "In ra " << n << " so le dau tien" << endl;
int count = 0;
int i = 0;
do {
if (i % 2 != 0) {
cout << i << " ";
count++;
}
i++;
} while (count < n);
}
...