Moät soá kieán thöùc cô sôû veà laäp trình baèng ngoân ngöõ C

Phaâàn tröôùc | Muïc luïc | Phaâàn sau

XXII. Nhaäp vaø xuaát teäp II

  • Truy caäp teäp ngaãu nhieân
  • Ñoïc hay ghi döõ lieäu nhò phaân
  • Ñoåi höôùng caùc stream maëc ñònh (Redirecting the standard streams)

Trong ñoù, moät soá caùc haøm I/O ñöôïc giôùi thieäu:

  • fseek(), ftell(), vaø rewind()
  • fscanf() vaø fprintf()
  • freopen()

 

Truy caäp teäp ngaãu nhieân

Caùc haøm trong phaàn tröôùc cho pheùp ta truy caäp tuaàn töï döõ lieäu trong caùc taäp tin. Tuy nhieân coù nhieàu khi chuùng ta caàn laáy hoaëc ghi döõ lieäu vaøo moät vò trí baát kyø naøo ñoù cuûa taäp tin. Ngoân ngöõ taïo ñieàu kieän cho ta thöïc hieän thoâng qua haøm fseek() vaø ftell(). Nhö ta bieát, khi môû moät teäp ñeå truy caäp, coù moät phaàn töû ñaëc bieät goïi laø ñieåm baùo vò trí (position indicator) cho ta vò trí töùc thôøi ñeå truy caäp döõ lieäu trong teäp. Baèng hai haøm treân, ta coù theå bieát vò trí ñoù vaø coù theå dòch chuyeån indicator ñeán vò trí caàn thieát.

fseek(): Haøm dòch chuyeån indicator ñeán vò trí baát kyø

#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);

stream laøcon troû ñeán teäp ñang môû, offset chæ soá byte caùch vò trí xaùc ñònh bôûi whence, whence coù theå coù 3 giaù trò: SEEK_SET (vò trí ñaàu teäp), SEEK_END (vò trí cuoái teäp), SEEK_CUR (vò trí töùc thôøi cuûa indicator). Neáu thaønh coâng, haøm traû laïi giaù trò 0, neáu khoâng haøm traû laïi giaù trò khaùc khoâng.

ftell(): Haøm baùo cho bieát vò trí indicator

#include <stdio.h>
long ftell(FILE *stream);

Haøm traû lai giaù trò soá byte keå töø ñaàu teäp, neáu haøm sai, seõ traû laïi -1L.

Ví duï:

1:  /* Random access to a file */
2:  #include <stdio.h>
3:
4:  enum {SUCCESS, FAIL, MAX_LEN = 80};
5:
6:  void PtrSeek(FILE *fptr);
7:  long PtrTell(FILE *fptr);
8:  void DataRead(FILE *fptr);
9:  int ErrorMsg(char *str);
10:
11: main(void)
12: {
13:    FILE *fptr;
14:    char filename[]= "haiku.txt";
15:    int reval = SUCCESS;
16:
17:    if ((fptr = fopen(filename, "r")) == NULL){
18:       reval = ErrorMsg(filename);
19:    } else {
20:       PtrSeek(fptr);
21:       fclose(fptr);
22:    }
23:
24:    return reval;
25: }
26: /* function definition */
27: void PtrSeek(FILE *fptr)
28: {
29:    long offset1, offset2, offset3;
30:
31:    offset1 = PtrTell(fptr);
32:    DataRead(fptr);
33:    offset2 = PtrTell(fptr);
34:    DataRead(fptr);
35:    offset3 = PtrTell(fptr);
36:    DataRead(fptr);
37:
38:    printf("\nRe-read the haiku:\n");
39:    /* re-read the third verse of the haiku */
40:    fseek(fptr, offset3, SEEK_SET);
41:    DataRead(fptr);
42:    /* re-read the second verse of the haiku */
43:    fseek(fptr, offset2, SEEK_SET);
44:    DataRead(fptr);
45:    /* re-read the first verse of the haiku */
46:    fseek(fptr, offset1, SEEK_SET);
47:    DataRead(fptr);
48: }
49: /* function definition */
50: long PtrTell(FILE *fptr)
51: {
52:    long reval;
53:
54:    reval = ftell(fptr);
55:    printf("The fptr is at %ld\n", reval);
56:
57:    return reval;
58: }
59: /* function definition */
60: void DataRead(FILE *fptr)
61: {
62:    char buff[MAX_LEN];
63:
64:    fgets(buff, MAX_LEN, fptr);
65:    printf("---%s", buff);
66: }
67: /* function definition */
68: int ErrorMsg(char *str)
69: {
70:    printf("Cannot open %s.\n", str);
71:    return FAIL;
72: }

