Introduction to C Lecture 9: File inputoutput and the C compiler PowerPoint PPT Presentation

presentation player overlay
1 / 46
About This Presentation
Transcript and Presenter's Notes

Title: Introduction to C Lecture 9: File inputoutput and the C compiler


1
Introduction to CLecture 9 File
input/outputand the C compiler
  • P. Harris

2
Files
  • Before you can read from and write to a file, you
    need to carry out certain procedures, and you
    need information about the file and its state.
    For example, you need to open the file and you
    need to know what sort of file it is and while
    you are looking at it, you need to keep track of
    whereabouts in the file you are.
  •  
  • All of this information is kept lumped together
    in a structure. This structure has the generic
    name FILE, and it is defined for you as part of
    the information that you bring in with the header
    stdio.h.
  •  
  • You do not need to know details of this
    structure you simply assign a pointer to a file
    structure, open the file (analogy a file is like
    a closed book you cant do anything with it
    until you open it), read from/write to it, and
    then close it.
  • Example

3
File i/o
  • include ltstdio.hgt
  •  
  • int main(void)
  • int a, sum 0
  • FILE ifp, ofp / input file pointer, output
    file pointer /
  •  
  • ifp fopen(my_file, r) / open for
    reading /
  • ofp fopen(outfile, w) / open for
    writing /
  • .....
  •  
  • fclose(ifp)
  • fclose(ofp)
  •  

4
File i/o
  • include ltstdio.hgt
  •  
  • int main(void)
  • int a, sum 0
  • FILE ifp, ofp / input file pointer, output
    file pointer /
  •  
  • ifp fopen(my_file, r) / open for
    reading /
  • ofp fopen(outfile, w) / open for
    writing /
  • .....
  •  
  • fclose(ifp)
  • fclose(ofp)
  •  

Pointers to file structure
5
File i/o
  • include ltstdio.hgt
  •  
  • int main(void)
  • int a, sum 0
  • FILE ifp, ofp / input file pointer, output
    file pointer /
  •  
  • ifp fopen(my_file, r) / open for
    reading /
  • ofp fopen(outfile, w) / open for
    writing /
  • .....
  •  
  • fclose(ifp)
  • fclose(ofp)
  •  

The modes for opening files are r (read), w
(write), a (append), rb (read from binary file
not appropriate for Unix, which doesnt
distinguish between binary and text files), wb,
ab. You may also add a to give, for example,
r for both reading and writing. If the open
fails (e.g. file to be read doesnt exist) the
pointer returned is NULL. Open for writing causes
the file to be created if it doesnt exist, and
overwritten if it does.
6
fprintf(), fscanf()
  • For output to/input from files, you can use the
    functions fprintf( ) and fscanf( ), which operate
    in exactly the same manner as printf and scanf,
    except that a file pointer has to be specified.
    Usage
  •  
  • fprintf(file_ptr, control_string, other_args)
  • fscanf(file_ptr, control_string, other_args)
  •  

7
fprintf(), fscanf()
  • For output to/input from files, you can use the
    functions fprintf( ) and fscanf( ), which operate
    in exactly the same manner as printf and scanf,
    except that a file pointer has to be specified.
    Usage
  •  
  • fprintf(file_ptr, control_string, other_args)
  • fscanf(file_ptr, control_string, other_args)
  •  

control string things like s12.2f\n
8
fprintf(), fscanf()
  • For output to/input from files, you can use the
    functions fprintf( ) and fscanf( ), which operate
    in exactly the same manner as printf and scanf,
    except that a file pointer has to be specified.
    Usage
  •  
  • fprintf(file_ptr, control_string, other_args)
  • fscanf(file_ptr, control_string, other_args)
  •  
  • In fact, printf and scanf are special cases of
    these there are three file pointers defined,
    stdin, stdout and stderr, the first of which
    points to the keyboard and the other two of which
    point to the screen. printf( ) is therefore
    equivalent to fprintf(stdout, ....).
  •  
  • Note that, when you read from/write to a file,
    the system will keep track of where in the file
    you have reached, so that subsequent calls to
    fprintf( ) or fscanf( ) can carry on where you
    left off rather than starting again from the
    beginning.

