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ố 1

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
ACheck the day of the week.
BSort an array ascending.
CSort an array descending.
DFind the average value of a sequence.
Lời giải
Đáp án đúng: "Check the day of the week." Lệnh switch so khớp một giá trị nguyên hoặc ký tự với từng nhãn hằng, nên nó hợp đúng với bài toán phân loại theo một tập giá trị rời rạc biết trước; thứ trong tuần chỉ có bảy giá trị nên mỗi case ứng một thứ, đọc rõ hơn chuỗi if else dài. "Sort an array ascending." sai vì sắp xếp cần so sánh và đổi chỗ từng cặp phần tử trong vòng lặp, không có tập nhãn hằng nào để so khớp. "Sort an array descending." sai vì lý do y hệt, chỉ khác chiều so sánh; switch không so sánh lớn nhỏ, nó chỉ xét bằng. "Find the average value of a sequence." sai vì tính trung bình là cộng dồn rồi chia, việc của vòng lặp và biểu thức số học, hơn nữa số phần tử không giới hạn nên không thể liệt kê thành case.
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 →
Đề 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 →
Đề bài
double a = -7.5, b = 7.5;
printf( "%.0f : %.0f\n", ceil( a ), ceil( b ) );
printf( "%.0f : %.0f\n", floor( a ), floor( b ) );
A-7 : 8 -8 : 7
B-7 : 7 -8 : 8
C-8 : 7 -8 : 7
D-8 : 7 -7 : 8
Lời giải
Đáp án đúng: "-7 : 8 -8 : 7". Hàm ceil làm tròn lên, lấy số nguyên nhỏ nhất không nhỏ hơn đối số: với -7.5 là -7 vì trên trục số -7 nằm bên phải -7.5, với 7.5 là 8. Hàm floor làm tròn xuống, lấy số nguyên lớn nhất không lớn hơn đối số: với -7.5 là -8, với 7.5 là 7. Vì vậy dòng đầu in -7 : 8 rồi dòng sau in -8 : 7; định dạng %.0f chỉ bỏ phần thập phân khi hiển thị, mà các giá trị đã nguyên nên không làm tròn thêm lần nào. "-7 : 7 -8 : 8" sai ở cột số dương vì ceil của 7.5 phải là 8. "-8 : 7 -8 : 7" lặp kết quả của floor cho cả hai dòng, tức coi ceil cũng làm tròn xuống. "-8 : 7 -7 : 8" đảo vai hai hàm, gán kết quả floor cho dòng gọi ceil và ngược lại.
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 →
Aint average( double, double);
Bdouble average( double, double);
Cchar average( double, double);
Dvoid average( double, double);
Lời giải

Đáp án đúng: "double average( double, double);". Trung bình của hai số thực nói chung vẫn là số thực, chẳng hạn trung bình của 1.0 và 2.0 là 1.5, nên kiểu trả về phải giữ được phần thập phân; double là kiểu thực chuẩn của C và cùng kiểu với hai tham số nên không mất mát khi tính. "int average( double, double);" sai vì kiểu nguyên cắt bỏ phần thập phân lúc trả về, 1.5 thành 1. "char average( double, double);" sai vì char chỉ một byte, dành cho ký tự hoặc số nguyên rất nhỏ, không chứa nổi một giá trị thực. "void average( double, double); " sai vì void nghĩa là không trả về gì, hàm sẽ không có cách nào đưa kết quả ra ngoài bằng lệnh return.

