Danh sách câu hỏi của đề

Câu hỏi: PRF192 Cơ sở lập trình – Đề thi cuối kỳ SU26

50 câu trắc nghiệm kèm lời giải của môn PRF192 - Cơ sở lập trình, xếp đúng thứ tự trong đề. Trang 2/3 — câu 21–40.

Danh sách câu hỏi

40/50 câuCòn 10
AIt is used to decide whether the part of the code will be executed or not based on the specified condition.
BIt allows you to repeat a block of code a specified number of times.
CIt is used to define a function in a programming language.
DIt is used to declare variables and assign values to them.
Lời giải
Đáp án đúng: "It is used to decide whether the part of the code will be executed or not based on the specified condition." Cấu trúc if tính giá trị biểu thức điều kiện, coi khác không là đúng, rồi chạy nhánh tương ứng, nhờ đó một khối mã có chạy hay không phụ thuộc dữ liệu lúc chạy. Cần nhớ nhánh không bọc ngoặc nhọn chỉ ôm đúng một lệnh, nên lệnh viết sau đó nằm ngoài nhánh dù được thụt vào. Câu "It allows you to repeat a block of code a specified number of times." là việc của vòng lặp; if không bao giờ quay lại chạy khối lần nữa. Câu "It is used to define a function in a programming language." sai vì định nghĩa hàm cần kiểu trả về, tên hàm và danh sách tham số. Câu "It is used to declare variables and assign values to them." là việc của câu khai báo và phép gán, hai thứ độc lập với điều kiện.
Mở trang câu hỏi này →
ATo execute a block of codes repeatedly as long as a specified condition is true.
BTo perform mathematical calculations.
CTo define variables within a program.
DTo execute a statement based on a condition
Lời giải
Đáp án đúng: "To execute a block of codes repeatedly as long as a specified condition is true." Vòng lặp trong C gồm một điều kiện và một thân; mỗi nhịp kiểm điều kiện rồi chạy thân, nên cùng một đoạn mã được dùng lại nhiều lần với dữ liệu khác nhau, và dừng khi điều kiện hết đúng. Thân là cả khối nếu bọc ngoặc nhọn, còn không thì chỉ gồm đúng một lệnh. Câu "To perform mathematical calculations." sai vì phép tính là việc của toán tử và hàm thư viện, thân vòng lặp có thể chẳng có phép tính nào. Câu "To define variables within a program." là việc của câu khai báo; phần khởi tạo của for có thể khai báo biến đếm nhưng đó không phải mục đích của vòng lặp. Câu "To execute a statement based on a condition" mô tả if: chạy hay không chạy một lần, thiếu hẳn ý lặp lại.
Mở trang câu hỏi này →
A(condition) ? True_Value : False_Value
Bfor ( InitBlock; Condition; Task2) Task1;
Cdo{ statements;} while (condition) ;
Dwhile (condition){ statements; }
Lời giải

Đáp án đúng: "(condition) ? True_Value : False_Value". Đây là toán tử điều kiện ba toán hạng: nó tính điều kiện rồi cho ra một trong hai giá trị, tức là một biểu thức trả về giá trị, chạy đúng một lần và không có cơ chế quay lại, nên không phải cấu trúc lặp. Dạng "for ( InitBlock; Condition; Task2) Task1; " là for chuẩn với ba phần khởi tạo, điều kiện, cập nhật, còn thân chỉ là một lệnh nên không cần ngoặc nhọn. Dạng "do{ statements;} while (condition) ; " là do while, chạy thân trước rồi mới kiểm điều kiện nên thân luôn chạy ít nhất một lần, và dấu chấm phẩy cuối là bắt buộc. Dạng "

Lời giải
while (condition){
  statements;
}

" là while chuẩn, kiểm điều kiện trước mỗi nhịp. Ba dạng này đều lặp được, chỉ toán tử điều kiện là không.

Mở trang câu hỏi này →
Đề bài
#include<stdio.h>

