Tất cả câu hỏi

Ngân hàng câu hỏi trắc nghiệm có giải thích chi tiết.

340/11.248 câuCòn 10.908
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 →
Đề 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 →
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 →
Đề 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 →
Đề 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 →
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 →
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 →
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 →
A2.5
B2.0
C2
D3.5
Lời giải
Đáp án đúng: "2.0". Biểu thức 5 / 2 chỉ gồm hai hằng số nguyên nên trình dịch dùng phép chia nguyên, cho 2 và bỏ phần dư; kiểu của biến đích không quay lại ảnh hưởng cách tính biểu thức bên phải, đây là chỗ bẫy của câu hỏi. Giá trị 2 sau đó mới được nâng lên float thành 2.0, và %.1f in một chữ số sau dấu chấm nên màn hình hiện 2.0. Muốn có phép chia thực phải để ít nhất một toán hạng là số thực, chẳng hạn viết 5.0 / 2. Số "2.5" là kết quả của phép chia thực, chỉ xuất hiện khi đã có toán hạng thực. Số "2" là cách in một số nguyên bằng %d, còn %.1f luôn kèm dấu chấm và một chữ số. Số "3.5" không ứng với cách tính nào của 5 chia 2, dù chia nguyên hay chia thực.
Mở trang câu hỏi này →
Aint a = 25;
Ba = 25;
CInt a = 25;
Da = (Int) 25;
Lời giải
Đáp án đúng: "int a = 25;". Một khai báo đầy đủ cần tên kiểu đứng trước, rồi tên biến, và có thể kèm dấu bằng với giá trị khởi tạo; int là từ khoá kiểu nguyên viết toàn chữ thường, nên dòng này vừa tạo biến vừa gán giá trị đầu cho nó. Dòng "a = 25;" chỉ là một phép gán, nó đòi a phải được khai báo ở đâu đó trước; chuẩn C hiện hành đã bỏ luật ngầm hiểu kiểu int nên dòng này không tự tạo ra biến. Dòng "Int a = 25;" sai vì C phân biệt chữ hoa chữ thường, từ viết hoa đó không phải từ khoá mà bị coi là một tên kiểu chưa từng định nghĩa. Dòng "a = (Int) 25;" mắc cả hai lỗi cùng lúc: không có khai báo kiểu cho a, và phép ép kiểu lại viện tới một tên kiểu không tồn tại.
Mở trang câu hỏi này →
331What is printed?4 lựa chọncó code
Đề bài
char sentence[81] = "This is a test";
int n = strlen(sentence);
printf("%d", n);
A13
B14
C15
DCompilation error
Lời giải
Đáp án đúng: "14". Mảng sentence có tám mươi mốt ô nhưng được khởi tạo từ hằng chuỗi, nên chỉ phần đầu mang nội dung, ô ngay sau chữ cuối giữ byte rỗng kết thúc và các ô còn lại cũng bằng không. Hàm strlen đếm số ký tự tới trước byte kết thúc, kể cả dấu cách: bốn chữ của This, một dấu cách, hai chữ của is, một dấu cách, một chữ a, một dấu cách rồi bốn chữ của test, cộng lại đúng 14. Số "13" là kết quả khi bỏ sót một dấu cách, lỗi đếm thường gặp vì dấu cách không nhìn thấy rõ. Số "15" là số byte chuỗi thật sự chiếm, tức mười bốn ký tự cộng byte kết thúc. Kết luận "Compilation error" sai vì khởi tạo mảng char tám mươi mốt ô bằng một chuỗi ngắn hơn là hợp lệ.
Mở trang câu hỏi này →
A14
B3
C10
D0
Lời giải
Đáp án đúng: "3". Trong hằng chuỗi, dãy gồm dấu chéo ngược và số không là một ký tự duy nhất, chính là byte rỗng dùng để đánh dấu kết thúc chuỗi. Khi trình dịch dựng hằng này, vùng nhớ lần lượt chứa ba chữ in hoa của FPT, một byte rỗng, mười chữ của University, rồi một byte rỗng nữa, tổng cộng mười lăm byte. Hàm strlen đi từ byte đầu và dừng ở byte rỗng đầu tiên, nên nó chỉ đếm được ba ký tự. Số "14" là số chữ cái nhìn thấy trên mặt chữ, tức cách đếm bỏ qua ý nghĩa của byte rỗng. Số "10" là độ dài của phần đứng sau byte rỗng, phần mà strlen không bao giờ chạm tới. Số "0" chỉ đúng nếu ký tự đầu tiên đã là byte rỗng, trong khi ở đây byte đầu là một chữ in hoa.
Mở trang câu hỏi này →
A0
B1
C10
D11
Lời giải
Đáp án đúng: "0". Dấu chấm than là phép phủ định logic trên một toán hạng: C coi mọi giá trị khác không là đúng và chỉ số không là sai, còn kết quả của phép logic luôn là int mang giá trị 0 hoặc 1. Toán hạng 1 là đúng nên phủ định nó cho sai, tức 0. Số "1" là kết quả của phép phủ định hai lần, hoặc là chính toán hạng ban đầu khi quên áp phép toán. Số "10" ứng với cách hiểu nhầm dấu chấm than thành phép ghép ký tự, như thể viết 1 rồi 0 cạnh nhau; C không có phép nối số kiểu đó. Số "11" cũng là một dãy ký tự ghép lại, lại thêm hiểu nhầm rằng phủ định của 1 vẫn là 1. Cần phân biệt phủ định logic với đảo bit, vì đảo bit của 1 trên int bốn byte cho -2.
Mở trang câu hỏi này →
334Given the following code snippet:4 lựa chọncó code
Đề bài
#include <stdio.h>
#define MONTHS_IN_YEAR 12
int main() {
    const int WORKING_DAYS = 22;
    printf("%d ", MONTHS_IN_YEAR);
    printf("%d", WORKING_DAYS);
    return 0;
}

