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

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

49 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/49 câuCòn 9
AChecking the return value of fopen()
BUsing ferror()
CUsing feof()
DUsing fprintf()
Lời giải
Đáp án đúng: "Checking the return value of fopen()". Trong C, fopen là chỗ duy nhất cho biết việc mở tệp có thành công hay không: thành công thì nó trả về một con trỏ FILE hợp lệ, thất bại thì trả về NULL, chẳng hạn khi đường dẫn sai hoặc tiến trình không có quyền ghi. Vì mọi hàm làm việc với tệp về sau đều cần con trỏ ấy, bắt buộc phải so nó với NULL ngay sau khi gọi, trước khi đem ra dùng. Ý "Using ferror()" sai vì ferror chỉ tra cờ lỗi của một dòng tệp đã mở được, muốn gọi nó thì trong tay phải có sẵn con trỏ FILE hợp lệ, nghĩa là việc mở đã thành công rồi. Ý "Using feof()" sai vì feof cho biết đã đọc tới cuối tệp, chuyện đó không liên quan gì tới việc mở tệp để ghi. Ý "Using fprintf()" sai vì fprintf là hàm ghi dữ liệu; nếu con trỏ truyền vào là NULL thì chương trình rơi vào hành vi không xác định chứ không nhận được thông báo lỗi nào.
Mở trang câu hỏi này →
22What does the following program display?4 lựa chọncó code
Đề bài
#include <stdio.h>