9
getc(), putc()
  • Functions getc(file_ptr), putc(file_ptr) are just
    like getchar and putchar, except that they read
    from/write to files. However, you should note
    that the EOF (end-of-file) character is not in
    the usual Ascii character set, and you need an
    int not a char if you are going to use it
  • int c
  • ....
  • c getchar(inpt_file)

10
Moving around in files
  • When reading or writing from a file, fprintf( )
    etc. will normally begin where they left off
    record is kept of the current position in a file.
    However it is often useful to access a file at
    some random position instead. Useful commands
    are
  •  
  • rewind(file_ptr) resets the position indicator
    to the start of the file
  • ftell(file_ptr) returns the
    current value of the file position
    indicator i.e. no. of bytes from start of
    file
  • fseek(file_ptr, offset, place) moves file
    position indicator to specified position
  •  
  • The latter command moves the indicator to offset
    bytes from place place can be SEEK_SET, SEEK_CUR
    or SEEK_END (actually 0, 1 or 2) for beginning,
    current position or end of file respectively.
    Offset can be negative as well as positive.
    Example

11
Example of moving within files
  • / Write a file backwards /
  • include ltstdio.hgt
  • define MAXSTRING 100
  • int main(void)
  • char fnameMAXSTRING
  • int c
  • FILE ifp
  •   fprintf(stdout, "\nInput a filename ")
  • scanf("s", fname)
  • ifp fopen(fname, "r") / open for
    reading /
  • fseek(ifp, 0, SEEK_END) / move to end of
    file /
  • fseek(ifp, -1, SEEK_CUR) / back up one
    char /
  • while (ftell(ifp) gt 0)
  • c getc(ifp) / move ahead one
    char /
  • putchar(c)
  • fseek(ifp, -2, SEEK_CUR) / back up 2
    chars /
  • return 0

12
Example of moving within files
  • / Write a file backwards /
  • include ltstdio.hgt
  • define MAXSTRING 100
  • int main(void)
  • char fnameMAXSTRING
  • int c
  • FILE ifp
  •   fprintf(stdout, "\nInput a filename ")
  • scanf("s", fname)
  • ifp fopen(fname, "r") / open for
    reading /
  • fseek(ifp, 0, SEEK_END) / move to end of
    file /
  • fseek(ifp, -1, SEEK_CUR) / back up one
    char /
  • while (ftell(ifp) gt 0)
  • c getc(ifp) / move ahead one
    char /
  • putchar(c)
  • fseek(ifp, -2, SEEK_CUR) / back up 2
    chars /
  • return 0

Notice we have to back up 2 chars, because the
act of reading in one char increments the file
position indicator by 1.
13
Executing system commands
  • You can execute system commands by simple use of
    system( ). Example
  • system(date)passes the string date to the
    operating system, which executes it before
    returning control to the program.
  • The following example, from KP, does a directory
    listing in uppercase to the screen. To understand
    it, you need to know a couple of things
  • The function tmpnam(NULL) gives a name that you
    can use for a temporary file (one that doesnt
    exist already)
  • If you do ls gt junk.dat(on Unix) you get a
    directory listing written to the file junk.dat.
    (Remember the redirection operator, gt )
  • As you will see, this is rather a clumsy method
    it asks the system to write the directory to a
    temporary file, and then reads in from the
    temporary file and writes out to the screen.

14
Example
  • include ltctype.hgt
  • include ltstdio.hgt
  • include ltstdlib.hgt
  • int main(void)
  • char command_string100, tmp_filename
  • int c
  • FILE ifp
  •   tmp_filename tmpnam(NULL)
    sprintf(command_string, "ls gt s",
    tmp_filename)
  • system(command_string) ifp
    fopen(tmp_filename, "r")while ((c getc(ifp))
    ! EOF)
  • putchar(toupper(c))remove(tmp_filename)
  • return 0

15
Example
  • include ltctype.hgt
  • include ltstdio.hgt
  • include ltstdlib.hgt
  • int main(void)
  • char command_string200, tmp_filename
  • int c
  • FILE ifp
  •   tmp_filename tmpnam(NULL)
    sprintf(command_string, "ls gt s",
    tmp_filename)
  • system(command_string) ifp
    fopen(tmp_filename, "r")while ((c getc(ifp))
    ! EOF)
  • putchar(toupper(c))remove(tmp_filename)
  • return 0

