You are on page 1of 73

môn

hành trình theo các trúc và

:
Cài các trúc toán
vào bài toán .
Ngôn trình: C

, vào ra file

môn Cú pháp trình gcc


Môi : Các tham :
hành UNIX -Wall : các báo
trình : gcc -c: tin object
trình mã : Emacs, K-Developper. -o: tin trình
-g: thêm thông tin
-l: kèm

gcc Wall hello.c o runhello


./runhello

3 4
Ôn các : liên các cùng , cùng tên
, có khai báo nào
xâu ký , VD: int A[10]; là khai báo 10 nguyên .
con . Các ví
Xây trình dòng Danh sách các sinh viên
Thao tác tin Dãy dùng
ghi tin theo ký Véc
ghi tin theo dòng Ma
ghi tin theo
Các bài trình

5 6

trong trong theo


Dãy liên các cùng , nhau #include <stdio.h>

Tên ô tiên
int main(void){
Ví :
double A[10];
double S[10];
printf("please enter 10 numbers:\n");
for(int i=0; i<10; i++)
scanf("%f", &A[i]);
k A truy qua : A[k-1] (
0) printf("numbers in reversed order:\n");
for(int i=9; i>=0; i--)
0 1 2 3 4 5 6 7 8 9 printf("%3.4f\n", A[i]);

S
return 0;
}

7 8
Bài : Tìm trong mã
trình ví trên có giá avg = average(a, SIZE); // tính giá trung bình các
giá trung bình các
mindiff = 1000000;
for (i=0; i<SIZE; i++){
ý: trong khai báo kích diff = fabs(a[i] - avg);
. if (diff <mindiff) {
mindiff = diff;
medianindex = i;
}
}
return a[medianindex]

9 10

Bài án (phiên 1)
trình vào xâu ký và #define ALPHABET_LEN 26
ký có trong xâu.
int main(void){
int i = 0,
count[ALPHABET_LEN] = {0};
xâu vào: hello, world!
char c = '\0';
The letter 'd' appears 1 time(s). printf("Please enter a line of text: \n");
The letter 'e' appears 1 time(s). /* Read in letter by letter and update the count array */
The letter 'h' appears 1 time(s). c = getchar();
The letter 'l' appears 3 time(s). while (c != '\n' && c >= 0){
The letter 'o' appears 2 time(s). if (c <= 'z' && c >= 'a')
The letter 'r' appears 1 time(s). ++count[c - 'a'];
The letter 'w' appears 1 time(s). if (c <= 'Z' && c >= 'A')
++count[c - 'A'];
c = getchar();
}
các ký trong xâu là cái !

11 12
án (phiên 1) án (phiên 2)
#include <stdio.h>
#include <string.h>
for (i = 0; i < ALPHABET_LEN ; ++i) { #define ALPHABET_LEN 26
if (count[i] > 0) int main(){
printf("The letter '%c' appears %d time(s).\n", 'a' + i, count[i]); int i = 0,
} count[ALPHABET_LEN] = {0};
return 0; char s[20], c = '\0';
} printf("Please enter a line of text: \n"); gets(s);
for (i=0; i<strlen(s);i++) {
c = s[i];
if (c <= 'z' && c >= 'a ) ++count[c - 'a'];
if (c <= 'Z' && c >= 'A ) ++count[c - 'A'];
}
for (i = 0; i < ALPHABET_LEN ; ++i) {
if (count[i] > 0)
printf("The letter '%c' appears %d time(s).\n", 'a' + i, count[i]);
}
return 0;
}

13 14

Bài : Hàm có là án
hàm là hai nguyên, có cùng #include <stdio.h>
. Hàm 1 hai có dung trùng nhau và 0
cho các còn . #define SIZE 5

tra hàm qua trình.


int compare_arrays(int arr1[], int arr2[], int size){
Hoàn thành nhà: Hàm -1 2 có dung int i = 0;
( này kia)
for (i = 0; i < size; ++i){
if (arr1[i] != arr2[i])
return 0;
}

/* if we got here, both arrays are identical */


return 1;
}

15 16
án Xâu ký trong C
int main(void){ các ký .
int input1[SIZE], input2[SIZE], i;
chính .
printf("Please enter a list of %d integers:\n", SIZE); Có khi khai báo:
for (i = 0; i < SIZE; ++i) scanf("%d", &input1[i]); char str[] = "Text";

printf("Please enter another list of %d integers:\n", SIZE);


for (i = 0; i < SIZE; ++i) scanf("%d", &input2[i]);

if (compare_arrays(input1, input2, SIZE) == 1)


printf("Both lists are identical!\n"); . 's'
'H' '#'
'e' ''l'' 'f'
'l' 'd'
'o' 'y'
'' '4'
'w' '7'
'o' '$'
'r' '_'
'l' 'e'
'd' 'g'
'\0' 'd' '.' 'p' 'v' .
else
printf("The lists are not identical...\n"); str

return 0;
Terminator
}

17 18

Xâu ký Các hàm xâu ký và ký


In order to hold a string of N characters we need an array of getchar()
length N + 1 c = getchar()
So the previous initialization is equivalent to scanf
char str[] = {'b', 'l', 'a', 'b', 'l', 'a', '\0'}; scanf("%s", str);
gets()
gets(str);

19 20
Các hàm lý xâu ký Bài
strlen(const char s[]) hàm :
ký xâu s (không tính ký NULL) Có tham là xâu ký và hai ký
strcmp(const char s1[], Hàm xâu và thay các ký trong xâu
const char s2[]) ký hai.
so sánh s1 s2 trình tra hàm nói trên:
strcpy(char s1[], xâu không ký và hai ký , sau hàm
const char s2[]) các trên và in ra .
sao chép dung s2 vào s1 Ví
vào
strcat(char s1[], char s2[])
s2 vào s1, sau vào s1

21 22

án (hàm) án ( trình)
void replace(char str[], char replace_what, char replace_with){ #define STRING_LEN 100
int i; int main(void){

for (i = 0; str[i] != '\0'; ++i){ char str[STRING_LEN + 1];

if (str[i] == replace_what) char replace_what, replace_with, tmp;


printf("Please enter a string (no spaces)\n");
str[i] = replace_with;
scanf("%100s", str);
}
printf("Letter to replace: ");
}
scanf(" %c", &replace_what);
do {tmp=getchar();} while (tmp!='\n');

printf("Letter to replace with: ");


scanf(" %c", &replace_with);

replace(str, replace_what, replace_with);


printf("The result: %s\n", str);
return 0;
}

23 24
Bài : Tách Con
trình xâu ký câu Con là dùng giá .
dùng. Sau trình trong câu trên .
dòng. là dãy các ký liên không ký khai báo ký * tên.
.
Ví :
vào: « The house nextdoor is very old. »
:
The
house *

25 26

Con Con
Con ptr là point c giá nó là
c int n;
int *iptr; /* khai báo P là con int */
n = 7;
iptr = &n;

C printf iptr); /*
*iptr = 177;
7 3 4
printf
172 173 174 175 176 177 178 179 180 181
iptr = 177; /* Phép gán không !! */

Ptr
174 3 4
832 833 834 835 836 837 838 839 840 841

27 28
Bài án
hàm là (double) và nguyên void split(double num, int *int_part, double *frac_part){
và phân . *int_part = (int)num;
*frac_part = num - *int_part;
}
trình minh hàm trên,
dùng. int main(void){
double num, fraction;
int integer;

printf("Please enter a real number: ");


scanf("%f", &num);

split(num, &integer, &fraction);


printf("The integer part is %d\n", integer);
printf("The remaining fraction is %f\n", fraction);

return 0;
}

29 30

Bài nhà: Sinh câu trình dòng


trình có sinh ra các câu Các dòng trong hàm main
trên nhiên. trình dùng main thân là hàm các hàm khác
xâu ký các (article), danh (noun), Nó có các vào ( dòng gõ
(verb), (preposition). Câu ra cách dùng)
nhiên các trong các trên và ghép theo : Vai trò trình nó (the calling function) trong
, danh , , và danh . Câu sinh ra này là hành, trình khác
in hoa và thúc . trình sinh
ra 10 câu.

Ví các
: "the", "a", "one", "some" and "any";
danh : "boy", "girl", "dog", "town" and "car";
: verbs "drove", "jumped", "ran", "walked" and "skipped";
: "to", "from", "over", "under" and "on".

31 32
Nguyên hàm main Nguyên hàm main

int main(int argc, char* argv[]) int main(int argc, char* argv[])
Khi chúng ta trình các dòng ,
hàm main trên, : argc : 3
argc các
argv là các con char các xâu ký
và các giá các argv :
.
tiên luôn là tên trình. p t 1
r e 7
o x 8
g t \0
n \0
a
m
e
\0

33 34

Các trình dòng Bài


cú pháp cho hàm main trình hai làm dòng , cho
dài và hình .
tra giá argc dùng .
sai, thông báo cùng cú pháp trình trên tính toán và in ra tích và chu vi hình
trình. .
VD: Hello Hanoi 1 , giá argc nên là : 1+1 =2
giá các argv[], argv[1] và
sang khi .
các hàm atoi, atol, atof trong <stdlib.h>
lý, tính toán trên các nói trên.

35 36
án Bài : câu
#include <stdio.h>
trình cho phép dùng câu
#include <stdlib.h> dòng ( trong câu là ). trình
int main(int argc, char* argv[]){ dung câu câu .
double width, height;
VD: ./inverse I love HUST
if (argc != 3)
printf("Wrong number of arguments!\n"); Cho : HUST love I
printf( CORRECT SYNTAX: RECT <WIDTH> <HEIGHT>\n");
return 1;
}
width = atof(argv[1]);
height = atof(argv[2]);
printf("The rectangle's area is %f\n", width * height);
printf("The rectangle's perimeter is %f\n , 2 * (width + height));
return 0;
}

37 38

Bài nhà Bài nhà


trình tính x nhiên ex . dùng có trình có tên sde dòng là các
trình hai cú pháp: trình 2 ax2 + bx +c =0 và trình, in ra màn
< > <giá > ví : e 50 hình các .
Cú pháp sde a b c
< > <giá >< >. Ví : Ví : ./sde 1 2 1 cho : x1=x2 =-1
e 50 0.0003

39 40
Làm tin Các thao tác khi làm tin
tin (file) cho phép thông tin lâu dài trong ngoài. tin
trình không bàn phím, trên
màn hình mà có tin, ghi ra tin. tin vào trình ( là vào các )
Ngôn C cho phép giao các tin thông qua
là con ( ) file.
Các hàm , ghi tin con file là Ghi ( ) trình ra tin
Sau thao tác /ghi trí con file thay .
tin
Khai báo: FILE *fptr;

41 42

File và File phân tin


File : hàm fopen()
có dung là các ký nhìn . Nguyên : FILE *fopen(const char *filename, const char
*mode);
Notepad, Notepad++, Sublime Text,

FILE *fptr;
if ((fptr = fopen("test.txt", "r")) == NULL){
File phân printf("Cannot open test.txt file.\n");
dung phân ( 0 và 1) exit(1);
và không gian . }

43 44
tin Các tham mode cho tin
filename: và tên tin.
giá là giá xâu ký : data.txt
Có tin: mode Ý
/root/hedspi/CProgrammingBasic/Lab1/data.txt
Có dùng ký :
"r" tin có . tin
char file_name[] = junk.txt ; không , fopen() NULL.
"w" tin ghi.
ý: không mô , tin
cùng trình.
"a" tin có ghi thêm vào .

"r+" tin có
tin không , fopen() NULL.
"w+" file cho phép và ghi.

"a+" file cho phép và ghi « append »

45 46

Các tham mode cho tin phân tin


Hàm fclose con
tin tin mà nó tham .
mode Ý
int fclose(FILE *stream);
"rb" tin phân có .

"wb" tin phân ghi. tin khi hoàn các thao tác ghi .

"ab" tin phân có ghi thêm vào .

"r+b" tin phân có

"w+b" tin phân cho phép và ghi.

"a+b" tin phân cho phép và ghi vào


.

47 48
Ví : và tin và ghi tin (I)
#include <stdio.h> Trong ngôn C, trình có các thao tác vào/ra
enum {SUCCESS, FAIL}; ( /ghi) theo cách khác nhau:
main() { ghi ký
FILE *fptr;
char filename[]= "haiku.txt"; ghi dòng .
int reval = SUCCESS;
if ((fptr = fopen(filename, "r")) == NULL){
ghi (block) các ký (byte) .
printf("Cannot open %s.\n", filename);
reval = FAIL;
} else {
printf("The value of fptr: 0x%p\n", fptr);
printf("Ready to close the file.");
fclose(fptr);
}
return reval;
}

49 50

Thao tác tin theo ký Bài : Sao chép dung tin


ghi ký . file tên lab1.txt dung , trong
cùng trình.

hàm trong stdio.h: fgetc() and fputc() trình file trên ký , sau ghi
chúng vào file tên lab1w.txt

Nguyên :
int fgetc(FILE *stream);
int fputc(int c , FILE *stream);

Ký EOF: khi tin, các hàm trên EOF.

51 52
án án
enum {SUCCESS, FAIL};
#include <stdio.h>
enum {SUCCESS, FAIL}; main(void) {
FILE *fptr1, *fptr2;
void CharReadWrite(FILE *fin, FILE *fout) char filename1[]= "lab1a.txt";
char filename2[]= "lab1.txt";
{
int reval = SUCCESS;
int c;
while ((c=fgetc(fin)) != EOF){ if ((fptr1 = fopen(filename1, "w")) == NULL){
fputc(c, fout); /* write to a file */ printf("Cannot open %s.\n", filename1);
reval = FAIL;
putchar(c);
} else if ((fptr2 = fopen(filename2, "r")) == NULL){
/* display character on the screen */ printf("Cannot open %s.\n", filename2);
} reval = FAIL;
} } else {
CharReadWrite(fptr2, fptr1);
fclose(fptr1);
fclose(fptr2);
}
return reval;
}

53 54

Bài : Thao tác tin theo ký án


trình dung tin , dung hàm CharReadWrite hàm
ký . lý ký có trong <ctype.h>
trình ký cái hoa thành ký cái
và , sau ghi vào tin khác. void CharReadWrite(FILE *fin, FILE *fout){

Chú ý các ký khác trình sao chép int c;


cách thông sang tin . while ((c=fgetc(fin)) != EOF){
if islower(c) c=toupper(c);
else if isupper(c) c=tolower(c);
fputc(c, fout); /* write to a file */
putchar(c); /* display character on the screen */
}
}

55 56
Bài nhà Bài nhà: trình tin
trình có tên mycp cp trong các trình tên hai dòng , sau
hành UNIX/LINUX. Nó có sao chép tin sang hành ghép dung tin hai vào tin .
tin theo cú pháp: hai tin .
mycp Cú pháp :
apd <file1> <file2>
, tên các tin cung dòng .
Chú ý: trình tra cú pháp (vd Chú ý: trình tra cú pháp (vd
thông báo và khi ..) thông báo và khi ..)

57 58

Bài nhà: sang hoa Bài


trình có tên uconvert có trình double_line tin vào và
các cái trong dung tin ( cung dung nó sau: trình chèn thêm 1 dòng
trong dòng ) thành hoa và ghi dung các dòng trong . ghi vào
vào chính tin . ra. trình dòng
Cú pháp: uconvert tata.txt sau: ./double_line <File 1> <File 2>

Ví Ví minh dung hai file khi trình


File tata.txt: helloworld
dung tata.txt sau khi trình : HELLOWORD.

Welcome to Welcome to
C Programming!
C Programming!

59 60
án tham án tham
#include <stdio.h> void double_space(FILE *ifp, FILE *ofp){
#include <stdlib.h> int c;
void double_space(FILE *, FILE *); while ((c = fgetc(ifp)) != EOF) {
void print_info(char *); fputc(c, ofp);
int main(int argc, char **argv) { /* ký dòng nhân nó */
FILE *ifp, *ofp; if (c == '\n') fputc('\n', ofp);
if (argc != 3) { }
print_info(argv[0]); exit(1); }
} void prn_info(char *pgm_name){
ifp = fopen(argv[1], "r"); /* file 1 */ printf("\n%s%s%s\n\n%s\n\n",
ofp = fopen(argv[2], "w"); /* file 2 ghi */ "Usage: ", pgm_name, " infile outfile",
double_space(ifp, ofp); "The contents of infile will be double-spaced and written to outfile.");
fclose(ifp); }
fclose(ofp);
return 0;
}

61 62

Bài nhà: Mã hóa Caesar Thao tác tin theo dòng


trình có cùng lúc hai hai hàm: fgets() and fputs()
mã hóa và mã tin mã
char *fgets(char *s, int n, FILE *stream);
Caesar (mã hóa ) sau. trình ba :
s : tham xâu ký dùng dùng dòng
< tin >< >< tin > tin.
Khi mã hóa, trình (offset) n n: dài xâu ký s tính ký NULL.
là nguyên . trình thay ký
trong tin ký sau nó n trí trong mã Hàm fgets() khi mãn trong các sau:
ASCII. Ví offset =3 thì A D, B E n-1 ký tin, ký dòng EOF. Sau thêm
ký null vào xâu s.
Khi mã, trình vào là tin mã hóa và
giá là âm (VD offset = -3)
nâng cao (tùy ): các ký là cái
vòng tròn: A-> D, ..., Z -> C

63 64
Thao tác tin theo dòng Bài
Hàm: int fputs(const char *s, FILE *stream); bài trình sao chép dung tin, tuy nhiên thay
vì hàm fgetc và fputc ta hàm fgets và fputs
s: Xâu ký ghi ra tin
tin và ghi vào tin dòng trong dung
stream: con file .

0 thao tác thành công


khác 0 .

65 66

án án
#include <stdio.h> main(void) {
enum {SUCCESS, FAIL, MAX_LEN = 81 }; FILE *fptr1, *fptr2;
char filename1[]= "lab1a.txt"; char filename2[]= "lab1.txt";
void LineReadWrite(FILE *fin, FILE *fout){ int reval = SUCCESS;
char buff[MAX_LEN]; if ((fptr1 = fopen(filename1, "w")) == NULL){
while (fgets(buff, MAX_LEN, fin) != NULL) { printf("Cannot open %s.\n", filename1);
fputs(buff, fout); reval = FAIL;
printf("%s", buff); } else if ((fptr2 = fopen(filename2, "r")) == NULL){
} printf("Cannot open %s.\n", filename2);
} reval = FAIL;
} else {
LineReadWrite(fptr2, fptr1);
fclose(fptr1);
fclose(fptr2);
}
return reval;
}

