[Tự học lập trình C/C++] Bài 13: Xử lý tệp tin (file)

---------------------------------
* TÓM TẮT LÝ THUYẾT
---------------------------------

1. Khái niệm tệp tin (file)
Trong các chương trình trước thì các dữ liệu đưa vào chương trình chỉ được tồn tại trong RAM, khi thoát chương trình thì tất cả dữ liệu đều bị mất. Để khắc phục tình trạng này Borland C cung cấp cho ta các hàm để lưu trữ và truy xuất tập tin, đó là kiểu FILE .

Có 2 loại tập tin thường dùng:
 - Tập tin văn bản: là tập tin dùng để ghi các ký tự lên đĩa theo các dòng.
 - Tập tin nhị phân: là tập tin dùng để ghi các cấu trúc dạng nhị phân (được mã hoá).

2. Quá trình thao tác trên tập tin gồm 4 bước
Bước 1: Khai báo con trỏ trỏ đến tập tin.
Bước 2: Mở tập tin.
Bước 3: Các xử lý trên tập tin.
Bước 4: Đóng tập tin.

 -----------
- Cụ thể từng bước:
B1: Khai báo
FILE *< tên biến >;

Ví dụ :   
//  Khai bao bien con tro file f

FILE *f;

------------
B2. Mở tập tin
fopen (< đường dẫn tên tập tin> , < kiểu truy nhập >);

Ví dụ :  
//Khai bao bien con tro f
FILE *f;
// Mo tep tin VD1.txt trong C:\
  f = fopen ("C:\\VD1.txt","rt") ;  
 
 Các kiểu truy nhập tập tin thông dụng:  
 t: kiểu truy nhập tập tin đối với dạng tập tin văn bản (text).
b: kiểu truy nhập tập tin đối với dạng tập tin nhị phân (binary).
r: mở ra để đọc ( ready only).
w: mở ra để ghi (create / write).
a: mở ra để thêm vào (append).
r+:   mở ra để đọc và ghi (modify).

  -------------
  B3.  Các hàm đọc ghi nội dung tập tin
   i) Tập tin văn bản
    a. Đọc tập tin
+ Đọc dữ liệu từ một tập tin theo định dạng.
fscanf(<FILE *>, <định dạng>, <các tham biến>);

Ví dụ: 
fscanf(f, "%d", &x);

+ Đọc một chuỗi ký tự từ một tập tin với kích thước tối đa cho phép, hoặc gặp ký tự xuống dòng.
fgets(<vùng nhớ>, <kích thước tối đa>, <FILE *>);

Ví dụ:
char s[80];
fgets(s, 80, f);
 
  + Đọc một ký tự từ tập tin đang mở.
getc(< FILE * >);

Ví dụ: 
char c=getc(f);

   b. Ghi tập tin
   + Ghi dữ liệu theo một định dạng nào đó vào tập tin.
fprintf(<FILE *>, <định dạng>[, <các tham biến>]);

Ví dụ: 
fprintf(f,“%d”,x);

   + Ghi một chuỗi ký tự vào tập tin đang mở.
fputs(<chuỗi ký tự>, <FILE*>);

Ví dụ:
fputs("Giao trinh BT", f);

  ii)Tập tin nhị phân
    a. Đọc tập tin
fread(<&ptr>, <size>, <len>, <FILE *>);

Trong đó:
ptr: vùng nhớ để lưu dữ liệu đọc.
size: kích thước mỗi ô nhớ (tính bằng byte).
len: độ dài dữ liệu cần đọc.
FILE: đọc từ tập tin nhị

 Ví dụ: 
int a[30], b, n;
fread(a,sizeof(int), n , f);
fread(&b, sizeof(int), 1 , f);

  b. Ghi tập tin
fwrite(<&prt>, <size>, <len>,<FILE *> );

Trong đó:
ptr: vùng nhớ để lưu dữ liệu ghi.
size: kích thước mỗi ô nhớ (tính bằng byte).
len: độ dài dữ liệu cần ghi.
FILE: ghi vào tập tin nhị

  Ví dụ:
 fwrite(a, sizeof(int), n , f);

  ---------------
  B4.  Đóng tập tin
Sau khi không còn làm việc với tập tin, để đảm bảo an toàn cho dữ liệu thì nhất thiết ta phải đóng tập tin lại.

fclose ( < biến con trỏ tập tin > ) ;