Number hard-coded in is not very nice but for
command-line, probably ok as long as you set a
limit unlikely to be exceeded!
16
Example
  • include ltctype.hgt
  • include ltstdio.hgt
  • include ltstdlib.hgt
  • int main(void)
  • char command_string200, tmp_filename
  • int c
  • FILE ifp
  •   tmp_filename tmpnam(NULL)
    sprintf(command_string, "ls gt s",
    tmp_filename)
  • system(command_string) ifp
    fopen(tmp_filename, "r")while ((c getc(ifp))
    ! EOF)
  • putchar(toupper(c))remove(tmp_filename)
  • return 0

Notice the character is of type int not char
because the end-of-file character isnt in the
ASCII set, so we need a larger range than 0-255
17
Example
  • include ltctype.hgt
  • include ltstdio.hgt
  • include ltstdlib.hgt
  • int main(void)
  • char command_string200, tmp_filename
  • int c
  • FILE ifp
  •   tmp_filename tmpnam(NULL)
    sprintf(command_string, "ls gt s",
    tmp_filename)
  • system(command_string) ifp
    fopen(tmp_filename, "r")while ((c getc(ifp))
    ! EOF)
  • putchar(toupper(c))remove(tmp_filename)
  • return 0

Here we make a temporary file temp.dat or
something.
18
Example
  • include ltctype.hgt
  • include ltstdio.hgt
  • include ltstdlib.hgt
  • int main(void)
  • char command_string200, tmp_filename
  • int c
  • FILE ifp
  •   tmp_filename tmpnam(NULL)
    sprintf(command_string, "ls gt s",
    tmp_filename)
  • system(command_string) ifp
    fopen(tmp_filename, "r")while ((c getc(ifp))
    ! EOF)
  • putchar(toupper(c))remove(tmp_filename)
  • return 0

ls gt s,tmp_filename becomes equivalent to
ls gt temp.dat (or whatever the file is
called)....
19
Example
  • include ltctype.hgt
  • include ltstdio.hgt
  • include ltstdlib.hgt
  • int main(void)
  • char command_string200, tmp_filename
  • int c
  • FILE ifp
  •   tmp_filename tmpnam(NULL)
    sprintf(command_string, "ls gt s",
    tmp_filename)
  • system(command_string) ifp
    fopen(tmp_filename, "r")while ((c getc(ifp))
    ! EOF)
  • putchar(toupper(c))remove(tmp_filename)
  • return 0

... which sprintf then writes IN TO the string
called command_string
20
Example
  • include ltctype.hgt
  • include ltstdio.hgt
  • include ltstdlib.hgt
  • int main(void)
  • char command_string200, tmp_filename
  • int c
  • FILE ifp
  •   tmp_filename tmpnam(NULL)
    sprintf(command_string, "ls gt s",
    tmp_filename)
  • system(command_string) ifp
    fopen(tmp_filename, "r")while ((c getc(ifp))
    ! EOF)
  • putchar(toupper(c))remove(tmp_filename)
  • return 0

The command string ls gt temp.dat (or whatever)
is now sent to the system
21
Example
  • include ltctype.hgt
  • include ltstdio.hgt
  • include ltstdlib.hgt
  • int main(void)
  • char command_string200, tmp_filename
  • int c
  • FILE ifp
  •   tmp_filename tmpnam(NULL)
    sprintf(command_string, "ls gt s",
    tmp_filename)
  • system(command_string) ifp
    fopen(tmp_filename, "r")while ((c getc(ifp))
    ! EOF)
  • putchar(toupper(c))remove(tmp_filename)
  • return 0

Now we open the temporary file for reading, so we
can read the directory information from it
22
Example
  • include ltctype.hgt
  • include ltstdio.hgt
  • include ltstdlib.hgt
  • int main(void)
  • char command_string200, tmp_filename
  • int c
  • FILE ifp
  •   tmp_filename tmpnam(NULL)
    sprintf(command_string, "ls gt s",
    tmp_filename)
  • system(command_string) ifp
    fopen(tmp_filename, "r")while ((c getc(ifp))
    ! EOF)
  • putchar(toupper(c))remove(tmp_filename)
  • return 0