Choose the correct statement:

AThe output will be: 12 22
BNo output
CCompile error
DRuntime error
Lời giải
Đáp án đúng: "The output will be: 12 22". Dòng define là chỉ thị tiền xử lý: trước khi dịch, mọi chỗ viết MONTHS_IN_YEAR bị thay bằng dãy ký tự 12, nên lệnh in đầu nhận hằng số 12. Biến WORKING_DAYS khai báo const int kèm giá trị khởi tạo là hợp lệ, vì const chỉ ngăn gán lại về sau chứ không ngăn khởi tạo, nên lệnh in thứ hai cho 22. Chuỗi định dạng đầu có dấu cách sau %d nên hai số cách nhau một khoảng. Kết luận "No output" sai vì cả hai lệnh printf đều chạy với đối số hợp lệ. Kết luận "Compile error" sai vì không có vi phạm nào: tên hằng viết hoa chỉ là quy ước, và const int khởi tạo ngay là lối dùng đúng. Kết luận "Runtime error" sai vì chương trình chỉ in hai số nguyên rồi trả về 0, không chạm tới vùng nhớ nào có thể gây lỗi.
Mở trang câu hỏi này →
A2 bytes
B1 byte
C8 bytes
D4 bytes
Lời giải
Đáp án đúng: "4 bytes". Trên gần như mọi trình dịch C hiện hành, float là số thực theo chuẩn IEEE 754 độ chính xác đơn: ba mươi hai bit chia thành một bit dấu, tám bit số mũ và hai mươi ba bit phần định trị, tức đúng bốn byte, và sizeof(float) trả về 4. Số "2 bytes" là kích thước thường thấy của short int, không có kiểu thực chuẩn nào nhỏ như vậy. Số "1 byte" là kích thước của char, kiểu mà chuẩn ấn định bằng một byte, quá nhỏ để chứa cả dấu, số mũ và phần định trị. Số "8 bytes" là kích thước của double, bản độ chính xác kép với mười một bit số mũ và năm mươi hai bit định trị; chính vì gấp đôi chỗ mà double giữ được nhiều chữ số nghĩa hơn float.
Mở trang câu hỏi này →
336What will the following code output?4 lựa chọncó code
Đề bài
#include <stdio.h>
int main() {
    int a = 5, b = 3;
    printf("%d", a & b);
    return 0;
}
A1
B2
C3
D5
Lời giải
Đáp án đúng: "1". Một dấu và đơn lẻ là phép và theo từng bit, khác hẳn hai dấu và của phép và logic. Viết 5 ở hệ hai là 0101, viết 3 là 0011; ghép từng cặp bit cùng vị trí, chỉ chỗ nào cả hai đều bằng 1 mới cho 1, nên kết quả là 0001, tức 1, và printf in nó bằng %d. Số "2" ở hệ hai là 0010, nó đòi bit thứ hai bằng 1 trong cả hai toán hạng, nhưng 5 không có bit đó. Số "3" là chính giá trị của b, ứng với việc hiểu nhầm dấu và thành phép lấy toán hạng bên phải. Số "5" là chính giá trị của a, ứng với việc hiểu nhầm thành phép lấy toán hạng bên trái; cả hai cách hiểu đó đều bỏ qua việc so từng bit, thứ làm nên bản chất của toán tử này.
Mở trang câu hỏi này →
Đề bài
for (i = 2; i <= n; i++) {
    S *= i;
}
printf("%d", S);
A120
B60
C24
D100
Lời giải
Đáp án đúng: "120". Biến tích khởi tạo bằng 1 vì đó là phần tử trung tính của phép nhân; khởi tạo bằng 0 thì mọi phép nhân sau đó đều cho 0. Vòng lặp cho i chạy từ 2 tới n là 5, mỗi nhịp nhân dồn, nên giá trị lần lượt là 2, 6, 24 rồi 120, đúng bằng giai thừa của 5. Số "60" đúng bằng tích của 3, 4 và 5, tức bỏ mất nhịp nhân với 2 ở đầu vòng lặp. Số "24" là giai thừa của 4, tức kết quả khi điều kiện dừng ở i nhỏ hơn n thay vì nhỏ hơn hoặc bằng n, bỏ mất nhịp cuối. Số "100" không phải tích của dãy số nguyên liên tiếp nào bắt đầu từ 2. Ở đây thân vòng có ngoặc nhọn nên phạm vi rõ ràng, dù bên trong chỉ có một lệnh.
Mở trang câu hỏi này →
Afopen("file.txt", "r")
Bopen("file.txt", "w")
Cfopen("file.txt", "w")
Dopen("file.txt", "r")
Lời giải
Đáp án đúng: "fopen("file.txt", "r")". Thư viện chuẩn mở tệp bằng fopen: hàm nhận tên tệp và chuỗi chế độ, trả về con trỏ tệp hoặc giá trị rỗng nếu thất bại; chế độ đọc mở tệp sẵn có, đặt vị trí ở đầu và không làm hỏng nội dung. Lệnh "fopen("file.txt", "w")" vẫn đúng hàm nhưng chế độ ghi cắt tệp về rỗng nếu tệp đã có, dùng để đọc là mất dữ liệu. Lệnh "open("file.txt", "r")" sai hàm: open là lời gọi hệ thống của POSIX, khai báo trong fcntl.h, nhận cờ dạng số chứ không nhận chuỗi chế độ, và trả về số hiệu tệp chứ không phải con trỏ tệp. Lệnh "open("file.txt", "w")" sai cả hai mặt, vừa dùng lời gọi hệ thống với chuỗi chế độ không hợp lệ, vừa nhắm ý ghi trong khi đề hỏi mở để đọc.
Mở trang câu hỏi này →
Afputs()
Bfscanf()
Cfgets()
Dfopen()
Lời giải
Đáp án đúng: "fputs()". Hàm này nhận một chuỗi kết thúc rỗng cùng con trỏ tệp, rồi ghi các ký tự của chuỗi vào luồng, bỏ lại byte kết thúc và không tự thêm dấu xuống dòng, nên nó là cách trực tiếp nhất để đưa một chuỗi ra tệp. Hàm "fscanf()" đi hướng ngược lại, đọc dữ liệu từ tệp theo chuỗi định dạng và cần địa chỉ biến để nạp vào, nên không ghi gì cả. Hàm "fgets()" cũng là hàm đọc, lấy một dòng từ tệp vào vùng đệm có giới hạn độ dài; cặp fgets và fputs dễ nhầm chính vì tên gần giống nhau mà hướng dữ liệu trái ngược. Hàm "fopen()" chỉ mở tệp và trả về con trỏ tệp cho các hàm khác dùng, bản thân nó không chuyển một byte nội dung nào.
Mở trang câu hỏi này →
AWriting formatted data to a file.
BReading formatted data from a file.
CAppending formatted data to a file.
DClosing a file.
Lời giải
Đáp án đúng: "Writing formatted data to a file." Hàm fprintf là bản mở rộng của printf: tham số đầu là con trỏ tệp chỉ luồng đích, phần sau vẫn là chuỗi định dạng và danh sách giá trị, nên nó biến các giá trị trong bộ nhớ thành văn bản rồi ghi vào luồng đó. Mô tả "Reading formatted data from a file." là việc của fscanf, hàm đi hướng ngược lại và cần địa chỉ biến để nạp vào. Mô tả "Appending formatted data to a file." nói về vị trí ghi chứ không phải về hàm: ghi nối vào cuối hay ghi từ đầu do chế độ mở trong fopen quyết định, cùng một fprintf sẽ nối thêm với chế độ mở nối và ghi đè với chế độ mở ghi. Mô tả "Closing a file." là việc của fclose, hàm đẩy nốt vùng đệm xuống đĩa rồi giải phóng cấu trúc tệp.
Mở trang câu hỏi này →