hoặc fcloseall () ;

Ví dụ : 
fclose (f)  ;

3.  Các thao tác khác trên tập tin
* Xoá tập tin :
remove ( < đường dẫn tập tin> );

* Đổi tên tập tin :
rename ( < tên tập tin cũ >, < tên tập tin mới > );

* Di chuyển con trỏ tập tin :
fseek ( < FILE * >, < độ dời >, < mốc > );

Các mốc :
   SEEK_SET dời dến đầu tập tin  (giá trị 0).
   SEEK_END dời đến cuới tập tin  (giá trị 2).
   SEEK_CUR dời vị trí hiện hành  (giá trị 1).

Ví dụ : 
// dời vị trí hiện hành về cuối 5 bytes  
      feek ( f , +5 , SEEK_CUR );

// dời vị trí hiện hành về trước 4 bytes
      feek ( f, -4 , SEEK_CUR );


* Cho biết vị trí con trỏ file:
ftell ( < FILE *  > );

Ví dụ :
int size = ftell ( f );

/*size: khoảng cách từ đầu tập tin đến vị trí hiện hành (tính bằng byte)*/


---------------------------------
** VÍ DỤ
---------------------------------

Ví dụ 1:

+ Yêu cầu: Viết chương trình
- Nhập vào 2 số nguyên từ bàn phím, ghi 2 số vừa nhập vào tệp tin D:\test.txt
- Đọc 2 số nguyên trong tệp tin D:\test.txt , tính tổng của chúng.

+ Code:

#include<conio.h>
#include<stdio.h>
#include<iostream>

using namespace std;

int n, m;
// ghi 2 so nguyen vao file
void GhiFile()
{
FILE *f; 
// mo file
f = fopen ("D:\\test.txt" ,"wt"); 
// Nhap n,M tu ban phim
cout<<"\n n = "; cin>>n;
cout<<"\n m = "; cin>>m;
// ghi n, m vao file
fprintf (f, "%d %d",n,m); 
// dong file
fclose (f);
}

// Doc du lieu tu file test, tinh tong 2 so
void DocFile()
{
FILE *f; 
// mo file
f = fopen ("D:\\test.txt" , "rt" ); 
// doc du lieu 
fscanf(f, "%d %d", &n, &m ); 
// Tinh tong 
int s=n+m;
// In tong
cout<<"\n Tong: "<<s;
// dong file
fclose (f);
}

// ham main
int main () {
GhiFile(); 
DocFile();
return 0;
}

---------------

Ví dụ 2:

+ Yêu cầu: Viết chương trình
  - Đọc file input.txt (dữ liệu đồ thị)
   
     Ví dụ: 
        Đơn đồ thị vô hướng 3 đỉnh, có ma trân kề như sau:
   
     3
     0 1 1
     1 0 1
     1 1 0
   - Tìm số thành phần liên thông
 
  + Code:
 
#include<conio.h>
#include<stdio.h>
#include<iostream>

using namespace std;

//doc du lieu tu tap tin
void Doc_File(int **A,int &n) {
  FILE*f = fopen("input.txt","rb");
  fscanf(f,"%d",&n);
  *A = new int [n];
   cout<<"Ma Tran Lien Ket Cua Do Thi";
   for(int i =0;i<n;i++) {   
      A[i] = new int [n];  
      cout<<endl;  
      for(int j =0;j<n;j++) {      
        fscanf(f,"%d",&A[i][j]);    
        cout<<" "<<A[i][j];    
     }
   }
   fclose(f);
}

//ham tra ve so thanh phan lien thong cua do thi
int TPLien_Thong(int **A, int n) {
    char*DanhDau = new char [n];
    char ThanhCong;
    int Dem=0, i,j, MLT=0;
    //khoi tao cac dinh chua danh dau
    for( i = 0; i<n; i++)
            DanhDau[i] = 0;    
        do {
            j = 0;      
           //tim 1 dinh chua duoc danh dau      
           while(DanhDau[j]==1)
              j++;      
  //danh dau dinh tim duoc  
           DanhDau[j] = 1;      
           //tang so dinh danh dau len 1      
           Dem++;      
           //tang so thanh phan lien thong len 1      
           MLT++;      
          do {      
     ThanhCong =0;      
     for(i = 0; i<n; i++)      
        if(DanhDau[i]==1)      
           for(j = 0; j<n; j++)      
                 if (DanhDau[j] == 0 && A[i][j] > 0) {      
                      DanhDau[j] = 1;      
                      ThanhCong =1;      
                      Dem++;      
                      if(Dem == n) return MLT;      
                  }      
    }while (ThanhCong == 1);  
   //lap lai khi con dinh chua duoc danh dau    
}  while(Dem<n);
return MLT;
}