67 68
Bài : dòng & dung ( cat) ý
trình sao chép trình mã hàm LineReadWrite:
dung tin ra màn hình, sau các dòng fputs
. dòng dòng.
Minh giao trình:
int LineReadWrite(FILE *fin, FILE *fout)
Reading file Haiku.txt . done! {
char buff[MAX_LEN]; int count =0;
Haiku haiku while (fgets(buff, MAX_LEN, fin) != NULL) {
count++; printf("%s", buff);
Tokyo }
return count;
Hanoi }
This file has 3 lines.
// version 2
int LineReadWrite(FILE *fin)
{
char buff[MAX_LEN]; int count =0;
while (fgets(buff, MAX_LEN, fin) != NULL) {
count++; printf("%s", buff);
}
return count;
}

69 70

Hàm main Bài : dòng trong tin


enum {SUCCESS, FAIL}; trình tin và ra màn hình
main() {
dòng, theo sau là dung dòng . Tên tin
FILE *fptr1; int c =0;
cung dòng .
char filename1[]= haiku.txt"; Ví tin có dung
int reval = SUCCESS; This is sample file.
Hello!
if (fptr1 = fopen(filename1, "r")) == NULL){
printf("Cannot open %s.\n", filename1);
trên màn hình là:
reval = FAIL; 1 This is sample file.
} else { 2 Hello!
printf( Reading file %s done!\n , filename1);
c= LineReadWrite(fptr2, fptr1);
printf( The file has %d lines.\n , c);
fclose(fptr1);
}
return reval;
}