int main()
{
    char i, j;
    for (i = 'A'; i <= 'E'; i++)
    {
        for (j = 'A'; j <= i; j++)
        {
            printf("%c", i);
        }
        printf("\n");
    }
    return 0;
}
AA BB CCC DDDD EEEEE
BAAAAA BBBB CCC DD E
CA AB ABC ABCD ABCDE
DA AA AAA AAAA AAAAA
Lời giải
Đáp án đúng: "A BB CCC DDDD EEEEE". Vòng ngoài cho i chạy từ ký tự A tới E; với mỗi i, vòng trong cho j chạy từ A tới i nên số lượt đúng bằng thứ tự của i trong bảng mã, và thân vòng trong luôn in i chứ không in j. Vì thế dòng đầu có một ký tự A, dòng sau hai ký tự B, rồi ba ký tự C, bốn ký tự D, năm ký tự E; lệnh xuống dòng nằm trong vòng ngoài nên mỗi giá trị của i xuống dòng một lần. «AAAAA BBBB CCC DD E» sai vì số ký tự mỗi dòng phải tăng dần theo i, lại thêm khoảng trắng thụt đầu dòng mà mã không hề in. "A AB ABC ABCD ABCDE" là kết quả nếu thân vòng trong in j; ở đây in i nên các ký tự trên cùng một dòng giống nhau. "A AA AAA AAAA AAAAA" là kết quả nếu luôn in một ký tự cố định, nhưng ký tự in ra đổi theo i.
Mở trang câu hỏi này →
AThe loop exits immediately.
BThe loop continues with the next iteration and skips the remaining statements.
CThe program terminates completely, and all variables are destroyed.
DNothing happens; the break statement is completely ignored in for loops
Lời giải
Đáp án đúng: "The loop exits immediately." Lệnh break chuyển điều khiển ra ngay lệnh đầu tiên sau thân vòng lặp, bỏ luôn phần còn lại của lượt hiện tại và không chạy bước cập nhật biến đếm nữa; đó là cách thoát sớm khi đã tìm được thứ cần tìm, chỉ thoát một cấp vòng lặp gần nhất. "The loop continues with the next iteration and skips the remaining statements." là mô tả của continue, một lệnh khác: continue bỏ phần còn lại của lượt rồi quay về bước cập nhật và kiểm tra điều kiện. "The program terminates completely, and all variables are destroyed." sai vì kết thúc chương trình là việc của return trong main hoặc hàm exit. "Nothing happens; the break statement is completely ignored in for loops" sai vì break có hiệu lực giống nhau trong for, while, do while và switch.
Mở trang câu hỏi này →
AA module performs a single, specific task.
BA module performs multiple unrelated tasks.
CA module shares data with many other modules
DA module can be used in multiple programs.
Lời giải
Đáp án đúng: "A module performs a single, specific task." Kết dính cao nghĩa là mọi phần bên trong một mô đun cùng phục vụ một nhiệm vụ rõ ràng; nhờ vậy mô đun dễ đặt tên, dễ kiểm thử riêng, và khi yêu cầu đổi thì chỉ phải chạm một chỗ. "A module performs multiple unrelated tasks." tả đúng tình trạng kết dính thấp, thứ cần tránh, vì sửa một việc dễ làm vỡ việc khác nằm chung mô đun. "A module shares data with many other modules" nói về mức liên kết giữa các mô đun, lại theo chiều chặt, đó là tiêu chí khác và cần giảm chứ không cần tăng. "A module can be used in multiple programs." nói về khả năng tái dùng; đó thường là hệ quả tốt của kết dính cao chứ không phải định nghĩa của nó.
Mở trang câu hỏi này →
Đề bài
#include <stdio.h>

int f(int a, int b, int c) {
    int t = 2*(a+b-c)/5;
    return t;
}