//ham main
int main() {
   int **A,n;
   Doc_File(A,n);
   cout<<"\nTHANH PHAN LIEN THONG: "<<TPLien_Thong(A,n);
   delete *A;
   return 0;
}

-----------------

Ví dụ 3:

+ Yêu cầu:
Viết một chương trình để quản lý các sản phẩm máy tính xách tay bao gồm các chức năng sau :
Chức năng 1 : sản phẩm nhập khẩu
Chức năng 2 : Sắp xếp sản phẩm
Chức năng 3 : Tìm kiếm sản phẩm

Trong đó:

+ Chức năng 1 :
  – Yêu cầu người sử dụng bao nhiêu sản phẩm cần nhập khẩu , sau đó cho phép người dùng nhập thông tin cho các sản phẩm bao gồm:

  Mã sản phẩm
  Tên sản phẩm
  số lượng sản phẩm
giá sản phẩm

  - Chúng được lưu trong một file văn bản có tên là ” Products.txt ” .

  Ví dụ: "Products.txt" tập tin
   Mã Tên Số lượng Giá ( triệu )
   01 Asus Vivo 3 12
   02 Vaio E 2 10
   03 Acer X 4 11.5

+ Chức năng 2 :
  Cho phép người dùng đọc tập tin ” Products.txt ” ; sắp xếp sản phẩm theo giá sản phẩm, và sau đó lưu các tập tin.

+ Chức năng 3 :
  Người dùng có thể tìm kiếm sản phẩm từ tập tin ” Products.txt” theo mã sản phẩm hoặc tên sản phẩm và thông tin sản phẩm phù hợp .

+ Code:

#include<conio.h>
#include<stdio.h>
#include<iostream>
#include <stdlib.h>
#include <string.h>

#define fio "Products.txt"
#define fbin "Products.dat"
using namespace std;

 typedef struct products{
    char Id[50], name[50];
    int quantity; // so luong
    double cost; // gia
   } product;


void input(product prd[], int *n);

void writeBin(product prd[], int n);

void write(product prd[], int n);

void sort_cost(product prd[], int n);

void readBin(product prd[], int *n);

void output(product prd[], int n);

void search_id(product prd[], int n, char id[]);

void search_name(product prd[], int n, char name[]);

void search(product prd[], int n);

// ham main
int main() {
    product prd[50];
    int n, i;
    FILE *f = fopen(fio, "r");
    int select;
    do {
        printf("Products:\n-----------------\n");
        printf("1: input\n2: read and sort by cost\n3: Search\n4: exit\n");
        printf("Enter the number to work: ");
        scanf("%d", &select);
        switch(select){
            case 1: {
                printf("1: INPUT\n");
                input(prd, &n);
                write(prd, n);
                break;
            }
            case 2: {
                printf("2: READ AND SORT BY COST\n");
                printf("Befor sort:\n--------------\n");
                readBin(prd, &n);
                output(prd, n);
                sort_cost(prd, n);
                write(prd, n);
                printf("After sort:\n--------------\n");
                readBin(prd, &n);
                output(prd, n);
                break;
            }
            case 3: {
                printf("SEARCH\n");
                search(prd, n);
                break;
            }
            case 4: return 0;
            default : printf("Error select !"); break;
        }
    }
    while (select != 4);
    return 0;
}

// ham input
void input(product prd[], int *n){
    int i;
    char s[50];
    printf("Enter the number of products: ");
    scanf("%d", n);
    gets(s);
    printf("\n");
    for (i = 0; i < (*n); i++){
        printf("Enter the Id of products %d : ", i+1);
        gets(prd[i].Id);
        printf("\tEnter the nam of products %d : ", i+1);
        gets(prd[i].name);
        printf("\tEnter the quantity of products %d : ", i+1);
        scanf("%d", &prd[i].quantity);
        printf("\tEnter the cost of products %d : ", i+1);
        scanf("%lf", &prd[i].cost);
        gets(s);
    }
}

