We have created some scripts that can automatically run your program against some tests. To run these tests you can execute the dry run program with an argument that corresponds to the lab and week, i.e. lab06 for this week. It expects to find all the programs to be submitted as part of this lab in the current directory. You can use dry run as follows:
prompt$ ~cs1921/bin/dryrun lab06 |
or specific tests (e.g. test #2) as follows:
prompt$ ~cs1921/bin/dryrun lab06 2 |
Exercises
Just 3 exercises this week.
- Write a program called colours.c that reads a sequence of people's names and integers from stdin into an array of structs. The array must be dynamic (and hence may not be fixed length). A struct here has the form:
#define NAMLEN 50typedef struct { char name[NAMLEN]; int colour;} Preferences;
0=cyan, 1=pink, 2=green, 3=red, 4=yellow, 5=blue, 6=unknown
You may use the following test data:
20Xiang 5Bin 1Navid 0Abdul 1Ming-Tak 5Surya 2Jingxu 3Lasit 2Yi 4Ghit-Hong 6John 3Nam-Thanh 3Jian 0Kuninda 1Wenxi 6Wenfei 4Fei 1Xiaotian 0Ke 2Ge 6
Notice that the first line of this data indicates the number of people. The output for this test data should be:
Xiang likes blueBin likes pinkNavid likes cyanAbdul likes pinkMing-Tak likes blueSurya likes greenJingxu likes redLasit likes greenYi likes yellowGhit-Hong likes unknownJohn likes redNam-Thanh likes redJian likes cyanKuninda likes pinkWenxi likes unknownWenfei likes yellowFei likes pinkXiaotian likes cyanKe likes greenGe likes unknown
Note:
- the only fixed-length array that you should use is in the struct definition
- you should use an array of structs to store the data
- the array should be dynamic
- be sure your program works for an empty input or if the first line is not numeric: it should write to stderr:
- be sure your program works if the data is in the wrong format or if there is data missing: it should write to stderr:
- be sure your program works when the given number is 0 (it should produce no output)
Missing number in data file
Error in data file
-
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
There are only 3 possible values for securityClearanceLevel, namely, none, high and top. For example, the first few lines of the database.txt file may look like this
Dracula Martin 1285 i_am_undead top is actually a vampireGregorius Abdul 1953 password123 high has broken his leg while tap dancingPham Fei 1985 wordpass098 none second cousin of chuck norris
A sample run of the program would look like this:
$ gcc -Wall -Werror -O -o security security.c$ ./securityusername: MartinDraculapassword: i_am_undeadcorrect username/password enteredAbdul's secret is 'has broken his leg while tap dancing'Fei's secret is 'second cousin of chuck norris'$ ./securityusername: AbdulGregoriuspassword: wrongpasswordyou did not enter a correct username/password combination
Assumptions:
- no two people in the database have the same name.
- the database.txt is correct, and all fields have proper values
- longest line in the file is no more than 90 characters long
- the database.txt file 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 100#define TRUE 1#define FALSE 0void chomp(char* string);typedef struct person { char* firstName; char* lastName; // TODO add something for clearance level here perhaps? int age; char* password; char* secret;} person;int main(int argc, char* argv[]) { // open database file FILE* file = fopen(DATABASE_FILE, "r"); if (file == NULL) { fprintf(stderr, "could not open file"); return EXIT_SUCCESS; } 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 database 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 = malloc(sizeof(char) * strlen(lastName) + 1); strcpy(people[count].lastName, lastName); // firstname people[count].firstName = malloc(sizeof(char) * strlen(firstName) + 1); strcpy(people[count].firstName, firstName); // age people[count].age = age; // clearance ////////////////////////////////////////// // TODO you need to write some code here// ////////////////////////////////////////// // password people[count].password = malloc(sizeof(char) * strlen(password) + 1); strcpy(people[count].password, password); // secret chomp(secret); people[count].secret = malloc(sizeof(char) * strlen(secret) + 1); strcpy(people[count].secret, secret); count++; } else { fprintf(stderr, "error reading file\n"); } } fclose(file); ////////////////////////////////////////// // TODO you need to write some code here// ////////////////////////////////////////// return EXIT_SUCCESS;}// removes the newline, if it existsvoid chomp(char* string) { if (string[strlen(string) - 1] == '\n') { string[strlen(string) - 1] = '\0'; }}
-
Write a program called llbuild.c that builds a linked list from user input. The only functions that you may call are:
- NodeT *makeNode(int value): taken from the lecture
- void freeList(NodeT *head): take from the lecture
- void printList(NodeT *head): take from the lecture, needs modification
- NodeT *joinList(NodeT *head1, NodeT *head2): joins 2 linked lists head1 and head2. Needs to be implemented.
The program:
- starting with an initially NULL linked list called all (say)
- prompts the user with the message "Enter a number: "
- makes a linked list node called new from user's response
- joins the nodes all and new
- asks for more user input and repeats the cycle
- the cycle is terminated when the user enters any non-numeric character
- on termination the program generates the message "Finished: list is " followed by the contents of the linked list
- if the user has entered no data, then the message is simply "Finished"
A sample interaction is:
prompt$ ./llbuildEnter an integer: 12Enter an integer: 34Enter an integer: 56Enter an integer: quitFinished: list is 12->34->56
Note that any non-numeric data 'finishes' the interaction:
prompt$ ./llbuildEnter an integer: 100Enter an integer: byeFinished: list is 100
A longer interaction:
prompt$ ./llbuildEnter an integer: 421Enter an integer: 456732Enter an integer: 321Enter an integer: 4Enter an integer: 86Enter an integer: 89342Enter an integer: 9Enter an integer: #Finished: list is 421->456732->321->4->86->89342->9
If the user provides no data, then no list is output:
prompt$ ./llbuildEnter an integer: coffeeFinished
Note, please ensure:
- the linked list all is initially NULL