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

Câu hỏi: PRF192 Cơ sở lập trình – Bộ ôn tập số 5

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 đề.

Danh sách câu hỏi

20/50 câuCòn 30
AThe comment mark will be removed. The content of the comments will be compiled line by line.
BThe comment is treated as an array of characters.
CComments are removed in the pre-processing step.
DEach comment is compiled as a statement that does nothing.
Lời giải
Đáp án đúng: "Comments are removed in the pre-processing step." Chú thích chỉ dành cho người đọc, không mang nghĩa gì với máy, nên nó bị loại bỏ ngay ở bước tiền xử lý, trước khi khâu phân tích cú pháp nhìn tới mã; mỗi chú thích được thay bằng một khoảng trắng, vì vậy mã máy sinh ra không đổi dù chú thích dài hay ngắn. "The comment mark will be removed. The content of the comments will be compiled line by line." sai vì nội dung chú thích không bao giờ được biên dịch; nếu biên dịch thì mọi câu văn trong chú thích đều thành lỗi cú pháp. "The comment is treated as an array of characters." sai vì chỉ chuỗi nằm trong dấu nháy kép mới trở thành mảng ký tự trong bộ nhớ, chú thích không sinh ra byte dữ liệu nào. "Each comment is compiled as a statement that does nothing." sai vì không có lệnh rỗng nào được sinh ra, chương trình dịch xong không còn dấu vết của chú thích.
Mở trang câu hỏi này →
AAssign value to n
BPrint n
CRead an integer input
DDeclare n
Lời giải
Đáp án đúng: "Read an integer input". Lời gọi này đọc một số nguyên từ dòng nhập chuẩn: đặc tả %d bỏ qua khoảng trắng dẫn đầu, gom các chữ số thành một số nguyên, rồi ghi số đó vào ô nhớ mà toán tử lấy địa chỉ đã chỉ ra, bởi scanf phải có địa chỉ mới ghi được ra ngoài phạm vi của chính nó. Mô tả "Assign value to n" bỏ mất phần quan trọng nhất là nguồn dữ liệu: giá trị không do chương trình ấn định mà do người dùng nhập, và việc ghi xảy ra qua con trỏ chứ không bằng toán tử gán. Mô tả "Print n" nói ngược chiều dữ liệu, đưa nội dung ra màn hình là việc của printf hoặc puts. Mô tả "Declare n" sai loại câu lệnh: khai báo là dòng nêu tên và kiểu của biến, phải có trước lời gọi này, còn scanf chỉ dùng biến đã tồn tại.
Mở trang câu hỏi này →
A13
B14
C15
D16
Lời giải
Đáp án đúng: "15". Chuỗi trong C không mang theo độ dài, thư viện nhận ra chỗ hết chuỗi nhờ một ký tự có mã 0 đặt ngay sau ký tự cuối, và ký tự đó cũng chiếm trọn một ô của mảng. Mảng khai 16 ô nên nhiều nhất 15 ô dành cho nội dung, ô còn lại để dành cho dấu kết thúc. Giá trị "16" là tổng số ô; dùng hết cho nội dung thì không còn chỗ cho dấu kết thúc, và các hàm như strlen hay printf sẽ đọc tràn sang bộ nhớ bên cạnh. Giá trị "14" trừ đi hai ô, tức đếm thừa một dấu kết thúc, trong khi chuẩn chỉ đòi đúng một ô cho dấu đó. Giá trị "13" trừ ba ô, không khớp với cách tính nào của ngôn ngữ. Chính quy ước này là lý do các hàm như strncpy hay snprintf luôn phải tính thêm một byte cho dấu kết thúc.
Mở trang câu hỏi này →
Đề bài
#include <stdio.h>
int main() {
    int quantity;
        double cost;
        printf("Enter the number of apples desired: ");
        scanf("%d", &quantity);
        printf("Now enter the cost of one apple (in $): ");
        scanf("%lf", &cost);
        printf("That will cost $%.2lf\n", quantity * cost);
    return 0;
}
AThat will cost $2.00
BThat will cost $2.000000
CThat will cost $2.0000
DThat will cost $2
Lời giải
Đáp án đúng: "That will cost $2.00". Lệnh scanf với %d nạp 4 vào quantity, rồi %lf nạp 0.5 vào cost. Biểu thức quantity * cost nâng số nguyên 4 lên double trước khi nhân, cho 2.0. Chuỗi định dạng viết %.2lf, nghĩa là in dạng thập phân với đúng hai chữ số sau dấu chấm, nên giá trị 2.0 hiện ra là 2.00. Thụt lề lệch trong thân main không ảnh hưởng gì vì C chỉ đọc dấu chấm phẩy và ngoặc nhọn. Dòng "That will cost $2.000000" là thứ printf in khi dùng %f trần, tức độ chính xác mặc định sáu chữ số, nhưng ở đây độ chính xác đã bị chỉ định là hai. Dòng "That will cost $2.0000" đòi bốn chữ số, ứng với %.4lf. Dòng "That will cost $2" đòi không chữ số nào sau dấu chấm, ứng với %.0lf, và cũng không phải cách printf in số thực mặc định.
Mở trang câu hỏi này →
ATo define how values are stored and how operations are performed
BTo determine the variable name and its scope within the program
CTo specify the program's execution order and control flow
DTo control the program's memory allocation and deallocation process
Lời giải
Đáp án đúng: "To define how values are stored and how operations are performed". Kiểu dữ liệu quyết định hai điều: số byte cấp cho biến cùng cách các byte đó mã hoá giá trị, và tập phép toán cùng ngữ nghĩa khi áp lên giá trị. Chính vì thế 5 / 2 cho 2 với int nhưng cho 2.5 với double, còn con trỏ int nhảy bốn byte mỗi lần tăng. Mô tả "To determine the variable name and its scope within the program" sai vì tên do người viết đặt, còn phạm vi do vị trí khai báo quyết định. Mô tả "To specify the program's execution order and control flow" là việc của câu rẽ nhánh và vòng lặp. Mô tả "To control the program's memory allocation and deallocation process" chỉ đúng một góc rất nhỏ: cấp phát rồi thu hồi vùng nhớ động là việc của malloc và free, kiểu chỉ cho biết một giá trị cần bao nhiêu byte.
Mở trang câu hỏi này →
Aint _a3;
Bint a_3;
Cint 3_a;
Dint _3a
Lời giải
Đáp án đúng: "int 3_a;". Quy tắc đặt tên trong C bắt buộc định danh phải bắt đầu bằng chữ cái hoặc dấu gạch dưới, các ký tự sau đó mới được phép là chữ số. Lý do nằm ở bộ phân tích từ vựng: gặp ký tự số đứng đầu, nó cố đọc một hằng số, nên 3_a bị nhận là số 3 dính thêm phần rác phía sau và trình biên dịch báo lỗi cú pháp. Ý "int _a3;" hợp lệ vì mở đầu bằng dấu gạch dưới, sau đó là chữ và số. Ý "int a_3;" hợp lệ vì mở đầu bằng chữ cái, còn dấu gạch dưới và chữ số đều được phép đứng ở giữa tên. Ý "int _3a" cũng là một tên hợp lệ, dấu gạch dưới đứng đầu khiến chữ số theo sau không còn gây nhập nhằng; chỗ thiếu dấu chấm phẩy ở ý này chỉ là sai sót lúc chép đề, bản thân cái tên không vi phạm quy tắc nào.
Mở trang câu hỏi này →
7What does the following program display?4 lựa chọncó code
Đề bài
#include <stdio.h>
int main() {
    int arr[] = {5, 10, 15};
    for (int i = 0; i < 3; i++)
        printf("%d ", arr[i]);
    return 0;
}
A5 10 15
B15 10 5
C0 1 2
D10 15 20
Lời giải
Đáp án đúng: "5 10 15". Khai báo arr[] = {5, 10, 15} tạo mảng ba phần tử theo đúng thứ tự liệt kê, chỉ số chạy từ 0 tới 2. Vòng for đặt i bằng 0, còn chạy khi i nhỏ hơn 3 và tăng i sau mỗi nhịp; thân vòng không có ngoặc nhọn nên chỉ ôm đúng một lệnh printf, lệnh đó in arr[i] theo %d kèm một dấu cách, cho ba lần in lần lượt 5, 10 rồi 15. Dòng "15 10 5" là thứ tự ngược, muốn có nó phải cho i đi từ 2 giảm về 0. Dòng "0 1 2" là dãy chỉ số i, sẽ ra nếu in i thay vì arr[i]. Dòng "10 15 20" là dãy đã cộng thêm 5 vào từng phần tử, không có phép tính nào trong mã làm việc đó.
Mở trang câu hỏi này →
A+=
B+
C++
D-
Lời giải
Đáp án đúng: "+=". Bảng ưu tiên của C xếp phép gán, kể cả gán phức hợp, ở gần đáy, chỉ trên toán tử phẩy; lý do là gán phải nhận trọn giá trị của biểu thức bên phải nên mọi phép tính bên phải buộc phải xong trước. Vì thế a += b * 2 được hiểu là a += (b * 2) chứ không phải (a += b) * 2. Toán tử "+" cộng hai toán hạng, nằm ở mức cộng trừ, chặt hơn mức gán. Toán tử "++" tăng một đơn vị, thuộc nhóm một toán hạng, đứng ở mức cao nhất cùng với ngoặc tròn và chỉ số mảng. Toán tử "-" khi trừ hai số thì cùng mức với phép cộng, còn khi làm dấu âm một toán hạng thì còn cao hơn nữa, nên cả ba đều ưu tiên hơn phép gán phức hợp.
Mở trang câu hỏi này →
A5
B6
C4
DUndefined
Lời giải
Đáp án đúng: "5". Hàm strlen đếm số ký tự thực của chuỗi bằng cách đi từ byte đầu tới khi gặp byte rỗng kết thúc, và không tính byte đó. Chuỗi hello có năm chữ cái nên hàm trả về 5, dù mảng str chiếm sáu byte trong bộ nhớ. Đây là ranh giới cần nhớ: strlen cho độ dài logic, còn sizeof cho kích thước vùng nhớ. Số "6" chính là sizeof(str), tức năm ký tự cộng byte kết thúc, không phải thứ strlen trả về. Số "4" thiếu một ký tự, chỉ đúng nếu chuỗi là hell. Kết luận "Undefined" sai vì mảng được khởi tạo từ hằng chuỗi nên byte kết thúc đã có sẵn, strlen tìm thấy điểm dừng hợp lệ và kết quả hoàn toàn xác định.
Mở trang câu hỏi này →
Đề bài
char s[] = "AbCd";
printf("%d;%d;%d;%d", s[1],  s[2],  s[3],  s[4]);
A97;98;99;100
B65;66;67;68
C65;98;67;100
D98;67;100;0
Lời giải
Đáp án đúng: "98;67;100;0". Mảng s chiếm năm byte: bốn chữ cái và byte rỗng kết thúc ở chỉ số 4. Mỗi phần tử là một char, in bằng %d nên giá trị được nâng lên int và hiện ra dưới dạng mã ASCII. Chỉ số đếm từ 0, vậy s[1] là chữ b thường mã 98, s[2] là chữ hoa thứ hai mã 67, s[3] là chữ d thường mã 100, còn s[4] là byte kết thúc mang giá trị 0. Dãy "97;98;99;100" là mã của bốn chữ thường liên tiếp, tức giả định chuỗi toàn chữ thường và đọc từ chỉ số 0. Dãy "65;66;67;68" là mã của bốn chữ hoa liên tiếp, cũng không khớp vì chuỗi xen chữ thường. Dãy "65;98;67;100" đọc từ s[0] nên lấy mã chữ hoa đầu tiên, lệch một nhịp so với yêu cầu của đề.
Mở trang câu hỏi này →
Đề bài
#include <stdio.h>