read from file one character at a time, convert
to uppercase and put out to the screen
23
Example
  • include ltctype.hgt
  • include ltstdio.hgt
  • include ltstdlib.hgt
  • int main(void)
  • char command_string200, tmp_filename
  • int c
  • FILE ifp
  •   tmp_filename tmpnam(NULL)
    sprintf(command_string, "ls gt s",
    tmp_filename)
  • system(command_string) ifp
    fopen(tmp_filename, "r")while ((c getc(ifp))
    ! EOF)
  • putchar(toupper(c))remove(tmp_filename)
  • return 0

delete the temporary file
24
Pipes
  • In Unix, you can use pipes to communciate
    directly with the operating system this avoids
    the need for the temporary file in the previous
    example. This example, uppercase2.c, is also from
    KP.
  • include ltctype.hgt
  • include ltstdio.hgt
  • int main(void)
  • int c
  • FILE ifp
  •  
  • ifp popen("ls", "r") / open pipe /
  • while ((c getc(ifp)) ! EOF)
  • putchar(toupper(c))
  • pclose(ifp)
  • return 0

25
Pipes
  • In Unix, you can use pipes to communciate
    directly with the operating system this avoids
    the need for the temporary file in the previous
    example. This example, uppercase2.c, is also from
    KP.
  • include ltctype.hgt
  • include ltstdio.hgt
  • int main(void)
  • int c
  • FILE ifp
  •  
  • ifp popen("ls", "r") / open pipe /
  • while ((c getc(ifp)) ! EOF)
  • putchar(toupper(c))
  • pclose(ifp)
  • return 0

Open a pipe to the operating system...
26
Pipes
  • In Unix, you can use pipes to communciate
    directly with the operating system this avoids
    the need for the temporary file in the previous
    example. This example, uppercase2.c, is also from
    KP.
  • include ltctype.hgt
  • include ltstdio.hgt
  • int main(void)
  • int c
  • FILE ifp
  •  
  • ifp popen("ls", "r") / open pipe /
  • while ((c getc(ifp)) ! EOF)
  • putchar(toupper(c))
  • pclose(ifp)
  • return 0

... only for reading ...
27
Pipes
  • In Unix, you can use pipes to communciate
    directly with the operating system this avoids
    the need for the temporary file in the previous
    example. This example, uppercase2.c, is also from
    KP.
  • include ltctype.hgt
  • include ltstdio.hgt
  • int main(void)
  • int c
  • FILE ifp
  •  
  • ifp popen("ls", "r") / open pipe /
  • while ((c getc(ifp)) ! EOF)
  • putchar(toupper(c))
  • pclose(ifp)
  • return 0

... and ask it to send a directory listing
28
Pipes
  • In Unix, you can use pipes to communciate
    directly with the operating system this avoids
    the need for the temporary file in the previous
    example. This example, uppercase2.c, is also from
    KP.
  • include ltctype.hgt
  • include ltstdio.hgt
  • int main(void)
  • int c
  • FILE ifp
  •  
  • ifp popen("ls", "r") / open pipe /
  • while ((c getc(ifp)) ! EOF)
  • putchar(toupper(c))
  • pclose(ifp)
  • return 0

read from the pipe one character at a time,
convert to uppercase and put out to the screen
29
Pipes
  • In Unix, you can use pipes to communciate
    directly with the operating system this avoids
    the need for the temporary file in the previous
    example. This example, uppercase2.c, is also from
    KP.
  • include ltctype.hgt
  • include ltstdio.hgt
  • int main(void)
  • int c
  • FILE ifp
  •  
  • ifp popen("ls", "r") / open pipe /
  • while ((c getc(ifp)) ! EOF)
  • putchar(toupper(c))
  • pclose(ifp)
  • return 0

... and close the pipe
30
Arguments to main( )
  • Two arguments, conventionally called argc and
    argv, can be used with main() to communicate with
    the operating system. argc counts the arguments
    (including the program name itself), and argv
    is an array of strings corresponding to the
    arguments. Filenames are often passed in this
    way. Example echoinput.c
  • / Echoing command line arguments... from
    KP/include ltstdio.hgtint main(int argc, char
    argv) int i printf("argc d\n",
    argc) for (i 0 i lt argc i)
    printf("argvd s\n", i, argvi) return
    0

