Thứ Sáu, 31 tháng 12, 2021

3: Nhập Và Xuất Dữ Liệu (Phần 3) - Kiểu Nhị Phân Và Kiểu Văn Bản

 

3:  Nhập Và Xuất Dữ Liệu


- Kiểu Nhị Phân Và Kiểu Văn Bản

1. Mã sang dòng theo hai kiểu:
Trong dạng văn bản, một kí tự chuyển dòng tương ứng với 2 mã CR và LF khi ghi vào tập tin trên đĩa.
Ngược lại khi đọc, tổ hợp CR/LF trên đĩa tương ứng với kí tự sang dòng mới. Tuy nhiên nếu mở tập tin theo kiểu nhị phân thì 2 mã CR và LF là phân biệt nhau. Từ đó số kí tự mà chương trình đếm được khác với trường hợp
mở tập tin bằng kiểu văn bản

Chương trình 3-11 : Chương trình đếm số kí tự bằng cách mở tập tin theo kiểu nhị phân
// InOut_11
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

void main(int argc,char *argv[])   
{     
    FILE *fp;     
    char string[81];     
    int count=0;     
    clrscr();     
    if (argc!=2)       
    {  
        printf("Format c:\<ten chuong trinh>  <ten tap tin>");  
        getch();  
        exit(1);       
    }     
    if ((fp=fopen(argv[1],"rb"))==NULL)       
    {  
        printf("Khong mo duoc tap tin\n");  
        getch();  
        exit(1);       
    }     
    while (getc(fp)!=EOF)       
        count++;     
    fclose(fp);     
    printf("Tap tin %s co %d ki tu",argv[1],count);     
    getch();   
}

2. Mã kết thúc tập tin theo 2 kiểu:
Sự khác biệt thứ hai khi mở tập tin theo kiểu nhị phân hay kiểu kí tự còn là ở chỗ nhìn nhận kí tự kết thúc tập tin.
Nói chung các tập tin đều được quản lí theo kích thước của nó và khi đọc hết số byte đã chỉ ra trong kích thước tập tin thì dấu hiệu EOF sẽ được thông báo, dấu hiệu đó ứng với mã 1Ah(hay 26 ở hệ 10).

Khi đóng tập tin văn bản , mã 1A sẽ được tự động chèn vào cuối tập tin để làm dấu hiệu kết thúc tập tin (tương đương mã Ctrl-Z.).
Do vậy nếu bằng cáh nào đó ta chèn mã 1A vào một vị trí giữa tập tin, thì khi mở tập tin theo kiểu văn bản và đọc đến mã này chương trình đọc sẽ ngừng hẳn vì chính lúc đó hầm đọc phát sinh giá trị -1 để báo cho chương trình là đã kết thúc tập tin.
Nếu đã lưu số vào tập tin theo dạng nhị phân thì khi mở tập tin cần phải mở theo dạng nhị phân.
Nếu không sẽ có một số nào đó là 1A và việc đọc tập tin theo kiểu văn bản sẽ kết thúc ngoài ý định.
Tương tự, với tập tin mở theo kiểu nhị phân mã 10 không được nhìn nhận là mã sang dòng mới vì không được xem là tương ứng với tổ hợp CR/LE nữa.

3. Chương trình minh hoạ:
Chúng ta xét một chương trình dùng kiểu nhị phân để khảo sát tập tin.

Chương trùnh 3-12 :
// InOut_12
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define length 10
#define true 0
#define false -1

void main(int agrc,char *argv[])   
{
    FILE * fp;
    int ch;
    int j, noteof;
    unsigned char string[length + 1];


    if (agrc != 2)
    {
        printf("Dang c:\<ten chuong trinh> <ten tap tin>");
        getch();
        exit(1);
    }
    if ((fp = fopen(argv[1], "rb")) == NULL)
    {
        printf("Khong mo duoc tap tin\n");
        getch();
        exit(1);
    }
    noteof = true;
    do
    {
        for (j = 0; j < length; j++)
        {
            if ((ch = getc(fp)) == EOF)
                noteof = false;
            printf("%3x", ch);
            if (ch > 31)
                *(string + j) = ch; /* ki tu in duoc*/
            else
                *(string + j) = '.'; /* ki tu khong in duoc*/
        }
        *(string + j) = '\0';
        printf("  %s\n", string);
    }
    while (noteof == true);
    fclose(fp);
    getch();
}

4. Các hàm fread và fwrite:

- Ghi cấu trúc bằng ƒwrife:
Ta xét một chương trình ghi cấu trúc lên đĩa. Trong chương trình ta dùng hàm fread().
Hàm này có 4 đối số: địa chỉ để ghi cấu trúc, kích thước của cấu trúc, số cấu trúc sẽ phi và con trỏ chỉ tới tập tin.

Chương trùnh 3-13 :
// InOut_13
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

int main()   
{     
    char chso[10];     
    FILE *fp;
    struct nguoi {
        char ten[30];
        int so;
        float cao;
    }
    nv;

    if ((fp = fopen("nhanvien.rec", "wb")) == NULL)
    {
        printf("Khong mo duoc file\n");
        getch();
        exit(1);
    }
    do
    {
        printf("\nCho ten : ");
        gets(nv.ten);
        printf("Cho ma so : ");
        gets(chso);
        nv.so = atoi(chso);
        printf("Cho chieu cao :");
        gets(chso);
        nv.cao = atof(chso);
        fwrite( & nv, sizeof(nv), 1, fp);
        printf("Tiep tuc khong y/n?");
    }
    while (getch() == 'y');
    fclose(fp);
    
    return 0;
}