Mở trang câu hỏi này →
28What will be the output of the following C code?4 lựa chọncó code
Đề bài
#include <stdio.h>
void main()
{
    int *ptr, a = 10;
    ptr = &a;
    *ptr += 1;
    printf("%d,%d\n", *ptr, a);
}
A10,10
B10,11
C11,10
D11,11
Lời giải
Đáp án đúng: "11,11". Lệnh ptr = &a làm ptr giữ địa chỉ ô nhớ của a, nên *ptr và a là hai cách gọi cùng một chỗ chứ không phải hai bản sao; *ptr += 1 cộng 1 vào chính ô đó nên a thành 11, và khi in thì cả *ptr lẫn a đều đọc ra 11. Bản chất là bí danh: con trỏ không chứa giá trị, nó chỉ chứa địa chỉ. "10,10" sai vì phép cộng đã thực sự ghi vào bộ nhớ, giá trị không còn là 10. "10,11" sai vì *ptr không thể đọc ra giá trị cũ khi ô nhớ đã đổi. "11,10" sai vì a không phải bản sao riêng, nó chính là ô nhớ mà ptr trỏ tới, nên không thể giữ 10 trong khi *ptr đã là 11.
Mở trang câu hỏi này →
29What is the output of the following code snippet?4 lựa chọncó code
Đề bài
#include <stdio.h>
int num(int a, int b){
    int sum;
    sum = a + b;
    return sum;
}

int main()
{
    int a, b, result;
    a = 10;
    b= 12;
    result = num(a, b);
    printf("%d", result);
    return 0;
}
A22
B10
C12
D21
Lời giải
Đáp án đúng: "22". Hàm num nhận hai tham số rồi trả về tổng của chúng; main gọi num(a, b) với a bằng 10 và b bằng 12 nên a + b bằng 22, giá trị đó đi ra ngoài qua lệnh return, được gán cho result rồi in. Tham số trong C truyền theo giá trị nên hàm làm việc trên bản sao và không đổi được a hay b ở main, nhưng kết quả vẫn ra ngoài được nhờ return. "10" chỉ là giá trị của a, ứng với việc hiểu hàm trả về tham số thứ nhất. "12" chỉ là giá trị của b, ứng với việc hiểu hàm trả về tham số còn lại. "21" không khớp phép cộng nào của hai số này, nó lệch một đơn vị so với tổng thật.
Mở trang câu hỏi này →
Adouble
Bfloat
Cint
Dlong
Lời giải
Đáp án đúng: "double". Thư viện math.h làm việc với số thực độ chính xác kép, nên sqrt nhận một đối số double và trả về double; nhờ vậy căn bậc hai của 2 giữ được nhiều chữ số có nghĩa, và muốn in thì dùng định dạng %f hoặc %lf. "float" sai vì bản trả về float có tên riêng là sqrtf; gán kết quả của sqrt vào biến float thì bị thu hẹp và mất chính xác. "int" sai vì căn bậc hai nói chung không nguyên, trả về kiểu nguyên sẽ cắt mất phần thập phân, chẳng hạn căn của 2 thành 1. "long" sai cùng lý do, long vẫn là kiểu nguyên, chỉ khác độ rộng lưu trữ.
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 →
Arandom()
Brand()
Cgenerate_random()
Dgetrand()
Lời giải
Đáp án đúng: "rand()". Hàm rand khai báo trong stdlib.h, mỗi lần gọi trả về một số nguyên giả ngẫu nhiên nằm trong khoảng từ 0 tới RAND_MAX, trong đó RAND_MAX là hằng do thư viện định nghĩa; muốn thu về đoạn hẹp hơn thì lấy phần dư, muốn dãy khác nhau giữa các lần chạy thì gọi srand với mầm thay đổi. "random()" không thuộc thư viện chuẩn C, nó là hàm mở rộng của một số hệ điều hành họ Unix và trả về kiểu long với khoảng giá trị khác. "generate_random()" không tồn tại trong thư viện chuẩn, gọi tới sẽ lỗi ở khâu liên kết. "getrand()" cũng không có trong thư viện chuẩn, tên này thường do người học tự đặt theo thói quen gọi hàm lấy giá trị.
Mở trang câu hỏi này →
AIt checks if a character is an alphabet.
BIt returns to a non-zero value if the character is a digit (0-9).
CIt only works with float inputs.
DIt converts a digit to integer.
Lời giải
Đáp án đúng: "It returns to a non-zero value if the character is a digit (0-9)." Hàm isdigit trong ctype.h xét mã ký tự và trả về giá trị khác 0 khi ký tự đó là một trong mười chữ số, trả 0 với mọi ký tự khác; đây là cách kiểm tra đúng khi đọc chuỗi nhập để biết người dùng có gõ số hay không. "It checks if a character is an alphabet." sai vì việc xét chữ cái thuộc hàm isalpha. "It only works with float inputs." sai vì hàm nhận một tham số kiểu int chứa mã ký tự, nó không liên quan gì tới số thực. "It converts a digit to integer." sai vì hàm chỉ kiểm tra chứ không chuyển đổi; muốn đổi ký tự số thành giá trị thì trừ đi mã của ký tự 0, hoặc dùng atoi cho cả chuỗi.
Mở trang câu hỏi này →
Đề bài
#include <stdio.h>
#include <conio.h>
int main() {
    int n = 267, *pn = &n;
    char* pc = pn;
    *pc = 0;
    printf("n = %d", n);
    return 0;
}
An = 0
Bn = 267
Cn = 256
Derror
Lời giải
Đáp án đúng: "n = 256". n bằng 267, viết ở hệ mười sáu là 0x010B, tức một byte chứa 0x0B là 11 và byte cao hơn chứa 0x01 ứng với 256. Con trỏ pc giữ cùng địa chỉ của n nhưng mang kiểu con trỏ ký tự, nên *pc = 0 chỉ ghi 0 vào đúng một byte, byte nằm ở địa chỉ thấp nhất; trên máy lưu byte nhỏ trước, byte đó chính là 0x0B, vì vậy n còn lại 0x0100 là 256. "n = 0" sai vì một phép gán qua con trỏ ký tự chỉ xoá một byte, các byte còn lại của int không bị chạm. "n = 267" sai vì phép ghi đã thực sự thay đổi bộ nhớ. "error" sai vì gán con trỏ int cho con trỏ ký tự chỉ khiến trình biên dịch cảnh báo kiểu không khớp, mã vẫn dịch và chạy ra kết quả.
Mở trang câu hỏi này →
35Consider the following code:4 lựa chọncó code
Đề bài
int func(int* a, int n){
    int S = 0;
    for(int i = 0; i < n; i++) {
        S = S + (a[i] % 2)*a[i];
    }
    return S;
}

