đặt vấn đề mở rộng sang hệ thống thư viện tiện ích của ngôn ngữ. Khi làm quen với một ngôn ngữ lập trình nào đó, không nhất thiết phải lệ thuộc quá nhiều vào hệ thống thư viện hàm của ngôn ngữ, mà điều quan trọng hơn là trước một bài toán cụ thể, chúng ta sử dụng ngôn ngữ để giải quyết nó thế nào, và phương án tốt nhất là lập trình bằng chính hệ thống thư viện hàm của riêng mình. Do vậy, đối với các ngôn ngữ lập trình, chúng ta chỉ cần nắm vững một số các công cụ tối thiểu như sau; 1. Tập các phép toán Tập các phép toán số học: + (cộng); - (trừ); * (nhân); % (lấy phần du); / (chia).
Táp các phép toán số học mở rộng: ++a ®a=a+l; _ //tăng giá trị biến nguyên a lên một đơn vị; -a @a=a-l; // giảm giá trị biến nguyên a xuống một đơn vị; a+=n$®a=a+n; //tăng giá trị biến nguyên a lên n đơn vị; a-=n%®a=a-n; // giảm giá t rị biến nguyên a xuống n đơn vị; a% =n & a=a%n; // lay gid tri biến a modul với n; a/=n®a=a/n; //lấy giá trị biến a chia cho n; a*=n%®a=a*n; //lấy giá trị biến a nhân với n; Chương 1: Đại cương về kỹ thuật lập trình cấu trúc 21 Tập các phép toán so sánh: > (lớn hơn), < (nhỏ hơn), > = (lớn hơn hoặc bằng), <= (nhỏ hơn hoặc bằng), == (đúng bằng), != (khác). | - Qui tắc viết được thể hiện như sau: if(a>b){.} /J nếu a lớn hơn b if(a<b){.} // nếu a nhỏ hơn b if(a>=b) {.} // nếu a lớn hơn hoặc bằng b if(a<=b) {.} // néu a nho hon hoac bang b if(a==b){.} // néu a đúng bằng b if(al=b) {.} // néu a khac b Tp cdc phép toan logic: && (va), |l (hoac), ! (phủ định) &&: Phép và logic chỉ cho giá trị đúng khi hai biểu thức tham gia đều có giá trị đúng (giá trị đúng của một biển thức trong ngôn ngữ lập trình C được hiểu là biểu thức có giá trị khác 0). ll: Phép hoặc logic chỉ cho giá trị sai khi cả hai biểu thức tham gia đều có giá trị sai. !: Phép phủ định cho giá trị đúng nếu biểu thức có giá trị sai và ngược lại cho giá trị sai khi biểu thức có giá trị đúng.
Ngữ nghĩa của các phép toán được minh họa thông qua các câu lệnh sau: Inta=3,b= 5; if((a !=0) && (b !=0)) // néu a khac 0 va b khác 0 if((a != 0) Il (b !=0)) // néu a khac 0 hoac b khac 0 if(a) /¡ phủ định a khác 0 if(a == b) //néu a ding bang b Các toán tử thao tác bit (Không sử dụng cho float và double): &: Phép hội các bịt. |: Phép tuyển các bit. 22 Giáo trình Kỹ thuật lập trình ^: Phép tuyển các bit có loại trừ. << : Phép dịch trái (dịch sang trái n bit gia tri 0) >> : Phép dịch phải (dịch sang phải n bit có giá trị 0) ~: Phép lấy phần bù.
Viết chương trình kiểm tra các toán tử thao tác bit #include <stdio.h> void main(void) { unsigned int a = 3, b = 5, c; clrser(); ec=a&b; printf(\nc =a & b = %d”, c); c=a|b; printf“n e = a |b = %d”, c); c=a^b;printf(*nc=a^b = %d”, c); c¢ = ~a; printf(‘\n c = ~a = %d”, c); c=a <<b; printf(‘\n c =a << b = %d”, c); c=a>>b; printf(\nc=a>>b=%d’",c); getch(); Toán tử chuyển đổi kiểu: Ta có thể dùng toán tử chuyển đồi kiểu để nhận được kết quả tính toán như mong muốn. Qui tác chuyển đổi kiểu được thực hiện theo qui tắc: (kiểu) biến. Tính giá trị phép chia hai số nguyên a và b #include <stdio.h> Chương 1: Đại cương về kỹ thuật lập trình cấu trúc 23 void main(void) int'a = 3, b = 5; float c; Cc = (float) a/ (float) b; printf(\n thương c = a/b = %8.2f”, c); getch(); Thứ tự ưu tiên các phép toán: Khi viết một biểu thức, chúng ta cần lưu ý tới thứ tự ưu tiên tính toán các phép toán, các bảng tổng hợp sau đây phản ánh trật tự ưu tiên tính toán của các phép toán số học và phép toán so sánh. Bảng dưới đây tổng hợp thứ tự ưu tiên tính toán các phép toán số học và so sánh.
Tên toán tử Chiều tính toán 0. 24 i Giáo trình Kỹ thuật lập trình 1. Tập các lệnh vào ra cơ bản Nhập dữ liệu từ bàn phím: scanf(“format_string, .); Nhập dữ liệu từ tệp (file): fscanf(file pointer, 'format_string, ¶meter, .); Nhận một ký tự từ bàn phím: getch(); getchar(); Nhận một ký tự từ tệp: fgetc(file_pointer, character_name); Nhập một string (xâu) từ bàn phím: gets(string_name); Nhận một string từ tệp text (văn bản): fgets(string name, number_character, file_ pointer); Xuất dữ liệu ra màn hình: printf('format_string.); Xuất dữ liệu ra tệp: fprintf(file_pointer, “format_string .”, parameter an, Xuất một ký tự ra màn hình: putch(character_name); Xuất một ký tự ra tệp: fputc(file_pointer, character_name); Xuất một string ra màn hình: puts(const_string_name); Xuất một string ra t€p: fputs(file_pointer, const_string_name), 1. Thao tác trên các kiểu dữ liệu có cấu trúc 1.
Tập thao tác trên string + Cách tổ chức string và các thao tác trén string: char *strchr(const char *s, int c): tìm ký tự c đầu tiên xuất hiện trong Xxâu S; char *stpcpy(char *dest, const char *src): copy xâu src vào dest; int stremp(const char *s1, const char *s2): so sánh hai xâu s1 và s2 theo thứ tự từ điển, nếu s1 < s2 thì hàm trả lại giá trị nhỏ hơn 0. Nếu sl > s2 ham tra lại giá trị dương. Nếu sI == s2 ham tra lại giá trị 0. Chương 1: Đại cương về kỹ thuật lập trình cấu trúc 25 char *strcat(char *dest, const char *src): thêm xâu src vào sau xâu dest, char *strlwr(char *s): chuyển xâu s từ ký tự in hoa thành ký tự in thường.
char *strupr(char *s): chuyển xâu s từ ký tự thường hoa thành ký tự in hoa. char *strrev(char *s): dao nguoc xau s. char *strstr(const char *s1, const char *s2): tìm vị trí đầu tiên của xâu s2 trong xau s1. int strlen(char *s): cho độ dài của xâu ký tự s.
Tập thao tác trên con trỏ Thao tác lấy địa chỉ của biến: ¶meter_name; Thao tác lấy nội dung biến (biến có kiểu cơ bản): *bointer_name; Thao tác trỏ tới phần tử tiếp theo: ++pointer_name; Thao tác trỏ tới phần tử thứ n kể từ vị trí hiện tại: pointer_name = pointer_name +n; Thao tác trỏ tới phần tử sau con trỏ kể từ vị trí hiện tại: --pointer_ name; Thao tác trỏ tới phần tử sau n phần tử kể từ vị trí hiện tại: pointer_name = pointer_name - n; Thao tác cấp phát bộ nhớ cho con trỏ: void *malloc(size_t size); void *calloc(size_t nitems, size_t size); Thao tác cấp phát lại bộ nhớ cho con trỏ: void *realloc(void *block, size_t size); Thao tác giải phóng b6 nhé cho con tro: void free(void *block); 3. Táp thao tác trên cấu trúc Định nghĩa cấu trúc: 26 Giáo trình Kỹ thuật lập trình struct struct_name { type_ 1 parameter_name_ 1; type_2 parameter_name_2; type_k parameter_name_k; } struct_parameter_name; Phép truy nhập tới thành phần cấu trúc: stiuct_parameter_name. Phép gán hai cấu trúc cùng kiểu: struct_parameter_name_1 = struct_parameter_name_2; Phép tham chiếu tới thành phần của con tro cấu trúc: pointer_struct_parameter_name - > struct_parameter_name. Tập thao tác trên tệp Khai báo con trỏ tệp: FILE * file_pointer; Thao tác mở tệp theo mode: FILE *fopen(const char *filename, const char *mode); Thao tác đóng tệp: int fclose(FILE *stream); Thao tác đọc từng dòng trong tệp: char *fgets(char ˆs, int n, FILE *stream); Thao tác đọc từng khối trong tệp: size_tfread(void *ptr, size_t size, size_t n, FILE “stream); Thao tác ghi từng dòng vào tệp: int fputs(const char *s, FILE *stream); Thao tác ghi từng khối vào tệp: size_t fwrite(const void “ptr, size_t size, size_tn, FILE *stream); Thao tác kiểm tra sự tồn tại của tệp: int access(const char “filename, int amode); Thao tác đổi tên tệp: int rename(const char *oldname, const char = “newname); Thao tác loại bỏ tệp: int unlink(const char *filename); Chương 1: Đại cương về kỹ thuật lập trình cấu trúc 27 1.
NGUYÊN LÝ ĐỊA PHƯƠNG Các biến địa phương trong hàm, thủ tục hoặc chu trình cho dù có trùng tên với biến toàn cục thì khi xử lý biến đó trong hàm hoặc thủ tục vẫn không làm thay đổi giá trị của biến toàn cục. Tên của các biến trong đối của hàm hoặc thủ tục đêu là hình thức. Mọi biến hình thức truyền theo trị cho hàm hoặc thủ tục đêu là các biến địa phương. Các biến khai báo bên trong các chương trình con, hàm hoặc thủi tục đều là biến địa phương.
Khi phải sử dụng biến phụ nên dùng biến địa phương và hạn chế tối đa việc sử dụng biến toàn cục để tránh xảy ra các hiệu ứng phụ. Ví dụ hoán đổi giá trị của hai số a và b sau đây sẽ minh họa rõ hơn về nguyên lý địa phương. Hoán đổi giá trị của hai biến a và b.h> int a, b; /J khai báo a, b là hai biến toàn cục. : Giáo trình Kỹ thuật lập trình } void main(void) { a=1;b=8; /I khởi đầu giá tri cho biến toàn cục a, b.
Swap(); printf(“n Kết quả sau khi thực hiện thủ tục a = %5d b = %5d”, a, b); getch(); Két qua thuc hién chuong trinh: Kết quả thực hiện trong thủ tục a = 5 b = 3 Kết quả sau khi thực hiện thủ tục a = 1b =8 Trong ví dụ trên a, b là hai biến toàn cục, hai biến a, b trong thủ tục Swap là hai biến cục bộ. Các thao tác trong thủ tục Swap gán cho a giá trị 3 và b giá trị 5 sau đó thực hiện đổi giá trị của a = 5 và b = 3 là công việc xử lý nội bộ của thủ tục mà không làm thay đổi giá trị của biến toàn cục của a, b sau thi thực hiện xong thủ tục Swap. Do vậy, kết quả sau khi thực hiện Swap a = 1, b = 8; điều đó chứng tỏ trong thủ tục Swap chưa bao giờ sử dụng tới hai biến toàn cục a và b. Tuy nhiên, trong ví dụ sau, thủ tục Swap lai lam thay đổi giá trị của biến toàn cục a và b vì nó thao tác trực tiếp trên biến toàn cục.
Đổi giá trị của hai biến a và b #include <stdio.h> int a, b; II khai báo a, b là hai biến toàn cục. void Swap(void) { int temp; /! khai báo a, b là hai biến địa phương a=3;b=5; // gan gia trị cho a và b Chương 1: Đại cương về kỹ thuật lập trình cấu trúc 29 temp = a; a = b; b = temp; 1I đổi giá trị của a và b printf("n Kết quả thực hiện trong thủ tục a = %5d b = %5d", a, b); } void main(void){ a=1; be 8; JJ khởi đầu giá trị cho biến toàn cục a, b.