CSM210: Systems Programming in C. Practical Session 2

Description

Modify strncpy.c, written for Practical 1 in the following ways. First, the source string will come from a file specified on the command line, or, if it is not specified, from standard input. Consequently, the program will be invoked by a.out n [filename]. n is the number of character to copy from filename to the target string. n can be converted to an integer using the C library function atoi().

Read the introduction to file handling for more information.

Once the program has been modified to take its input from a file, modify the program to perform its own dynamic memory management to allocate space for the target string.

See the introduction to dynamic memory management for more information.


Introduction to File Handling in C

Before a file can be read or written it must be opened by the library function fopen. fopen takes a filename and an open mode and returns a pointer to a location where data can be read from/written to.

The pointer returned by fopen is of type FILE - a structure declaration (e.g., FILE *fp).

The function prototype for fopen is

FILE*fopen(char *name, char *mode);
For example,
FILE *fp;

fp = fopen("a_file.txt", "r");
Some of the open modes are "r" to open a file for reading, "w" for writing, and "a" for apending.
Reading and Writing files
The simplest ways to read and write a file are as follows...
int getc(FILE *fp)

int putc(int c, FILE *fp)
Reading from standard input
C provides a pointer to buffer into which data from standard input will be read.

The pointer is called stdin.

We don't need to fopen stdin.

Simply get(stdin) ...

NOTE: stdin and fp are pointers to compatible structures...


Introduction to Dynamic Memory Management in C

There are 2 main things to remember when a program must manage its own memory for its data.

1. C must be asked for space.

2. The program must keep track of the space it is using.

Keeping track of space allocations
In order to keep track of the space that is being used to store dynamic variable length data, we need to record where in memory each piece of data is being stored. Invariably, this requires that each piece that makes up the data will also contain a pointer to the location where the next piece of data can be found.

In order to store a string one character at a time we must have a data structure which contains the character just read and a pointer to another location in memory where the next character to be read will be stored.

The following is an example of such a data structure:

struct string {
 char a;
 struct string *ptr;
} copy;
This defines a string data structure which is composed of a character and a pointer to a string structure. It also declares copy to be new string structure.

To traverse the structure it is necessary to start from the first item that was declared and subsequently use the pointer members of each item to traverse the rest of the linked list. The last item will have a null pointer.

Asking C for space
The malloc function can be used to ask C for space. malloc takes the amount of space required as a parameter, and returns a pointer to a free location in memory, or NULL if the request caot be granted. void *malloc(size_t n); The sizeof function can be used to determine how much space is required, e.g., malloc(sizeof(struct string)). From the function prototype for malloc we see that a pointer to void is returned, so this must be type cast as a pointer to the data type that we want to store in the location starting at pointer. (struct string *) malloc(sizeof(struct string)); Remember that C passes structures between functions by value, so to pass them by reference you must use & and the function definition of the called function must contain the struct keyword.

E.g.,

strmcpy(*fp, ©, n);

int strmcpy(FILE *fp struct string *copy, int n);

Reading the source string from a file

Adding Dynamic Memory Management