31
Arguments to main( )
  • Two arguments, conventionally called argc and
    argv, can be used with main() to communicate with
    the operating system. argc counts the arguments
    (including the program name itself), and argv
    is an array of strings corresponding to the
    arguments. Filenames are often passed in this
    way. Example echoinput.c
  • / Echoing command line arguments... from
    KP/include ltstdio.hgtint main(int argc, char
    argv) int i printf("argc d\n",
    argc) for (i 0 i lt argc i)
    printf("argvd s\n", i, argvi) return
    0

argc is the number of arguments
32
Arguments to main( )
  • Two arguments, conventionally called argc and
    argv, can be used with main() to communicate with
    the operating system. argc counts the arguments
    (including the program name itself), and argv
    is an array of strings corresponding to the
    arguments. Filenames are often passed in this
    way. Example echoinput.c
  • / Echoing command line arguments... from
    KP/include ltstdio.hgtint main(int argc, char
    argv) int i printf("argc d\n",
    argc) for (i 0 i lt argc i)
    printf("argvd s\n", i, argvi) return
    0

argc is the number of arguments
argv are the arguments themselves e.g. if you
run program as echoinput file1 file2 then argc
will be 3 argv0 will be echoinput argv1
will be file1 argv2 will be file2
33
The C compiler
  • You are used to
  • cc filename.cto compile your programs.
    This uses the systems own C compiler. However,
    there are other compilers around one good one is
    gcc, the Gnu C compiler, provided by the Free
    Software Foundation.
  •  
  • Options include
  • -o output file name, which you are used to
  • -lm to include the maths library, which you
    normally do by default.
  • -E to see output from preprocessor only i.e.
    dont compile.
  • The compiler works in three stages it
    preprocesses (replacing the include, define
    etc) it compiles and then it links all of the
    pieces of code together into the executable
    program.
  • For a large program you often want to compile a
    small piece at a time, and link it to larger,
    pre-compiled parts. You can avoid the link, i.e.
    compile only, with
  • cc -c filename.cThis creates object files
    (whose names end in .o), which can then be linked
    as desired.

34
C Compiler Libraries
  • You can also create libraries, which are
    (generally large) collections of useful object
    code ready for linking, so you dont have to
    write the same bits of code over and over again
    for different programs that might use them. To
    do this with your set of .o files,
  • ar ruv g_lib.a gfopen.o gfclose.o
    gcalloc.o.......
  • This makes a library file called g_lib.a.

35
C Compiler Libraries
  • You can also create libraries, which are
    (generally large) collections of useful object
    code ready for linking, so you dont have to
    write the same bits of code over and over again
    for different programs that might use them. To
    do this with your set of .o files,
  • ar ruv g_lib.a gfopen.o gfclose.o
    gcalloc.o.......
  • This makes a library file called g_lib.a.

ar means archive
36
C Compiler Libraries
  • You can also create libraries, which are
    (generally large) collections of useful object
    code ready for linking, so you dont have to
    write the same bits of code over and over again
    for different programs that might use them. To
    do this with your set of .o files,
  • ar ruv g_lib.a gfopen.o gfclose.o
    gcalloc.o.......
  • This makes a library file called g_lib.a.  

ruv means replace, update, verbose
37
C Compiler Libraries
  • You can also create libraries, which are
    (generally large) collections of useful object
    code ready for linking, so you dont have to
    write the same bits of code over and over again
    for different programs that might use them. To
    do this with your set of .o files,
  • ar ruv g_lib.a gfopen.o gfclose.o
    gcalloc.o.......
  • This makes a library file called g_lib.a.  

g_lib.a is the output archive file name
38
C Compiler Libraries
  • You can also create libraries, which are
    (generally large) collections of useful object
    code ready for linking, so you dont have to
    write the same bits of code over and over again
    for different programs that might use them. To
    do this with your set of .o files,
  • ar ruv g_lib.a gfopen.o gfclose.o
    gcalloc.o.......
  • This makes a library file called g_lib.a.  

your object files to go in the library
39
C Compiler Libraries
  • You can also create libraries, which are
    (generally large) collections of useful object
    code ready for linking, so you dont have to
    write the same bits of code over and over again
    for different programs that might use them. To
    do this with your set of .o files,
  • ar ruv g_lib.a gfopen.o gfclose.o
    gcalloc.o.......
  • This makes a library file called g_lib.a. Follow
    this by
  • ranlib g_lib.a
  • which organises the file in a form that is useful
    for the linker.
  • To make the functions available to other
    programs, just compile as usual cc -o pgm
    main.c file1.c g_lib.a
  •  