What does the above code snippet do?

ACalculates the sum of the absolute value of all odd elements in the array a of size n.
BCalculates the sum of all odd elements in the array a of size n.
CCalculates the sum of all even elements in the array a of size n.
DCalculates the sum of squares of all elements in the array a of size n.
Lời giải
Đáp án đúng: "Calculates the sum of the absolute value of all odd elements in the array a of size n." Chìa khoá là biểu thức (a[i] % 2)*a[i]: với số chẵn phần dư là 0 nên hạng tử bằng 0; với số lẻ dương phần dư là 1 nên hạng tử bằng chính a[i]; với số lẻ âm, phép lấy dư trong C giữ dấu của toán hạng bên trái nên -3 % 2 cho -1, hạng tử thành -1 nhân -3 là 3, tức trị tuyệt đối. "Calculates the sum of all odd elements in the array a of size n." chỉ trùng kết quả khi mảng không có số lẻ âm, nên sai trong trường hợp tổng quát: gặp -3 thì hàm cộng 3 chứ không cộng -3. "Calculates the sum of all even elements in the array a of size n." sai vì số chẵn cho phần dư 0 nên không góp gì vào tổng. "Calculates the sum of squares of all elements in the array a of size n." sai vì bình phương phải là a[i] nhân a[i], còn ở đây một thừa số chỉ nhận 0, 1 hoặc -1.
Mở trang câu hỏi này →
AThe number of elements in arr
BThe size of arr in bytes
CThe number of bytes occupied by each element in arr
DThe total size of arr in bytes
Lời giải
Đáp án đúng: "The number of elements in arr". Toán tử sizeof cho số byte mà toán hạng chiếm; với một mảng thật thì sizeof(arr) là tổng số byte của cả mảng và sizeof(arr[0]) là số byte của một phần tử, nên phép chia cho ra số phần tử mà không cần biết kiểu. Mẹo này chỉ đúng ở nơi arr còn là mảng: truyền mảng vào hàm thì nó suy biến thành con trỏ và phép chia cho ra số vô nghĩa. "The size of arr in bytes" sai vì đó là giá trị của riêng sizeof(arr), chưa chia. "The number of bytes occupied by each element in arr" sai vì đó là giá trị của riêng sizeof(arr[0]), tức số chia chứ không phải thương. "The total size of arr in bytes" cũng chỉ là tử số; phép chia đã triệt tiêu đơn vị byte nên thương là một số đếm, không còn là dung lượng.
Mở trang câu hỏi này →
37What 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 →
38What will be the output of the C program?4 lựa chọncó code
Đề bài
int arr[5] = { 2, 3, 5, 4, 7 };
int *ptr = (&arr + 1);
printf("%d %d\n", *(arr + 1), *(ptr - 1));
A2 3
B3 2
C3 7
D2 6356728
Lời giải
Đáp án đúng: "3 7". Tên mảng arr khi dùng trong biểu thức suy biến thành con trỏ tới phần tử đầu, nên *(arr + 1) chính là arr[1], bằng 3. Nhưng &arr lại mang kiểu con trỏ tới cả mảng năm int, nên &arr + 1 nhảy qua trọn mảng và trỏ vào ô ngay sau arr[4]; gán vào int *ptr rồi ptr - 1 lùi đúng một ô int nên về arr[4], bằng 7. Chương trình in 3 7. Cần công bố khuyết điểm: bản khoá in kèm ghi 3 2, giá trị đó chỉ ra được nếu hiểu &arr + 1 nhảy một phần tử như arr + 1, khi đó ptr - 1 mới về arr[0], nên "3 2" sai. "2 3" lấy arr[0] cho vế đầu, nhưng vế đầu là arr[1]. "2 6356728" giả định đọc phải rác ngoài mảng, trong khi ptr - 1 vẫn trỏ vào đúng phần tử cuối của arr.
Mở trang câu hỏi này →
ABecause arrays allow fast insertion/deletion of elements
BBecause elements in an array are allocated in scattered memory locations
CBecause elements can be accessed directly by unique index
DBecause arrays automatically expand in size when new elements are added
Lời giải
Đáp án đúng: "Because elements can be accessed directly by unique index". Mảng nằm liền khối trong bộ nhớ và mọi phần tử cùng kích thước, nên địa chỉ phần tử thứ i tính được ngay bằng địa chỉ đầu cộng i nhân kích thước một phần tử; phép tính đó tốn thời gian như nhau với mọi i, không phải dò tuần tự. "Because arrays allow fast insertion/deletion of elements" sai vì chèn hay xoá giữa mảng buộc phải dịch chuyển mọi phần tử phía sau. "Because elements in an array are allocated in scattered memory locations" sai ngược hẳn: chính tính liền khối mới cho phép tính địa chỉ, còn nằm rải rác là đặc điểm của danh sách liên kết. "Because arrays automatically expand in size when new elements are added" sai vì mảng trong C có kích thước cố định, muốn lớn hơn phải tự cấp phát vùng mới rồi chép sang.
Mở trang câu hỏi này →
40What will be the output of the following program?4 lựa chọncó code
Đề bài
int main()
{
        int i = 101;
            int *p = &i;
            printf("%d\n", *p++);
    return 0;
}
A101
B102
C0
DAddress of i
Lời giải
Đáp án đúng: "101". Trong biểu thức *p++, toán tử tăng hậu tố gắn với p chứ không với *p, và nó trả về giá trị con trỏ trước khi tăng, nên phép lấy nội dung làm việc trên địa chỉ cũ, tức đọc i và in 101; chỉ sau lệnh đó p mới trỏ ra ô kế tiếp, điều này vô hại vì p không được dùng nữa. "102" là kết quả nếu tăng chính giá trị được trỏ, tức viết (*p)++ hoặc ++*p; ở đây phép tăng chạm vào con trỏ, không chạm vào i. "0" không có cơ sở nào vì ô nhớ của i chứa 101 và không bị ghi lại. "Address of i" sai vì biểu thức *p đã lấy nội dung chứ không phải địa chỉ, hơn nữa muốn in địa chỉ thì phải dùng p với định dạng %p.
Mở trang câu hỏi này →