Keát quaû:

The fptr is at 0
---Leading me along
The fptr is at 18
---my shadow goes back home
The fptr is at 44
---from looking at the moon.
Re-read the haiku:
---from looking at the moon.
---my shadow goes back home
---Leading me along

rewind(): reset indicator vaø ñöa noù veà ñaàu file

#include <stdio.h>
void rewind(FILE *stream);

Leänh

rewind(fptr);

töông ñöông

 
(void)fseek(fptr, 0L, SEEK_SET);

Ñoïc hay ghi döõ lieäu nhò phaân

Môû taäp tin nhò phaân nhö sau:

fptr = fopen("test.bin", "rb");

Ví duï:

1:  /* Reading and writing binary data */
2:  #include <stdio.h>
3:
4:  enum {SUCCESS, FAIL, MAX_NUM = 3};
5:
6:  void DataWrite(FILE *fout);
7:  void DataRead(FILE *fin);
8:  int ErrorMsg(char *str);
9:
10: main(void)
11: {
12:    FILE *fptr;
13:    char filename[]= "double.bin";
14:    int reval = SUCCESS;
15:
16:    if ((fptr = fopen(filename, "wb+")) == NULL){
17:       reval = ErrorMsg(filename);
18:    } else {
19:       DataWrite(fptr);
20:       rewind(fptr);  /* reset fptr */
21:       DataRead(fptr);
22:       fclose(fptr);
23:    }
24:
25:    return reval;
26: }
27: /* function definition */
28: void DataWrite(FILE *fout)
29: {
30:    int i;
31:    double buff[MAX_NUM] = {
32:               123.45,
33:               567.89,
34:               100.11};
35:
36:    printf("The size of buff: %d-byte\n", sizeof(buff));
37:    for (i=0; i<MAX_NUM; i++){
38:       printf("%5.2f\n", buff[i]);
39:       fwrite(&buff[i], sizeof(double), 1, fout);
40:    }
41: }
42: /* function definition */
43: void DataRead(FILE *fin)
44: {
45:    int i;
46:    double x;
47:
48:    printf("\nRead back from the binary file:\n");
49:    for (i=0; i<MAX_NUM; i++){
50:       fread(&x, sizeof(double), (size_t)1, fin);
51:       printf("%5.2f\n", x);
52:    }
53: }
54: /* function definition */
55: int ErrorMsg(char *str)
56: {
57:    printf("Cannot open %s.\n", str);
58:    return FAIL;
59: }

Keát quaû:

The size of buff: 24-byte
123.45
567.89
100.11
 
Read back from the binary file:
123.45
567.89
100.11

Haøm fscanf() vaø fprintf()

Nhö rta ñaõ bieát, haøm scanf() vaø printf() duøng ñeå ñoïc hay ghi döõ lieäu coù format vaøo caùc I/O chuaån (stdin vaø stdout). Ñ/v caùcI/O ra disk file, ta cuõng coù 2 haøm töông ñöông: fscanf() vaø fprintf(), taùc duïng ñoïc vaø ghi vaøo file y heät nhö scanf() vaø printf().

#include <stdio.h>
int fscanf(FILE *stream, const char *format, …);
 
#include <stdio.h>
int fprintf(FILE *stream, const char *format, …);

Ví duï:

1:  /* Using the fscanf() and fprintf() functions */
2:  #include <stdio.h>
3:
4:  enum {SUCCESS, FAIL,
5:        MAX_NUM = 3,
6:        STR_LEN = 23};
7:
8:  void DataWrite(FILE *fout);
9:  void DataRead(FILE *fin);
10: int ErrorMsg(char *str);
11:
12: main(void)
13: {
14:    FILE *fptr;
15:    char filename[]= "strnum.mix";
16:    int reval = SUCCESS;
17:
18:    if ((fptr = fopen(filename, "w+")) == NULL){
19:       reval = ErrorMsg(filename);
20:    } else {
21:       DataWrite(fptr);
22:       rewind(fptr);
23:       DataRead(fptr);
24:       fclose(fptr);
25:    }
26:
27:    return reval;
28: }
29: /* function definition */
30: void DataWrite(FILE *fout)
31: {
32:    int i;
33:    char cities[MAX_NUM][STR_LEN] = {
34:               "St.Louis->Houston:",
35:               "Houston->Dallas:",
36:               "Dallas->Philadelphia:"};
37:    int miles[MAX_NUM] = {
38:               845,
39:               243,
40:               1459};
41:
42:    printf("The data written:\n");
43:    for (i=0; i<MAX_NUM; i++){
44:       printf("%-23s  %d miles\n", cities[i], miles[i]);
45:       fprintf(fout, "%s  %d", cities[i], miles[i]);
46:    }
47: }
48: /* function definition */
49: void DataRead(FILE *fin)
50: {
51:    int i;
52:    int miles;
53:    char cities[STR_LEN];
54:
55:    printf("\nThe data read:\n");
56:    for (i=0; i<MAX_NUM; i++){
57:       fscanf(fin, "%s%d", cities, &miles);
58:       printf("%-23s  %d miles\n", cities, miles);
59:    }
60: }
61: /* function definition */
62: int ErrorMsg(char *str)
63: {
64:    printf("Cannot open %s.\n", str);
65:    return FAIL;
66: }