int main()
{
    int x = 5, y = 3, z = 1;
    x = x % 3 + z++;
    z = x * y--;
    printf("%d %d %d", x, y, z);

    return 0;
}
A5 3 1
B3 2 9
C2 2 5
DCompiler error
Lời giải
Đáp án đúng: "3 2 9". Đề hỏi biến b nhưng chương trình không có biến nào tên b, nên chỉ có thể trả lời theo đúng thứ printf in ra. Dòng x = x % 3 + z++ tính 5 % 3 bằng 2, còn z++ là tăng sau nên nó đưa vào biểu thức giá trị cũ 1 rồi mới nâng z lên 2; vậy x thành 3. Dòng z = x * y-- lấy x bằng 3 nhân với giá trị cũ của y là 3, cho 9, sau đó y giảm còn 2. Lúc printf chạy, x bằng 3, y bằng 2, z bằng 9. Dãy "5 3 1" là bộ giá trị khởi tạo ban đầu, tức bỏ qua cả hai phép gán. Dãy "2 2 5" ứng với việc tính x chỉ bằng 5 % 3 mà bỏ quên phần cộng z++, nên cả ba số sau đó đều lệch. Kết luận "Compiler error" sai vì mã hợp lệ: phép lấy dư, tăng sau và giảm sau đều áp đúng trên biến int.
Mở trang câu hỏi này →
AThe condition
BThe initialization block
CThe iteration statement
DThe body of the loop
Lời giải
Đáp án đúng: "The initialization block". Cấu trúc for có ba phần trong ngoặc tròn, cách nhau bằng dấu chấm phẩy, và phần đầu chạy đúng một lần trước khi vòng lặp thực sự bắt đầu, thường để tạo và gán giá trị đầu cho biến đếm. Thứ tự sau đó lặp lại mãi: kiểm điều kiện, chạy thân, rồi chạy phần cập nhật. Mô tả "The condition" được kiểm trước mỗi nhịp kể cả nhịp đầu, nhưng nó chỉ chạy sau khi phần khởi tạo đã xong nên không phải thứ chạy trước vòng lặp. Mô tả "The iteration statement" là phần thứ ba, chạy ở cuối mỗi nhịp rồi mới quay lại kiểm điều kiện. Mô tả "The body of the loop" chỉ chạy khi điều kiện còn đúng, và có thể không chạy lần nào nếu điều kiện sai ngay từ đầu.
Mở trang câu hỏi này →
13What will be the output of the C program?4 lựa chọncó code
Đề bài
int 2_var = 15;
printf("%d", 2_var);
A0
B15
CCompilation error.
DRuntime error.
Lời giải
Đáp án đúng: "Compilation error." Tên định danh trong C phải bắt đầu bằng chữ cái hoặc dấu gạch dưới, các ký tự sau mới được là chữ số. Dãy 2_var mở đầu bằng chữ số nên bộ phân tích từ vựng tách nó thành hằng số 2 rồi tới _var, câu khai báo trở thành vô nghĩa và lỗi bị bắt ngay lúc dịch, chương trình không bao giờ có tệp chạy. Kết quả "0" giả định biến vẫn tồn tại và mang giá trị rỗng, điều chỉ xảy ra với biến toàn cục chưa gán. Kết quả "15" giả định khai báo chạy được và printf in đúng số vừa gán, nhưng đoạn mã không qua nổi bước dịch nên không có gì được in. Kết luận "Runtime error." đòi chương trình phải chạy rồi mới hỏng, trong khi đây là lỗi cú pháp thuần, phát hiện trước khi chạy.
Mở trang câu hỏi này →
Đề bài
    #include <stdio.h>
    int main()
    {
        int a = 1;
        switch (a)
        case 1:
            printf("%d", a);
        case 2:
            printf("%d", a);
        case 3:
            printf("%d", a);
        return 0;
}
ANo error, output is 1111
BNo error, output is 1
CCompile time error, no break statements
DCompile time error, case label outside switch statement
Lời giải
Đáp án đúng: "Compile time error, case label outside switch statement". Phạm vi của một khối do ngoặc nhọn quyết định, không do thụt lề: sau switch (a) ở đây không có ngoặc nhọn nào, nên thân của switch chỉ ôm đúng một lệnh, và lệnh đó là lệnh mang nhãn case 1 kèm lời gọi in giá trị a. Hai nhãn case 2 và case 3 viết tiếp phía sau đã nằm ngoài thân switch dù được thụt vào, mà nhãn case chỉ hợp lệ bên trong một switch, nên trình biên dịch dừng với lỗi nhãn case nằm ngoài lệnh switch. Kết luận "No error, output is 1111" sai cả hai mặt: chương trình không dịch được, và trong mã cũng chỉ có ba lệnh in. Kết luận "No error, output is 1" cũng giả định dịch được, hơn nữa nếu các nhãn đều nằm trong thân switch thì do không có break nên các nhánh sau vẫn chạy tiếp. Kết luận "Compile time error, no break statements" đúng chuyện có lỗi nhưng sai nguyên nhân: thiếu break không phải lỗi, đó là hành vi rơi xuống nhánh dưới mà chuẩn cho phép.
Mở trang câu hỏi này →
A#define is a preprocessor command often used to introduce named constants
Bdouble and goto are keyword for declaring data type.
Creturn 0; is normally the last statement in main()
DThe file stdio.h is the library where the compiler finds scanf().
Lời giải