int main() {
    int x = 5, y = 6, z = 7;
    int t = 3*f(y,x,z);
    printf("%d", t);
    return 0;
}
A3
B1
C8
D2
Lời giải
Đáp án đúng: "3". Thứ tự đối số là chỗ cần bám: lời gọi f(y,x,z) gán a bằng 6, b bằng 5, c bằng 7. Trong hàm, a cộng b trừ c cho 4, nhân 2 thành 8, rồi 8 chia 5 là phép chia giữa hai số nguyên nên C cắt phần thập phân cho ra 1, không làm tròn lên 2. Hàm trả về 1, main nhân 3 và in 3. Lựa chọn "1" là giá trị hàm trả về, bỏ quên phép nhân 3 ở main. Lựa chọn "8" là tử số 2 nhân với 4, tức dừng lại trước khi chia cho 5. Lựa chọn "2" ứng với cách hiểu 8 chia 5 bằng 1.6 rồi làm tròn thành 2, nhưng chia nguyên trong C luôn cắt về phía 0, và ngay cả khi làm tròn thì kết quả cuối vẫn còn phải nhân 3 nữa.
Mở trang câu hỏi này →
Atime.h
Bconio.h
Cmath.h
Dstdlib.h
Lời giải
Đáp án đúng: "stdlib.h". Chuẩn C xếp hàm abs vào nhóm tiện ích số nguyên của stdlib.h cùng với labs, llabs và div, bởi abs làm việc trên int chứ không trên số thực, trong khi math.h được dành riêng cho các hàm toán học trên số thực. Ý "time.h" sai vì tệp tiêu đề đó khai báo những thứ liên quan tới thời gian như time, clock, difftime. Ý "conio.h" sai vì nó không phải tệp tiêu đề chuẩn, chỉ tồn tại trên một số trình biên dịch để làm các thao tác màn hình và bàn phím kiểu getch hay clrscr. Ý "math.h" sai vì nơi đó khai báo fabs cho double chứ không phải abs cho int; nhiều trình biên dịch có kèm thêm khai báo abs trong math.h như phần mở rộng riêng, nhưng chỗ được chuẩn hoá chính thức vẫn là stdlib.h.
Mở trang câu hỏi này →
Đề bài
#include<stdio.h>
void updatePosition(int *time, float* position, float v)
{
    if ((*position < 5) && (*position > -5))
        *position += v;
    else
        *position += -0.1*(*position);
    time += 1;
}

main()
{
    float p = 4.0, v = 1;
    int t = 0;
    printf("t = %d, p = %f\n", t, p);
    updatePosition(&t, &p, v);
    updatePosition(&t, &p, v);
    printf("t = %d, p = %f\n", t, p);
}

What is the result displayed to the screen?

At = 0, p = 4.000000 t = 2, p = 6.000000
Bt = 0, p = 4.000000 t = 2, p = 5.000000
Ct = 0, p = 4.000000 t = 2, p = 4.500000
Dt = 0, p = 4.000000 t = 2, p = 4.000000
Lời giải
Đáp án đúng: "t = 0, p = 4.000000 t = 2, p = 4.500000". Lần gọi đầu, giá trị trỏ tới nằm giữa -5 và 5 nên p tăng thêm v, thành 5.0. Lần gọi sau, điều kiện nhỏ hơn 5 đã sai vì p đúng bằng 5.0, nên nhánh else chạy: p cộng thêm -0.1 nhân 5.0, tức giảm 0.5 còn 4.5. Phải nói thẳng một khuyết điểm của đề: lệnh time += 1 chỉ dịch bản sao con trỏ trong hàm chứ không ghi qua dấu sao, nên t thật sự vẫn là 0, mà cả bốn lựa chọn đều in t = 2; vì vậy chỉ giá trị của p phân định được, và 4.500000 là con số duy nhất đúng. Dòng "t = 0, p = 4.000000 t = 2, p = 6.000000" coi như cả hai lần gọi đều vào nhánh cộng v. Dòng "t = 0, p = 4.000000 t = 2, p = 5.000000" dừng ở kết quả lần gọi đầu. Dòng "t = 0, p = 4.000000 t = 2, p = 4.000000" coi như lần gọi sau trả p về giá trị cũ.
Mở trang câu hỏi này →
Đề bài
void swap(int *a, int *b) {
    int t = *a;
    *a = *b;
    *b = t;
}

