Đặt vấn đề 1
Hãy nghiên cứu chương trình sau rồi trả lời các câu hỏi bên dưới. Chúng tôi muốn bạn trả lời các câu hỏi bằng cách chỉ xem mã nguồn, tức là vui lòng không sao chép mã này vào một tệp, hãy biên dịch tệp đó và trả lời các câu hỏi dựa trên việc chạy mã đó. Điều này sẽ khiến bạn mất đi niềm vui!
int main() { int counter, first, last, next; first = 1; last = 2; for (counter = first; counter <= last; counter++) { cout << "\n " << counter; next = counter * counter; cout << " " << next; } counter = first; while (counter <= last) { cout << "\n " << counter; next = counter * counter; cout << " " << next; counter++; } counter = first; do { cout << "\n " << counter; next = counter * counter; cout << " " << next; counter++; } while (counter < last); }
Câu hỏi 1: Kết quả của chương trình này là gì?
Đáp: |
1 2 2 4 1 2 2 4 1 2 2 4 |
T) |
1 1 2 4 1 1 2 4 1 1 2 4 |
C) |
1 1 2 4 1 1 2 4 1 1 |
D) |
1 1 2 4 1 1 1 1 2 4 |
Đ) | Quá trình này không xuất ra bất kỳ nội dung nào – có lỗi trong cú pháp. |
Câu hỏi 2: Điều gì sẽ xảy ra nếu chúng ta xoá khởi tạo "bộ đếm" trước vòng lặp do- while?
Đáp: | Vòng lặp vô hạn – vòng lặp do- while sẽ xuất ra một loạt |
T) | Kết quả của chương trình sẽ không thay đổi |
C) | Vòng lặp do- while cho ra kết quả là 2 và 4. |
D) | Vòng lặp do-time sẽ không cho ra kết quả nào |
Đ) | Vòng lặp do- while cho ra kết quả là 3 và 9. |
Câu hỏi 3: Với chương trình ban đầu ở đầu trang này, giả sử chúng ta có xoá dòng khởi tạo biến bộ đếm trước vòng lặp while. Mục tiêu sẽ xảy ra nếu chúng ta cũng xoá dòng counter++ bên trong vòng lặp while, như trong sau đây không?
Đáp: | Vòng lặp while không xuất ra kết quả nào. |
T) | Vòng lặp while cho ra 1 và 1; vòng lặp do-in không cho ra kết quả nào. |
C) | Đầu ra của vòng lặp while giống như khi cả hai dòng bao gồm. |
D) | Hệ thống sẽ cho ra các số ngẫu nhiên cho đến khi chúng ta bật máy tính tắt. |
Đ) | Vòng lặp while là một Vòng lặp vô hạn |
Câu hỏi 4: Với chương trình ban đầu ở đầu trang này, điều gì sẽ xảy ra liệu vòng lặp while có dạng như thế này không?
counter = first; while (counter <= last) { cout << "\n" << counter; if (first % 2 == 0) next = counter * counter; cout << " " << next; counter++; }
Đáp: | Kết quả của vòng lặp while giống như trong chương trình gốc. |
T) | Vòng lặp when sẽ không tạo ra kết quả nào |
C) | Đầu ra của vòng lặp while là 1 1 và 1 4. |
D) | Đầu ra của vòng lặp while là 1 2 và 2 4. |
Đ) | Đầu ra của vòng lặp while là 1 4 và 2 4. |
Nữ) | Đầu ra của vòng lặp while là 2 4 và 2 4. |
Câu hỏi 5: Điều gì sẽ xảy ra nếu biến đầu tiên lớn hơn biến cuối cùng?
Đáp: | Vòng lặp while sẽ tạo ra nội dung nào đó nhưng không có nội dung nào khác. |
T) | Vòng lặp while sẽ cho ra nội dung nào đó, nhưng không có nội dung nào khác. |
C) | Sẽ không có dữ liệu đầu ra nào. |
D) | Chương trình sẽ phân loại lỗi hoặc sự cố |
Đ) | Vòng lặp for sẽ tạo ra nội dung nào đó, nhưng không có nội dung nào khác. |
Câu hỏi 6: Chương trình sẽ cho ra kết quả gì nếu khởi tạo biến đầu tiên giống với biến cuối cùng?
Đáp: | Vòng lặp while sẽ cho ra nội dung nào đó, nhưng không có nội dung nào khác. |
T) | Vòng lặp while sẽ tạo ra nội dung nào đó nhưng không có nội dung nào khác. |
C) | Mỗi vòng lặp sẽ cho ra một dòng. |
D) | Vòng lặp do while sẽ xuất ra 2 dòng và vòng lặp còn lại sẽ là một dòng. |
Đ) | Không trả về kết quả nào |
Nữ) | Vòng lặp for sẽ tạo ra nội dung nào đó, nhưng không có nội dung nào khác. |
Đặt vấn đề 2
Như trong phần đặt vấn đề trước, sau đây là một chương trình để bạn xem xét. Vui lòng trả lời các câu hỏi tiếp theo bằng cách chỉ xem mã nguồn.
#include <iostream> using namespace std; int main() { int Boys = 3, Girls = 5; void F1(int males, int females); void F2(int &m, int &f); F1(Boys, Girls); cout << "\nAfter calling F1, within main()"; cout << "\n\tBoys = " << Boys; // #2 cout << "\n\tGirls = " << Girls; F2(Boys, Girls); cout << "\nAfter calling F2, within main()"; cout << "\n\tBoys = " << Boys; // #4 cout << "\n\tGirls = " << Girls; } void F1(int b, int g) { b += 3, g += 4; cout << "\nF1"; cout << "\n\tBoys = " << b; // #1 cout << "\n\tGirls = " << g; } void F2(int &b, int &g) { b = b + 8, g = g + 5; cout << "\nF2"; cout << "\n\tBoys = " << b; // #3 cout << "\n\tGirls = " << g; }
Câu hỏi 1: Đầu ra của biến Boys trên các đường được đánh dấu là gì?
Đáp: |
Số 1: 6 Số 2: 3 Số 3: 11 Số 4: 11 |
T) |
Số 1: 6 Số 2: 3 Số 3: 11 Số 4: 3 |
C) |
Số 1: 6 Số 2: 6 Số 3: 11 Số 4: 11 |
D) | Hàm này không tạo ra kết quả nào vì không biên dịch hoặc chạy. |
Câu 2: Chọn tất cả câu trả lời phù hợp với các dòng sau của chương trình:
void F1(int males, int females); void F2(int &m, int &f);
Đáp: | Quy tắc C++ nêu rõ rằng chúng ta có thể xoá hai dòng này miễn là các phương thức được xác định trước khi sử dụng. |
T) | Quy tắc C++ nêu rõ rằng tên đối số phải giống nhau giữa phần khai báo và định nghĩa. |
C) | Chương trình này sẽ gặp sự cố nếu chúng tôi xoá hai dòng này. |
D) | Thông thường, việc khai báo được khai báo trong ngôn ngữ chung phạm vi. |
Đ) | Đây được gọi là nội dung khai báo chuyển tiếp. |
Câu hỏi 3: Nếu chúng ta di chuyển dòng sau từ main() và đặt nó trong lệnh điều gì sẽ xảy ra?
int Boys = 3, Girls = 5;
Đáp: | Kết quả sẽ tương tự. |
T) | Con trai sẽ = 3 và con gái sẽ = 5 trong tất cả kết quả |
C) | Con trai sẽ = 3 và Con gái sẽ chỉ = 5 trong kết quả từ main() |
Câu hỏi 4: Nếu chúng ta thay đổi phần đầu của chương trình thành như sau:
// We have moved moved these to global scope const int Boys = 3; const int Girls = 5; void main() { //int Boys = 3, Girls = 5;
Đáp: | Chương trình này sẽ biên dịch được nhưng sẽ gặp sự cố khi chúng ta thử chạy. |
T) | Kết quả đầu ra sẽ không thay đổi |
C) | Kết quả sẽ là Con trai = 3 Cô gái = 5 trong suốt chương trình |
D) | Đầu ra sẽ là Con trai = 3 Cô gái = 5 chỉ trong đầu ra từ main() |
Đ) | Chương trình có thể sẽ không biên dịch (tuỳ thuộc vào trình biên dịch). |
Câu 5: Dữ liệu được truyền theo giá trị trong F2.
Đáp: | Đúng. |
T) | Sai. |
Đặt vấn đề 3
Như trong phần đặt vấn đề trước, sau đây là một chương trình để bạn xem xét. Năn nỉ trả lời các câu hỏi tiếp theo bằng cách chỉ xem mã nguồn.Câu hỏi này là thú vị hơn hai phần trước - hãy theo dõi mã cẩn thận.
#include <iostream> using namespace std; const int MAX_SIZE = 20; typedef int ARR2D[MAX_SIZE][MAX_SIZE]; void Print(ARR2D in_array, int rows, int cols); void Fill(ARR2D in_array, int rows, int cols); int main() { ARR2D matrix; int row, col; do { cout << "Please enter the size of the matrix to generate (rows and cols) :" << endl; cin >> row >> col; } while (row <= 0 || row > MAX_SIZE || col <= 0 || col > MAX_SIZE); Fill(matrix, row, col); Print(matrix, row, col); return(0); } void Print(ARR2D in_array, int rows, int cols) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) cout << '\t' << in_array[i][j]; cout << endl; } } void Fill(ARR2D in_array, int rows, int cols) { for(int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) in_array[i][j] = 0; const int limit = rows * cols; int cNum = 1; int cRow = 0; int cCol = 0; int cDir = 0; // 0-north, 1-east, 2-south, 3-west while(true) { // Place the number. in_array[cRow][cCol] = cNum; cNum++; if (cNum > limit) break; int fRow = cRow; int fCol = cCol; while (true) { fRow = cRow; fCol = cCol; switch(cDir) { case 0: fRow--; break; case 1: fCol++; break; case 2: fRow++; break; case 3: fCol--; break; } if ( fRow >= 0 && fRow < rows && fCol >= 0 && fCol < cols && in_array[fRow][fCol] == 0) break; cDir = (cDir + 1) % 4; } cRow = fRow; cCol = fCol; } }
Câu hỏi 1: Chương trình này xuất ra gì với đầu vào là 3 cho các hàng và 4 cho các hàng của bạn?
Đáp: |
1 2 3 4 5 6 7 8 9 10 11 12 |
T) |
1 2 3 4 5 6 7 8 9 10 11 12 |
C) |
12 11 10 9 8 7 6 5 4 3 2 1 |
D) |
1 3 2 4 8 6 7 5 9 11 10 12 |
Đ) |
1 2 3 4 10 11 12 5 9 8 7 6 |
T) |
9 8 7 6 10 11 12 5 1 2 3 4 |
Cao) | Quá trình này không đưa ra bất kỳ kết quả nào – logic bị lỗi. |
I) | Quá trình này không xuất ra bất kỳ nội dung nào – có lỗi cú pháp. |
J) | Không được xuất dữ liệu nào. |
N) | Hàm này cho ra 12 số đầu tiên mà bạn nghĩ khi đang chờ chương trình chạy. |
Câu hỏi 2: Điều gì xảy ra nếu chúng ta thêm dòng sau vào hàm main()?
MAX_SIZE = 10;
Đáp: | Điều này không được phép trong C++. |
T) | Điều này được phép; chương trình sẽ chạy với MAX_SIZE được đặt thành 20 |
C) | Điều này được phép; chương trình sẽ chạy với MAX_SIZE được đặt thành 10. |
Câu hỏi 3: Hãy xem xét bốn dòng sau trong chương trình trên:
const int MAX_SIZE = 20; typedef int ARR2D [MAX_SIZE][MAX_SIZE]; void Print (ARR2D A, int rows, int cols); void Fill (ARR2D A, int rows, int cols);
1) Có thể sử dụng const trong typedef không?
2) Có thể sử dụng typedef trong phần khai báo trước khi một biến được khai báo thuộc loại đó không?
Đáp: | 1) Có 2) Có |
T) | 1) Không 2) Không |
C) | 1) Không 2) Có |
D) | 1) Có 2) Không |
Câu hỏi 4: Chúng ta có thể sử dụng:
#define MAX_SIZE 20
const int MAX_SIZE = 20;
Đáp: | Đúng, mã này sẽ hoạt động và bạn cũng có thể sử dụng #define cho các hằng số trong C++ |
T) | Đúng, mã này sẽ hoạt động nhưng chúng ta thường không sử dụng #define cho hằng số trong C++ |
C) | #define không có sẵn trong C++ |
D) | Bạn không thể thực hiện một trong những thao tác sau trong C |
Câu hỏi 5: typedef được dùng để tạo bí danh cho tên loại.
Đáp: | Đúng. |
T) | Sai. |
Câu hỏi 6: Điều gì sẽ xảy ra nếu chúng ta không khởi tạo mảng bằng 0 trong hàm Fill()?
Đáp: | Đoạn mã sẽ chạy nhưng kết quả sẽ là toàn bộ 12 |
T) | Hàm này sẽ chạy tốt và tạo ra kết quả tương tự như thể mảng đã khởi tạo về 0 |
C) | Chương trình sẽ không chạy hoặc sẽ gặp sự cố |
D) | Chương trình sẽ chạy nhưng kết quả đầu ra sẽ toàn là 0 |
Đ) | Hàm này sẽ chạy nhưng có thể không tạo ra bất kỳ đầu ra nào |
Câu hỏi 7: Chọn tất cả các câu trả lời đúng. Tại sao chúng ta sử dụng const cho MAX_SIZE trong chương trình này? Nhập "20" sẽ không dễ hơn à thay vì MAX_SIZE cho dù ở bất cứ đâu cần thiết không?
Đáp: | MAX_SIZE là giá trị C++ tích hợp sẵn mà bất cứ ai cũng có thể sử dụng. Chỉ đặt và sử dụng nó. |
T) | Bạn nên tránh sử dụng bao hàm toàn cục giống như biến toàn cục |
C) | Việc dùng hằng số giúp chương trình của chúng tôi dễ hiểu hơn |
D) | Số ma thuật trong một chương trình thường được xem là phương pháp hay. |
Đ) | Nếu muốn thay đổi MAX_SIZE, chúng ta chỉ cần thay đổi trong một địa điểm |
Câu hỏi 8: Câu lệnh chuyển đổi trong hàm Fill() nên có giá trị mặc định vì đây được xem là kiểu phù hợp để đưa vào.
Đáp: | Đúng. |
T) | Sai. |
Câu 9: Lưu ý trong hàm Fill(), chúng ta khai báo các biến ở giữa các câu lệnh. Ví dụ: cNum và cRow được khai báo và khởi tạo sau khi một vòng lặp for chạy. Điều này sẽ hoạt động trong C++ hay làm tất cả các biến phải được khai báo ở đầu hàm không?
Đáp: | Bạn có thể làm việc này. |
T) | Bạn phải khai báo tất cả biến ở đầu hàm. |
C) | Cả hai cách đều sai – C++ không cho phép biến ở bất kỳ đâu trong một . |
D) | Bạn phải khai báo tất cả biến trong phạm vi toàn cục. |
Đặt vấn đề 4
Dưới đây là một tập hợp các tệp xác định và kiểm thử một lớp đơn giản. Như thường lệ, hãy trả lời các câu hỏi tiếp theo bằng cách chỉ tham chiếu đến mã nguồn.
Đây là tệp tiêu đề (cow.h):
#ifndef COW_H #define COW_H using namespace std; typedef enum Color {black, brown, beige, blackandwhite, nocolor}; class Cow { public: Cow(); ~Cow(); // accessors double weight() { return weight_; }; string name() { return name_; }; Color color() { return color_; }; // mutators void set_name(string inName) { name_ = inName; }; void set_color(Color inColor) { color_ = inColor; }; void set_weight(double inWeight) {weight_ = inWeight; }; void Moo(); void Properties(); private: Color color_; double weight_; string name_; }; #endif
Dưới đây là tệp .cc được liên kết (cow.cc):
#include <iostream> #include "cow.h" using namespace std; Cow::Cow() {} Cow::~Cow() {} void Cow::Moo() { cout << name() << " says MOO." << endl; } void Cow::Properties() { cout << name() << " weighs " << weight() << ", is " << color() << " and says MOO." << endl; }
Và đây là một chương trình ứng dụng cho lớp này (cowmain.cc):
#include <iostream> #include "cow.h" using namespace std; int main() { Cow cow1; cow1.set_name("betsy"); cow1.set_weight(400.0); cow1.set_color(black); cow1.Moo(); cow1.Properties(); }
Câu hỏi 1: Chương trình này cung cấp gì?
Đáp: | betsy nói MOO. betsy nặng 400, là 0 và nói MOO. |
T) | betsy nói MOO. betsy nặng 400, là màu đen và nói MOO. |
C) | betsy nói MOO. Betsy nặng 400, là |
Câu hỏi 2: Chúng ta không bao giờ nên đặt mã cho phương thức truy cập và biến đổi trong tệp tiêu đề. (Lưu ý rằng trình truy cập là một phương thức trả về một giá trị và một biến thể là phương thức sửa đổi một giá trị).
Đáp: | Đúng. |
T) | Sai. |
Câu hỏi 3: Chúng ta có cần hàm "Bò::" trước mỗi định nghĩa hàm trong cow.cc?
Đáp: | Không, vì có cow.h |
T) | Có |
Câu hỏi 4: Vai trò của bạn:
#ifndef COW_H #define COW_H ... #endif
phát trong tệp tiêu đề?
Hãy chọn tất cả câu trả lời phù hợp:
Đáp: | Các tệp này không phục vụ mục đích nào vì tên của tệp là cow.h chứ không phải COW_H. |
T) | Nếu không làm điều này, chúng tôi sẽ gặp lỗi thời gian chạy |
C) | Nếu chúng tôi không thực hiện việc này, chúng tôi có thể bao gồm tệp nhiều lần |
D) | Chúng không làm gì cả vì một hoặc nhiều từ khoá bị viết sai chính tả. |
Đ) | Chúng không làm gì cả vì lớp Cow chỉ có một tệp tiêu đề. |
Câu hỏi 5: Điều gì sẽ xảy ra nếu chúng ta thêm dòng sau vào cowmain.cc?
cow1.weight_ = 24;
Đáp: | Chương trình sẽ chạy và biến trọng số sẽ được sửa đổi theo dòng này. |
T) | Chương trình sẽ biên dịch và chạy được nhưng sẽ gặp sự cố trên dòng đó. |
C) | C++ không cho phép điều này. |
D) | Chương trình sẽ biên dịch và chạy nhưng biến trọng số thì không bị thay đổi bởi dòng này. |
Câu hỏi 6: Khi dòng sau được thực thi, hàm khởi tạo trong lớp Cow được gọi:
Cow cow1;
Một số đặc điểm quan trọng của hàm khởi tạo là gì?
Chọn tất cả các câu trả lời phù hợp
Đáp: | Các hàm này thường không trả về giá trị nào |
T) | Nếu không cung cấp hàm khởi tạo trong lớp, lớp này sẽ không biên dịch |
C) | Hàm khởi tạo trong lớp Cow không điển hình vì chưa khởi chạy các biến riêng tư. |
D) | Các lớp này luôn trùng tên với lớp |
Đ) | Chúng ta có thể có một số hàm dựng trong một lớp miễn là các đối số khác nhau |
Nữ) | Một hàm khởi tạo được gọi khi một lớp được tạo sẵn. |
Câu hỏi 7: Một số đặc điểm quan trọng của hàm huỷ là gì?
Đáp: | Hàm huỷ được gọi khi một đối tượng nằm ngoài phạm vi |
T) | Hàm khởi tạo có cùng tên với lớp nhưng đứng sau "~" |
C) | Có vấn đề về hàm khởi tạo trong cow.cc không làm gì cả. |
D) | Nếu chúng ta không tạo một hàm huỷ cho lớp của mình, lớp này sẽ không biên dịch |
Câu hỏi 8: Với cách thức mà chương trình khách hàng đang sử dụng lớp này, hãy cân nhắc sau:
Việc phân chia thành viên thành công và tư trong tầng lớp Bò là không phù hợp. Điều đó có nghĩa là nội dung riêng tư nên được công khai hoặc nội dung công khai nên được đặt ở chế độ riêng tư.
Đáp: | Đúng. |
T) | Sai. |
Câu hỏi 9: Điều gì sẽ xảy ra nếu chúng ta thêm một hàm dựng khác ngoài hàm khởi tạo đó chúng tôi phải cow.cc. Hàm khởi tạo mới sẽ có dạng như sau
Cow::Cow(string inName, double inWeight, Color inColor) { set_name(inName); set_weight(inWeight); set_color(inColor); }
Và chúng ta thêm các dòng sau vào main():
Cow cow2("milly", 350.2, brown); cow2.Moo(); cow2.Properties();
Chúng tôi có thể làm việc này không?
Chọn tất cả các câu trả lời phù hợp
Đáp: | Dòng trong main() nơi chúng ta khởi tạo cow2 sẽ gặp sự cố. |
T) | Chúng ta chỉ có thể có một hàm khởi tạo. |
C) | Điều này thường xảy ra trong C++ |
D) | Có, nhưng đây không phải là cách sử dụng C++ thông thường |
Đ) | Thao tác này sẽ chạy bình thường, nhưng sẽ không xuất ra kết quả nào vì privates chưa được khởi tạo. |
Nữ) | Chúng ta không thể gọi setName(), setColor() và setWeight() từ bên trong một phương thức của cùng một lớp. |
Câu hỏi bổ sung
Câu hỏi 1) Kết quả sau đây là gì?
#include <iostream> using namespace std; void HelpMe(int *p, int *num, int *q); void WhereAmI(int *p, int *q, int a); void HelpMe(int *p, int *num, int *q) { int a; a = 2; q = &a; *p = *q + *num; num = p; } void WhereAmI(int *p, int *q, int a) { a = 6; *p = a + *p; *q = a + 3; HelpMe(q, &a, p); } int main() { int *p; int q; int *num; int a; a = 3; q = 5; p = &a; num = &q; HelpMe(&a, p, num); WhereAmI(&q, p, *num); cout << "*p = " << *p << " q = " << q << " *num = " << *num << endl; }
Câu 2) Hãy xem xét câu lệnh sau, giả sử một lớp Apple tồn tại và đã được khởi tạo. Lớp Apple có một biến thực thể color_:
Apple* granny_smith = new Apple;
Chọn tất cả các câu dưới đây là đúng:
Đáp: | Apple* granny_smith = NULL; if (granny_smith == NULL)... Điều này KHÔNG được - NULL không phải là một giá trị có thể được kiểm tra theo cách này. |
T) | Apple* granny_smith, fuji; Thao tác này khai báo hai con trỏ đến đối tượng Apple |
C) | Biến granny_smith chứa các giá trị của biến thực thể được liên kết với một đối tượng Apple |
D) | Apple* granny_smith = NULL; Không sao, |
Đ) | Biến granny_smith chứa địa chỉ của đối tượng Apple |
Nữ) | chuỗi gs_color = *(granny_smith.get_color(); Câu lệnh này trả về màu của đối tượng granny_smith, giả sử đối tượng này đã được khởi tạo. |
T) | Bộ nhớ cho đối tượng Apple mới được phân bổ trong vùng nhớ khối xếp |
Cao) | Bộ nhớ cho đối tượng Apple mới được phân bổ trên ngăn xếp thời gian chạy |
I) | int* a = &b; Thao tác này sẽ đặt địa chỉ của b vào a. |
Câu 3) Kết quả của chương trình sau là gì?
#include <iostream> using namespace std; const int kNumVeggies = 4; void Grill(int squash, int *mushroom); int Saute(int onions[], int celery); void Grill(int squash, int *mushroom) { *mushroom = squash/4; cout << *mushroom + squash << endl; } int Saute(int onions[], int celery) { celery *= 2; onions[celery]++; Grill(onions[0], &onions[3]); cout << celery << " " << onions[3] << endl; return celery; } int main() { int broccoli, peppers[kNumVeggies], *zucchini; for (broccoli = 0; broccoli < kNumVeggies; broccoli++) peppers[broccoli] = kNumVeggies - broccoli; zucchini = &peppers[Saute(peppers,1)]; Grill(*zucchini, zucchini); zucchini--; cout << peppers[3] + *zucchini + *(zucchini + 1) << endl; }
Câu trả lời đố vui
Bạn nên cố gắng hoàn thành tất cả các câu hỏi trên mà không xem câu trả lời. Bạn nên nhờ người khác trợ giúp thay vì chuyển thẳng đến trang đáp án để được trợ giúp.
Bạn có thể xem câu trả lời cho các vấn đề trên tại đây.