Sams Teach Yourself C in 24 Hours (60 page)

BOOK: Sams Teach Yourself C in 24 Hours
7.71Mb size Format: txt, pdf, ePub

28 067231861x CH22 4.10.2000 11:04 AM Page 375

Using Special File Functions

375

You can obtain the current value of the file position indicator by calling the ftell() function.

22

The syntax for the ftell() function is

AX

#include

long ftell(FILE *stream);

YNTS
, Here stream is the file pointer associated with an opened file. The ftell() function returns the current value of the file position indicator.

The value returned by the ftell() function represents the number of bytes from the beginning of the file to the current position pointed to by the file position indicator.

If the ftell() function fails, it returns –1L (that is, a long value of minus 1). One thing that can cause the failure of the ftell() function is that the file is a terminal or some other type for which the file position indicator becomes meaningless.

The program in Listing 22.1 shows how to randomly access a disk file by using the fseek() and ftell() functions.

TYPE

LISTING 22.1

Random Access to a File

1: /* 22L01.c: Random access to a file */

2: #include

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:

continues

28 067231861x CH22 4.10.2000 11:04 AM Page 376

376

Hour 22

LISTING 22.1

continued

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: }

28 067231861x CH22 4.10.2000 11:04 AM Page 377

Using Special File Functions

377

I have the following output shown on the screen of my computer after running the executable 22L01.exe of the program in Listing 22.1:

22

The fptr is at 0

OUTPUT
---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

The purpose of the program in Listing 22.1 is to move the file position indicator
ANALYSIS
around in order to read different verses from the haiku.txt file.

Inside the main() function, a file pointer fptr is defined in line 13, and the name of the haiku.txt file is assigned to the array called filename in line 14. Then, in line 17, you try to open the haiku.txt file for reading by calling the fopen() function. If successful, you invoke the PtrSeek() function with the fptr file pointer as the argument in line 20.

The definition of your first function, PtrSeek(), is shown in lines 27–48. The statement in line 31 obtains the original value of the fptr file pointer by calling your other function, PtrTell(), which is defined in lines 50–58. The PtrTell() function finds and prints out the value of the file position indicator with the help of the ftell() function.

The original value of the file position indicator contained by fptr is assigned to the long variable offset1 in line 31.

In line 32, the third function, DataRead(), is called to read one line of characters from the opened file and print out the line of characters on the screen. Line 33 gets the value of the fptr file position indicator right after the read operation and assigns the value to another long variable offset2.

Then the DataRead() function in line 34 reads the second line of characters from the opened file. Line 35 obtains the value of the file position indicator that points to the first byte of the third verse and assigns the value to the third long variable, offset3. Line 36

calls the DataRead() function to read the third verse and print it out on the screen.

Therefore, from the first portion of the output, you can see the three different values of the file position indicator at three different positions, and the three verses of the haiku written by Sodo. The three values of the file position indicator are saved respectively by offset1, offset2, and offset3.

28 067231861x CH22 4.10.2000 11:04 AM Page 378

378

Hour 22

Now, starting from line 40 to line 47, you read Sodo’s haiku backward, one verse at a time. That is, you read the third verse first, and then the second verse, and finally the first verse. To do so, you first call the fseek() function to move the file position indicator to the beginning of the third verse by passing the value contained by offset3 to the function. Then you call fseek() again and pass the value of offset2 to the function so that the file position indicator is set to point to the first byte of the second verse. Finally, you move the file position indicator to the beginning of the first verse by passing the value of offset1 to the fseek() function. Therefore, in the second portion of the output, you see the three verses of the haiku in reverse order.

The
rewind()
Function

Sometimes you might want to reset the file position indicator and put it at the beginning of a file. There is a handy C function, called rewind(), which can be used to rewind the file position indicator.

The syntax for the rewind() function is

AX

#include

void rewind(FILE *stream);

YNTS
Here stream is the file pointer associated with an opened file. No value is returned by

,

the rewind() function.

In fact, the following statement of the rewind() function:

rewind(fptr);

is equivalent to this:

