"Structure" in C is very important, especially when dealing with files. Hence we discuss "structure" first, before we come to "files".
Exercise : What are the common data types in C ? Name some.
Ans : char, short, long, int, float, double ....
Exercise : From the previous chapters, can you remember any other ways to define new data types?
Ans : e.g.
typedef struct { int age;
double wages;
} New_data_type;
New_data_type arecord, *ptr;
Notice that "typedef" and "struct" are keywords.
Above we have a new data type called "New_data_type", which is a structure and consists of 2 elements, one an integer and the other a double precision number.
The declaration
New_data_type arecord, *ptr;
declares "arecord" to be of this data type, and "ptr" a pointer for this new data type.
Direct direction without the use of "typedef"
e.g.
struct { int age;
double wages;
} arecord, *ptr;
Exercise : Suppose we wish to have a data type consisting of
name which is a string of 40 bytes
age which is an integer
wages which is a double
and we wish to have two variables "reca, recb" as well as a pointer "prec" to
this data type. How are we to declare it?
Ans :
struct { char name[40];
int age;
double wages;
} reca, recb, *prec ;
Exercise : How are we to access data in "reca, recb, prec " ?
Ans : e.g. reca.name, reca.age, reca.wages, recb.name, recb.age,
recb.wages, prec->name, prec->age, prec->wages (OR we may use
(*prec).age, (*prec).age, (*prec).wages , but usually we will use
the
Give a name to a structure first, then ...
e.g.
struct recname
{ int age;
double wages;
} ;
struct recname arecord, *ptr;
Notice that "recname" may be any name. A valid variable name is also a
valid structure name.
Exercise : Would it be correct if we omit "struct" , e.g.
struct recname
{ int age;
double wages;
} ;
recname arecord, *ptr;
(and NOT)
struct recname arecord, *ptr;
?
Ans : No. "recname arecord, *ptr; " is wrong in syntax. We should use "struct recname arecord, *ptr; ". We will discuss "typedef" later, and with it, we do not have to use "struct".
Exercise : For the structure,
name which is a string of 40 bytes
age which is an integer
wages which is a double
How are we to declare "reca, recb, *prec" ?
Ans :
struct staffrec
{ char name[40];
int age;
double wages;
} ;
struct staffrec reca, recb, *prec ;
Using "typedef"
This is what we have been doing, e.g.
typedef struct { int age;
double wages;
} New_data_type;
New_data_type arecord, *ptr;
Exercise : For the structure,
name which is a string of 40 bytes
age which is an integer
wages which is a double
How are we to declare "reca, recb, *prec" using "typedef" ?
Ans :
typedef struct
{ char name[40];
int age;
double wages;
} staffrec;
staffrec reca, recb, *prec ;
(Notice that we DO NOT HAVE TO USE "struct" here !)
Exercise : How are we to access data in "reca, recb, prec " ?
Ans : Same as before, with : reca.name, reca.age, reca.wages, recb.name, recb.age, recb.wages, prec->name, prec->age, prec->wages
Exercise : What are the data type of "vara, varb, varc, vard, pvar" in the following :
int vara;
double varb;
char varc[40];
double vard[20];
char *pvar;
Ans :
vara is an integer,
varb is a double precision floating point number,
varc is a character array (or string) of 40 bytes long,
vard is an array of double precision floating point number and has 20 elements,
pvar is a character pointer.
Exercise : Now suppose we put "typedef" before the declarations, i.e.
typedef int vara;
typedef double varb;
typedef char varc[40];
typedef double vard[20];
typedef char *pvar;
Then what are the data type of "d1, d2, d3, d4, pd5" in the declarations
vara d1;
varb d2;
varc d3;
vard d4;
pvar pd5;
Ans :
d1 is of type "int", as if we have declared it with "int d1;"
d2, "double", as if we have declared it with "double d2;"
d3 is, as if we have declared it with "char d3[40];", i.e. a character array
of 40 bytes,
d4 is an array of double precision floating point number and has 20 elements
pd5 is a character pointer, same as if we have declared it with "char *pd5;"
WHENEVER A VARIABLE NAME HAVE BEEN "typedef", THEN ANY OTHER VARIABLES DECLARED WITH THIS VARIABLE NAME HAVE IDENTICAL DATA TYPE.
Exercise :Declare "Boolean" as "unsigned short", then declare variables "ia, ib, ic" as "Boolean".
Ans :
typedef unsigned short Boolean;
Boolean ia, ib, ic;
Exercise :What is "p" in the declaration "Boolean *p;" ?
Ans : "p" is a pointer for "unsigned short".
Exercise :"typedef" the following structure as "Masterrec", then declare "rectom, recmary, recjack" as three variables of this type. Also declare "prec" as a pointer to this new data type.
name which is a string of 40 bytes
tel which is a string of 20 bytes
addr which is a string of 60 bytes
wages which is a double
Ans :
typedef struct
{ char name[40];
char tel[20];
char addr[60];
double wages;
} Masterrec;
Masterrec rectom, recmary, recjack, *prec;
Exercise : What do the following statements do ?
prec = &recmary;
prec->wages = 5000;
Ans : The first statement loads the effective address of "recmary" into the address pointer "prec". The second statement is the same as
"recmary.wages = 5000; ".
Exercise : (WORD ALIGNMENT IN MICROPROCESSOR) The number of lines in "data bus" nowadays is usually 32 (i.e. 4 bytes
will be loaded/stored at one time). For 64 bits microprocessor, the number of lines in "data
bus" is 64. Hence 8 bytes of data may be loaded/stored at one time.
For efficient loading/storing of data, variable should be stored in addresses "aligned with
word boundary".
Would the following "structure" be efficient in storing/loading ? (Assuming
a 32 bits microprocessor will be used.)
typedef struct
{ char name[47];
char tel[25];
char addr[66];
double wages;
} Masterrec;
Ans : No, because 47, 25, 66 are NOT DIVISIBLE BY 4. Hence a better one should be
typedef struct
{ char name[48];
char tel[24];
char addr[68];
double wages;
} Masterrec;
(Note : in actual implementation, a C compiler would usually "pad" the field so that it becomes aligned on
word boundaries, e.g. "char name[47];", compiler would pad one idle byte to make it 48. For
"char tel[25];", compiler would pad 3 idle bytes to make it 28. For "char addr[66];", compiler would
pad 2 idle bytes to make it 68.The syntax (or grammar) of a computer language is usually specified in the following two ways :-
Diagram

e.g.
int i, j, k=5, ia, ib ;
double x=10.2, y, z=60.7 ;
Using "recursive descend" type of specification
e.g. ( Notice that the vertical stroke | means "OR" )
expression = assignment-expression
| conditional-expression
| unary-expression
| ....
....
....
additive-expression = multiplicative-expression
| additive-expression + multiplicative-expression
| additive-expression - multiplicative-expression
multiplicative-expression = unary-expression
| multiplicative-expression * unary-expression
| multiplicative-expression / unary-expression
unary-expression = primary-expression
| unary-expression[expression]
| unary-expression(expression,expression, ... )
| unary-expression.identifier
| unary-expression->identifier
primary-expression = identifer
| constant
| string
| (expression)
You will have noticed that "expression" is defined in terms of "assignment-expression, ..."
which in turn are defined in terms of "additive-expression". And "additive-expression" is defined in terms of "multiplicative-expression". And "multiplicative-expression" is defined in terms of "unary-expression". "unary-expression" is defined in terms of "identifier, constant,
string", and a bracket with "expression" inside !
You will have noticed that nearly all such definitions are "circular".
Moreover : (1) "identifier, constant, string" have to be defined in terms of alphabets and digits. (2) the definition "expression" is CIRCULAR, i.e. it is defined in terms of itself. "Circular definition" makes no sense in Mathematics, but it makes sense in computer parsing, because after each parsing operation, the original sentence gets shorter and shorter, and as the sentence is of finite length, the process will terminate, and will not go on indefinitely.
The above are EXAMPLES only, and are much abbreviated. For a full description of C syntax (or grammar), please refer to the Appendix of K&R's book "The C Programming Language".
In <stdio.h> (Standard Input/Output Header File), there is defined a structure to be used with file operations,
struct _IO_FILE
{ char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr; /* Current put pointer. */
char* _IO_write_end; /* End of put area. */
char* _IO_buf_base; /* Start of reserve area. */
char* _IO_buf_end; /* End of reserve area. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno;
int _blksize;
_IO_off_t _offset;
unsigned short _cur_column;
char _unused;
char _shortbuf[1];
struct _IO_lock_t _IO_lock;
};
typedef struct _IO_FILE FILE ;
Notice that this defintion of "struct ... ; typedef ...;" varies from system to system, but usually it contains similar items.
These subroutines are those described in "stdio.h" (The standard Input/Output subroutines that comes with an ANSI C compiler.)
(1) FILE *fopen(char *filename, char *mode)
e.g. FILE *filein; /*This declares "filein" to be
a FILE pointer. It is to store
the return value from "fopen(..)" */
filein = fopen("testfile","r"); /*Opens the file for reading*/
This subroutine requires 2 arguments : one is a character string containing
the filename. The other is mode, and
Mode may be
"r" for reading.
"w" for writing. Original content will be overwritten.
"a" append at the end.
"r+" for both read and write, i.e. update a file.
"w+" for write and read. Create file if it doesn't exist.
"a+" append as well as read.
If it fails to open the file, it returns NULL (which is
usually defined to be 0). Otherwise, it returns (FILE *),
the address where a structure of type "FILE" is stored.
Another example,
FILE *fileout;
if ( (fileout = fopen("outfile","w")) == NULL )
{perror("Unable to open file");
exit(1);
}
....
....
Here we test if the file has been successfully opened or not. If not,
we use "perror(..)" ("print error to file stderr" - one of the three
standard files opened by the system automatically :
stdin - standard input, usually the keyboard;
stdout - standard output, usually the screen;
stderr - standard error output, usually the screen too.)
"exit(expression)" is another subroutine usually supplied, though not in
the standard IO library. It will flush out all data in buffers and close all
opened files. "expression" in exit(..) is the return code, much like "return 0;"
in the main program ( NOTE : you may use "return .." instead of exit(..) ).
Exercise : What is wrong with the following
(1) FILE fin;
fin = fopen("testfile","r");
(2) FILE *fout;
fout = fopen("outfile",'w');
Ans :
(1) FILE pointer required, not FILE structure, hence it should be
FILE *fin;
And not
FILE fin;
(2) "w" which is a string, but 'w' is a character.
|
(2) void perror(char *s)
This subroutine prints the string (char *s) to stderr - standard error file.
|
(3) int fclose(FILE *ptr)
If the file is closed successfully, it returns 0, otherwise it returns EOF,
which is a constant defined in <stdio.h>, and is usually = -1.
e.g. fclose(fin);
fclose(fout);
|
(4) FILE *tmpfile(void)
Usually we want a temporary file, for temporary storing of data.
This will open a file, and we NEED NOT supply a filename.
The file may be used for both read/write.
It returns an address (FILE pointer) if successful, or NULL if it fails in
any way.
The file will be deleted when program terminates.
|
(5) int feof(FILE *ptr)
This tests if "end of file" has been reached or not.
If "eof" has been reached, it returns non-zero (i.e. "true". Remember in C,
any value other than 0 is regarded as "true". 0 means "false"),
otherwise, it returns 0.
e.g.
if (feof(fin)) { ...... }
Note that we seldom test EOF this way. The reason being that EOF condition
may be set before a read operation, or after a read operation, and is system
dependent. In practice, we test EOF using the return values of "fscanf(..)"
etc. You may find examples of testing EOF below.
|
(6) void rewind(FILE *ptr)
This rewind the file to its starting position. For example, we may write
onto a temporary file, then rewind it, and read back the data.
|
(7) int printf(char *format, ...)
int sprintf(char *targetstring, char *format, ...)
int fprintf(FILE *ptr, char *format, ...)
We have discussed "printf" (print with format) in Chapter 4 "Simple Input and
Output".
There are two additional ones : sprintf(...) and fprintf(...)
sprintf(...) will print onto a string.
fprintf(...) will print onto a file.
If the subroutine succeeds, it will return the number of characters printed,
otherwise, it will return a negative number.
|
(8) int scanf(char *format, ...)
int sscanf(char *sourcestring, char *format, ...)
int fscanf(FILE *ptr, char *format, ...)
We have discussed "scanf" (scan with format) in Chapter 4 "Simple Input and
Output".
There are two additional ones : sscanf(...) and fscanf(...)
sscanf(...) will scan from a string, (char *sourcestring, above)
fscanf(...) will scan from a file.
If successful, it will return the number of items that have been successfully
scanned. If it fails, it will return EOF (usually defined to be -1 in <stdio.h>),
and the most probable reason for failure is End of File is reached.
Incidentally, this is more useful and safer in testing EOF condition, than that
of using "feof(FILE *ptr)".
|
(9) We have used
int getchar(void) /* gets one character from stdin, keyboard.
Returns character. */
int putchar(int c) /* prints one character to stdout, screen */
char *gets(char *s) /* gets one string from stdin, keyboard */
char *puts(char *s) /* prints one string to stdout, screen */
For their counterparts that deal with file, we have
int fgetc(FILE *ptr) /* gets one character from file. Returns character */
int fputc(int c, FILE *ptr) /* prints one character to file. Returns character
written */
char *fgets(char *s, int n, FILE *ptr)
/* gets at most n-1 characters from file
and put it in string char *s.
One character is reserved for '\0'
If error occurs, usually when EOF is
reached, it returns NULL */
int fputs(char *s, FILE *ptr) /* prints the string char *s to file */
If error occurs, they (except fgets(..)) return EOF. (End of File
Condition is regarded as an error too.)
|
CAUTION : For gets(..), it will strip away the newline '\n' character and
replaces it with '\0' - end of string character.
For puts(..), it will automatically add '\n'.
NOT so with fgets(...). It will NOT strip away the '\n' character.
For fputs(...), it will NOT add the '\n' character.
Personally, I think this is a design flaw. User would expect similar
behavior from "gets(..), puts(...)" and "fgets(...), fputs(...)"
except one is from keyboard and the other, from file.
Also for the scanf(...) or fscanf(...) subroutine. They will ignore
blank (or newline, or tab), e.g.
scanf("%d%d", &i, &j); /* If we key in one number, then press
Enter (='\n'), then key in another
number, they will be scanned in
correctly into i,j */
But gets(..), fgets(..) will not ignore newline character '\n'.
Exercise : Will fscanf(...) work correctly in
fscanf(fin,"%d%d%d%d", &i, &j, &k, &l);
if (1) The four numbers are on the same line in the data file, e.g.
30 40 50 73
(2) If the four numbers are on separate lines in the data file, e.g.
30
40
50
73 ?
Ans : Yes. Because '\n' is ignored by scanf(..) or fscanf(..).
I myself have some frustrating experiences with "scanf(..), fscanf(..)".
I don't know whether they are design flaws or that my computer has been
sabotaged - my PC can be radio-controlled by persons I have no idea of.
Suggested REMEDIES :
(1) Use gets(..), or fgets(...) to read in one whole line,
including the '\n' character, into a string first. Then use
sscanf(...) (String_scan_with_format) to scan the string.
We will be using this method throughout this book, to avoid
problems caused by '\n'.
(2) Write custom scanning subroutines for your data file. The
scanning subroutines need not be general purpose scanning
subroutines, but just for your particular data file. This
will be illustrated by an example near the end of this chapter,
(Part 2) where we are to read a data file prepared by "Qbasic,
under MSDOS".
(3) Use "structure" to write and read files. This will be explained
later (Part 2). But unfortunately, files prepared this way
cannot be typed out with "cat", i.e. they are not human-readable,
nor can the data file be prepared with an editor like "emacs".
Example of this use will be given later (Part 2).
|
OPEN "C:\test\master.txt" FOR OUTPUT AS #1
L20:
INPUT "Enter name "; name$
IF name$ <> "****" THEN
INPUT "Enter age "; age
INPUT "Enter telephone no. "; tel
WRITE #1, name$, age, tel
GOTO L20
ELSE
CLOSE #1
END
END IF
which accepts inputs from the keyboard, "name, age, tel", and then writes the data onto a file. The QBasic statement "write #1 .... " will output the data in the format, e.g.
Now write a C program, but output the file in the format"Wu Siu Yan",50,23003 "tom",60,93939 "mary",30,939393 "jackie chan",49,3003
i.e. one data on one line. Use "char name[40], tel[24]". Ans : e.g.Wu Siu Yan 50 23003 tom 60 93939 mary 30 939393 jackie chan 49 3003
#include <c.h>
int main()
{ char name[40], tel[24], buffer[80];
int age;
FILE *fout;
if ( (fout = fopen("master.txt","w") ) == NULL )
{perror("Unable to open file");
exit(1);
}
L20:
printf("Enter name\n");
gets(name);
if ( strcmp(name,"****") == 0 )
{fclose(fout);
return 0;
}
printf("Enter age\n");
gets(buffer);
sscanf(buffer,"%d",&age);
printf("Enter telephone no\n");
gets(tel);
fprintf(fout,"%s\n%d\n%s\n", name, age, tel);
printf("%s\n%d\n%s\n", name, age, tel);
goto L20;
}
strcmp(s1,s2) is a subroutine described in <string.h>. It compares two strings.
Note that if you have not put the "#include
The command to compile should be somewhat like
gcc -Wall t1.c -I/home/tom/include/ -lmif you have used <c.h.>. Exercise : Write a C program to read in the above data file, and print them as
Name Age Tel
xxxxxxxx xxx xxxxxxxxx
xxxxxxxx xxx xxxxxxxxx
Ans : e.g.
#include <c.h>
void erasenewline(char *a)
{ int c;
L20:
c=*a;
if (c == '\n')
{*a='\0';
return;
}
a++;
goto L20;
}
int main()
{ char name[40], tel[24], buffer[80];
int age;
FILE *fin;
if ( (fin = fopen("master.txt","r") ) == NULL )
{perror("Unable to open file");
exit(1);
}
printf(" Name Age Tel\n\n");
L20:
/* Note : NULL means EOF in fgets(..) */
if ( fgets(name,40,fin) == NULL )
{fclose(fin);
return 0;
}
fgets(buffer,80,fin);
sscanf(buffer,"%d",&age);
fgets(tel,24,fin);
erasenewline(name);
erasenewline(tel);
printf(" %-40s %3d %-24s\n", name, age, tel);
goto L20;
}
Note :
Exercise : First use "emacs" to create a file "/home/tom/data.txt" with the following data,
Then write a program, to read in these data, and print them out, together with the average of them. Draw the flowchart first. Notice that the the file contains only numbers, hence we may use "fscanf(..)" to read in the data. Ans :40.34 52.12 70.5 38.213 68.4
#include <c.h>
int main()
{ double total = 0., x, average;
int ncount = 0;
FILE *fin;
if ( (fin=fopen("data.txt","r")) == NULL )
{perror("Unable to open file");
exit(1);
}
L20 :
if ( fscanf(fin,"%lf",&x) == EOF )
{goto L40;}
/* When EOF is reached, "fscanf(..)" returns EOF */
ncount++;
total += x;
printf("%20.7f %20.7f\n", x, total);
goto L20;
L40:
average = total/ncount;
printf("\nAverage is %20.7f\n\n", average);
fclose(fin);
return 0;
}
Notice that "%lf" is the format to read in a double precision number (= long floating point number).
Exercise : Use the program in the first exercise to create a master file "master.txt" with the following data, assuming that they are students in a tutorial class.
Name Age Telephone No.
---- --- ------------
Tom 16 1234
Mary 16 6635
Jack 17 7899
Lee See 16 1222
Chan Sam 17 8386
Suppose they obtained the following results in a Maths test,
Now write a program, that reads the names from "master.txt", and prints out the name one by one, and prompts for input, e.g.70.4 68 73.6 55 47
Tom ? 70.4
Mary ? 68
Jack ? 73.6
Lee See ? 55
Chan Sam ? 47
And then write the test results in a file named "math.txt". i.e. the file "math.txt" should contain
70.4 68 73.6 55 47
Ans :
#include <c.h>
void erasenewline(char *a)
{ int c;
L20:
c=*a;
if (c == '\n')
{*a='\0';
return;
}
a++;
goto L20;
}
int main()
{ char name[40], buffer[80], filename[40];
double xmark;
FILE *fmaster, *fout;
if ( (fmaster = fopen("master.txt","r") ) == NULL )
{perror("Unable to open master file");
exit(1);
}
printf("Enter filename for output file\n");
gets(filename);
if ( (fout = fopen(filename,"w")) == NULL )
{perror("Unable to open output file");
exit(1);
}
L20:
/* Note : NULL means EOF in fgets(..) */
if ( fgets(name,40,fmaster) == NULL )
{fclose(fmaster);
fclose(fout);
return 0;
}
/* These two statements read in age, tel, but will not use them */
fgets(buffer,80,fmaster);
fgets(buffer,80,fmaster);
erasenewline(name); /* get rids of newline character */
printf("%s ? ", name);
gets(buffer);
sscanf(buffer,"%lf",&xmark);
printf("%s %10.3f\n",name,xmark);
fprintf(fout,"%10.3f\n",xmark);
goto L20;
}
Exercise : Use the above program to enter the test results for English "eng.txt", and the test results for Chinese "chi.txt".
Suppose the English test results are
And the Chinese test results are60 50 58 70 74
Now write a program that opens 4 files "master.txt", "math.txt", "eng.txt", and "chi.txt" and then prints a report to output file "out.txt", e.g.68 72 75 66.3 59
Student : Tom
Mathematics 70.4
English 60.0
Chinese 68.0
Student : Mary
Mathematics 68.0
English 50.0
Chinese 72.0
.....
.....
Ans :
#include <c.h>
void erasenewline(char *a)
{ int c;
L20:
c=*a;
if (c == '\n')
{*a='\0';
return;
}
a++;
goto L20;
}
int main()
{ char name[40], buffer[80];
double xmath, xeng, xchi;
FILE *fmaster, *fout, *fmath, *feng, *fchi;
int iflag=0;
if ( (fmaster = fopen("master.txt","r") ) == NULL )
{perror("Unable to open master file");
iflag=1;
}
if ( (fmath = fopen("math.txt","r") ) == NULL )
{perror("Unable to open maths file");
iflag=1;
}
if ( (feng = fopen("eng.txt","r") ) == NULL )
{perror("Unable to open English file");
iflag=1;
}
if ( (fchi = fopen("chi.txt","r") ) == NULL )
{perror("Unable to open Chinese file");
iflag=1;
}
if ( (fout = fopen("out.txt","w") ) == NULL )
{perror("Unable to open output file");
iflag=1;
}
if (iflag==1) {exit(1);}
L20:
/* Note : NULL means EOF in fgets(..) */
if ( fgets(name,40,fmaster) == NULL )
{fclose(fmaster);
fclose(fmath);
fclose(feng);
fclose(fchi);
fclose(fout);
return 0;
}
/* These two statements read in age, tel, but will not use them */
fgets(buffer,80,fmaster);
fgets(buffer,80,fmaster);
erasenewline(name); /* get rids of newline character */
fscanf(fmath,"%lf", &xmath);
fscanf(feng,"%lf", &xeng);
fscanf(fchi,"%lf", &xchi);
fprintf(fout, " Student %-40s\n\n"
" Mathematics %5.2f\n"
" English %5.2f\n"
" Chinese %5.2f\n\n\n"
, name, xmath, xeng, xchi);
goto L20;
}
When the number of files are large, it is advisable to use an array. The following program does the same as above, but uses arrays.
#include <c.h>
void erasenewline(char *a)
{ int c;
L20:
c=*a;
if (c == '\n')
{*a='\0';
return;
}
a++;
goto L20;
}
int main()
{ char name[40], buffer[80];
char *fname[] = {"master.txt", "math.txt", "eng.txt", "chi.txt", "out.txt"};
char *mode[] = {"r", "r", "r", "r", "w"};
double xmark[5];
int i, iflag;
FILE *f[5];
for (iflag=0, i=0; i<5; i++)
{if ( (f[i] = fopen(fname[i],mode[i])) == NULL )
{printf("Unable to open %s\n",fname[i]);
iflag=1;
}
}
if (iflag==1) {exit(1);}
L20:
/* Note : NULL means EOF in fgets(..) */
if ( fgets(name,40,f[0]) == NULL )
{for (i=0;i<5; i++)
{fclose(f[i]);
}
return 0;
}
/* These two statements read in age, tel, but will not use them */
fgets(buffer,80,f[0]);
fgets(buffer,80,f[0]);
erasenewline(name); /* get rids of newline character */
for (i=1; i<=3; i++)
{fscanf(f[i],"%lf", &xmark[i]);
}
fprintf(f[4], " Student %-40s\n\n"
" Mathematics %5.2f\n"
" English %5.2f\n"
" Chinese %5.2f\n\n\n"
, name, xmark[1], xmark[2], xmark[3]);
goto L20;
}
In Part 2 of this Chapter, we shall discuss how to use "structure" in sequential files, and also how to read a file prepared by "Qbasic - MSDOS".
| [Previous] | [Home] | [Next] |