int main() {
    int x = 5, y = 10;
    swap(&x, &y);
    printf("%d %d", x, y);
    return 0;
}
A10 5
B5 10
C0 0
DCompilation error
Lời giải
Đáp án đúng: "10 5". C truyền tham số theo giá trị, nên muốn hàm sửa được biến của nơi gọi thì phải truyền địa chỉ: lời gọi swap(&x, &y) đưa địa chỉ của x và của y vào hai con trỏ. Trong hàm, t giữ bản sao giá trị đầu là 5, rồi ô mà con trỏ thứ nhất trỏ tới nhận 10 nên x thành 10, cuối cùng ô của con trỏ thứ hai nhận t nên y thành 5. Mọi phép ghi đều qua dấu sao, tức ghi thẳng vào ô nhớ gốc, nên sau lời gọi printf in 10 rồi 5. Dãy "5 10" là thứ tự ban đầu, nó xảy ra nếu hàm nhận hai bản sao int thường và chỉ đổi chỗ bản sao. Dãy "0 0" sai vì không có chỗ nào gán 0. Kết luận "Compilation error" sai vì nguyên mẫu nhận con trỏ int, lời gọi truyền đúng địa chỉ, và phép gán qua dấu sao hoàn toàn hợp lệ.
Mở trang câu hỏi này →
AA lowercase letter
BAn uppercase letter
CA digit
DA punctuation character
Lời giải
Đáp án đúng: "A lowercase letter". Hàm islower thuộc ctype.h, nhận mã của một ký tự và trả về giá trị khác 0 khi ký tự đó là chữ cái viết thường, trả 0 trong mọi trường hợp khác. Chuẩn chỉ hứa khác 0 chứ không hứa đúng bằng 1, nên nên dùng hàm này trực tiếp trong điều kiện thay vì so sánh với 1. "An uppercase letter" là việc của isupper; gặp chữ in hoa thì islower trả 0. "A digit" là việc của isdigit, ký tự chữ số không phải chữ cái thường nên cũng cho 0. "A punctuation character" là việc của ispunct, các dấu câu như dấu phẩy hay dấu chấm đều khiến islower trả 0.
Mở trang câu hỏi này →
Đề bài
int a = 0;
char line1[] = "Hi";
char line2[] = "Hello";
a = strcmp(line1, line2);
A0
BA positive value
CA negative value
DNAN
Lời giải
Đáp án đúng: "A positive value". Hàm strcmp so từng cặp ký tự theo mã của chúng và trả về chênh lệch tại vị trí đầu tiên khác nhau. Hai chuỗi cùng mở đầu bằng một chữ hoa giống nhau, sang vị trí thứ hai thì chuỗi ngắn có ký tự i mã 105 còn chuỗi dài có ký tự e mã 101; vì 105 lớn hơn 101 nên hàm cho ra số dương, nghĩa là chuỗi thứ nhất đứng sau theo thứ tự từ điển. Chú ý việc so sánh dừng ngay tại cặp lệch đầu tiên, độ dài chuỗi không quyết định. Lựa chọn "0" chỉ đúng khi hai chuỗi giống nhau hoàn toàn tới ký tự kết thúc. Lựa chọn "A negative value" sẽ đúng nếu ký tự lệch đầu tiên của chuỗi thứ nhất nhỏ hơn, tức khi đổi thứ tự hai đối số. Lựa chọn "NAN" không có nghĩa ở đây vì strcmp trả về int, không phải số thực, nên không bao giờ sinh giá trị không phải số.
Mở trang câu hỏi này →
Adouble result = sqrt(9);
Bint result = sqrt(9);
Cfloat result = sqrt(9);
Dresult = power(9, 0.5);
Lời giải
Đáp án đúng: "double result = sqrt(9);". Hàm sqrt được khai báo trong math.h với kiểu trả về double, nên hứng kết quả bằng một biến double là cách duy nhất giữ trọn giá trị mà hàm trả về, không có phép chuyển đổi thu hẹp nào xảy ra. Ý "int result = sqrt(9);" sai vì gán double cho int buộc phải cắt phần thập phân, ở đây tình cờ ra đúng 3 nhưng với căn của 2 hay của 10 thì mất hết phần lẻ. Ý "float result = sqrt(9);" sai vì float hẹp hơn double nên giá trị bị làm tròn khi gán, một lần nữa chỉ vô tình đúng với số chính phương. Ý "result = power(9, 0.5);" sai vì thư viện chuẩn không có hàm nào tên là power, hàm luỹ thừa tên là pow; thêm nữa biến result ở đó còn chưa được khai báo kiểu.
Mở trang câu hỏi này →
Aint a[5] = {0};
Bint a[5] = [0, 0, 0, 0, 0];
Cint a[5] = (0, 0, 0, 0, 0);
Dint a[5];
Lời giải
Đáp án đúng: "int a[5] = {0};". Danh sách khởi tạo của mảng trong C đặt trong cặp ngoặc nhọn, và chuẩn quy định nếu số giá trị ít hơn số phần tử thì phần còn lại được khởi tạo về 0, nên viết đúng một số 0 là đủ để cả năm phần tử bằng 0. Cách viết "int a[5] = [0, 0, 0, 0, 0];" dùng ngoặc vuông làm danh sách, nhưng ngoặc vuông trong C chỉ dành cho khai kích thước và truy cập phần tử, nên đây là lỗi cú pháp. Cách viết "int a[5] = (0, 0, 0, 0, 0);" dùng ngoặc tròn nên vế phải thành một biểu thức với toán tử phẩy, giá trị của nó là một số 0 đơn lẻ và không thể gán cho cả mảng. Cách viết "int a[5];" không có phần khởi tạo: mảng cục bộ như vậy chứa đúng những byte rác còn lại trong bộ nhớ, chỉ mảng toàn cục hoặc static mới tự về 0, nên không bảo đảm được điều đề bài đòi.
Mở trang câu hỏi này →
AThe program compiles and runs without any errors, but the behavior is undefined
BThe program compiles and runs without any errors, and the 11th element is accessed
CThe program fails to compile due to a compilation error
DThe program compiles and runs without any errors, and the 11th element is automatically added to the array
Lời giải
Đáp án đúng: "The program compiles and runs without any errors, but the behavior is undefined". C đổi an toàn lấy tốc độ: chỉ số mảng chỉ là phép cộng địa chỉ rồi lấy giá trị, không kèm mã kiểm biên nào, nên chương trình vẫn dịch xong và vẫn chạy, chỉ là nó đọc ghi vào vùng không thuộc mảng. Chuẩn gọi đó là hành vi không xác định: có thể ra số rác, có thể phá biến khác, có thể gây lỗi truy cập, và kết quả đổi theo máy lẫn trình dịch. Câu "The program compiles and runs without any errors, and the 11th element is accessed" sai vì phần tử thứ mười một không tồn tại, thứ bị chạm tới là ô nhớ kế bên. Câu "The program fails to compile due to a compilation error" sai vì chỉ số thường chỉ biết lúc chạy. Câu "The program compiles and runs without any errors, and the 11th element is automatically added to the array" sai vì mảng trong C có kích thước cố định lúc khai báo.
Mở trang câu hỏi này →
36What will be the output of the following C code?4 lựa chọncó code
Đề bài
#include <stdio.h>
int main()
{
    int a,b,c;
    a = b = c = 10;
    c = a++ || ++b && ++c;
    printf("%d %d %d",c, a, b);
    return 0;
}
A1 11 10
B10 11 1
C10 11 10
D1 1 10
Lời giải
Đáp án đúng: "1 11 10". Toán tử và kết chặt hơn toán tử hoặc, nên biểu thức được hiểu là a++ || (++b && ++c). Phép a++ trả về giá trị cũ 10, khác 0 nên vế trái đã đúng; toán tử hoặc rút mạch nên vế phải không được tính lần nào, do đó b giữ nguyên 10 và c không hề tăng. Giá trị của cả biểu thức luận lý là 1, và chính 1 đó được gán cho c, còn a đã tăng thành 11; thứ tự in là c, a, b nên ra 1 11 10. Cần công bố khuyết điểm: bản khoá in kèm ghi 10 11 10, giá trị đó chỉ đúng nếu phép gán nhận giá trị của a thay vì giá trị chân lý của biểu thức, nên "10 11 10" sai. "10 11 1" vừa gán sai cho c vừa đổi chỗ b với c khi in. "1 1 10" sai vì a đã tăng thành 11, không thể còn 1.
Mở trang câu hỏi này →
Đề bài
int a[] = {1,2,3,4};
int i=0, s=0;
for (; a[i]; ++i)
    s += a[i];