// ghi
void writeBin(product prd[], int n){
    FILE *f = fopen(fbin,"wb");;
    int i;
    if(f==NULL) printf("Error load file");
    else fwrite(prd,sizeof(product),n,f);
    fclose(f);
}

void write(product prd[], int n){
    int i;
    FILE *f = fopen(fio, "w");
    if(f==NULL) printf("Error load file");
    fprintf(f, "%-10s %-15s %-10s %-10s\n", "Id", "Name", "Quantity", "Cost");
    for (i = 0; i < n; i++)
        fprintf(f, "%-10s %-15s %-10d %-10.2lf\n", prd[i].Id, prd[i].name, prd[i].quantity, prd[i].cost);
    fclose(f);
    writeBin(prd, n);
    printf("input and write success to file!\n");
}

void sort_cost(product prd[], int n){
    int i, j;
    for (i = 0; i < n - 1; i++){
        for (j = i + 1; j < n; j++){
            if (prd[i].cost > prd[j].cost){
                product temp = prd[i];
                prd[i] = prd[j];
                prd[j] = temp;
            }
        }
    }
}

void output(product prd[], int n){
    int i;
    printf("%-10s %-10s %-15s %-10s %-10s\n", "Order", "Id", "Name", "Quantity", "Cost");
    for (i = 0; i < n; i++)
        printf("%-10d %-10s %-15s %-10d %-10.2lf\n", i + 1, prd[i].Id, prd[i].name, prd[i].quantity, prd[i].cost);
}

 void readBin(product prd[], int *n){
    FILE *f = fopen(fbin,"rb");
    fseek(f,0,SEEK_END); //Nhay ve cuoi file, di chuyen di 0 vi tri
    (*n) = (ftell(f)+1)/sizeof(product); //ftell(); tra ve vi tri hien tai cua con tro
    // SEEK_CUR: di chuyen bat dau tu vi tri hien tai cua con tro, chi dung trong fseek()
    fseek(f,0,SEEK_SET); //Nhay ve dau file, di chuyen di 0 vi tri
    fread(prd,sizeof(product),(*n),f);
    fclose(f);
}

void search_id(product prd[], int n, char id[]){
    int i, check = 0;
    for (i = 0; i < n; i++){
        if (strcmp(id, prd[i].Id) == 0){
            check = 1;
            printf("%-10s %-10s %-15s %-10s %-10s\n", "Order", "Id", "Name", "Quantity", "Cost");
            printf("%-10d %-10s %-15s %-10d %-10.2lf\n", i + 1, prd[i].Id, prd[i].name, prd[i].quantity, prd[i].cost);
            break;
        }
        if (check == 0 && i == n - 1)
            printf("Not found product have Id is %s !\n", id);
    }
}

void search_name(product prd[], int n, char name[]){
    int i, check = 0;
    for (i = 0; i < n; i++){
        if (strcmp(name, prd[i].name) == 0){
            check = 1;
            printf("%-10s %-10s %-15s %-10s %-10s\n", "Order", "Id", "Name", "Quantity", "Cost");
            printf("%-10d %-10s %-15s %-10d %-10.2lf\n", i + 1, prd[i].Id, prd[i].name, prd[i].quantity, prd[i].cost);
            break;
        }
        if (check == 0 && i == n - 1)
            printf("Not found product have name is %s !\n", name);
    }
}

 void search(product prd[], int n){
    int select;
    char s[50];
    do{
        printf("\t1: Id\n\t2: Name\n\t3: exit search\nEnter the type you want search: ");
        scanf("%d", &select);
        gets(s);
        switch(select){
            case 1: {
                printf("Enter Id want search: ");
                char id[50];
                gets(id);
                search_id(prd, n, id);
                break;
            }

            case 2: {
                printf("Enter name want search: ");
                char name[50];
                gets(name);
                search_name(prd, n, name); break;
            }
            case 3: return;
            default : printf("Error select !"); break;
        }
    }while (select != 3);
}

Một số tài liệu và khoá học bổ ích dành cho bạn: 

# Giáo Trình: Kỹ Thuật Lập Trình C/C++ Căn Bản Và Nâng Cao [Click để xem]

# Khoá học online: Học lập trình C/C++ TỪ A - Z [Click để xem]


------------------------
Xem bài khác:

Tìm kiếm nội dung khác: