Professional Documents
Culture Documents
Lớp: CNT61
BÁO CÁO HỌC PHẦN MÔN HỌC
Lập Trình căn bản C
A.Phần lí thuyết
Câu 1: Trình bày cấu trúc của chương trình C
Một chương trình C bao gồm những phần sau đây:
Các lệnh tiền xử lý
Các hàm
Các biến
Các lệnh và biểu thức
Các comment
--Code đơn giản với hai từ Hello World
#include <stdio.h>
int main()
{
/* Day la chuong trinh C dau tien */
printf("Hello, World! \n");
return 0;
}
Các phần của chương trình bên trên:
Dòng đầu tiên của chương trình #include <stdio.h> là lệnh tiền xử lý, nhắc nhở bộ
biên dịch C thêm tệp stdio.h trước khi biên dịch.
Dòng tiếp theo int main() là hàm main, nơi chương trình bắt đầu.
Dòng tiếp theo /*...*/ là dòng comment được bỏ qua bởi bộ biên dịch compiler và
được dùng để thêm các chú thích cho chương trình. Đây được gọi là phần
comment của chương trình.
Dòng tiếp theo printf(...) là một hàm chức năng khác của ngôn ngữ C , in ra thông
điệp "Hello, World!" hiển thị trên màn hình.
Dòng tiếp theo return 0; kết thúc hàm chính và trả về giá trị 0.
Câu 2: Trình bày các kiểu dữ liệu cơ bản trong ngôn ngữ lập trình
C , cách khai báo biến trong ngôn ngữ lập trình C
Trong ngôn ngữ lập trình C, các kiểu dữ liệu ám chỉ phần mở rộng của hệ thống
được sử dụng cho khai báo biến với cái kiểu khác nhau. Kiểu của biến xác định
lượng bộ nhớ được dùng để lưu biến đó và cách các bit được lưu trữ khi được
thông dịch.
Các kiểu biến trong C được phân chia như sau:
ST
Kiểu và miêu tả
T
Kiểu cơ bản
1 Là các kiểu dữ liệu số học và bao gồm 2 kiểu chính: a)
kiểu số nguyên và b) kiểu số thực dấu chấm động.
Kiểu liệt kê
Kiểu void
3 Kiểu định danh void là kiểu đặc biệt thể hiện rằng không
có giá trị nào.
Các kiểu dữ liệu mảng và cấu trúc được sử dụng trong tập hợp như các kiểu dữ liệu
gộp. Các kiểu là hàm chỉ định loại kiểu mà hàm trả về. Chúng ta sẽ xem các kiểu
dữ liệu cơ bản ở phần dưới đây, trong đó những kiểu còn lại sẽ được nhắc đến ở
các chương sau.
Kiểu số nguyên (kiểu int) trong C
Bảng dưới đây đưa cho bạn những hiểu biết chi tiết về kiểu số nguyên với cỡ lưu
trữ cũng như giới hạn của nó:
Kiểu Cỡ lưu trữ Dãy giá trị
unsigned
1 byte 0 tới 255
char
unsigned 2 hoặc 4
0 tới 65,535 hoặc 0 tới 4,294,967,295
int bytes
unsigned
2 bytes 0 tới 65,535
short
unsigned
4 bytes 0 tới 4,294,967,295
long
Bạn có thể lấy cỡ chính xác của các kiểu của các biến trên những nền tảng cụ thể,
bạn có thể sử dụng toán tử sizeof. Biểu thức sizeof(kieu) trả về cỡ của đối tượng
hoặc kiểu dưới dạng byte. Dưới đây là ví dụ để lấy về size của đối tượng int trên
bất kỳ máy tính nào.
#include <stdio.h>
#include <limits.h>
int main()
{
printf("Kich co luu tru cho so nguyen (int) la: %d \n", sizeof(int));
return 0;
}
Biên dịch và chạy chương trình C trên sẽ cho kết quả:
Kich co luu tru cho so nguyen (int) la: 4
Kiểu số thực dấu chấm động (Floating-Point) trong C
Bảng dưới đây đưa cho bạn những hiểu biết cụ thể về các kiểu số thực dấu chấm
động tiêu chuẩn với cỡ lưu trữ và dải giá trị cũng như độ chính xác:
Cỡ lưu
Kiểu Dãy giá trị Độ chính xác
trữ
6 vị trí thập
float 4 byte 1.2E-38 tới 3.4E+38
phân
15 vị trí thập
double 8 byte 2.3E-308 tới 1.7E+308
phân
float.h trong Header file định nghĩa các macro cho phép bạn sử dụng các giá trị này
và các kiểu cụ thể khác về giá trị biểu diễn nhị phân của số thực trong chương trình
của bạn. Dưới đây là ví dụ sẽ in ra cỡ của kiểu float cũng như dải giá trị của nó:
#include <stdio.h>
#include <float.h>
int main()
{
printf("Lớp lưu trữ cho số thực (float) là: %d \n", sizeof(float));
printf("Giá trị số thực dương nhỏ nhất là: %E\n", FLT_MIN );
printf("Giá trị số thực dương lớn nhất là: %E\n", FLT_MAX );
printf("Độ chính xác: %d\n", FLT_DIG );
return 0;
}
Biên dịch và chạy chương trình C trên sẽ cho kết quả:
Lớp lưu trữ cho số thực (float) là: 4
Giá trị số thực dương nhỏ nhất là: 1.175494E-38
Giá trị số thực dương lớn nhất là: 3.402823E+38
Độ chính xác: 6
Kiểu void trong C
Kiểu void xác định không có giá trị nào. Nó được sử dụng trong 3 trường hợp sau
đây:
Hàm trả về void: Có rất nhiều hàm trong ngôn ngữ C mà không trả về dữ liệu nào
và bạn có thể nói rằng đó là hàm void. Một hàm mà không trả về giá trị nào có kiểu
là void. Ví dụ: void exit (int status);
Hàm với tham số void: Có những hàm trong C mà không chấp nhận bất kỳ tham
số. Một hàm với không có tham số nào có thể chấp nhâu là một void. Ví dụ: int
rand(void);
Con trỏ tới void: Một con trỏ có kiểu void * đại diện cho địa chi của đối tượng, chứ
không phải là một kiểu. Ví dụ hàm cấp phát bộ nhớ void *malloc (size_t size); trả
về một con trỏ void có thể ép kiểu sang bất kỳ một đối tượng nào.
Tên
Ý nghĩa
kiểu
Đơn vị cơ bản nhất có thể địa chỉ hóa được; nó là một byte. Đây là một
Char
kiểu nguyên.
Loại số nguyên theo kích cỡ tự nhiên nhất của các máy tính. Thông
thường nó có thể lấy trọn một khoảng có thể địa chỉ hoá được của
int
một word với độ lớn biến thiên từ 16, 32, hay 64 bit tùy theo kiến trúc
của CPU và hệ điều hành.
float Một giá trị dấu chấm động có độ chính xác đơn.
double Một giá trị dấu chấm động có độ chính xác kép.
Để khai báo một biến có kiểu cơ bản, tên của kiểu được ghi ra trước sau đó đến tên
của biến mới (hay của nhiều biến mới cách phân cách nhau bởi dấu phẩy) -- (Xem
thêm định nghĩa dãy điểm)
char red;
int blue, yellow;
Các định tính khác nhau có thể đặt vào trong các kiểu cơ bản này để điều chỉnh
kích cỡ và sẽ được miêu tả trong phần sau.
Câu 3: Câu lệnh đưa kết quả ra màn hình (hàm printf)
Đưa kết quả lên màn hình - hàm printf:
Cách dùng:
prinf(điều khiển, đối số 1, đối số 2, ...);
Hàm printf chuyển, tạo khuôn dạng và in các đối của nó ra thiết bị ra chuẩn dưới
sự điều khiển của xâu điều khiển. Xâu điều khiển chứa hai kiểu đối tượng: các ký
tự thông thường, chúng sẽ được đưa ra trực tiếp thiết bị ra, và các đặc tả chuyển
dạng, mỗi đặc tả sẽ tạo ra việc đổi dạng và in đối tiếp sau của printf.
Chuỗi điều khiển có thể có các ký tự điều khiển:
sang dòng mới
f sang trang mới
lùi lại một bước
dấu tab
Dạng tổng quát của đặc tả:
%[-][fw][.pp]ký tự chuyển dạng
Mỗi đặc tả chuyển dạng đều được đưa vào bằng ký tự % và kết thúc bởi một ký tự
chuyển dạng. Giữa % và ký tự chuyển dạng có thể có:
Dấu trừ:
Khi không có dấu trừ thì kết quả ra được dồn về bên phải nếu độ dài thực tế của kết
quả ra nhỏ hơn độ rộng tối thiểu fw dành cho nó. Các vị trí dư thừa sẽ được lấp đầy
bằng các khoảng trống. Riêng đối với các trường số, nếu dãy số fw bắt đầu bằng số
0 thì các vị trí dư thừa bên trái sẽ được lấp đầy bằng các số 0.
Khi có dấu trừ thì kết quả được dồn về bên trái và các vị trí dư thừa về bên phải
( nếu có ) luôn được lấp đầy bằng các khoảng trống.
fw:Khi fw lớn hơn độ dài thực tế của kết quả ra thì các vị trí dư thừa sẽ được lấp
đầy bởi các khoảng trống hoặc số 0 và nội dung của kết quả ra sẽ được đẩy về bên
phải hoặc bên trái.
Khi không có fw hoặc fw nhỏ hơn hay bằng độ dài thực tế của kết quả ra thì độ
rộng trên thiết bị ra dành cho kết quả sẽ bằng chính độ dài của nó.
Tại vị trí của fw ta có thể đặt dấu *, khi đó fw được xác định bởi giá trị nguyên của
đối tương ứng.
Ví dụ:
-2503 8 có -2503
-2503 08 có -2503
"abcdef" 08 có Abcdef
pp: Tham số pp chỉ được sử dụng khi đối tương ứng là một xâu ký tự hoặc một giá
trị kiểu float hay double.
Trong trường hợp đối tương ứng có giá trị kiểu float hay double thì pp là độ chính
xác của trường ra. Nói một cách cụ thể hơn giá trị in ra sẽ có pp chữ số sau số thập
phân.
Khi vắng mặt pp thì độ chính xác sẽ được xem là 6.
Khi đối là xâu ký tự:Nếu pp nhỏ hơn độ dài của xâu thì chỉ pp ký tự đầu tiên của
xâu được in ra. Nếu không có pp hoặc nếu pp lớn hơn hay bằng độ dài của xâu thì
cả xâu ký tự sẽ được in ra.
Ví dụ:
-435.645 10 2 có -435.65 7
-435.645 10 0 có -436 4
"alpha" 8 6 có alpha 5
Các ký tự chuyển dạng và ý nghĩa của nó:
Ký tự chuyển dạng là một hoặc một dãy ký hiệu xác định quy tắc chuyển dạng và
dạng in ra của đối tương ứng. Như vậy sẽ có tình trạng cùng một số sẽ được in ra
theo các dạng khác nhau. Cần phải sử dụng các ký tự chuyển dạng theo đúng qui
tắc định sẵn. Bảng sau cho các thông tin về các ký tự chuyển dạng.
Ký tự
chuyển Ý nghĩa
dạng
o Đối được chuyển sang hệ tám không dấu ( không có số 0 đứng trước )
x Đối được chuyển sang hệ mưới sáu không dấu ( không có 0x đứng trước )
Đối là xâu ký tự, các ký tự trong xâu được in cho tới khi gặp ký tự không hoặc cho
s
số lượng ký tự được xác định bởi các đặc tả về độ chính xác pp.
Đối được xem là float hoặc double và được chuyển sang dạng thập phân có dạng [-
e
hoặc -] với độ dài của xâu chứa n là pp.
Đối được xem là float hoặc double và được chuyển sang dạng thập phân có dạng [-
f với độ dài của xâu chứa n là pp. Độ chính xác mặc định là 6. Lưu ý rằng độ chính x
xác định ra số các chữ số có nghĩa phải in theo khuôn dạng f.
g Dùng %e hoặc %f, tuỳ theo loại nào ngắn hơn, không in các số 0 vô nghĩa.
Câu 4: Câu lệnh lập dữ liệu cho biến ( hàm scanf ) ; hàm gets
*Hàm scanf() trong C
+Hàm int scanf(const char *format,...) trong Thư viện C chuẩn đọc input đã được
định dạng từ stdin.
Hàm scanf không chấp nhận khoảng trống giữa hai chuỗi (khác với hàm gets()),
tức là chỉ có thể nhập một chuỗi liền nhau, nếu bạn nhập cả phần khoảng trống thì
phần nội dung sau khoảng trống đầu tiên sẽ không được chấp nhận.
-Khai báo hàm scanf() trong C
Dưới đây là phần khai báo cho hàm scanf() trong C:
int scanf(const char *format, ...)
-Tham số
format -- Đây là chuỗi chứa một trong các item sau:
Ký tự Whitespace, ký tự Non-whitespace và Format specifier. Một format specifier
sẽ là dạng [=%[*][width][modifiers]type=], được giải thích như sau:
Tham số Miêu tả
Đây là một dấu hoa thị bắt đầu
(tùy ý) để chỉ rằng dữ liệu là
được đọc từ Stream nhưng bị
*
bỏ qua, ví dụ: nó không được
lưu trữ trong tham số tương
ứng
-Hàm char *gets(char *str) trong Thư viện C chuẩn đọc một dòng từ stdin và lưu
trữ nó bên trong chuỗi được trỏ bởi str. Nó dừng khi bắt gặp end-of-file hoặc ký tự
newline (dòng mới) được đọc.
Hàm gets() khác hàm scanf() ở chỗ là hàm này chấp nhận các chuỗi có khoảng
trống.
-Khai báo hàm gets() trong C:
Dưới đây là phần khai báo cho hàm gets() trong C:
char *gets(char *str)
-Tham số:
str -- Đây là con trỏ tới mảng các char nơi chuỗi được lưu trữ.
-Trả về giá trị:Hàm này trả về str nếu thành công, và NULL nếu có lỗi hoặc xuất
hiện End-Of-File, trong khi không có ký tự nào đã được đọc.
Câu 5: Trình bày cú pháp và giải thích các cấu trúc điều khiển
( lệnh if – else ; Swich – case ; For ; while ; do while ;
Một câu lệnh if cho phép chương trình có thể thực hiện khối lệnh này hay khối
lệnh khác phụ thuộc vào một điều kiện được viết trong câu lệnh là đúng hay sai
Cú pháp
if (điều kiện) {
khối lệnh 1;
} else {
khối lệnh 2;
}
if(điều kiện)
{
khối lệnh 1;
}
Trong cú pháp trên câu lệnh if có hai dạng: có else và không có else. điều kiện là
một biểu thức lôgic tức nó có giá trị đúng (khác 0) hoặc sai (bằng 0). Khi chương
trình thực hiện câu lệnh if nó sẽ tính biểu thức điều kiện.
Nếu điều kiện đúng chương trình sẽ tiếp tục thực hiện các lệnh trong khối lệnh 1,
ngược lại nếu điều kiện sai chương trình sẽ thực hiện khối lệnh 2 (nếu có else)
hoặc không làm gì (nếu không có else).
Đặc điểm
- Đặc điểm chung của các câu lệnh có cấu trúc là bản thân nó chứa các câu lệnh
khác. Điều này cho phép các câu lệnh if có thể lồng nhau.
- Nếu nhiều câu lệnh if (có else và không else) lồng nhau việc hiểu if và else nào
đi với nhau cần phải chú ý. Qui tắc là else sẽ đi với if gần nó nhất mà chưa được
ghép cặp với else khác.
Swich
Câu lệnh if cho ta khả năng được lựa chọn một trong hai nhánh để thực hiện, do đó
nếu sử dụng nhiều lệnh if lồng nhau sẽ cung cấp khả năng được rẽ theo nhiều
nhánh. Tuy nhiên trong trường hợp như vậy chương trình sẽ rất khó đọc, do vậy
C++ còn cung cấp một câu lệnh cấu trúc khác cho phép chương trình có thể chọn
một trong nhiều nhánh để thực hiện, đó là câu lệnh switch.
Lệnh switch case là một cấu trúc điều khiển & rẽ nhánh hoàn toàn có thể được
thay thế bằng cấu trúc if else. Tuy nhiên, việc sử dụng switch case sẽ giúp code của
chúng ta dễ viết và dễ đọc hơn; Một điều nữa là sử dụng switch case có vẻ như cho
hiệu năng tốt hơn so với sử dụng if else
Cú pháp
switch (biểu thức điều khiển) {
case biểu_thức_1: khối lệnh 1 ; break;
case biểu_thức_2: khối lệnh 2 ; break;
case ……………...: ............... ; break;
case biểu_thức_n: khối lệnh n ; break;
default: khối lệnh n+1;
}
Biểu thức điều khiển được sử dụng trong một lệnh switch phải có kiểu
là integer hoặc liệt kê, hoặc là một trong các kiểu lớp trong đó lớp có một hàm
biến đổi đơn tới một kiểu integer hoặc kiểu liệt kê.
Bạn có thể có bất kỳ số lệnh case nào trong một switch. Mỗi case được theo sau
bởi giá trị để được so sánh và một dấu hai chấm.
biểu_thức_n, là biểu thức hằng, cho một case phải cùng kiểu dữ liệu với biến
trong switch, và nó phải là hằng số.
Khi biến được chuyển tới cùng giá trị với một case nào đó, lệnh theo sau case đó sẽ
thực thi tới khi gặp lệnh break.
Khi gặp lệnh break, switch kết thúc, và dòng điều khiển nhảy tới dòng lệnh tiếp
theo của lệnh switch đó.
Không nhất thiết mỗi case cần phải chứa một lệnh break. Nếu không có
lệnh break nào xuất hiện, dòng điều khiển sẽ không tới được case tiếp theo cho
tới khi bắt gặp một lệnh break.
Một lệnh switch có thể có một case mặc định tùy chọn, và phải xuất hiện ở cuối
cùng của lệnh switch. Case mặc định này có thể được sử dụng để thực hiện một
nhiệm vụ khi không có case nào là đúng (true). Trong trường hợp case mặc định
này thì không cần lệnh break.
Theo mặc định, C/C++ sử dụng gọi bởi giá trị để truyền các tham số. Nhìn chung,
code đó trong một hàm không thể thay đổi các tham số được dùng để gọi hàm đó
và trong ví dụ trên, khi gọi hàm max() là dùng phương thức tương tự.
Giá trị mặc định cho các tham số trong C/C++
Khi định nghĩa một hàm, có thể xác định một giá trị mặc định cho mỗi tham số
cuối cùng. Giá trị này sẽ được sử dụng nếu tham số tương ứng là để trống bên trái
khi gọi hàm đó.
Nếu một giá trị cho tham số đó không được truyền khi hàm được gọi, thì giá trị
mặc định đã cung cấp sẽ được sử dụng, nhưng nếu một giá trị đã được xác định, thì
giá trị mặc định này bị bỏ qua và, thay vào đó, giá trị đã truyền được sử dụng. ví dụ
#include <iostream>
using namespace std;
int sum(int a, int b=20)
{
int ketqua;
ketqua = a + b;
return (ketqua);
}
int main ()
{
// Khai bao bien cuc bo:
int a = 100;
int b = 200;
int ketqua;
// goi ham de tinh tong hai so.
ketqua = sum(a, b);
cout << "Tong gia tri la: " << ketqua << endl;
// goi ham mot lan nua.
ketqua = sum(a);
cout << "Tong gia tri la: " << ketqua << endl;
return 0;
}
Chạy chương trình C/C++ trên sẽ cho kết quả sau:
Tong gia tri la: 300
Tong gia tri la: 120
Câu 7: Trình bày khai báo , truy xuất kiểu có cấu trúc ; ví dụ minh
họa
Định nghĩa:
Trước khi chúng ta có thể khai báo biến với struct, bạn cần định nghĩa nó – Đó
cũng là lý do tại sao struct được gọi là kiểu dữ liệu người dùng định nghĩa.
Khi nào chúng ta cần phải tự định nghĩa 1 kiểu cấu trúc? Khi bạn cần lưu trữ một
đối tượng có nhiều thuộc tính. Ví dụ, đối tượng SinhVien có các thuộc tính (Mã
sinh viên, họ, tên, giới tính, quê quán,…) hay đối tượng LopHoc có các thuộc tính
(Mã lớp, tên lớp, giáo viên chủ nhiệm, sĩ số,…). Khi đó chúng ta nên dùng struct
để quản lý chương trình.
Cú pháp định nghĩa:
struct structureName
{
dataType member1;
dataType member2;
...
};
Ví dụ:
struct SinhVien {
int maSV;
char ho[20];
char ten[20];
bool gioiTinh;
char queQuan[100];
};
Như vậy, kiểu dữ liệu SinhVien đã được định nghĩa. Từ đây chúng ta có thể khai
báo các biến với kiểu dữ liệu này.
Cách khai báo biến cấu trúc:
Việc khai báo biến với struct cũng giống như cách khai báo biến thông thường,
trong đó kiểu dữ liệu là kiểu struct trong C mà bạn vừa định nghĩa.
Ví dụ:
struct SinhVien
{
int maSV;
char ho[20];
char ten[20];
bool gioiTinh;
char queQuan[100];
};
int main(){
// Khai báo 2 biến sv1 và sv2 có kiểu SinhVien
SinhVien sv1, sv2;
// Ta nên thêm từ khóa struct ở đầu,
// để phân biệt được biến này là biến của kiểu dữ liệu tự định nghĩa
struct SinhVien sv3, sv4;
// Khai báo mảng
struct SinhVien sv[100];
}
Truy xuất:
Chúng ta có 2 toán tử dùng để truy xuất tới các biến thành viên của kiểu struct
trong C.
Sử dụng . => Toán tử truy xuất tới thành viên khi khai báo biến bình thương.
Sử dụng -> => Toán tử truy xuất tới thành viên khi biến là con trỏ.
Giả sử trong ví dụ trên, bạn muốn truy xuất gioiTinh của đối tượng sinh viên, làm
như sau:
SinhVien sv;
// to do
printf("Gioi tinh: %s", sv.gioiTinh);