40
C Compiler Libraries
  • You can also create libraries, which are
    (generally large) collections of useful object
    code ready for linking, so you dont have to
    write the same bits of code over and over again
    for different programs that might use them. To
    do this with your set of .o files,
  • ar ruv g_lib.a gfopen.o gfclose.o
    gcalloc.o.......
  • This makes a library file called g_lib.a. Follow
    this by
  • ranlib g_lib.a
  • which organises the file in a form that is useful
    for the linker.
  • To make the functions available to other
    programs, just compile as usual cc -o pgm
    main.c file1.c g_lib.a
  •  

g_lib.a is the output archive file that youve
just made.
41
C Compiler Profiler
  • The option -p activates the profiler when the
    compiled program is run, a file called mon.out is
    created, containing details of how much time was
    spent in each function, and how many times each
    function was called. You then use gprof prog.
    name to write these details onto the screen cc
    -p -o quicksort main.c quicksort.c
  • quicksort
  • gprof quicksort
  • Some of the functions that appear will be system
    calls.

42
Preprocessor
  • The preprocessor is very useful and powerful. A
    simple exampledefine DEBUG 1 /set debug to
    true at top of file/......if
    DEBUG printf(debug a d\n,
    a)endifBecause DEBUG has value 1, the printf
    statements will be compiled. When weve finished
    our debug procedure, we can turn off all such
    statements by setting DEBUG 0 at the start.
    You can deactivate and reactivate other chunks of
    code in the same way.
  • An alternative is ifdef DEBUG ....endifwhich
    will include the lines if DEBUG (or whatever) is
    defined at all at the top. There is also an
    ifndef, which includes lines if (whatever) is
    not defined. There is also an undef function to
    remove previous definitions, in order to prevent
    clashes.
  • To match the if, there is an else there is
    also elif, which is short for else if.

43
Preprocessor
  •  Two more examples of the use of the
    preprocessordefine SQ(x) ((x) (x))will
    replace, e.g., d/SQ(a b) by d/((a b) (a
    b)) . Note here that all of the parentheses are
    needed!
  • Anddefine min(x, y) (((x) lt (y)) ? (x) (y))
    will replace an expression such asm min(u,
    v)bym (((u) lt (v)) ? (u) (v))The arguments
    of m can be arbitrary expressions of comparable
    type.
  •  
  • Be warned, though debugging code that contains
    macros with arguments can be very difficult!

44
Writing large programs
  • A large program will normally be stored as a
    collection of .h and .C files in its own
    directory. If we are developing a program called
    pgm, we make a header file called pgm.h, and put
    it in a directory called pgm with all of the .C
    files. The .C files should then have
  • include pgm.h
  • at the top. pgm.h will contain includes,
    defines and a list of function prototypes.
  • Note that, when you make your own files to be
    included, the name goes in quotes rather than in
    lt gt. The compiler then knows that it should look
    in the current directory rather than the place
    that it expects to find the standard C header
    files.
  • There should also be a README file with text
    information about the program.
  • You then compile with the usual command, listing
    all of the .C files (but not the .h files, which
    are included automatically by the include
    preprocessor commands).
  • However...

45
Writing large programs, contd
  • Header files can create a problem. You often
    want to include the same header files in several
    different sourcecode files. When you compile
    them together, though, it complains because you
    have multiple definitions of the same functions
    etc. How do we get around this?
  • Let us assume we have a header file called
    MyHeaderFile1.h. You use the preprocessor
    directives define, ifndef if not defined as
    follows
  • ifndef MYHEADERFILE1define MYHEADERFILE1....
    everything you want goes here function
    prototypes, definitions and so on.... and at the
    end of the fileendif
  • Thus, the material in the file is only included
    if it hasnt been included already.

46
Next Lecture
  • Next weeks session will be essentially all
    exercise class rather than lecture. However, as
    an inducement to come, I plan to show you how to
    include some simple graphics...
Write a Comment
User Comments (0)
About PowerShow.com