The University of Western Australia
CITS2002 Systems Programming
 

Department of Computer Science and Software Engineering

CITS2002 Systems Programming

Solutions for Labsheet 5 - for the week commencing 23rd September 2019

Exercises

  1. Write a function named money that accepts a single integer parameter that represents a total number of cents, and breaks the total down into its numbers of dollars and cents. Your function should calculate the number of dollars, and the number of "left-over" cents, and provide these to its calling function through its parameters. For example, a value of 524 should be "returned" as 5 dollars and 24 cents.

    Your function should have the prototype:

         void money(int total, int *dollars, int *cents);

    and be called as:

         money(524, &dollars, &cents);

    void money(int total, int *dollars, int *cents)
    {
        *dollars = total / 100;
        *cents   = total % 100;
    }
    

  2. String functions.

    strcat:
    //  The strcat() function implemented using arrays 
    
    char *strcat_a(char dest[], char src[])
    {
        char        *orig   = dest;
        int         d=0, s=0;
    
        while(dest[d] != '\0') {
            ++d;
        }
        while(src[s] != '\0') {
            dest[d] = src[s];
            ++s;
            ++d;
        }
        dest[d]     = '\0';
    
        return orig;
    }
    
    //  The strcat() function re-implemented using pointers
    
    char *strcat_p(char *dest, char *src)
    {
        char        *orig   = dest;
    
        while(*dest != '\0') {
            ++dest;
        }
        while(*src != '\0') {
            *dest   = *src;
            ++dest;
            ++src;
        }
    
        return orig;
    }
    

    strcmp:
     //  The strcmp() function implemented using arrays
    
    int strcmp_a(char s1[], char s2[])
    {
        int	i=0;
    
        while(s1[i] != '\0' && s1[i] == s2[i]) {
    	++i;
        }
    
        return (s2[i] - s1[i]);
    }
    
    //  The strcmp() function re-implemented using pointers
    
    int strcmp_p(char *s1, char *s2)
    {
        while(*s1 != '\0' && *s1 == *s2) {
    	++s1;
    	++s2;
        }
    
        return (*s2 - *s1);
    }
    

    strncmp:
    //  The strncmp() function implemented using arrays
    
    int strncmp_a(char s1[], char s2[], size_t n)
    {
        int	i=0;
    
        while(n > 0 && s1[i] != '\0' && s1[i] == s2[i]) {  
    	++i;
    	--n;
        }
    
        return (s2[i] - s1[i]);
    }
    
    // The strncmp() function re-implemented using pointers
    
    int strncmp_p(char *s1, char *s2, size_t n)
    {
        while(n > 0 && *s1 != '\0' && *s1 == *s2) {
    	++s1;
    	++s2;
    	--n;
        }
    
        return (*s2 - *s1);
    }
    

    strrchr:
    //  The strrchr() function implemented using arrays
    
    #define	NOTFOUND	(-1)
    char *strrchr_a(char s1[], int ch)
    {
        int		i=0, found = NOTFOUND;
    
        while(s1[i] != '\0') {
    	if(s1[i] == ch)
    	    found	= i;
    	++i;
        }
    
        if(found == NOTFOUND) {
    	return NULL;
        }
        else {
    	return &s1[found];
        }
    }
    #undef	NOTFOUND
    
    // The strrchr() function re-implemented using pointers
    
    char *strrchr_p(char *s1, int ch)
    {
        char	*found = NULL;
    
        while(*s1 != '\0') {
    	if(*s1 == ch)
    	    found	= s1;
    	++s1;
        }
    
        return found;
    }
    

  3. 🌶 Write a filter program named reverse, which prints out the lines of a text file in reverse order - the last line is printed first, and the first line is printed last. Ensure that your program can operate on files named on the command-line, and from text lines arriving via stdin.

    //  A SOLUTION USING DYNAMIC MEMORY ALLOCATION
    void reverse1(FILE *fp)
    {
        char        **lines = NULL;         // pointer to a vector of lines
        int         nlines  = 0;            // number of lines in file
        char        line[BUFSIZ];           // holds each line of the file
    
    //  READ LINES FROM FILE, EXTEND THE VECTOR OF LINES, DUPLICATE CURRENT LINE
        while(fgets(line, sizeof line, fp) != NULL) {
            lines         = realloc(lines, (nlines+1) * sizeof(lines[0]));
    
            if(lines == NULL) {             // was allocation successful?
                fprintf(stderr, "realloc() failed\n");
                exit(EXIT_FAILURE);
            }
    
            lines[nlines] = strdup(line); // save copy of current line
    
            if(lines[nlines] == NULL) {   // was allocation successful?
                fprintf(stderr, "strdup() failed\n");
                exit(EXIT_FAILURE);
            }
            ++nlines;
        }
    
    //  PRINT THE LINES IN THEIR REVERSE ORDER
        for(int i=nlines-1 ; i>= 0 ; --i) {
            printf("%s", lines[i]);
        }
    
    //  DEALLOCATE THE MEMORY HOLDING THE LINES
        for(int i=0 ; i<nlines; ++i) {
            free(lines[i]);
        }
        free(lines);
    }
    
    //  A SOLUTION USING RECURSION
    void reverse2(FILE *fp)
    {
        char line[BUFSIZ];
    
        if(fgets(line, sizeof line, fp) != NULL) {
            reverse2(fp);
            fputs(line, stdout);
        }
    }
    
    int main(int argc, char *argv[])
    {
    //  ATTEMPT TO OPEN AND READ FROM PROVIDED FILENAME
        if(argc > 1) {
            FILE *fp = fopen(filename, "r");
    
            if(fp == NULL) {
                fprintf(stderr, "cannot open %s\n", filename);
                exit(EXIT_FAILURE);
            }
            reverse1(fp);
    	rewind(fp);      //  works with files, but not with stdin
            reverse2(fp);
            fclose(fp);
        }
    //  NO FILENAME PROVIDED, READ FROM STANDARD-INPUT
        else {
            reverse1(stdin);
        }
        return 0;
    }
    

  4. Locate a single-file program consisting of several functions, such as the one developed in Workshop-3.

    Now, break the single-file program into a multi-file project consisting of:

    • a single C header file (providing the function declarations), and
    • several C source code files (with each C file providing at least one function definition).

    Next, develop a simple Makefile, as introduced in Lecture-12, to compile and link your multi-file project using make.

    Determine how to test that your Makefile correctly represents the dependencies between your source and header files.

    Extend your Makefile by adding a new target to cleanup (remove) any unnecessary files (careful!).

    A sample solution: haversine-project.zip

  5. Rewrite the sample solution for the 1st project using structures.

  6. sortPointers()

Department of Computer Science and Software Engineering

This Page

Written by: Chris.McDonald@uwa.edu.au