- Đọc cấu trúc bằng fread:
Ta dùng hàm fread() để đọc cấu trúc ghi trên một tập tin. Các đối số của fread() cũng giống như fwrite().
Hàm fread() trả về số của những mục
đã được đọc tới. Nếu tập tin đã kết thúc nó cho trị âm.
Ta xét ví dụ sau:

Chương trình 3-14:
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

int main()   
{     
    FILE *fp;     
    struct nguoi {      
        char ten[30];      
        int so;      
        float cao;    
    }
    nv;     
   
    if((fp=fopen("nhanvien.rec","rb"))==NULL)   
    {  
        printf("Khong mo duoc file\n");  
        getch();  
        exit(1);       
    }

    do {
        printf("\nTen :%s\n", nv.ten);
        printf("Ma so :%03d\n", nv.so);
        printf("Chieu cao :%.2f\n", nv.cao);
    }
    while (fread( & nv, sizeof(nv), 1, fp) == 1);
    fclose(fp);
    getch();
    
    return 0;
}

- Ghi mảng bằng ƒwrife():
Hàm fwrite() cũng dùng ghi mảng lên đĩa. Ta xét ví dụ sau:

Chương trình 3-15:
// InOut_15
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

int table[10]={1,2,3,4,5,6,7,8,9,10};
int main()   
{
    FILE * fp;

    if ((fp = fopen("table.rec", "wb")) == NULL)
    {
        printf("Khong mo duoc file\n");
        getch();
        exit(1);
    }
    fwrite(table, sizeof(table), 1, fp);
    fclose(fp);
    
    return 0;
}

- Đọc mảng bằng fread():
Sau khi ghi mảng lên đĩa ta có thể đọc các phần tử của mảng từ đĩa bằng hàm fread().
Chương trình 3-16:
// InOut_16
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

int main()
{
    FILE * fp;
    int a[10];
    int i;

    if ((fp = fopen("table.rec", "rb")) == NULL)
    {
        printf("Khong mo duoc file\n");
        getch();
        exit(1);
    }
    for (i = 0; i < 10; i++)
    {
        fread(a, sizeof(a), 10, fp);
        printf("\%3d", a[i]);
    }
    fclose(fp);
    getch();
    
    return 0;
}

- Ví dụ về cơ sở dữ liệu:
Ta xét chương trình quản lí nhân viên với các tập tin trên đĩa như sau:
Chương trinh 3-17:
// InOut_17
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#define true 1
struct nguoi {         
    char ten[30];         
    int so;         
    float cao;       
};
struct nguoi nv[10];
int n=0;
char numstr[10];

void newname()
{
    char numstr[81];
    printf("\nBan ghi so %d\nCho ten : ", n + 1);
    gets(nv[n].ten);
    printf("Cho ma so co 3 chu so : ");
    gets(numstr);
    nv[n].so = atoi(numstr);
    printf("Cho chieu cao :");
    gets(numstr);
    nv[n++].cao = atof(numstr);
}

void listall()
{
    int j;
    if (n < 1) printf("Danh sach rong\n");
    for (j = 0; j < n; j++)
    {
        printf("\nBan ghi so %d\n", j + 1);
        printf("Ten :%s\n", nv[j].ten);
        printf("Ma nhan vien : %3d\n", nv[j].so);
        printf("Chieu cao :%4.2f\n", nv[j].cao);
    }
}

void wfile() {
    FILE * fp;
    if (n < 1) {
        printf("Danh sach rong , khong ghi\n");
        getch();
        exit(1);
    }
    if ((fp = fopen("nv.rec", "wb")) == NULL)
    {
        printf("Khong mo duoc file\n");
        getch();
        exit(1);
    }
    else
    {
        fwrite(nv, sizeof(nv[0]), n, fp);
        fclose(fp);
        printf("Da ghi %3d ban ghi len dia\n", n);
    }
}

void rfile()
{
    FILE * fp;
    if ((fp = fopen("nv.rec", "rb")) == NULL)
    {
        printf("Khong mo duoc file\n");
        getch();
        exit(1);
    }
    else
    {
        while (fread( & nv[n], sizeof(nv[n]), 1, fp) == 1)
        {
            printf("Ban ghi so %3d\n", n + 1);
            printf("Ten nhan vien :%s\n", nv[n].ten);
            printf("Ma nhan vien :%3d\n", nv[n].so);
            printf("Chieu cao cua nhan vien :%.2f\n", nv[n].cao);
            getch();
            n++;
        }
        fclose(fp);
        printf("Xong ! Tong so ban ghi da doc %3d\n", n);
    }
}

int main() {
    char ch;
    void newname(void);
    void listall(void);
    void wfile(void);
    void rfile(void);


    while (true)
    {
        printf("\nGo 'e' de nhap nhan vien moi\n");
        printf("Go 'l'de liet ke nhan vien\n");
        printf("Go 'w' de ghi len dia\n");
        printf("Go 'r'de doc file tu dia\n");
        printf("Go 'q' de ket thuc chuong trinh\n\n");
        ch = getch();
        switch (ch)
        {
            case 'e':
                newname();
                break;
            case 'l':
                listall();
                break;
            case 'w':
                wfile();
                break;
            case 'r':
                rfile();
                break;
            case 'q':
                exit(1);
            default:
                printf("Nhap sai ki tu , chon lai!");
        }
    }
}

0 bình luận:

Đăng nhận xét