71 72
Bài : hai tin theo dòng ý
void LineMerge(FILE *f1, FILE *f2, FILE *f3){
trình có dòng sau
char buff1[MAX_LEN], buff2[MAX_LEN];
merge <file1> <file2> <file3> int len;
while ((fgets(buff1, MAX_LEN, f1) != NULL)&& (fgets(buff2, MAX_LEN, f2) != NULL)) {
fputs(buff1,f3);
trình ghi vào file 3 cách và dòng fputs(buff2,f3);
file 1 và file 2. trình dòng file 1, ghi vào file 3 sau }
dòng file 2 ghi vào file 3. Chú ý: File 1 và File 2 có if (buff1!= NULL) fputs(buff1,f3);

có dòng khác nhau, khi dung file, trình sao while (fgets(buff1, MAX_LEN, f1) != NULL {
chép các dòng theo file còn vào file 3. fputs(buff1,f3);
}
while (fgets(buff2, MAX_LEN, f2) != NULL {
fputs(buff2,f3);
}
}

73 74

Bài nhà Bài nhà


trình mycat và dung tin trình dòng là file
trên màn hình. trình hai cú pháp sau: ( dung 80 dòng). trình thêm dòng
cat <filename> : toàn dung vào file nói trên dung các ký tiên các
dòng trong file ban .
cat <filename> -p : theo trang. dùng
phím xem trang theo.

75 76
và ghi tin Bài
là các hàm ích lý có trúc ( các trình dòng tin, sau tính
khác nhau) . dài xâu ký trên dòng và ghi ra tin theo
sau: < dài dòng> < dung dòng>
Ví , dòng trong tin vào:
int fscanf( FILE *stream, const char *format, ...);
Hàm fscanf hàm scanf, khác là nó The quick brown fox jumps over the lazy dog.
dung tin ( con file) ghi vào các trong tin ra dòng là:
.
44 The quick brown fox jumps over the lazy dog.

int fprintf(FILE *stream, const char *format, ...);


hàm printf thay vì dung ra màn
hình thì nó ghi dung các ra tin ( con
file).

77 78

án Bài
thay hàm LineReadWrite hàm strlen và fprintf dãy bàn phím và ghi chúng ra
ghi vào
file.
void LineReadWrite(FILE *fin, FILE *fout){
Cú pháp bàn phím sau: tiên là các trong
char buff[MAX_LEN]; dãy , sau là dãy các nguyên. Ví : khi dùng : 4 12 -
int len; 45 56 3
while (fgets(buff, MAX_LEN, fin) != NULL) { là các , bao - dung tin
len = strlen(buff)-1; là, 26 là 4
fprintf(fout, "%d %s", len, buff); 3 56 -45 12 26
printf("%s", buff); Vì các thay theo , trình
} phát cho các này hàm malloc( ).
}

79 80
án án
#include <stdio.h> while(i<n) {
#include <stdlib.h> scanf("%d", &value);
#include <string.h> p[i++]=value;
enum {SUCCESS, FAIL}; sum+=value;
}
int main(void){ if ((fp = fopen("out.txt","w")) == NULL){
FILE *fp; printf("Can not open %s.\n", "out.txt");
int *p; reval = FAIL;
int i,n, value, sum; }
int reval = SUCCESS; for (i=n-1; i>=0;i--){
fprintf(fp,"%d ",p[i]);
printf("Enter a list of numbers with the first is the size of list: \n"); }
scanf("%d", &n); fprintf(fp,"%d ",sum);
p = (int *)malloc(n*sizeof(int)); i=0; sum=0; fclose(fp);
free(p);
return reval;
}

81 82

Bài
tin có tên product.txt, dòng trong Khi double dùng fscanf
thông tin : ID ( int), Product Name (xâu ký %lf
không ký ), Price ( double). Các trên
phân tách nhau ký space tab. Ví Trong các phân tách các ký
; hay , (delimiter), có fscanf và fgetc
1 Samsung_Television_4K 20000000
2 Apple_MacBook_2020 18560000 1000, John_Allan, 28, NewYork
trình tin trên vào các trúc
và sau dung trên ra màn hình :
No Product Name Price
1 Samsung_Television_4K 20000000

83 84
Bài Bài

#include <stdio.h>
if ((fp = fopen("product.txt","r")) == NULL){
enum {SUCCESS, FAIL, MAX_ELEMENT = 10}; printf("Can not open %s.\n", "product.txt");
typedef struct { reval = FAIL;
} else {
int no; while (fscanf(fp,"%d%s%lf", &arr[i].no, arr[i].name, &arr[i].price) != EOF){
char name[20]; i++;
}
double price;
n=i;
}product ; for (i=0; i<n; i++)
int main(void){ printf("%-6d%-24s%-6.2f\n",arr[i].no,arr[i].name,arr[i].price);
}
FILE *fp; fclose(fp);
product arr[MAX_ELEMENT]; return reval;
int i=0,n; }

int reval = SUCCESS;


printf("Loading file...\n");

85 86

Bài nhà
file dung là danh sách ít 6 sinh viên.
dòng 4 sau:
STT( ) Mã sinh viên và tên (không ký )
. Ví
1 20181110 Bui_Van 0903112234
2 20182111 Joshua_Kim 0912123232 Thank you
trình tin trên vào các trúc phù . for your
trình yêu sung thêm cho sinh attentions!
viên sau ghi vào tin bangdiem.txt (transcript.txt)
các nói trên (cùng ).

87 88
Ôn trúc
phát
Thao tác tin phân
Các bài trình

, vào ra file

phát Hàm malloc


Các thông có kích void * malloc(unsigned int nbytes);
các
biên .
Xin phát vùng ( ) có kích nBytes
Kích này không thay sau khi trình ra
Tuy nhiên chúng ta không luôn malloc con vùng xin phát thành
trình làm bao nhiêu . công, con NULL .
phát (dynamic memory allocation) ý: Luôn luôn tra xem có phát thành công
Xin phát theo yêu hay không.
trình stdlib.h: #include <stdlib.h>
phát lý con .

3 4
Bài : mã còn
#include <stdlib.h> int main(){
int main(){ . . .
int i, n, *p; /* các nguyên */
printf("How many numbers do you want to enter?\n"); printf("Please enter numbers now:\n");
scanf("%d", &n); for (i = 0; i < n; i++)
p = (int *)malloc(n * sizeof(int)); scanf("%d", &p[i]);
if (p == NULL){
printf("Memory allocation failed!\n");
/* theo */
return 1;
printf("The numbers in reverse order are - \n");
}
for (i = n - 1; i >= 0; --i)
/* các nguyên */
printf("%d ",p[i]);
...
/* chúng theo */ printf("\n");

... free(p);
return 0;
free(p); /* phóng */ }
return 0;
}

5 6

Vì sao ép ? Hàm calloc


Phép ép trong câu void *calloc(size_t nitems, size_t size);
p = (int *)malloc(n*sizeof(int));
là vì hàm malloc void * : phát vùng xác nitems các cùng
, có kích size byte.
void * malloc(unsigned int nbytes);
các giá là 0, trong khi hàm malloc
không hành cho phát.
(void *) con khái quát, có ép con vùng xin phát thành công,
con nào. con NULL .
ptr = (float*) calloc(25,sizeof(float));

7 8
Tái phát hàm Reallocate Minh hàm realloc
khi trình phát thêm sau xin phát
tiên.
void *realloc(void *ptr, size_t size)
Thay kích vùng con ptr phát
hàm malloc calloc
Các tham
ptr là con vùng phát và phát .
con này là NULL, vùng phát và
hàm.
size Kích vùng tính theo byte. nó
là 0 and ptr vùng phát, vùng
ptr này phóng và hàm NULL.
Giá
con vùng yêu phát thành
công, con NULL . : geeksforgeeks

9 10

Ví phóng phát
#include <stdio.h>
#include <stdlib.h> void free(void *ptr);
int main(){ Hàm free(p) phóng phát p
char *str; p không vùng nào, thi trình
str = (char *) malloc(15);
strcpy(str, "tutorialspoint"); Luôn phóng các vùng phát khi không còn
printf("String = %s, Address = %u\n", str, str); chúng (VD: Khi thoát trình)
/* phát */
str = (char *) realloc(str, 25);
strcat(str, ".com");
printf("String = %s, Address = %u\n", str, str);
free(str);
return 0;
}

11 12
Bài án hàm my_strcat
Cài hàm my_strcat :
vào là hai xâu ký s1 và s2
char *my_strcat(char *str1, char *str2){
ra: con - vùng dung là xâu
phép hai xâu s1 và s2 int len1, len2; char *result;
len1 = strlen(str1); len2 = strlen(str2);
Ví : Phép và hello_world
result = (char*)malloc((len1 + len2 + 1) * sizeof(char));
phát if (result == NULL) {
Test your function printf("Allocation failed! Check memory\n");
return NULL;
}
strcpy(result, str1);
strcpy(result + len1, str2);
return result;
}

13 14

án: hàm main() Bài nhà


Xây và minh (demo) hàm sau
int main(){
char str1[MAX_LEN + 1], str2[MAX_LEN + 1];
char* subStr(char* s1, int offset, int number)
char *cat_str; Hàm tách xâu con xâu s1 ký offset (tính 0)
printf("Please enter two strings\n"); và có dài number ký .
scanf("%100s", str1); Chú ý tra tính các . Trong giá
scanf("%100s", str2); number dài còn xâu s1 tính trí offset,
cat_str = my_strcat(str1, str2); xâu con là còn s1 tính trí offset.
if (cat_str == NULL) {
printf("Problem allocating memory!n");
return 1;
}
printf("The concatenation of %s and %s is %s\n", str1, str2, cat_str);
free(cat_str);
return 0;
}

15 16
trúc do dùng Ví :
trong tên.
struct complex {
Là cách nhóm các thông tin có liên quan ( chung
int real;
1 trong bài toán) nhau.
int img;
Các góp ra struct là các thành hay };
.
struct complex num1, num2, num3;

struct struct-name typedef struct complex {


{ int real;
field-type1 field-name1; int img;
field-type2 field-name2;
field-type3 field-name3; } complex_t;

...
}; complex_t num1, num2;

17 18

Bài
int is_in_circle(point_t *p, circle_t *c){
Cho hai trúc sau: double x_dist, y_dist;
typedef struct point{ x_dist = p->x - c->center.x;
double x; y_dist = p->y - c->center.y;
double y; return (x_dist * x_dist + y_dist * y_dist <= c->radius * c->radius);
} point_t; }
int main(){
point_t p;
typedef struct circle{
circle_t c;
point_t center;
printf("Enter point coordinates\n"); scanf("%lf%lf", &p.x, &p.y);
double radius;
printf("Enter circle center coordinates\n");
} circle_t; scanf("%lf%lf", &c.center.x, &c.center.y);
printf("Enter circle radius\n"); scanf("%lf", &c.radius);
if (is_in_circle(&p, &c))
hàm is_in_circle 1 p trong tròn c.
printf("point is in circle\n");
tra hàm trình.
else
printf("point is out of circle\n");
return 0;
}

19 20
Bài nhà Bài nhà
hàm tra xem hai hình tròn có giao nhau hay không. bài danh sách sinh viên
trình cho phép ra các là các hình sau:
tròn, do dùng cung Thay vì thông , trình phát
trình. file danh sách .
dùng có :
sung tính thêm: trình sinh viên
công thông tin cho hình tròn sung, sau tái phát có cho
sinh thông tin nhiên cho hình tròn. , hàm realloc.
Chú ý: file danh sách ít 10 dòng, .
trình hàm nói trên và :
Thông tin các hình tròn
Thông tin hình tròn giao hình tròn khác (cùng
thông tin chi , ví giao các hình tròn nào..)

21 22

Các tham mode cho tin phân Vào ra theo các (data block)
C cung hai hàm vào ra: fread() và fwrite(), cho phép các
thao tác vào ra theo các các byte.
mode Ý các hàm khác, các hàm trên làm là các
con file.
"rb" tin phân có .

"wb" tin phân ghi.

"ab" tin phân có ghi thêm vào .

"r+b" tin phân có

"w+b" tin phân cho phép và ghi.

"a+b" tin phân cho phép và ghi vào


.

23 24
fread() fwrite()
Nguyên hàm fread
Nguyên hàm fwrite
size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);
ptr là con
ptr là con ghi ra tin.
tin.
size: kích (theo byte).
size: kích (theo byte).
n: tin.
n: tin.
stream: con file file hay ghi.
stream: con file file hay ghi.
Hàm ghi thành công vào tin.
Hàm thành công tin.

25 26

Hàm feof Ví
int feof(FILE *stream); 80 byte tin haiku.txt.
tra xem trí con file tin hay .
Hàm 0 trí file; giá enum {MAX_LEN = 80};
khác không. int num;
FILE *fptr2;
char filename2[]= "haiku.txt";
char buff[MAX_LEN + 1];
if ((fptr2 = fopen(filename2, "r")) == NULL){
printf("Cannot open %s.\n", filename2);
reval = FAIL; exit(1);
}
. . . .
num = fread(buff, sizeof(char), MAX_LEN, fptr2);
buff[num * sizeof(char)] = `\0';
printf("%s", buff);

27 28
Bài án
#include <stdio.h>
trình sao chép tin ( lab1.txt sang lab1a.txt)
enum {SUCCESS, FAIL, MAX_LEN = 80};
các bài các thao tác ghi tin theo
void BlockReadWrite(FILE *fin, FILE *fout);
.
int main() {
các hàm: fread, fwrite, feof FILE *fptr1, *fptr2;
char filename1[]= "lab1a.txt";
char filename2[]= "lab1.txt";
int reval = SUCCESS;
if ((fptr1 = fopen(filename1, "w")) == NULL){
printf("Cannot open %s.\n", filename1);
reval = FAIL;
} else if ((fptr2 = fopen(filename2, "r")) == NULL){
printf("Cannot open %s.\n", filename2); reval = FAIL;
} else {
BlocReadWrite(fptr2, fptr1);
fclose(fptr1); fclose(fptr2);
}
return reval;
}

29 30

án Bài
trình mycat có cat trong Unix
void BlockReadWrite(FILE *fin, FILE *fout) {
vào ra theo .
int num;
char buff[MAX_LEN + 1];
ý:
dòng
while (!feof(fin)){ Dùng hàm fread
num = fread(buff, sizeof(char), MAX_LEN, fin);
buff[num * sizeof(char)] = `\0';

printf("%s", buff);
fwrite(buff, sizeof(char), num, fout);
}
}

31 32
án án
#include <stdio.h> void BlockCat(FILE *fin) {
enum {SUCCESS, FAIL, MAX_LEN = 80}; int num;
void BlockCat(FILE *fin); char buff[MAX_LEN + 1];
main(int argc, char* argv[]) {
FILE *fptr1, *fptr2; while (!feof(fin)){
int reval = SUCCESS; num = fread(buff, sizeof(char), MAX_LEN, fin);
if (argc !=2){ buff[num * sizeof(char)] = `\0';
printf("The correct syntax should be: cat1 filename \n");
reval = FAIL;
printf("%s", buff);
}
}
if ((fptr1 = fopen(argv[1], "r")) == NULL){
}
printf("Cannot open %s.\n", argv[1]);
reval = FAIL;
} else {
BlocCat(fptr1);
fclose(fptr1);
}
return reval;
}

33 34

Bài ý
trình sao chép file theo sao argc và argv[]
cho nó các tên tin và các
if(argc<3) { printf("%s <file1> <file2>n",argv[0]); exit(1); }
dòng .
argv[1] và argv[2] là tên các tin và .
if((fp=fopen(argv[1],"r"))==NULL) {
Ví : trình có tên "filecpy". Cú pháp
thi là:
};
./filecpy haiku.txt haiku2.txt
if((fp2=fopen(argv[2],"w"))==NULL) {

};

35 36
Bài nhà Bài
trình sao chép tin theo , lý danh mình
giao menu dòng các chính sau: trình. trúc danh các
1. Copy by character "name," "telephone number," "e-mail address, và khai báo
100 trúc trên.
2. Copy by line cho 10 .
3. Copy by block - optional size trình sau ghi dung các nói trên vào
4. Quit tin có tên phonebook.dat hàm fwrite.
sao chép, sau khi hoàn thành sao chép, tin vào hàm fread và in dung
gian theo mili giây so sánh. ra màn hình tra.
Chú ý: tin là tin có kích là
640KB.

37 38

enum {SUCCESS, FAIL, MAX_ELEMENT = 20};


#include <stdio.h>
// the phone book structure enum {SUCCESS, FAIL, MAX_ELEMENT = 20};
typedef struct phoneaddress_t { // the phone book structure
char name[20]; typedef struct phoneaddress_t {
char tel[11]; char name[20];
char email[25]; char tel[11];
}phoneaddress; char email[25];
}phoneaddress;

int main(void)
{
FILE *fp;
phoneaddress phonearr[MAX_ELEMENT];
int i,n, irc; // return code
int reval = SUCCESS;

39 40
( )
printf("How many contacts do you want to enter (<20)?");
scanf("%d", &n); //read from this file to array again

for (i=0; i<n; i++){ if ((fp = fopen("phonebook.dat","rb")) == NULL){

printf("name:"); scanf("%s",phonearr[i].name); printf("Can not open %s.\n", "phonebook.dat");


reval = FAIL;
printf("tel:"); scanf("%s",phonearr[i].tel);
}
printf("email:"); scanf("%s",phonearr[i].email);
irc = fread(phonearr, sizeof(phoneaddress), n, fp);
}
printf(" fread return code = %d\n", irc);
if ((fp = fopen("phonebook.dat","w+b")) == NULL){
for (i=0; i<n; i++){
printf("Can not open %s.\n", "phonebook.dat");
printf("%s-",phonearr[i].name);
reval = FAIL; printf("%s-",phonearr[i].tel);
} printf("%s\n",phonearr[i].email);
// write the entire array into the file }
irc = fwrite(phonearr, sizeof(phoneaddress), n, fp); fclose(fp);
printf(" fwrite return code = %d\n", irc); return reval;
fclose(fp); }

41 42

Bài nhà Truy nhiên tin


trình tin (bangdiem.txt hai hàm: fseek() and ftell()
bài danh sách sinh viên và cho) và fseek(): hàm trí con file mong
, sau ghi chúng ra tin phân trong tin.
grade.dat ( các trúc sinh viên). fseek(FILE *stream, long offset, int whence);
stream con tin
trình có : file grade.dat và trên
offset : dài tính theo byte.
màn hình, tìm sinh viên trên mã sinh viên và
dùng và vào tin. whence: và
SEEK_SET: tin, phía tin
trình nên tác menu dòng : SEEK_CUR: trí con file , phía
tin
1. TextToDat
SEEK_END: tin tin.
2. Display Dat file
3. Search and Update.
4 Quit.

43 44
Truy nhiên tin Bài
Hàm ftell: cho giá trí con file
Cú pháp: long ftell(FILE *stream); trình trong danh
trong tin phonebook.dat. Ví danh ( ghi)
2 3, hay 3 6. Sau thay giá
Hàm rewind(): trí con tin. email và ghi vào trí trích .
Cú pháp: void rewind(FILE *stream); trình phát
ra tin khi trình. Ví 4
trúc 3 6.

45 46

án án
#include <stdio.h>
#include <stdlib.h> if ((fp = fopen("phonebook.dat","r+b")) == NULL){
enum {SUCCESS, FAIL, MAX_ELEMENT = 20}; printf("Can not open %s.\n", "phonebook.dat"); reval = FAIL;
}
// the phone book structure
// Memory allocation
typedef struct phoneaddress {
phonearr = (phoneaddress *)malloc(2 * sizeof(phoneaddress));
char name[20];
if (phonearr == NULL){
char tel[11];
printf("Memory allocation failed!\n");
char email[25];
return FAIL;
}phoneaddress; }
int main(void){ if (fseek(fp,1*sizeof(phoneaddress),SEEK_SET) != 0){
FILE *fp; printf("Fseek failed!\n");
phoneaddress *phonearr; return FAIL;
}
int i,n, irc; // return code irc = fread(phonearr, sizeof(phoneaddress), 2, fp);
int reval = SUCCESS;
printf("Read from 2sd data to 3rd data \n");

47 48
án Bài nhà
trình Anh
for (i=0; i<2; i++){ sang phân.
printf("%s-",phonearr[i].name);
printf("%s-",phonearr[i].tel);

printf("%s\n",phonearr[i].email); http://www.denisowski.org/Vietnamese/vnedict.txt
} Miên : the Promised Land
// Modifying some data : Burma (short for )
strcpy(phonearr[1].name,"Lan Hoa");
: Burma
strcpy(phonearr[1].tel,"0923456");
Trung : Central Vietnam
strcpy(phonearr[1].email,"lovelybuffalo@hut.edu.vn");
fseek(fp,1*sizeof(phoneaddress),SEEK_SET); Sau trình tin , dùng
irc = fwrite(phonearr, sizeof(phoneaddress), 2, fp); trí và thúc và các các trí này
printf(" fwrite return code = %d\n", irc);
trong .
fclose(fp); free(phonearr);
return reval;
}

49 50

Bài nhà Bài nhà: Chia tách và ghép File


các trang web các showroom di , xây tin phonebook.dat ( bài trên Lab) ít
tin có tên PhoneDB.txt thông tin ít 20
iPhone, Samsung, Oppo, Huawei, 20 liên . các trình sau
dòng.. theo sau trình filesplit hai : tên file (.dat) và
Model Memory Space (GB) Screen Size (inches) Price nguyên N và tên hai file . Nó tách file thành 2 file,
trình có giao menu sau: trong file tiên N liên tiên và file hai
1. Import DB from text: file PhoneDB.txt và thành
phân PhoneDB.dat phát . các liên còn . Ví du
2. Import from DB: file PhoneDB.dat và vào filesplit phone.dat 10 phone1.dat phone2.dat
trình. Cho phép dùng hai :
toàn và ( trí ghi và thúc). trình filemerge ghép hai file tách thành file:
3. Print All Database: các trên màn
hình, dòng và các . filemerge phone1.dat phone2.dat phone.dat
4. Search by phone by Phone Model: Tìm trên trình fileread và danh sách các liên
model do dùng .
5. Exit trong file .dat ra màn hình. Nó tra
các trình filesplit and filemerge.

51 52
Thank you
for your
attentions!
quy

53

ch ng trình con ( /hàm) a ra chính nó nh ng


vào h n
quy Tình c
quy có vào a ra cách mà
quy quay lui không a ra quy

ch ng trình còn xây


quy và thông tin khác
#include <stdio.h>
int f(int n){
if(n == 1) return 1;
Other form return n + f(n-1);

f(n) = 1, if n = 1 }
int main(){
f(n-1) + n, if n > 1
printf("%d\n",f(4));
}
Dãy k n

C(k,n) = 1, if k = 0 or k = n
#include <stdio.h> C(k,n-1) + f(k-1,n-1),
int f(int n){
f(n) = 1, if n = 0 or n = 1 if(n <= 1) return 1;
f(n-1) + f(n-2), if n > 1 return f(n-1) + f(n-2);
#include <stdio.h>
}
int C(int k, int n){
int main(){
for(int i = 0; i <= 10; i++) if(k == 0 || k == n) return 1;

printf("%d ",f(i)); return C(k,n-1) + C(k-1,n-1);


} }
int main(){
printf("%d ",C(3,5));
}

k n k n
C(k,n) = 1, if k = 0 or k = n C(k,n) = 1, if k = 0 or k = n
C(k,n-1) + f(k-1,n-1), otherwise C(k,n-1) + f(k-1,n-1), otherwise

hàm cùng giá tham


tình tình #include <stdio.h>
ch ng trình con tham ch ng trình con tham
xác quy xác quy #define MAX 100
int M[MAX][MAX];// M[k][n] store the value of
l u l u // C(k,n)
ch ng trình con ch ng trình con int C(int k,int n){
tham tham if(k == 0 || k == n) M[k][n] = 1;
giá giá else if(M[k][n] == 0)
ghi ghi
M[k][n] = C(k,n-1) + C(k-1,n-1);
ch ng trình con ch a ch ng trình con ch a
nào nào return M[k][n];

ánh ánh }
các giá tham các giá tham int main(){
ch ng trình con ch ng trình con memset(M,0,sizeof(M));
printf("%d ",C(3,5));
}

Bài toán tháp Hà Bài toán tháp Hà


Có n kích th khác Có n kích th khác
nhau và 3 A, B, C nhau và 3 A, B, C
Ban n A Ban n A
theo trên theo trên
và d và d
Tìm cách n này
A sang B,
A B C C làm trung gian theo A B C
nguyên
1
trên cùng 1
sang khác
Không phép
ra tình to
bên trên
Bài toán tháp Hà #include <stdio.h>
Có n kích th khác int cnt = 0;
nhau và 3 A, B, C
void move(int n, char A, char B, char C){
Ban n A if(n == 1){
theo trên
cnt++;
và d
printf("Step %d: Move a disk from %c to %c\n",cnt,A,B);
Tìm cách n này
}else{
A sang B,
C làm trung gian theo A B C move(n-1,A,C,B);
nguyên move(1,A,B,C);
1 B1: A B
move(n-1,C,B,A);
trên cùng 1 B2: A C }
sang khác
B3: B C }
Không phép B4: A B int main(){
ra tình to B5: C A move(3,'A','B','C');
bên trên
B6: C B }
B7: A B

Áp các bài toán kê, bài toán u TRY(k)

A = {(x1, x2, . . ., xn ) | xi Ai, i = 1,. . ., n} Begin


Foreach v Ak
kê các x A mãn tính P nào
if check(v,k) /* tra xem v có không */
TRY(k): Begin
các giá v có gán cho xk mà không vi tính P xk = v;
giá v: if(k = n) ghi_nhan_cau_hinh;
Gán v cho xk else TRY(k+1);
k < n: quy TRY(k+1) giá cho xk+1 End
k = n: ghi hình End
Main()
Begin
TRY(1);
End
kê xâu phân kê xâu phân
void printSolution(){
Mô hình hoá hình: Mô hình hoá hình: for(int k = 0; k < n; k++)
x[n] trong x[i] {0,1} x[n] trong x[i] {0,1} printf [k]);
là bít i xâu phân là bít i xâu phân printf \
(i= 0, . . ., n-1) (i= 0, . . ., n-1) }

int TRY(int k) {
for(int v = 0; v <= 1; v++){
x[k] = v;
if(k == n-1) printSolution();
else TRY(k+1);
}
}

int main() {
TRY(0);
}

kê xâu phân kê xâu phân


kê các xâu phân sao cho kê các xâu phân sao cho int TRY(int k) {
không có 2 bit 1 nào không có 2 bit 1 nào for(int v = 0; v <= 1; v++){
nhau nhau if(x[k-1] + v < 2){
x[k] = v;
Mô hình hoá hình: Mô hình hoá hình:
if(k == n)
x[n] trong x[i] {0,1} x[n] trong x[i] {0,1} printSolution();
là bít i xâu phân là bít i xâu phân else TRY(k+1);
(i= 1, . . ., n) (i= 1, . . ., n) }
tính P: không có 2 bít 1 tính P: không có 2 bít 1 }
nào nhau nào nhau }

int main() {
x[0] = 0;
TRY(1);
}
kê kê
int TRY(int i) {
kê các k kê các k for(int v = x[i-1]+1; v <= n-k+i;
n n v++){
x[i] = v;
Mô hình hoá hình: Mô hình hoá hình: if(i == k)
x[k] trong x[i] {1, . . x[k] trong x[i] {1, . . printSolution();
., n} là i ., n} là i else TRY(i+1);
hình (i = 1, . . ., k) hình (i = 1, . . ., k) }
tính P: x[i] < x[i+1], tính P: x[i] < x[i+1], }
i k-1 i k-1
int main() {
x[0] = 0;
TRY(1);
}

kê hoán kê hoán

kê các hoán n kê các hoán n void TRY(int i) {


for(int v = 1; v <= n; v++){
Mô hình hoá hình: Mô hình hoá hình:
if(!m[v]) {
x[1,. . . , n] trong x[i] x[1,. . . , n] trong x[i] x[i] = v;
{1, . . ., n} là i {1, . . ., n} là i m[v] = true; //
hình hoán (i = 1, . . hình hoán (i = 1, . . if(i == n)
., n) ., n) printSolution();
tính P: tính P: else TRY(i+1);
x[i] x[j], 1 i <j x[i] x[j], 1 i <j m[v] = false;// khôi
n n }
m[v] = true m[v] = true }
(false) giá v (false) giá v }
(ch a ) trong (ch a ) trong void main() {
hình , v= hình , v= for(int v = 1; v <= n; v++)
n n m[v] = false;
TRY(1);
}
bài toán bài toán
n quân trên bàn
sao cho không có 2 quân nào n int check(int v, int k) { void TRY(int k) {
nhau
// tra xem v có gán for(int v = 1; v <= n; v++) {
Mô hình hoá // cho x[k] không if(check(v,k)) {
1 2 3 4
x[1, . . ., n] trong x[i] là hàng for(int i = 1; i <= k-1; i++) { x[k] = v;
quân trên i, i = 1, 1 X if(k == n) printSolution();
if(x[i] == v) return 0;
n 2 X else TRY(k+1);
if(x[i] + i == v + k) return 0;
tính P }
3 X if(x[i] i == v k) return 0;
x[i] x[j], 1 i<j n }
}

x[i] + i x[j] + j, 1 i<j n 4 X }


return 1; void main() {
x[i] i x[j] - j, 1 i<j n }
x = (3, 1, 4, 2) TRY(1);
}

kê các nguyên trình: kê các nguyên trình:


x1 + x2 + . . . + xn = M x1 + x2 + . . . + xn = M
Duy trì T là giá các giá
Hàm TRY(k)
Các x1, x2 k-1 giá
T = x1+ x2 xk-1
xk+1 + xk+2 xn n-k
xk M T (n - k)
bài toán Sudoku
kê các nguyên trình: các 1 9 vào các ô
x1 + x2 + . . . + xn = M trong vuông 9x9 sao cho trên
hàng, và vuông con
#include <stdio.h> void Try(int k){ 1 2 3 4 5 6 7 8 9
3x3 có 1 1
#define N 100 for(int v = 1; v <= M - T - (n-k); v++){
9 4 5 6 7 8 9 1 2 3
int n,M,T; if(check(v,k)){
7 8 9 1 2 3 4 5 6
int x[N]; x[k] = v;
T += v;
2 1 4 3 6 5 8 9 7
void solution(){
if(k == n) solution(); 3 6 5 8 9 7 2 1 4
for(int i = 1; i <= n; i++)
printf("%d ",x[i]);
else Try(k+1); 8 9 7 2 1 4 3 6 5
T -= v;
printf("\n"); 5 3 1 6 4 2 9 7 8
}
}
}
6 4 2 9 7 8 5 3 1
int check(int v, int k){ } 9 7 8 5 3 1 6 4 2
if(k == n) return T + v == M; int main(){
return 1; n = 3; M = 5; T = 0;
} Try(1);
}

bài toán Sudoku bài toán Sudoku


Mô hình hoá
2 x[0..8, 0..8]
: ô (0,0), theo
tính P 1 2 3 4 5 6 7 8 9 trái qua và trên d 1 2 3 4 5 6 7 8 9
x[i, j2] x[i, j1], i = 4 5 6 7 8 9 1 2 3
0, ,8, và 0 j1 < j2 8 4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
x[i1, j] x[i2, j], j = 7 8 9 1 2 3 4 5 6
0, ,8, và 0 i1 < i2 8 2 1 4 3 6 5 8 9 7
2 1 4 3 6 5 8 9 7
x[3I+i1, 3J+j1] x[3I+i2, 3J+j2], 3 6 5 8 9 7 2 1 4
3 6 5 8 9
v I, J = 0, , 2, và i1, j1, 8 9 7 2 1 4 3 6 5
i2, j2 {0,1, 2} sao cho i1 i2
5 3 1 6 4 2 9 7 8
ho j1 j2
6 4 2 9 7 8 5 3 1
9 7 8 5 3 1 6 4 2
bài toán Sudoku bài

Cho nguyên d ng M, N và N nguyên d ng A1, A2 AN.


bool check(int v, int r, int c){ void TRY(int r, int c){ kê các nguyên d ng ph ng trình
for(int i = 0; i <= r-1; i++) for(int v = 1; v <= 9; v++){
if(x[i][c] == v) return false; if(check(v,r,c)){ A1X1 + A2X2 + . . . + ANXN = M
x[r][c] = v;
for(int j = 0; j <= c-1; j++) bài toán và sudoku
if(r == 8 && c == 8){
if(x[r][j] == v) return false;
printSolution();
int I = r/3; int J = c/3;
}else{
int i = r - 3*I; int j = c - 3*J; if(c == 8) TRY(r+1,0);
for(int i1 = 0; i1 <= i-1; i1++) else TRY(r,c+1);
for(int j1 = 0; j1 <= 2; j1++) }
if(x[3*I+i1][3*J+j1] == v) }
return false; }
for(int j1 = 0; j1 <= j-1; j1++) }
if(x[3*I+i][3*J+j1] == v)
void main(){
return false;
TRY(0,0);
return true;
}
}

Thank you
for your
attentions!
Danh sách tính
dung Các thao tác trên danh sách liên

Cài các thao tác trên danh sách liên nút danh sách liên có trúc sau
Bài toán lý typedef struct Node{
Cài danh sách liên int value;
Cài danh sách liên struct Node* next;
}Node;

Cài các hàm


Node* insertLast(Node* h, int v);// insert a node at that last position
Node* removeFirst(Node* h, int v);// remove a first node having value v
Node* removeAll(Node* h, int v);// remove all nodes having value v
int count(Node* h);// count number of nodes
Node* reverse(Node* h);// reverse the linked list

2 3

Các thao tác trên danh sách liên Các thao tác trên danh sách liên

trúc Chèn thêm 1 nút vào danh sách ( và không quy)


#include <stdio.h> Node* insertLast(Node* h, int v){ Node* insertLastRecursive(Node* h, int v){
typedef struct Node{ Node* p = h; if(h == NULL){
int value; if(h == NULL){ return makeNode(v);
struct Node* next;// point to the next return makeNode(v); }
//element of the current element } h->next = insertLastRecursive(h->next, v);
}Node; // general case return h;
while(p->next != NULL) }
Node*makeNode(int v){// allocate memory for a new node p = p->next;
Node* p = (Node*)malloc(sizeof(Node));
p->value = v; p->next = NULL; Node* q = makeNode(v);
return p; p->next = q;
} return h;
}

4 5
Các thao tác trên danh sách liên Các thao tác trên danh sách liên
1 nút có giá v (không dùng quy) 1 nút có giá v( quy)
Node* removeNode(Node* h, int v){ Node* removeNodeRecursive(Node* h, int v){
Node* p = h; if(h == NULL) return NULL;
if(h == NULL) return NULL; if(h->value == v){
if(h->value == v Node* tmp = h; h = h->next; free(tmp); return h;
Node* tmp = h; h = h->next; }
free(tmp); return h; h->next = removeNodeRecursive(h->next, v);
} return h;
while(p->next != NULL){ }
if(p->next->value == v) break;
p = p->next;
}
if(p->next != NULL){
Node* q = p->next; p->next = q->next; free(q);
}
return h;
}

6 7

Các thao tác trên danh sách liên Các thao tác trên danh sách liên
các nút có giá v( quy) nút trên danh sách ( và không quy)
Node* removeAll(Node* h, int v){ int countRecursive(Node* h){ int count(Node* h){
// remove all nodes having value v from the linked list headed by h if(h == NULL) return 0; int cnt = 0;
if(h == NULL) return NULL; return 1+countRecursive(h->next); Node* p = h;
if(h->value == v){ } while(p != NULL){
Node* tmp = h; h = h->next; free(tmp); cnt += 1;
h = removeAll(h,v); // continue to remove other elements having value v p = p->next;
return h; }
} return cnt;
h->next = removeAll(h->next,v); }
return h;
}

8 9
Các thao tác trên danh sách liên Bài lý sinh viên
các nút trong danh sách
sinh viên bao :
Node* reverse(Node *h){
name: tên sinh viên
Node* p = h;
email: email sinh viên
Node* pp = NULL;
Node* np = NULL; trình trong tác dòng các
while(p != NULL){
trong lý sinh viên
np = p->next;
file vào danh sách
p->next = pp; In danh sách sinh viên
pp = p; Thêm 1 vào danh sách
p = np; Xóa 1
} Tìm
return pp; vào file
}

10 11

lý sinh viên: danh sách liên lý sinh viên: danh sách liên

Khai báo
Profile* makeProfile(char* name, char* email){
#include <stdio.h> Profile* node = (Profile*)malloc(sizeof(Profile));
#define MAX_L 256 strcpy(node->name,name);
strcpy(node->email,email);
node->next = NULL;
typedef struct Profile{
return node;
char name[MAX_L]; // ten sinh vien
}
char email[MAX_L];// email cua sinh vien
void initList(){
struct Profile* next;
first = NULL; last = NULL;
}Profile;
}
int listEmpty(){
Profile* first, *last; return first == NULL && last == NULL;
}

12 13
lý sinh viên: danh sách liên lý sinh viên: danh sách liên

void insertLast(char* name, char* email){


Profile* removeProfile(Profile* f, char* name){
Profile* profile = makeProfile(name,email);
if(listEmpty()) return NULL;
if(listEmpty()){
if(strcmp(f->name,name) == 0){
first = profile; last = profile;
Profile* tmp = f->next;
}else{
free(f);
last->next = profile; last = profile;
if(tmp == NULL) last = NULL;
}
return tmp;
}
}else{
void printList(){
f->next = removeProfile(f->next,name);
for(Profile* p = first; p != NULL; p = p->next)
return f;
printf("%s, %s\n",p->name, p->email);
}
}
}

14 15

lý sinh viên: danh sách liên lý sinh viên: danh sách liên

void load(char* filename){ void processFind(){

FILE* f = fopen(filename,"r"); char name[256];


scanf("%s",name);
if(f == NULL) printf("Load data -> file not found\n");
Profile* profile = NULL;
for(Profile* p = first; p != NULL; p = p->next){
while(!feof(f)){
if(strcmp(p->name,name)==0){
char name[256], email[256];
profile = p; break;
fscanf(f,"%s%s",name, email);
}
insertLast(name,email); }
} if(profile == NULL){
fclose(f); printf("NOT FOUND profile %s\n",name);
} }else{
printf("FOUND profile %s, %s\n",profile->name,profile->email);
}
}

16 17
lý sinh viên: danh sách liên lý sinh viên: danh sách liên
void processLoad(){// load du lieu tu file vao bo nho void processInsert(){
char filename[256]; char name[256], email[256];
scanf("%s",filename); scanf("%s%s",name,email);
load(filename); insertLast(name,email);
}
}
void processStore(){// luu du lieu DS vao file van ban
void processRemove(){
char filename[256];
char name[256];
scanf("%s",filename);
scanf("%s",name);
FILE* f = fopen(filename,"w");
first = removeProfile(first,name);
for(Profile* p = first; p != NULL; p = p->next){
}
fprintf(f,"%s %s",p->name,p->email);
if(p->next != NULL) fprintf(f,"\n");
}
fclose(f);
}

18 19

lý sinh viên: danh sách liên lý sinh viên: danh sách liên
int main(){// chay chuong trinh trong che do interactive
trúc
initList();
while(1){
printf("Enter command: "); #include <stdio.h>
char cmd[256]; #define MAX_L 256
scanf("%s",cmd);
if(strcmp(cmd,"Quit")==0) break; typedef struct Profile{
else if(strcmp(cmd,"Load")==0) processLoad(); char name[MAX_L];
else if(strcmp(cmd,"Print")==0) printList(); char email[MAX_L];
else if(strcmp(cmd,"Find")==0) processFind();
struct Profile* next;// pointer to the next element
else if(strcmp(cmd,"Insert")==0) processInsert();
struct Profile* prev;// pointer to the predecessor
else if(strcmp(cmd,"Remove")==0) processRemove();
}Profile;
else if(strcmp(cmd,"Store")==0) processStore();
}
Profile* first, *last;
}

20 21
lý sinh viên: danh sách liên lý sinh viên: danh sách liên

void initList(){
Profile* makeProfile(char* name, char* email){ first = NULL; last = NULL;
Profile* node = (Profile*)malloc(sizeof(Profile)); }
strcpy(node->name,name); int listEmpty(){
strcpy(node->email,email); return first == NULL && last == NULL;
node->next = NULL; }
node->prev = NULL; void printListLeft2Right(){
return node; for(Profile* p = first; p != NULL; p = p->next)
} printf("%s, %s\n",p->name, p->email);
}
void printListRight2Left(){
for(Profile* p = last; p != NULL; p = p->prev)
printf("%s, %s\n",p->name, p->email);
}

22 23

lý sinh viên: danh sách liên lý sinh viên: danh sách liên

void insertLast(char* name, char* email){ Profile* find(char*name){


Profile* profile = makeProfile(name,email); for(Profile* p = first; p != NULL; p = p->next){
if(listEmpty()){ if(strcmp(p->name,name)==0){
first = profile; last = profile; return p;
}else{ }
last->next = profile; profile->prev = last; }
last = profile; return NULL;
} }
}

24 25
lý sinh viên: danh sách liên lý sinh viên: danh sách liên

void load(char* filename){


void removeProfile(char* name){
if(listEmpty()) return NULL;
FILE* f = fopen(filename,"r");

Profile* profile = find(name); if(f == NULL) printf("Load data -> file not found\n");
if(profile == NULL){ initList();
printf("NOT FOUND %s\n",name); while(!feof(f)){
}else{ char name[256], email[256];
Profile* left = profile->prev;
fscanf(f,"%s%s",name, email);
Profile* right = profile->next;
insertLast(name,email);
if(left != NULL) left->next = right;
printf("insert %s, %s\n",name,email);
if(right != NULL) right->prev = left;
}
if(left == NULL) first = right;
if(right == NULL) last = left; fclose(f);
free(profile); }
}
}

26 27

lý sinh viên: danh sách liên lý sinh viên: danh sách liên

void processLoad(){
void processFind(){
char filename[256];
char name[256];
scanf("%s",filename);
scanf("%s",name); load(filename);
Profile* profile = find(name); }
if(profile == NULL){ void processStore(){
printf("NOT FOUND profile %s\n",name); char filename[256];

}else{ scanf("%s",filename);
FILE* f = fopen(filename,"w");
printf("FOUND profile %s, %s\n",profile->name,profile->email);
for(Profile* p = first; p != NULL; p = p->next){
}
fprintf(f,"%s %s",p->name,p->email);
}
if(p->next != NULL) fprintf(f,"\n");
}
fclose(f);
}

28 29
lý sinh viên: danh sách liên lý sinh viên: danh sách liên
void processPrintList(){
void processInsert(){
printf("Danh sach tu trai qua phai\n");
char name[256], email[256];
printListLeft2Right();
scanf("%s%s",name,email);
printf("Danh sach tu phai qua trai\n");
insertLast(name,email);
printListRight2Left();
}
}
void processRemove(){
void finalize(){
char name[256]; Profile* p = first;
scanf("%s",name); while(p != NULL){
removeProfile(name); Profile* np = p->next;
} free(p);
p = np;
}
}

30 31

lý sinh viên: danh sách liên


int main(){
initList();
while(1){
printf("Enter command: ");
char cmd[256];
scanf("%s",cmd);
if(strcmp(cmd,"Quit")==0) break;
else if(strcmp(cmd,"Load")==0) processLoad();
else if(strcmp(cmd,"Print")==0) processPrintList();
else if(strcmp(cmd,"Find")==0) processFind();
else if(strcmp(cmd,"Insert")==0) processInsert();
else if(strcmp(cmd,"Remove")==0) processRemove();
else if(strcmp(cmd,"Store")==0) processStore();
}
finalize();
}

32 33
dung

Cài và vào bài toán tra


Cài hàng và vào bài toán tìm trong mê cung

và hàng

1 2

danh sách liên , top Hàm phát top


bao
Node* makeNode(char x){
Data: ký ,
Node* p = (Node*)malloc(sizeof(Node));

Con p->c = x; p->next = NULL;


theo trong danh sách liên return p;

(top) danh sách liên }


con
danh sách liên
typedef struct Node{
char c;
struct Node* next;
}Node;
Node* top;

3 4
top Thao tác thêm và ra top

void push(char x){


void initStack(){ Node* p = makeNode(x);
top = NULL; p->next = top; top = p;
} }
int stackEmpty(){
return top == NULL; char pop(){
} if(stackEmpty()) return ' ';
char x = top->c;
Node* tmp = top; top = top->next; free(tmp);
return x;
}

5 6

tra tính dãy


[({})](): top
tra xem và có nhau hay không
([} {}): không
toán:
1 ng n S
int match(char a, char b){
dãy trái qua if(a == '(' && b == ')') return 1;
thì vào S if(a == '[' && b == ']') return 1;
if(a == '{' && b == '}') return 1;
S thì FALSE return 0;
S còn thì 1 ra }
S, tra sánh :
và không t ng
nhau thì FALSE
thúc , S còn thì
FALSE, ng thì TRUE

7 8
Hàng
Hàng là trúc các cách tính
tra tính xâu ký s Thêm 1 hàng (tail)
ra 1 hàng (head)
int check(char* s){
initStack(); Hàng có cài các bài toán tìm theo
for(int i = 0; i < strlen(s); i++){
( toán loang) trên không gian thái
if(s[i] == '(' || s[i] == '[' || s[i] == '{'){
push(s[i]);
}else{
if(stackEmpty()) return 0;
char x = pop();
if(!match(x,s[i])) return 0;
}
}
return stackEmpty();
}

9 10

Bài toán tìm trong mê cung (maze) Bài toán tìm trong mê cung (maze)

thái bài toán


mê cung (r,c) là
ma 0-1 aNxM trong ai,j = 1 hàng và trí thái
có ô (i,j) là , ai,j toán phát
= 0 có ô (i,j) là ô , có thái phát vào hàng
vào. s1 s2
ô , ta có di thái
sang trong 4 ô lân thúc
1 thái ra hàng s0
(lên trên, , sang X
, sinh ra các và các
trái, sang ) ô là thái lân nó vào
ô . hàng các thái s3 s4 s8
Tính toán ô này sinh ra
(i0, j0) thoát ra mê
ít di toán thúc khi sinh ra s5 s6
Thoát ra mê cung sau 7 thái

s7 s9

11 12
Bài toán tìm trong mê cung (maze) Bài toán tìm trong mê cung (maze)
#include <stdio.h>
trúc thái #include <stdlib.h>
#define MAX 100

typedef struct Node{ Node* head, *tail;


int row,col;// hang và thái Node* listNode[MAX*MAX];// các phát , phóng BN
int step; // di thái phát thái int szList = 0;// listNode
struct Node* next; // con theo trong hàng int A[MAX][MAX];
struct Node* parent;// con thái sinh ra thái int n,m;
}Node; int r0,c0;
int visited[MAX][MAX];

const int dr[4] = {1,-1,0,0};


const int dc[4] = {0,0,1,-1};
Node* finalNode;

13 14

Bài toán tìm trong mê cung (maze) Bài toán tìm trong mê cung (maze)
void initQueue(){
head = NULL; tail = NULL;
}
int queueEmpty(){
return head == NULL && tail == NULL;
}
void pushQueue(Node * node){
Node* makeNode(int row, int col, int step, Node* parent){ if(queueEmpty()){

Node* node = (Node*)malloc(sizeof(Node)); head = node; tail = node;


}else{
node->row = row; node->col = col; node->next = NULL;
tail->next = node; tail = node;
node->parent = parent; node->step = step;
}
return node; }
} Node* popQueue(){
if(queueEmpty()) return NULL;
Node* node = head; head = node->next;
if(head == NULL) tail = NULL;
return node;
}

15 16
Bài toán tìm trong mê cung (maze) Bài toán tìm trong mê cung (maze)
void input(){ int legal(int row, int col){
FILE* f = fopen("maze.txt","r"); return A[row][col] == 0 && !visited[row][col];
fscanf(f,"%d%d%d%d",&n,&m,&r0,&c0); }
for(int i = 1; i <= n; i++){ int target(int row, int col){
for(int j =1; j <= m; j++){ return row < 1 || row > n || col < 1 || col > m;
fscanf(f,"%d",&A[i][j]); }
} void finalize(){
} for(int i = 0; i < szList; i++){
fclose(f); free(listNode[i]);
} }
}
void addList(Node* node){// them phan tu vao listNode de thuc hien giai phong bo nho
listNode[szList] = node;
szList++;
}

17 18

Bài toán tìm trong mê cung (maze) Bài toán tìm trong mê cung (maze)
int main(){ if(legal(nr,nc)){
printf("MAZE\n"); visited[nr][nc] = 1;
input(); Node* newNode = makeNode(nr,nc,node->step + 1, node);

for(int r = 1; r <= n; r++) addList(newNode);


if(target(nr,nc)){
for(int c = 1; c <= m; c++)
finalNode = newNode; break;
visited[r][c] = 0;
}else
initQueue();
pushQueue(newNode);
Node* startNode = makeNode(r0,c0,0,NULL);
}
addList(startNode);
}
pushQueue(startNode); if(finalNode != NULL) break;// found solution
visited[r0][c0]= 1; }
while(!queueEmpty()){ Node* s = finalNode;
Node* node = popQueue(); while(s != NULL){
printf("POP (%d,%d)\n",node->row,node->col); printf("(%d,%d) ",s->row,s->col);
for(int k = 0; k < 4; k++){ s = s->parent;
int nr = node->row + dr[k]; }

int nc = node->col + dc[k]; finalize();


}

19 20
Cây 1

Thao tác cây quát Thao tác cây quát

nút cây có trúc sau trình C tác thao tác cây


typedef struct Node{ gia các sau:
char name[256]; Load <filename>: <filename> vào và
struct Node* leftMostChild; // pointer to the left-most child cây
struct Node* rightSibling;// pointer to the right sibling FindChildren <name>: in ra màn hình danh sách con
}Node; <name>
AddChild <name> <child>: thêm con <child> vào danh
cây text sau: sách con <name>
dòng 1 dãy các xâu ký s0, s1 sk thúc $ trong s1, s2
sk là con s0 trái qua (s1 là con trái s0) (ghi chú: dòng Print: In ra màn hình danh sách các thành viên trong gia
( dòng 1), s0 là con nút nào trong dòng ).
File thúc $$ Height <name>: in ra cao <name> trên cây
david Count: thành viên gia ( nút cây)
david jame peter john $
peter mary daisy $ Store <filename>: cây ra file <filename>
jame peter john
jame mike $
$$
mike mary daisy

2 3
Thao tác cây quát Thao tác cây quát

#include <stdio.h> Node* find(Node* r, char* name){


typedef struct Node{ if(r == NULL) return NULL;
char name[256]; if(strcmp(r->name,name) == 0) return r;
struct Node* leftMostChild; Node* p = r->leftMostChild;
struct Node* rightSibling; while(p != NULL){
}Node; Node* q = find(p,name);
Node* root; if(q != NULL) return q;
p = p->rightSibling;
Node* makeNode(char* name){ }
Node* p = (Node*)malloc(sizeof(Node)); }
strcpy(p->name,name);
p->leftMostChild = NULL; p->rightSibling = NULL;
return p;
}

4 5

Thao tác cây quát Thao tác cây quát


void printTree(Node* r){
Node* addLast(Node* p, char*name){ if(r == NULL) return;
if(p == NULL) return makeNode(name); printf("%s: ",r->name);
p->rightSibling = addLast(p->rightSibling, name); Node* p = r->leftMostChild;
return p; while(p != NULL){
} printf("%s ",p->name);
void addChild(char*name, char* child){ p = p->rightSibling;
Node* r = find(root,name); }
if(r == NULL) return; printf("\n");
r->leftMostChild = addLast(r->leftMostChild,child); p = r->leftMostChild;
} while(p != NULL){
printTree(p);
p = p->rightSibling;
}
}

6 7
Thao tác cây quát Thao tác cây quát
void printTreeF(Node* r, FILE* f){ void processFind(){
if(r == NULL) return; char name[256]; scanf("%s",name);
fprintf(f,"%s ",r->name); Node* p = find(root,name);
Node* p = r->leftMostChild; if(p == NULL) printf("Not Found %s\n",name);
while(p != NULL){ else printf("Found %s\n",name);
fprintf(f,"%s ",p->name); }
p = p->rightSibling;
}
fprintf(f," $\n");
p = r->leftMostChild;
while(p != NULL){
printTreeF(p,f);
p = p->rightSibling;
}
}

8 9

Thao tác cây quát Thao tác cây quát


void processFindChildren(){ int height(Node* p){
char name[256]; scanf("%s",name); if(p == NULL) return 0;
Node* p = find(root,name); int maxH = 0;
if(p == NULL) printf("Not Found %s\n",name); Node* q = p->leftMostChild;
else{ while(q != NULL){
printf("Found %s with children: ",name); int h = height(q);
Node* q = p->leftMostChild; maxH = maxH < h ? h : maxH;
while(q != NULL){ q = q->rightSibling;
printf("%s ",q->name); q = q->rightSibling; }
} return maxH + 1;
} }
printf("\n");
}

10 11
Thao tác cây quát Thao tác cây quát
void processHeight(){ int count(Node* r){
char name[256]; if(r == NULL) return 0;
scanf("%s",name); int cnt = 1;
Node* p = find(root,name); Node* q = r->leftMostChild;
if(p == NULL) printf("Not Found %s\n",name); while(q != NULL){
else{ cnt += count(q);
printf("Found %s having height = %d\n",name,height(p)); q = q->rightSibling;
} }
} return cnt;
}
void processCount(){
printf("Number of members is %d\n",count(root));
}

12 13

Thao tác cây quát Thao tác cây quát


void processStore(){ void freeTree(Node* r){
char filename[256]; if(r == NULL) return;
scanf("%s",filename); Node* p = r->leftMostChild;
FILE* f = fopen(filename,"w"); while(p != NULL){
printTreeF(root,f); Node* sp = p->rightSibling;
fprintf(f,"$$"); freeTree(p);
fclose(f); p = sp;
} }
printf("free node %s\n",r->name); free(r);
r = NULL;
}

14 15
Thao tác cây quát
void main(){
while(1){
char cmd[256];
printf("Enter command: "); scanf("%s",cmd);
if(strcmp(cmd,"Quit") == 0) break;
else if(strcmp(cmd,"Load")==0) processLoad();
else if(strcmp(cmd,"Print")==0) processPrint();
else if(strcmp(cmd,"Find")==0) processFind();
else if(strcmp(cmd,"FindChildren")==0) processFindChildren();
else if(strcmp(cmd,"Height")==0) processHeight();
else if(strcmp(cmd,"Count")==0) processCount();
else if(strcmp(cmd,"AddChild")==0) processAddChild();
else if(strcmp(cmd,"Store")==0) processStore();
}
freeTree(root);
}

16

Thao tác cây phân


nút cây phân có trúc sau

typedef struct Node{


int id; // identifier of the node
struct Node* leftChild;// pointer to the left child
struct Node* rightChild;// pointer to the right child

Cây 2 }Node;

cây trong file text sau:


dòng 3 nguyên t, u, v trong u và v ( khác -1) là
con trái và con t (ghi chú: giá t trên dòng ( dòng 1) là con
1 nào trên dòng )
File thúc -2
5
5 2 4
2 1 -1
2 4
4 3 6
1 3 6 3 -1 7
-2
7
1 2
Thao tác cây phân Thao tác cây phân
trình C trong tác các sau: #include <stdio.h>
Load <filename>: file <filename> và cây typedef struct Node{
Print: In cây ra màn hình int id;
AddLeftChild <cur_id> <child_id>: thêm nút con trái <child_id> ( struct Node* leftChild;
) vào nút danh <cur_id> trên cây <cur_id> struct Node* rightChild;
}Node;
AddRightChild <cur_id> <child_id>: thêm con <child_id> ( Node* root;
) vào nút có danh <cur_id> vào cây <cur_id>
Node* makeNode(int id){
Find <id>: tìm nút có danh <id>
Node* p = (Node*)malloc(sizeof(Node));
Count: nút cây
p->id = id;
FindLeaves: In ra màn hình các nút lá cây
p->leftChild = NULL; p->rightChild = NULL;
Height <id>: in ra màn hình cao nút <id> ( )
return p;
Store <filename>: cây ra file <filename> }
Quit: thoát trình

3 4

Thao tác cây phân Thao tác cây phân


Node* find(Node* r, int id){ void addRightChild(int u, int right){
if(r == NULL) return NULL; Node* pu = find(root,u);
if(r->id == id) return r; if(pu == NULL){
Node* p = find(r->leftChild,id); printf("Not found %d\n",u); return;
if(p != NULL) return p;
}
return find(r->rightChild,id);
if(pu->rightChild != NULL){
}
printf("Node %d has already rightChild\n",u); return;
void addLeftChild(int u, int left){
}
Node* pu = find(root,u);
pu->rightChild = makeNode(right);
if(pu == NULL){
printf("Not found %d\n",u); return; }

}
if(pu->leftChild != NULL){
printf("Node %d has already leftChild\n",u); return;
}
pu->leftChild = makeNode(left);
}

5 6
Thao tác cây phân Thao tác cây phân
void load(char* filename){ void printTree(Node* r){
FILE* f = fopen(filename,"r"); if(r == NULL) return;
root = NULL; printf("%d: ",r->id);
while(1){ if(r->leftChild == NULL) printf("leftChild = NULL");
int u; else printf("leftChild = %d",r->leftChild->id);
fscanf(f,"%d",&u); if(r->rightChild == NULL) printf(", rightChild = NULL");
if(u == -2) break;// termination else printf(", rightChild = %d",r->rightChild->id);
if(root == NULL) root = makeNode(u);// create the root printf("\n");
int l,r;
fscanf(f,"%d%d",&l,&r); printTree(r->leftChild);
if(l > -1) addLeftChild(u,l); printTree(r->rightChild);
if(r > -1) addRightChild(u,r); }
}
fclose(f);
}

7 8

Thao tác cây phân Thao tác cây phân


void printTreeF(Node* r, FILE* f){ void processLoad(){
if(r == NULL) return; char filename[256];
fprintf(f,"%d ",r->id); scanf("%s",filename);
if(r->leftChild == NULL) fprintf(f,"-1 "); load(filename);
else fprintf(f,"%d ",r->leftChild->id); }
if(r->rightChild == NULL) fprintf(f,"-1 "); void printChildren(Node* p){
else fprintf(f,"%d ",r->rightChild->id); if(p->leftChild == NULL) printf(" Node %d does not has leftChild",p->id);
fprintf(f,"\n"); else printf(", LeftChild = %d",p->leftChild->id);
if(p->rightChild == NULL) printf(" Node %d does not has rightChild\n",p->id);
printTreeF(r->leftChild,f); else printf(", RightChild = %d\n",p->rightChild->id);
printTreeF(r->rightChild,f); }
}

9 10
Thao tác cây phân Thao tác cây phân
void processFind(){ void processAddLeftChild(){
int id; int id,u;
scanf("%d",&id); scanf("%d%d",&id,&u);
Node* p = find(root,id); addLeftChild(id,u);
if(p == NULL) printf("Not found %d\n",id); }
else { void processAddRightChild(){
printf("Found node %d: ",id); int id,u;
printChildren(p); scanf("%d%d",&id,&u);
} addRightChild(id,u);
} }
void processPrint(){
printTree(root);
}

11 12

Thao tác cây phân Thao tác cây phân


int height(Node* p){ int count(Node* p){
if(p == NULL) return 0; if(p == NULL) return 0;
int maxH = 0; return 1 + count(p->leftChild) + count(p->rightChild);
int hl = height(p->leftChild); }
if(maxH < hl) maxH = hl;
void printLeaves(Node* p){
int hr = height(p->rightChild);
if(p == NULL) return;
if(maxH < hr) maxH = hr;
if(p->leftChild == NULL && p->rightChild == NULL)
return maxH + 1;
printf("%d ",p->id);
}
printLeaves(p->leftChild);
void processHeight(){
int id; printLeaves(p->rightChild);

scanf("%d",&id); }

Node* p = find(root,id); void processFindLeaves(){


if(p == NULL) printf("Not found %d\n",id); printLeaves(root); printf("\n");
else printf("Height of %d is %d\n",height(p)); }
}

13 14
Thao tác cây phân Thao tác cây phân
void processCount(){ void main(){
printf("Number of nodes = %d\n",count(root)); while(1){
char cmd[256]; // representing the input command
}
printf("Enter a command: ");
void processStore(){
scanf("%s",cmd);
char filename[256];
if(strcmp(cmd,"Quit") == 0) break;
scanf("%s",filename); else if(strcmp(cmd,"Load")==0) processLoad();
FILE* f = fopen(filename,"w"); else if(strcmp(cmd,"Print")==0) processPrint();
printTreeF(root,f); else if(strcmp(cmd,"Find")==0) processFind();
fprintf(f,"-2"); else if(strcmp(cmd,"Height")==0) processHeight();
fclose(f); else if(strcmp(cmd,"Count")==0) processCount();

} else if(strcmp(cmd,"FindLeaves")==0) processFindLeaves();


else if(strcmp(cmd,"AddLeftChild")==0) processAddLeftChild();
void freeTree(Node* r){
else if(strcmp(cmd,"AddRightChild")==0) processAddRightChild();
if(r == NULL) return;
else if(strcmp(cmd,"Store")==0) processStore();
freeTree(r->leftChild); }
freeTree(r->rightChild); freeTree(root);
free(r); r = NULL; }
}

15 16

1
Bài 1: sinh cho
Sinh trình vào là 3 nguyên n, m, và M, sinh ra
Cài 3 toán , chèn, n nguyên a1, a2 an giá nhiên trong m
M. ra file arr-n.txt sau
Thí và giá Dòng 1: ghi nguyên 6)

Dòng 2 ghi a1, a2 an. Các cách nhau 1 cách

Ví : 5, 7, 3, 8, 1, 2, 9, 4, 6
vào trí void selectionSort(int A[], int N) {
1 // index tu 1 -> N
for(int k = 1; k <= N; k++){
5 7 3 8 1 2 9 4 6 1 2 3 4 5 7 9 8 6
2 vào trí
int min = k;
2
for(int j = k+1; j <= N; j++){
3 vào trí if(A[min] > A[j]) min = j; 1 7 3 8 5 2 9 4 6 1 2 3 4 5 6 9 8 7
3 }
int tmp = A[min];
A[min] = A[k]; 1 2 3 8 5 7 9 4 6 1 2 3 4 5 6 7 8 9
A[k] = tmp;
}
} 1 2 3 8 5 7 9 4 6

1 2 3 4 5 7 9 8 6
Bài 2
trình vào 1 dãy nguyên a1, a2 an,
dãy cho theo không toán
toán ra qua các b void insertionSort(int A[], int N) {
k n // index tu 1 -> N
(stdin)
for(int k = 2; k <= N; k++){
Dòng 1: ghi nguyên 6) b k: chèn ak vào
int last = A[k];
trí trong dãy
Dòng 2: ghi a1, a2 an, ( ai 6)
a1, a2 ak-1 thu dãy int j = k;

(stdout) while(j > 1 && A[j-1] >


last){
Ghi dãy theo không , các cách Sau b k thì dãy a1, a3 ak A[j] = A[j-1];
nhau 1 cách , dãy còn
j--;
ak+1, . . ., an nguyên trí
}
stdin stdout
A[j] = last;
4 123445 }
543412 }

Bài 3
trình vào 1 dãy nguyên a1, a2 an,
dãy cho theo không toán chèn
Ví : 5, 7, 3, 8, 1, 2, 9, 4, 6
(stdin)
Dòng 1: ghi nguyên 6)

5 7 3 8 1 2 9 4 6 1 2 3 5 7 8 9 4 6 Dòng 2: ghi a1, a2 an, ( ai 6)

(stdout)
3 5 7 8 1 2 9 4 6 1 2 3 4 5 7 8 9 6 Ghi dãy theo không , các cách
nhau 1 cách
3 5 7 8 1 2 9 4 6 1 2 3 4 5 6 7 8 9
stdin stdout
1 3 5 7 8 2 9 4 6
4 123445
543412
1 2 3 5 7 8 9 4 6

8 9
dãy trái qua ( void bubleSort(int A[], int N) {

qua trái) // index tu 1 den N

b , so sánh 2 int swapped; Ví : 5, 7, 3, 8, 1, 2, 9, 4, 6


do{
nhau và hành
2 swapped = 0;
for(int i = 1; i < N; i++){
5 3 7 1 2 8 4 6 9
tr h n sau
if(A[i] > A[i+1]){
quá trình trên khi nào trong
dãy còn 2
int tmp = A[i];
3 5 1 2 7 4 6 8 9
A[i] = A[i+1];
nhau mà tr h n
A[i+1] = tmp;
sau 3 1 2 5 4 6 7 8 9
swapped = 1;
}
}
1 2 3 4 5 6 7 8 9
}while(swapped == 1);
}

10 11

Bài 4
trình vào 1 dãy nguyên a1, a2 an,
dãy cho theo không toán
(stdin)
Dòng 1: ghi nguyên 6)

Dòng 2: ghi a1, a2 an, ( ai 6)


Thank you
(stdout)
for your
Ghi dãy theo không , các cách
nhau 1 cách attentions!

stdin stdout
4 123445
543412

12
Sinh
Cài 3 toán , vun , nhanh
Thí và giá

Bài 1
nhân viên bao các
Profile-5.txt
thông tin sau
và tên Bui Hai An trên chia void mergeSort(int A[], int L, int R) {
1980-02-30 if(L < R){
Ngày, tháng, sinh Chia dãy a1 an thành 2 dãy con
Pham Viet Anh int M = (L+R)/2;
trình sinh ra n cách 1986-10-08 có dài nhau
mergeSort(A,L,M);
nhiên và ghi ra file profile-n.txt Do Duc Bang 2 dãy con toán mergeSort(A,M+1,R);
1990-04-24
merge(A,L,M,R);
Dòng 2i-1 và dòng 2i (i Dang Van Cuong
1987-08-17 2 dãy con }
ghi tên (không ) và ngày, nhau thu dãy ban }
tháng, sinh i. và Pham Viet Anh
tên ghi theo < > <tên > 1986-05-20
<tên> và ngày, tháng, sinh ghi theo #
YYYY-MM-DD
Dòng 2n+1: ghi ký #
thúc file

4
Bài 2
trình vào dãy n các file sinh ra
void merge(int A[], int L, int M, int R) { trong Bài trên), các theo không
trung gian // tron 2 day da sap A[L..M] va A[M+1..R] ( tiên so sánh tên , ngày, tháng, sinh)
l u trong quá trình int i = L; int j = M+1; toán
for(int k = L; k <= R; k++){ (profile-n.txt)
if(i > M){ TA[k] = A[j]; j++;}
Dòng 2i-1 và dòng 2i (i ghi tên (không ) và
else if(j > R){TA[k] = A[i]; i++;}
ngày, tháng, sinh i. và tên ghi theo
else{
< > <tên > <tên> và ngày, tháng, sinh ghi theo
if(A[i] < A[j]){ YYYY-MM-DD
TA[k] = A[i]; i++;
Dòng cùng: ghi ký # thúc file
}
else { (sorted-profile-n.txt)
TA[k] = A[j]; j++; Ghi dãy theo
} Dòng 2i-1 và dòng 2i (i ghi tên (không ) và
} ngày, tháng, sinh i. và tên ghi theo
} < > <tên > <tên> và ngày, tháng, sinh ghi theo
for(int k = L; k <= R; k++) A[k] = TA[k]; YYYY-MM-DD
} Dòng cùng: ghi ký # thúc file
5 6

Bài 2

Profile-5.txt Sorted-Profile-5.txt dùng làm (pivot)


Dang Van Cuong Bui Hai An dãy sao cho
1987-08-17 1980-02-30 Các tr không h n
Pham Viet Anh Pham Viet Anh
1986-10-08 1988-10-08 Các sau không h n
Bui Hai An Pham Viet Anh Khi (có thay trí) trí trong dãy
1980-02-30 1986-05-20 khi
Do Duc Bang Do Duc Bang
1990-04-24 1990-04-24
hành dãy con tr và sau
Pham Viet Anh Dang Van Cuong
nhanh
1986-05-20 1987-08-17
# #

7 8
Bài 2
trình vào dãy n các file sinh ra
trong Bài trên), các theo không
void quickSort(int A[], int L, int R) { int partition(int A[], int L, int R, int ( tiên so sánh tên , ngày, tháng, sinh)
if(L < R){ indexPivot) {
toán nhanh
int index = (L + R)/2; int pivot = A[indexPivot]; (profile-n.txt)
index = partition(A, L, R, index);
if(L < index)
swap(A[indexPivot], A[R]); Dòng 2i-1 và dòng 2i (i ghi tên (không ) và
quickSort(A, L, index-1);
int storeIndex = L; ngày, tháng, sinh i. và tên ghi theo
if(index < R)
for(int i = L; i <= R-1; i++){ < > <tên > <tên> và ngày, tháng, sinh ghi theo
quickSort(A, index+1, R);
if(A[i] < pivot){ YYYY-MM-DD
}
swap(A[storeIndex], A[i]); Dòng cùng: ghi ký # thúc file
} storeIndex++;
}
(sorted-profile-n.txt)
} Ghi dãy theo
swap(A[storeIndex], A[R]); Dòng 2i-1 và dòng 2i (i ghi tên (không ) và
return storeIndex; ngày, tháng, sinh i. và tên ghi theo
} < > <tên > <tên> và ngày, tháng, sinh ghi theo
YYYY-MM-DD
Dòng cùng: ghi ký # thúc file
9 10

trúc (max-heap)
Cây phân (complete tree) 19 Vun (heapify) 19
Khoá nút h n Tình :
khoá 2 nút con (tính Tính max- i] phá
max-heap) 11 9 11 9
Ánh dãy cây phân Tính max- các cây
con A[i] mãn
là A[1] 8 4 6 7 Vun khôi tính 8 4 6 7
A[2i] và A[2i+1] là con trái và con max-heap trên cây A[i]
A[i]
cao cây là logN + 1 6 2 6 2

11 12
Vun (heapify) void heapify(int A[], int i, int N) vun void buildHeap(int A[], int N) {
{
nút con Xây max-heap ( for(int i = N/2; i >= 1; i--)
int L = 2*i;
nút con và A[i] cho nhau buildHeap) heapify(A,i,N);
int R = 2*i+1; }
nút con này h n A[i] và int max = i;
A[1] và A[N] cho nhau
vun nút con void heapSort(int A[], int N) {
if(L <= N && A[L] > A[i]) Vun A[1] cho
này A[1..N-1] // index tu 1 -> N
max = L; buildHeap(A,N);
if(R <= N && A[R] > A[max]) A[1] và A[N-1] cho nhau for(int i = N; i > 1; i--) {
max = R; Vun A[1] cho swap(A[1], A[i]);
if(max != i){ A[1..N-2] heapify(A, 1, i-1);
swap(A[i], A[max]); }
heapify(A,max,N); }
}
}

13 14

trình vào dãy n các file sinh ra


trong Bài trên), các theo không
( tiên so sánh tên , ngày, tháng, sinh)
toán vun
(profile-n.txt)
Dòng 2i-1 và dòng 2i (i ghi tên (không ) và Thank you
ngày, tháng, sinh i. và tên ghi theo
< > <tên > <tên> và ngày, tháng, sinh ghi theo for your
YYYY-MM-DD attentions!
Dòng cùng: ghi ký # thúc file
(sorted-profile-n.txt)
Ghi dãy theo
Dòng 2i-1 và dòng 2i (i ghi tên (không ) và
ngày, tháng, sinh i. và tên ghi theo
< > <tên > <tên> và ngày, tháng, sinh ghi theo
YYYY-MM-DD
Dòng cùng: ghi ký # thúc file
15

You might also like