Đáp án đúng: "double and goto are keyword for declaring data type.". Trong C, double đúng là từ khoá của một kiểu số thực, nhưng goto là lệnh nhảy tới một nhãn trong cùng hàm và không khai báo kiểu gì cả, nên câu này sai và chính nó là thứ đề bài cần tìm. Câu "#define is a preprocessor command often used to introduce named constants" đúng: chỉ thị này do bộ tiền xử lý xử lý và hay dùng để đặt tên cho hằng số. Câu "return 0; is normally the last statement in main()" đúng với lệ thường, giá trị 0 báo cho hệ điều hành biết chương trình kết thúc bình thường. Câu "The file stdio.h is the library where the compiler finds scanf()" đúng về chỗ khai báo: tệp tiêu đề này cung cấp nguyên mẫu của scanf cùng nhóm hàm vào ra, nhờ đó trình biên dịch kiểm được kiểu các đối số.

Mở trang câu hỏi này →
A=
B||
C==
D!=
Lời giải
Đáp án đúng: "=". Dấu bằng đơn là phép gán: nó ghi giá trị của biểu thức bên phải vào ô nhớ bên trái rồi trả về chính giá trị vừa ghi, nên nó thuộc nhóm toán tử gán chứ không so sánh cũng không tổ hợp điều kiện. Đây là cái bẫy kinh điển của C, bởi viết if với một dấu bằng vẫn dịch được mà ý nghĩa đã khác hẳn phép so sánh bằng. Ý "||" sai vì đó là phép hoặc luận lý, nhận hai điều kiện và cho 1 khi có ít nhất một điều kiện đúng. Ý "==" sai vì đó là phép so sánh bằng, trả về 1 hoặc 0 tuỳ hai toán hạng có bằng nhau hay không. Ý "!=" sai vì đó cũng là một phép so sánh, nó kiểm tra hai toán hạng khác nhau và trả về 1 hoặc 0.
Mở trang câu hỏi này →
17What is the output?4 lựa chọncó code
Đề bài
int a = 8;
int b = 3;
int result = a % b * 2;
printf("%d", result);
A2
B4
C1
D5
Lời giải
Đáp án đúng: "4". Phép lấy dư và phép nhân cùng mức ưu tiên nên biểu thức a % b * 2 được tính từ trái sang phải: 8 % 3 cho 2 vì 8 chia 3 được 2 dư 2, rồi 2 nhân 2 cho 4, nên chương trình in 4. Thứ tự này là bản chất của ngôn ngữ, không phải quy ước toán học quen tay. "2" là giá trị của riêng 8 % 3, tức bỏ mất phép nhân 2 phía sau. "1" ứng với việc chia kết quả cho 2 bằng phép chia nguyên thay vì nhân, hoặc hiểu sai phần dư của 8 cho 3. "5" ứng với việc coi dấu phần trăm là phép trừ, lấy 8 trừ 3; trong C dấu đó chỉ có nghĩa lấy phần dư của phép chia nguyên và chỉ dùng được với toán hạng nguyên.
Mở trang câu hỏi này →
18What will be the output of the following C code?4 lựa chọncó code
Đề bài
#include <stdio.h>
void main()
{
    int total=0;
    for(int s=1; s<15; s++)
        total=total+s;
    printf("%d",total);
}
A105
B150
C120
D210
Lời giải
Đáp án đúng: "105". Biến s khởi tạo bằng 1 và vòng lặp còn chạy khi s nhỏ hơn 15, nên s nhận lần lượt các giá trị từ 1 tới 14; thân vòng không có ngoặc nhọn nên chỉ gồm đúng lệnh cộng dồn total = total + s. Tổng các số nguyên từ 1 tới 14 bằng 14 nhân 15 rồi chia 2, tức 105, và printf in giá trị đó. Số "150" không ứng với tổng của dãy liên tiếp nào ở đây. Số "120" là tổng từ 1 tới 15, tức hiểu điều kiện s nhỏ hơn 15 thành nhỏ hơn hoặc bằng 15, nhưng khi s lên 15 thì điều kiện đã sai và thân vòng không chạy nữa. Số "210" là tổng từ 1 tới 20. Kiểu void main không chuẩn nhưng nhiều trình dịch vẫn nhận, nên kết quả in ra không đổi.
Mở trang câu hỏi này →
Avoid
Bint
Cfloat
Dchar
Lời giải
Đáp án đúng: "void". Từ khoá void ở vị trí kiểu trả về nói với trình dịch rằng hàm không mang giá trị nào về cho nơi gọi, nên trong thân hàm lệnh return chỉ được viết trơ một mình để kết thúc sớm, và lời gọi hàm không dùng được làm toán hạng của biểu thức hay vế phải của phép gán. Kiểu "int" trả về số nguyên, bắt buộc với main và là mặc định của các trình dịch rất cũ, nhưng khai báo kiểu này rồi không trả giá trị là hành vi không xác định khi nơi gọi đọc kết quả. Kiểu "float" trả về số thực độ chính xác đơn, vẫn là một giá trị cụ thể. Kiểu "char" trả về một ký tự, tức một byte, cũng là một giá trị. Cả ba đều buộc hàm phải có giá trị để mang về, trái với điều câu hỏi nêu.
Mở trang câu hỏi này →
Đề bài
#include <stdio.h>
int main()
{
    int i,j,result=0;
    for(i=3;i<=5;i++){
            for(j=5;j>i;j--)
            result+=j;
        }
    printf("%d",result);
            return 0;
}
A14
B15
C16
D20
Lời giải

Đáp án đúng: "14". Vòng trong for(j=5;j>i;j--) không có ngoặc nhọn nên thân nó chỉ gồm đúng một lệnh result+=j; phạm vi khối trong C do ngoặc nhọn quyết định, không do thụt lề. Lần theo từng lượt: i bằng 3 thì j nhận 5 rồi 4, cộng được 9; i bằng 4 thì j chỉ nhận 5, result thành 14; i bằng 5 thì j khởi tạo bằng 5 không thoả j>i nên vòng trong không chạy lần nào. Chương trình in 14. Cần công bố khuyết điểm: bản khoá in kèm ghi 16, con số đó không khớp với bất kỳ lần lần theo trung thực nào của hai vòng lặp. "15" là tổng 5+4+3+2+1, chỉ ra được nếu bỏ ràng buộc j>i và cho j chạy tới 1. "16" lớn hơn tổng thật 2 đơn vị mà không lượt lặp nào cộng thêm 2. "20" đòi cộng cả những giá trị j mà điều kiện j>i đã chặn.

Mở trang câu hỏi này →