Keát quaû:

The data written:
St.Louis->Houston:     845 miles
Houston->Dallas:       243 miles
Dallas->Philadelphia:  1459 miles
 
The data read:
St.Louis->Houston:     845 miles
Houston->Dallas:       243 miles
Dallas->Philadelphia:  1459 miles

Ñoåi höôùng I/O maëc ñònh baèng freopen()

Ñ/v vaùv I/O maëc ñònh nhö stdin vaø stdout, ta duøng caùc leänh sau: scanf(), getc(), gets(), putc, vaø printf().

Tuy nhieân, ñoâi khi ta caàn höôùng stdin vaø stdout ra disk file thay vì baøn phím hoaëc maøn aûnh. Ngoân ngöõ C cho leänh freopen() ñeå gaén moät stream chuaån vôùi disk file.

#include <stdio.h>
FILE *freopen(const char *filename, const char *mode, FILE *stream);

filename laø con troû kyù töï tham chieáu teân disk file seõ gaén vôùi I/O chuaån stream, mode ñònh nghóa caùch môû file.
Haøm traû null pointer neáu coù loãi, neáu khoâng haøm seõ traû standard stream ñaõ gaén vôùi filename.

Ví duï:

1:  /* Redirecting a standard stream */
2:  #include <stdio.h>
3:
4:  enum {SUCCESS, FAIL,
5:        STR_NUM = 4};
6:
7:  void StrPrint(char **str);
8:  int ErrorMsg(char *str);
9:
10: main(void)
11: {
12:    char *str[STR_NUM] = {
13:           "Be bent, and you will remain straight.",
14:           "Be vacant, and you will remain full.",
15:           "Be worn, and you will remain new.",
16:           "---- by Lao Tzu"};
17:    char filename[]= "LaoTzu.txt";
18:    int reval = SUCCESS;
19:
20:    StrPrint(str);
21:    if (freopen(filename, "w", stdout) == NULL){
22:       reval = ErrorMsg(filename);
23:    } else {
24:       StrPrint(str);
25:       fclose(stdout);
26:    }
27:    return reval;
28: }
29: /* function definition */
30: void StrPrint(char **str)
31: {
32:    int i;
33:
34:    for (i=0; i<STR_NUM; i++)
35:       printf("%s\n", str[i]);
36: }
37: /* function definition */
38: int ErrorMsg(char *str)
39: {
40:    printf("Cannot open %s.\n", str);
41:    return FAIL;
42: }

Keát quaû:

Be bent, and you will remain straight.
Be vacant, and you will remain full.
Be worn, and you will remain new.
---- by Lao Tzu
 

Baøi taäp

  1. Coù töông ñöông khoâng?
rewind(fptr);
(void)fseek(fptr, 0L, SEEK_SET);
  1. Coù töông ñöông khoâng?  
rewind(fptr);
(void)fseek(fptr, 0L, SEEK_CUR);
  1. Giaû söû coù text file LaoTzu.txt nhö sau:
Be bent, and you will remain straight.
Be vacant, and you will remain full.
Be worn, and you will remain new.

Vieát chöông trình duøng ftell() tìm vò trí 3 caâu trong file, roài duøng fseek() ñeå chuyeån indicator sao cho caùc caâu ñöôïc in theo thöù töï ñaûo ngöôïc.

  1. Cho soá double 123.456 vaø soá int 10000. Vieát chöông trình löu noù trong file nhò phaân goïi laø data.bin vaø roài ñoïc laïi caùc giaù trò töø file nhò phaân.

Phaâàn tröôùc | Muïc luïc | Phaâàn sau