int main()
{
    int x = 1, y = 2, z = 3;

    x = x - --y;
    z = z + ++y;

    printf("%d %d %d", x, y, z);

    return 0;
}
A-1 5 3
B0 2 5
C1 2 4
D1 5 3
Lời giải
Đáp án đúng: "0 2 5". Phép giảm trước --y hạ y từ 2 xuống 1 rồi mới nộp giá trị mới là 1 cho biểu thức, nên x bằng 1 trừ 1 là 0. Ngay sau đó phép tăng trước ++y nâng y từ 1 lên 2 và nộp giá trị 2, nên z bằng 3 cộng 2 là 5, còn y dừng lại ở 2; ba số in ra là 0, 2 và 5. Ý "1 5 3" sai vì y chỉ dao động giữa 1 và 2 nên không thể thành 5, mà x cũng không thể giữ nguyên 1 khi vế phải bị trừ đi một lượng khác 0; đây là khuyết điểm phải công bố của câu này, bộ khoá đi kèm đề chốt đúng bộ số không thể xảy ra ấy. Ý "-1 5 3" sai vì z chắc chắn bị ghi lại ở lệnh thứ hai nên không còn là 3, và giá trị 5 của y vẫn vô căn cứ. Ý "1 2 4" sai vì nó đọc --y và ++y như thể là giảm sau và tăng sau, dùng giá trị cũ của y, trong khi dạng tiền tố luôn thay đổi y trước rồi mới trả giá trị mới.
Mở trang câu hỏi này →
Aptr = realloc( ptr, 5 * sizeof(int) );
Brealloc( ptr, 5 * sizeof(int) );
Cptr += malloc( 5 * sizeof( int ) );
Drealloc( ptr, 20);
Eptr = realloc( ptr, 20);
Lời giải
Đáp án đúng: "ptr += malloc( 5 * sizeof( int ) );". Lệnh này sai ngay từ lúc dịch vì phép cộng trên con trỏ chỉ chấp nhận một bên là con trỏ và bên kia là số nguyên; ở đây cả hai bên đều là con trỏ, malloc trả về một con trỏ void, nên biểu thức không có nghĩa và trình biên dịch báo toán hạng không hợp lệ. Ý tưởng ấy còn sai về bản chất: muốn nới một vùng nhớ đã cấp thì phải gọi realloc, chứ không phải dịch con trỏ đi đâu đó. Ý "ptr = realloc( ptr, 5 * sizeof(int) );" là cách viết đúng chuẩn, dịch được và chạy đúng. Ý "realloc( ptr, 5 * sizeof(int) );" vẫn dịch được, chỉ bỏ mất con trỏ mới trả về nên tiềm ẩn rò rỉ và con trỏ treo, nhưng đề hỏi lệnh gây lỗi nên nó không phải lựa chọn. Ý "realloc( ptr, 20);" cũng dịch được, chỉ là ghi cứng số byte. Ý "ptr = realloc( ptr, 20);" dịch được và chạy đúng khi int chiếm 4 byte.
Mở trang câu hỏi này →
Acondition ? expression1 : expression2
Bcondition ? expression1, expression2
Ccondition : expression1 ? expression2
Dexpression1 : condition ? expression2
Lời giải
Đáp án đúng: "condition ? expression1 : expression2". Toán tử điều kiện là toán tử ba toán hạng duy nhất của C: phần trước dấu hỏi là điều kiện, dấu hỏi mở ra nhánh giá trị dùng khi điều kiện đúng, dấu hai chấm tách sang nhánh giá trị dùng khi điều kiện sai. Cả cụm là một biểu thức có giá trị nên đặt được ngay trong phép gán hay trong đối số của printf, và chỉ đúng một trong hai nhánh được tính. Ý "condition ? expression1, expression2" sai vì thiếu dấu hai chấm, dấu phẩy ở đó lại là toán tử phẩy nên cụm sau dấu hỏi gộp thành một biểu thức duy nhất và không còn nhánh cho trường hợp sai. Ý "condition : expression1 ? expression2" sai vì đảo chỗ hai dấu, dấu hai chấm không được phép đứng ngay sau điều kiện. Ý "expression1 : condition ? expression2" sai vì điều kiện bị đẩy vào giữa, trong khi cú pháp buộc điều kiện phải đứng trước dấu hỏi.
Mở trang câu hỏi này →
ACompilation involves converting source code to machine code, while interpretation involves executing code line by line.
BCompilation and interpretation are two terms that are used interchangeably.
CAlgorithm is another term for interpretation in programming languages.
DIDE tools are responsible for both compilation and interpretation processes.
Lời giải
Đáp án đúng: "Compilation involves converting source code to machine code, while interpretation involves executing code line by line.". Khác biệt cốt lõi nằm ở thời điểm dịch: trình biên dịch đọc trọn mã nguồn, kiểm tra rồi sinh ra mã máy thành tệp thực thi, sau đó máy chạy trực tiếp tệp ấy mà không cần mã nguồn nữa; bộ thông dịch thì vừa đọc vừa thực hiện từng câu lệnh ở mỗi lần chạy. Ngôn ngữ C thuộc nhóm biên dịch, đó là lý do tệp nguồn phải dịch xong mới có chương trình để chạy. Ý "Compilation and interpretation are two terms that are used interchangeably." sai vì hai cơ chế khác nhau cả về sản phẩm trung gian lẫn cách báo lỗi. Ý "Algorithm is another term for interpretation in programming languages." sai vì thuật toán là trình tự các bước giải một bài toán, không phải một cách thực thi mã. Ý "IDE tools are responsible for both compilation and interpretation processes." sai vì môi trường phát triển chỉ gọi tới trình biên dịch, bản thân nó không làm việc dịch.
Mở trang câu hỏi này →
Amath.h
Bstdio.h
Cconio.h
Dmemory.h
Lời giải
Đáp án đúng: "math.h". Tệp tiêu đề này chứa nguyên mẫu của các hàm toán học trên số thực như sqrt, pow, sin, cos, fabs, ceil, floor, cùng các macro như HUGE_VAL. Có nguyên mẫu thì trình biên dịch mới biết hàm trả về double và mới kiểm được kiểu đối số; thiếu nó, lời gọi dễ bị hiểu sai kiểu trả về và cho ra kết quả lệch. Ý "stdio.h" sai vì nơi đó khai báo những thứ thuộc vào ra như printf, scanf, fopen và kiểu FILE. Ý "conio.h" sai vì đó không phải tệp tiêu đề chuẩn, nó chỉ có trên một số trình biên dịch để làm thao tác bàn phím và màn hình kiểu getch. Ý "memory.h" sai vì đó cũng là tệp ngoài chuẩn, gom vài hàm xử lý khối nhớ mà chuẩn C đặt trong string.h, chẳng hạn memcpy và memset.
Mở trang câu hỏi này →
AA compiler
BA text editor
CA file
DA program
Lời giải
Đáp án đúng: "A compiler". Máy chỉ hiểu được mã máy, còn tệp nguồn là văn bản viết theo quy tắc của ngôn ngữ, nên cần một chương trình chuyên trách đọc văn bản ấy, kiểm tra cú pháp và kiểu, rồi sinh ra các chỉ thị máy; chương trình chuyên trách đó là trình biên dịch. Ý "A text editor" sai vì bộ soạn thảo chỉ giúp gõ và lưu văn bản mã nguồn, nó không hiểu ngữ nghĩa của ngôn ngữ và không sinh ra mã máy. Ý "A file" sai vì tệp là nơi chứa dữ liệu, bản thân nó không thực hiện việc dịch nào. Ý "A program" sai vì nói chung chung như thế thì không phân biệt được gì: trình biên dịch đúng là một chương trình, nhưng đề hỏi cái gì đảm nhiệm việc dịch nên câu trả lời phải nêu đúng loại chương trình làm việc đó.
Mở trang câu hỏi này →
28What will the following code output?4 lựa chọncó code
Đề bài
#include <stdio.h>
int main() {
    int a = 7;
    printf("%d", (a << 2) | 1);
    return 0;
}
A28
B29
C15
D30
Lời giải
Đáp án đúng: "29". Biến a bằng 7 có dạng bit là 111. Phép dịch trái hai nhịp đẩy cả ba bit đó sang trái và lấp hai bit 0 vào cuối, thành 11100, tức là 28; đây cũng là lý do dịch trái n nhịp tương đương nhân với 2 lũy thừa n. Tiếp đó phép hoặc trên bit với 1 chỉ chạm vào bit thấp nhất, bit này đang là 0 nên nó được bật lên, cho 11101 là 29. Ý "28" sai vì nó dừng ở kết quả dịch trái, bỏ quên phép hoặc bit đứng sau. Ý "15" sai vì nó ứng với việc chỉ dịch trái một nhịp, ra 14 rồi bật bit thấp nhất thành 15. Ý "30" sai vì muốn ra 30 thì phải bật bit thứ hai tính từ phải, nghĩa là hoặc với 2, còn mặt nạ trong mã là 1; cũng cần nhớ đây là phép hoặc bit chứ không phải phép cộng, nên 28 không tự cộng thêm 2.
Mở trang câu hỏi này →
29What is the output of this reverse loop?4 lựa chọncó code
Đề bài
#define SIZE 5
int nums[SIZE] = {5, 10, 2, -45, 6};
for (int i = SIZE - 1; i >= 0; i--)
    printf("%d ", nums[i]);