printf("%d", s);
A10
BCompiler error
CRuntime error
DGarbage value
Lời giải
Đáp án đúng: "10". Vòng for bỏ trống phần khởi tạo vì i đã bằng 0 từ trước, và dùng chính a[i] làm điều kiện: C coi mọi số khác không là đúng, nên vòng còn chạy khi phần tử hiện tại khác 0. Bốn phần tử 1, 2, 3, 4 đều khác không nên s cộng dồn thành 10, rồi i lên 4. Cần nói rõ một điểm yếu của đề: mảng chỉ có bốn ô, nên lần đọc a[4] đã ra ngoài biên và theo chuẩn là hành vi không xác định; đề ngầm giả định ô kề đó bằng 0 để vòng dừng, và với giả định ấy printf in 10. Kết luận "Compiler error" sai vì cú pháp hợp lệ, phần khởi tạo của for được phép để trống. Kết luận "Runtime error" không bắt buộc xảy ra vì đọc một ô ngay sau mảng trên ngăn xếp thường không bị hệ điều hành chặn. Kết luận "Garbage value" chỉ xảy ra nếu ô ngoài biên khác 0, và khi đó tổng sẽ lớn hơn 10.
Mở trang câu hỏi này →
Aint *p;
Bint p*;
Cint +p;
Dint $p;
Lời giải
Đáp án đúng: "int *p;". Khai báo trong C đọc theo lối dùng là gì: dấu sao đứng trước tên nói rằng *p là một int, suy ra p là con trỏ tới int. Vì thế dấu sao thuộc về bộ phận khai báo của tên, viết int *p; hay int* p; đều cùng nghĩa, miễn nó đứng trước tên biến. Dòng "int p*;" đặt dấu sao sau tên, cú pháp không có dạng này nên trình dịch báo lỗi ngay; hậu tố trong khai báo chỉ dành cho ngoặc vuông của mảng và ngoặc tròn của hàm. Dòng "int +p;" dùng dấu cộng, thứ chỉ là toán tử trong biểu thức chứ không phải bộ phận khai báo, nên không tạo được con trỏ. Dòng "int $p;" dùng ký tự không thuộc tập cho phép của tên định danh; tên chỉ gồm chữ cái, chữ số và dấu gạch dưới, nên dòng này sai ngay ở bước tách từ.
Mở trang câu hỏi này →
39What will be the output of the following program?4 lựa chọncó code
Đề bài
void func(int *p){
    int j =11;
    *p = j;
}
int main() {
    int i = 1;
    int *p = &i;
    func(p);
    printf("%d,%d", i, *p);
    getchar();
    return 0;
}
A11,11
B1,1
C0,0
D0,1
Lời giải
Đáp án đúng: "11,11". Biến i của hàm chính bằng 1 và p giữ địa chỉ của i, nên truyền p vào func là truyền chính địa chỉ đó chứ không phải một bản sao của giá trị. Trong func, biến cục bộ j bằng 11 và lệnh ghi qua con trỏ đặt 11 vào ô nhớ mà p trỏ tới, tức ghi thẳng vào i; j chết khi hàm kết thúc nhưng giá trị đã nằm lại trong i. Sau lời gọi, i là 11 và nội dung chỗ p trỏ tới cũng là 11 vì p vẫn trỏ vào i, nên lệnh in xuất hai số 11 cách nhau bởi dấu phẩy. Dãy "1,1" là kết quả nếu hàm chỉ gán cho bản sao tham số, chẳng hạn cho con trỏ trỏ sang j, khi đó i không đổi. Dãy "0,0" cần một phép đặt về không, không có trong mã. Dãy "0,1" còn đòi hai số khác nhau, trong khi i và nội dung chỗ p trỏ tới luôn là cùng một ô nhớ nên không thể lệch nhau.
Mở trang câu hỏi này →
AIncrements
BSquare root
CDivision
DMultiplication
Lời giải
Đáp án đúng: "Increments". Con trỏ có số học riêng, định nghĩa trên phép cộng và trừ với số nguyên: tăng con trỏ một đơn vị là nhảy sang phần tử kế tiếp, tức địa chỉ cộng thêm đúng kích thước kiểu được trỏ, nên p++ là lối duyệt mảng rất thông dụng. Ngoài ra chỉ phép trừ hai con trỏ cùng kiểu là hợp lệ, cho khoảng cách theo số phần tử. Phép "Square root" trước hết không phải toán tử mà là hàm sqrt của thư viện toán, và nó nhận số thực chứ không nhận địa chỉ. Phép "Division" không có nghĩa với địa chỉ: chia một vị trí trong bộ nhớ cho một số không sinh ra vị trí nào có ý nghĩa, nên chuẩn C không định nghĩa nó cho con trỏ. Phép "Multiplication" cũng vậy, nhân địa chỉ lên nhiều lần cho ra một số nằm ngoài mọi vùng nhớ hợp lệ, trình dịch từ chối thẳng.
Mở trang câu hỏi này →