Homework • Introduction to HW7 – Complexity similar to HW6

advertisement
Homework
• Introduction to HW7
– Complexity similar to HW6
– Don’t wait until last minute to start on it
• File Access will be needed in HW8
1
Intro to Homework 7
• Data Structures behind the “Mapping”
Maplist L
char *key
int length
char *data
Block *head
Block *next
Block *tail
char *key
char *data
Block *next
“”
“”
All “real” Blocks
Are linked in here
“”
“”
NULL
2
Intro to Homework 7
• Why include the fake head and tail Blocks?
• So that we can use a pointer to the Block
previous to the Block that we are accessing
• For example: Deleting a Block from the list:
if(strcmp(bptr->next->key, key) == 0) {
sptr = bptr->next;
bptr->next = bptr->next->next;
free((void *)sptr->key);
free((void *)sptr->data);
free((void *)sptr);
}
3
Intro to Homework 7
• If we didn’t do that, we would need to either:
– Use a doubly linked list so that we could back up
to remove a Block from the linked list
OR
– Save a pointer to the previous Block as we moved
down the linked list so that we could back up to
remove a Block from the linked list
• Both of these solutions can be made to work,
but are a bit “messy” by comparison
4
File Access, K&R 7.5
• Dealing with named files is surprisingly similar to
dealing with stdin and stdout.
• Start by declaring a "file pointer":
FILE *fp;
/* See Appendix B1.1, pg. 242 */
• <stdio.h> header contains a structure definition
with typedef name FILE that contains component
variables (buffer, etc.) used in file I/O
• You don't need to know the details of these structs
to use simple file I/O
• Use standard file access functions such as fopen()
5
File Access
• To open a file
• Function prototype fopen :
FILE * fopen(const char *name, const char * mode);
• To ask fopen to open file (character string "name") in
a particular "use mode".
fp = fopen(name, mode)
• fp is the return value: set to NULL if fopen fails
• Legal “use mode” values: "r" for read, "w" for write,
and "a" for append
6
File Access
• An "r" mode file can be used like stdin
• Function prototype getc:
int getc(FILE *stream);
• To get a char from an "r" file
c = getc(fp);
• c is the return value:
Return value is the character read from the file OR
Set to EOF if getc fails
7
File Access
• A “w“ or “a" mode file can be used like stdout
• Function prototype putc:
int putc(int c, FILE *stream);
• To put a character to a “w” or “a” file
status = putc(c, fp)
• Return value: set to EOF if putc fails
8
File Access
• When we fopen a file in "w" or "a" mode:
• If the file does not already exist, it will be
created (like the vi editor creates a new file).
• If the file does already exist, then "w" mode
fopen will destroy the old contents (like the
command mv) and "a" mode will append new
contents to the end of the existing file (like
"save" command in mail).
9
File Access
• When you have finished reading from a file
or writing to a file, call fclose to close the file
status = fclose(fp);
• Function prototype:
int fclose(FILE *stream);)
• Function fclose( ) returns:
Zero for success OR
EOF if an error occurs
10
File Access
• Every file open requires resources and there is a limit
on number of files open at any one time
– close each fp when done using it
– close all files before program termination
• FILE structure has a buffer for disk data in memory
• When putc returns data may not get written to file
THE DATA IS NOT SAFELY ON DISK YET!
• Functions fclose( ) and fflush( ) flush buffer to disk
11
File Access
• When a C program is started, the operating system
opens three files and provides file pointers (FILE *)
to them: stdin, stdout, and stderr
• We can now define getchar and putchar as macros:
#define getchar( ) getc(stdin)
#define putchar(c) putc((c), stdout) /* why (c) in parens? */
• Other file oriented analogs for input / output
functions:
int fscanf(FILE *fp, char *format, . . .); /* mode must be "r"
int fprintf(FILE *fp, char *format, . . .); /* mode "w" or "a"
12
Error Handling
• Trying to read a file that does not exist is an error,
• There are other errors as well: reading or writing a
file without appropriate permission
• There are three streams opened by the O/S when a
program begins execution, stdin, stdout, and stderr.
• stderr usually goes to the screen even if stdout is
redirected to a file
prog . . . >outfile
prog . . . >&outfile
prog . . . >>outfile
/* redirect stdout; overwrite */
/* redirect stdout and stderr */
/* redirect stdout; append
*/
13
Error Handling
• How to write a program so error msgs go to stderr?
char *prog = argv[0];
/* pick up command name */
if ((fp = fopen(*++argv, "r")) == NULL) {
fprintf(stderr, "%s: can't open %s\n", prog, *argv);
exit(1);
}
• Variable prog is a pointer to char array containing
the command name used to invoke this program and
*argv is a pointer to char array containing the file
name that couldn’t be opened
14
Error Handling
• The exit(int) function (arg: 0-255) terminates
program execution and returns argument to
invoking process (debugger, shell, fork parent)
• Of course, a "return value" from main program
would do this as well, but exit() will terminate
execution as if we executed a return from main(),
and can be called from anywhere in program!
• A zero returned by a program means no error
• You can use conventions for meaning of non-zero
values - best to keep the values positive
15
Error Handling
• To show how the return value may be used:
• UNIX conditional sequence &&
% gcc myprog.c && a.out
Second program executes only if first returns == 0
• UNIX conditional sequence ||
% gcc myprog.c || echo compilation failed
Second program executes only if first returns != 0
16
Error Handling
• Note a problem with program on pg. 163
• To handle errors, should use:
#include <errno.h>
• The function ferror() tells us the last error
that occurred for a stream
if (ferror(stdout)) {
fprintf(stderr, “%s: error writing stdout\n”, prog);
exit(2);
}
17
Error Handling
• If not exiting, to avoid retaining a stale error
value from a previous failed operation, use:
void clearerr(FILE *stream);
• Example:
clearerr(stdout);
18
Error Handling
• More generally, errno.h contains a macro "errno"
that can be tested; it is zero if there is no problem
and non-zero otherwise
• Text in B1.7 says errno "may" contain an error
number; it will contain one if there has been an
error—any error, not just in a stream—unless the
error is so serious it corrupted the error structs
• We can use the function perror to write out the
error msg associated with errno, but we have to
test for error right after it occurs to get right one
19
Error Handling
• We can use the function perror to write out standard
error message associated with errno, but we have to
test for error right after it occurs to get correct one
if (errno != 0) {
perror("Error at myprog: exiting.");
exit(2);
}
• perror will print out a standard error message
corresponding to integer in errno, as if by:
fprintf(stderr, "%s: %s\n", s, "error message");
20
Download