A5 10 2 -45 6
B6 -45 2 10 5
C-45 2 10 5 6
DError
Lời giải
Đáp án đúng: "6 -45 2 10 5". Vòng for đặt i bắt đầu ở SIZE trừ 1 là 4, chạy tiếp khi i còn lớn hơn hoặc bằng 0 và giảm một đơn vị mỗi lượt, nên các chỉ số được thăm theo thứ tự 4, 3, 2, 1, 0. Đọc mảng theo thứ tự đó cho ra 6, -45, 2, 10, 5, mỗi số kèm một dấu cách vì chuỗi định dạng có dấu cách ở cuối. Ở đây vòng for không có cặp ngoặc nhọn nên nó chỉ ôm đúng một lệnh printf, vừa khớp ý định của mã. Ý "5 10 2 -45 6" sai vì đó là thứ tự xuôi, ứng với vòng lặp đi từ 0 lên. Ý "-45 2 10 5 6" sai vì nó bắt đầu từ chỉ số 3 rồi vòng lại phần tử cuối, không có phép lặp nào trong mã sinh ra trật tự ấy. Ý "Error" sai vì khai báo biến đếm ngay trong câu for là hợp lệ từ chuẩn C99, và chỉ số 4 vẫn nằm trong mảng 5 phần tử.
Mở trang câu hỏi này →
Afgets()
Bfputs()
Cftell()
Dfopen()
Lời giải
Đáp án đúng: "fgets()". Hàm này đọc từ một dòng tệp cho tới khi gặp ký tự xuống dòng hoặc khi đã lấy đủ số ký tự mà ta giới hạn, rồi tự thêm ký tự kết thúc chuỗi vào cuối vùng đệm. Chỗ giới hạn kích thước chính là lý do fgets được dùng thay cho gets, vì nó không cho dữ liệu vào tràn khỏi mảng đích. Ý "fputs()" sai vì nó làm việc ngược lại, ghi một chuỗi ra tệp. Ý "ftell()" sai vì nó chỉ cho biết vị trí hiện tại của con trỏ đọc ghi trong tệp, không chuyển một byte dữ liệu nào. Ý "fopen()" sai vì nó chỉ mở tệp và trả về con trỏ FILE cho các hàm khác dùng; mở xong vẫn chưa có ký tự nào được đọc vào bộ nhớ.
Mở trang câu hỏi này →
31What is the output of the following code snippet?4 lựa chọncó code
Đề bài
void main(){
    int x = 4;
    int *p = &x;
    int *k = p++;
    int r = p - k;
    printf("%d", r);
}
A1
B4
C5
D0
Lời giải
Đáp án đúng: "1". Phép tăng sau p++ nộp cho k giá trị cũ của p rồi mới đẩy p sang ô int kế tiếp, nên k trỏ vào x còn p trỏ vào ô liền sau. Hiệu hai con trỏ cùng kiểu trong C được tính theo số phần tử chứ không theo byte: trình biên dịch lấy khoảng cách byte rồi chia cho kích thước kiểu, vì vậy p trừ k bằng 1. Ý "4" sai vì 4 chính là khoảng cách tính bằng byte khi int chiếm 4 byte, tức là bỏ qua bước chia cho kích thước kiểu; nó lại trùng với giá trị của x nên càng dễ nhầm. Ý "5" sai vì không có phép tính nào cộng thêm 1 vào giá trị của x. Ý "0" sai vì nó cho rằng p++ chưa kịp có tác dụng hoặc k mãi mãi đi theo p; cần công bố rằng đây là khuyết điểm của đề, bộ khoá đi kèm ghi đúng giá trị 0 trong khi ngữ nghĩa của phép tăng sau buộc p và k phải lệch nhau đúng một phần tử.
Mở trang câu hỏi này →
Astrcat()
Bstrcomb()
Cstrmerge()
Dstrconnect()
Lời giải
Đáp án đúng: "strcat()". Thư viện chuỗi của C khai báo strcat trong string.h: nó tìm ký tự kết thúc của chuỗi đích, ghi tiếp chuỗi nguồn từ đúng chỗ đó rồi đặt lại ký tự kết thúc, nên người dùng phải tự bảo đảm mảng đích còn đủ chỗ cho cả phần cộng thêm và một byte kết thúc. Ý "strcomb()" sai vì không có hàm nào tên như vậy trong thư viện chuẩn, gọi nó sẽ gây lỗi lúc liên kết. Ý "strmerge()" sai vì đó cũng là một cái tên tự nghĩ ra, chuẩn C không định nghĩa. Ý "strconnect()" sai vì nó cũng không tồn tại; cần nhớ rằng tên các hàm chuỗi trong C đều rất ngắn và cố định, như strcpy để sao chép, strlen để đo độ dài, strcmp để so sánh và strcat để nối.
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 →
34What will be the output of the following C code?4 lựa chọncó code
Đề bài
#include <stdio.h>
void main()
{
    int k = 5;
    int *p = &k;
    int **m  = &p;
    **m = 6;
    printf("%d\n", k);
}
A5
BRun time error
C6
DJunk
Lời giải
Đáp án đúng: "6". Con trỏ p giữ địa chỉ của k, còn m giữ địa chỉ của p. Khi viết **m, lần lấy nội dung thứ nhất đi từ m sang p, lần thứ hai đi từ p sang chính ô nhớ của k, nên **m = 6 ghi số 6 thẳng vào ô của k. Vì k và **m là hai con đường tới cùng một ô, printf đọc ra 6. Đây là bản chất của con trỏ nhiều cấp: chúng không sao chép giá trị mà chỉ nối thêm một chặng đường tới ô nhớ gốc. Ý "5" sai vì 5 chỉ là giá trị ban đầu, nó đã bị ghi đè trước lúc in. Ý "Run time error" sai vì cả hai con trỏ đều trỏ vào biến còn sống trong hàm, không có địa chỉ nào không hợp lệ. Ý "Junk" sai vì k đã được khởi tạo rồi sau đó còn được gán tường minh, không còn chỗ nào để giá trị rác xen vào.
Mở trang câu hỏi này →
AArrays provide constant-time access to elements.
BArrays allow for dynamic resizing during runtime.
CArrays can store elements of different data types.
DArrays automatically adjust their size based on the number of elements.
Lời giải
Đáp án đúng: "Arrays provide constant-time access to elements.". Mảng chiếm một dải ô nhớ liên tục và mọi phần tử cùng một kiểu nên cùng kích thước; nhờ vậy địa chỉ phần tử thứ i tính ra ngay bằng địa chỉ đầu cộng i nhân kích thước một phần tử, một phép tính không phụ thuộc vào i, tức là thời gian truy xuất là hằng số. Ý "Arrays allow for dynamic resizing during runtime." sai vì mảng khai báo tĩnh có kích thước cố định từ lúc dịch, muốn thay đổi dung lượng thì phải tự cấp vùng nhớ động rồi gọi realloc, và đó không còn là mảng ban đầu nữa. Ý "Arrays can store elements of different data types." sai vì mảng đòi hỏi các phần tử đồng kiểu, chính điều đó mới cho phép tính địa chỉ bằng một bước nhảy cố định. Ý "Arrays automatically adjust their size based on the number of elements." sai vì số phần tử ghi trong khai báo là bất biến; khởi tạo thiếu giá trị thì phần còn lại nhận 0 chứ mảng không tự co lại hay nở ra.
Mở trang câu hỏi này →
ATrue
B1
C0
D-1
Lời giải
Đáp án đúng: "0". Hàm strcmp so sánh hai chuỗi theo từng cặp ký tự dựa trên mã của chúng và trả về một số nguyên thể hiện quan hệ thứ tự: âm khi chuỗi thứ nhất bé hơn, dương khi lớn hơn, và đúng 0 khi hai chuỗi trùng nhau tới ký tự kết thúc. Vì thế phép thử hai chuỗi giống nhau phải viết là strcmp bằng 0, một cách diễn đạt thoạt nghe trái trực giác. Ý "True" sai vì strcmp trả về int, trong C không có giá trị nào mang tên như vậy; hơn nữa đem kết quả dùng trực tiếp làm điều kiện thì hai chuỗi bằng nhau lại bị coi là sai. Ý "1" sai vì giá trị dương chỉ xuất hiện khi chuỗi thứ nhất lớn hơn, và chuẩn cũng không hứa đúng con số 1. Ý "-1" sai vì giá trị âm ứng với trường hợp chuỗi thứ nhất bé hơn, chuẩn chỉ hứa dấu chứ không hứa độ lớn.
Mở trang câu hỏi này →
37What is the main() function in C?4 lựa chọn
AIt is the function where the program's execution starts.
BEvery program has exactly one main function.
CThe main function always returns an integer value or void.
DAll answers are correct.
Lời giải
Đáp án đúng: "All answers are correct.". Cả ba nhận định còn lại đều nói về cùng một hàm và đều đúng: main là nơi quá trình thực thi bắt đầu, mỗi chương trình có đúng một hàm main vì nếu không bộ liên kết không biết chọn điểm vào nào, và kiểu trả về của nó là số nguyên theo chuẩn, còn dạng void chỉ được một số trình biên dịch chấp nhận. Ý "It is the function where the program's execution starts." đúng về nội dung nhưng không thể là lựa chọn vì nó bỏ qua hai tính chất kia, chọn nó là bỏ sót phần còn lại của câu trả lời. Ý "Every program has exactly one main function." cũng đúng mà vẫn thiếu, nó không nói gì về điểm khởi đầu hay kiểu trả về. Ý "The main function always returns an integer value or void." đúng theo cách dùng phổ biến nhưng cũng chỉ mô tả một mặt, không đủ bao phủ câu hỏi.
Mở trang câu hỏi này →
38What is the output?4 lựa chọncó code
Đề bài
int x = 0, y = 5;
printf("%d", (x && y));
A1
B5
C-1
D0
Lời giải
Đáp án đúng: "0". Phép và luận lý trong C cho ra kết quả thuộc kiểu int và chỉ nhận một trong hai giá trị 0 hoặc 1, nó không trả lại chính toán hạng. Thêm nữa nó tính tắt: thấy toán hạng bên trái bằng 0, nghĩa là sai, thì cả biểu thức đã chắc chắn sai nên y không cần đọc tới. Vì vậy đặc tả %d in ra 0. Ý "1" sai vì 1 chỉ xuất hiện khi cả hai toán hạng đều khác 0. Ý "5" sai vì nó tưởng phép và trả về giá trị của toán hạng cuối, đó là cách làm của một số ngôn ngữ khác chứ không phải của C. Ý "-1" sai vì chuẩn quy định kết quả của các phép luận lý chỉ là 0 hoặc 1, không bao giờ là số âm.
Mở trang câu hỏi này →
A'\0'
B'\n'
C'\t'
D'\'
Lời giải
Đáp án đúng: "'\0'". Chuỗi trong C không mang theo độ dài, nó chỉ là một dãy ký tự nằm liên tục và kết thúc bằng một byte giá trị 0; mọi hàm như strlen, strcpy hay printf với đặc tả %s đều dò tới byte đó để biết chỗ dừng. Đây là lý do mảng chứa chuỗi phải khai báo thừa một ô so với số ký tự thật. Ý "'\n'" sai vì đó là ký tự xuống dòng, nó chỉ là một ký tự nội dung bình thường có thể nằm giữa chuỗi. Ý "'\t'" sai vì đó là ký tự tab, cũng là nội dung chứ không phải dấu kết thúc. Ý "'\'" sai vì cách viết này còn không hợp lệ: dấu gạch chéo ngược mở đầu một chuỗi thoát nên muốn biểu diễn chính nó phải viết gấp đôi.
Mở trang câu hỏi này →
ATo determine the value of a variable.
BTo determine the type of a variable.
CTo determine the size (in bytes) occupied by a variable or type.
DTo determine the address of a variable.
Lời giải
Đáp án đúng: "To determine the size (in bytes) occupied by a variable or type.". Toán tử sizeof cho biết số byte mà một đối tượng hay một kiểu chiếm trong bộ nhớ, và nó được tính ngay lúc dịch chứ không phải lúc chạy, vì trình biên dịch đã biết trọn vẹn cách bố trí kiểu. Nhờ nó mà các lời gọi malloc hay realloc viết được theo kiểu dữ liệu, không phải ghi cứng con số byte vốn khác nhau giữa các nền tảng. Ý "To determine the value of a variable." sai vì sizeof không hề đọc giá trị, áp nó lên một biến chưa khởi tạo vẫn ra kết quả đúng. Ý "To determine the type of a variable." sai vì nó trả về một con số, mà hai kiểu khác nhau vẫn có thể cùng kích thước nên con số đó không nhận dạng được kiểu. Ý "To determine the address of a variable." sai vì muốn lấy địa chỉ phải dùng toán tử lấy địa chỉ, sizeof không liên quan tới vị trí của biến.
Mở trang câu hỏi này →