Week 6 Laboratory — Sample Solutions

  1. philatelic.c

    // philatelic.c: twice assign data to a struct and print
    #include <stdio.h>
    #include <stdlib.h>
    
    struct address {
      int number;
      char *street;
      char *city;
    };
    
    struct member {
      char *name;
      int phone;
      struct address addr;
    };
    
    int main(void) {
       struct member m, n;
       m.name = "Samuel Simon";
       m.phone = 9999999;
       m.addr.number = 20;
       m.addr.street = "Smith Street";
       m.addr.city = "Sydney";
       printf("Name: %s\n", m.name);
       printf("      Phone: %d\n", m.phone);
       printf("      Address: %d %s, %s\n", m.addr.number, m.addr.street, m.addr.city);
    
       n.name = "Louise Lion";
       n.phone = 9888888;
       n.addr.number = 81;
       n.addr.street = "Lyon Lane";
       n.addr.city = "Lismore";
       printf("Name: %s\n", n.name);
       printf("      Phone: %d\n", n.phone);
       printf("      Address: %d %s, %s\n", n.addr.number, n.addr.street, n.addr.city);
    
       return EXIT_SUCCESS;
    }
    

  2. security.c

    /* a file called database.txt stores all the user information for a top secret database.
       each line of the database corresponds to a single person and is of the following format
          lastname,firstname,year of birth,password,securityClearanceLevel,secret
       note that the fields in the database are separated by columns.
       for example, the first few lines of the database file may look like this:
          Dracula Martin 1285 i_am_undead top is actually a vampire
          Gregorius Abdul 1953 password123 high has broken his leg while tap dancing
          Pham Fei 1985 wordpass098 none second cousin of chuck norris
       Your task is to write a program, security.c, which reads in the data from this database
       and stores it in an appropriate way.
       You are then to ask the user for a username and password. a username is a persons
       first name and last name concatenated together, eg "MartinDracula".
       you are also to ask the user for a password.
       you can assume that no one in the database has the same name. you can also assume that
       the database is correct, and all fields have proper values, etc. you can assume that the
       longest line in the file is no more than 90 characters long and the database does not contain
       more than 1000 people
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define DATABASE_FILE "database.txt"
    #define DATABASE_DELIMITER ','
    #define MAX_LINE_LENGTH 100
    #define MAX_DATABASE_LENGTH 1000
    #define TRUE 1
    #define FALSE 0
    
    typedef enum {none,high,top} Clearance;
    
    void chomp(char *string);
    
    Clearance convertClearance(char *clearance);
    
    typedef struct person {
       char *firstName;
       char *lastName;
       int age;
       Clearance level;
       char *password;
       char *secret;
    } person;
    
    int main(int argc, char *argv[]) {
       int retval = EXIT_SUCCESS;
    
       // open database file
       FILE *file = fopen(DATABASE_FILE, "r");
       if (file == NULL) {
          fprintf(stderr, "could not open file");
          retval = EXIT_FAILURE;
       } else {
          person people[MAX_DATABASE_LENGTH];
          int count = 0;
          char firstName[MAX_LINE_LENGTH];
          char lastName[MAX_LINE_LENGTH];
          int age;
          char clearance[MAX_LINE_LENGTH];
          char password[MAX_LINE_LENGTH];
          char secret[MAX_LINE_LENGTH];
    
          // read entire databas into the people array
          while (fscanf(file,"%s %s %d %s %s ", lastName, firstName, &age, password, clearance) != EOF) {
             if (fgets(secret, MAX_LINE_LENGTH, file) != NULL) {
                // lastname
                people[count].lastName = (char *)malloc(sizeof(char) * strlen(lastName) + 1);
                strcpy(people[count].lastName, lastName);
                // firstname
                people[count].firstName = (char *)malloc(sizeof(char) * strlen(firstName) + 1);
                strcpy(people[count].firstName, firstName);
                // age
                people[count].age = age;
                // clearance
                people[count].level = convertClearance(clearance);
                // password
                people[count].password = (char *)malloc(sizeof(char) * strlen(password) + 1);
                strcpy(people[count].password, password);
                // secret
                chomp(secret);
                people[count].secret = (char *)malloc(sizeof(char) * strlen(secret) + 1);
                strcpy(people[count].secret, secret);
                count++;
             } else {
                fprintf(stderr, "error reading file\n");
                retval = EXIT_FAILURE;
             }
          }
          fclose(file);
       }
    
       if (retval == EXIT_SUCCESS) {
          printf("username: ");
          if (fgets(firstName, MAX_LINE_LENGTH, stdin) != NULL) {
             chomp(firstName);
          }
          printf("password: ");
          if (fgets(password, MAX_LINE_LENGTH, stdin) != NULL) {
             chomp(password);
          }
    
          int i;
          int found = FALSE;
          for (i = 0; i < count && !found; i++) {
             char username[MAX_LINE_LENGTH] = "";
             strcat(username, people[i].firstName);
             strcat(username, people[i].lastName);
             printf("%s =?= %s\n", username, firstName);
             if (strcmp(username, firstName) == 0 &&
                 strcmp(password, people[i].password) == 0) {
                printf("correct username + password entered\n");
                found = TRUE;
                int j;
                for (j = 0; j < count; j++) {
                   if (people[j].level < people[i].level) {
                      printf("%s's secret is '%s'\n", people[j].firstName, people[j].secret);
                   }
                }
             }
          }
    
          if (!found) {
             printf("you did not enter a correct username/password combination\n");
          }
       }
       return retval;
    }
    
    // removes the newline, if it exists
    void chomp(char *string) {
       if (string[strlen(string) - 1] == '\n') {
          string[strlen(string) - 1] = '\0';
       }
    }
    
    // converts a string
    Clearance convertClearance(char *clearance) {
       Clearance c;
       if (strcmp("high", clearance) == 0) {
          c = high;
       } else if (strcmp("top", clearance) == 0) {
          c = top;
       } else {
          c = none;
       }
       return c;
    }
    

  3. colours.c

    // colours.c: print the favourite colours of a group of people
    //            from a data file. Colours are coded as integers:
    //            0=cyan, 1=pink, 2=green, 3=red, 4=yellow, 5=blue, 6=unknown
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #define NAMLEN 50
    
    typedef struct {
       char name[NAMLEN];
       int colour;
    } Preferences;
    
    char *Colour[] = {"cyan", "pink", "green", "red", "yellow", "blue", "unknown"};
    
    int main(int argc, char *argv[]) {
       Preferences *member;
       int number;
       int retval = EXIT_SUCCESS;
    
       if (scanf("%d", &number) != 1) {
          fprintf(stderr, "Missing number in data file\n");
          retval = EXIT_FAILURE;
       } else {
          member = (Preferences *)malloc(number * sizeof(Preferences));
          assert(member != NULL);
    
          int dataGood = 1;
          int i;
          for (i=0; i<number && dataGood; i++) { // this uploads the heap from stdin
             if (scanf("%s %d", member[i].name, &member[i].colour) != 2) {
                dataGood = 0;
                fprintf(stderr, "Error in data file\n");
                retval = EXIT_FAILURE;
             }
          }
          if (dataGood) {
             for (i=0; i<number; i++) { // this prints each struct on the heap
                printf("%s likes %s\n", member[i].name, Colour[member[i].colour]);
             }
          }
          free(member);
       }
       return retval;
    }