fseek(fptr, 0L, SEEK_SET);

Listing 22.2 contains an example that calls the rewind() function to move the file position indicator to the beginning of an opened file.

More Examples of Disk File I/O

The following sections show several more examples of disk file I/O, such as reading and writing binary data and redirecting the standard streams. Three more I/O functions, fscanf(), fprintf(), and freopen(), are introduced too.

Reading and Writing Binary Data

As you learned in Hour 21, “Reading and Writing with Files,” you can indicate to the compiler that you’re going to open a binary file by setting a proper mode when calling 28 067231861x CH22 4.10.2000 11:04 AM Page 379

Using Special File Functions

379

the fopen() function. For instance, the following statement tries to open an existing binary file for reading:

22

fptr = fopen(“test.bin”, “rb”);

Note that the “rb” mode is used to indicate that the file you’re going to open for reading is a binary file.

Listing 22.2 contains an example of reading and writing binary data.

TYPE

LISTING 22.2

Reading and Writing Binary Data

1: /* 22L02.c: Reading and writing binary data */

2: #include

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:

continues

28 067231861x CH22 4.10.2000 11:04 AM Page 380

380

Hour 22

LISTING 22.2

continued

36: printf(“The size of buff: %d-byte\n”, sizeof(buff));

37: for (i=0; 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

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: }

After running the executable 22L02.exe, I have the following output on the screen of my computer:

The size of buff: 24-byte

OUTPUT
123.45

567.89

100.11

Read back from the binary file:

123.45

567.89

100.11

The purpose of the program in Listing 22.2 is to write three values of the double
ANALYSIS
data type into a binary file and then rewind the file position indicator and read back the three double values from the binary file. The two functions, DataWrite() and DataRead(), that perform the writing and reading, are declared in lines 6 and 7.

The enum names, SUCCESS, FAIL, and MAX_NUM, are defined in line 4 with values of 0, 1, and 3, respectively.

28 067231861x CH22 4.10.2000 11:04 AM Page 381

Using Special File Functions

381

Inside the main() function, the statement in line 16 tries to create and open a binary file called double.bin for both reading and writing. Note that the “wb+” mode is used in the
22

fopen() function in line 16.

If the fopen() function is successful, the DataWrite() function is called in line 19 to write three double data items, 123.45, 567.89, and 100.11, into the opened binary file, according to the definition of the DataWrite() function in lines 28–41. The fwrite() function in line 39 does the writing. Because the three double data items are saved in an array named buff, you also measure and print out the size of the buff array in line 36.

On my machine, the size of the buff array is 24 bytes because each double data item is 8 bytes.

Right after the execution of the DataWrite() function, the file position indicator is reset to the beginning of the binary file by calling the rewind() function in line 20 because you want to read back all the three double data items written to the file.

Then in line 21, the DataRead() function reads the three double data items from the opened binary file double.bin. From the definition of the DataRead() function in lines 43–53, you can see that the fread() function is used to perform the reading operation (see line 50).

The output from running the program in Listing 22.2 shows the three double data items before the writing and after the reading as well.

The
fscanf()
and
fprintf()
Functions

As you have learned, the two C library functions scanf() and printf() can be used to read or write formatted data through the standard I/O (that is, stdin and stdout). Among the C disk file I/O functions, there are two equivalent functions, fscanf() and fprintf(), that can do the same jobs as the scanf() and printf() functions. In addition, the fscanf() and fprintf() functions allow the programmer to specify I/O streams other than stdin and stdout.

The syntax for the fscanf() function is

AX

#include

int fscanf(FILE *stream, const char *format, …);

YNTS
Here stream is the file pointer associated with an opened file. format, whose usage is

,

the same as in the scanf() function, is a char pointer pointing to a string that contains

Other books

Forsaken by Leanna Ellis
His Love Lesson by Nicki Night
The Search for the Dice Man by Luke Rhinehart
Girls Just Wanna Have Guns by Toni McGee Causey
Dusk by Tim Lebbon
Destined by Aprilynne Pike
365 Days by Ronald J. Glasser