coursework/src/program.c
The original C source
All 347 lines of the submitted program, exactly as recovered. The skeleton functions came from the teaching staff; the five stages and the string comparison are mine. Every web feature on this site is a port of the functions below.
/* Emoticon message cleanser: * * Skeleton code written by Farhana Choudhury and Jianzhong Qi, April 2020 * */ #include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h> #define STAGE_NUM_ONE 1 /* stage numbers */#define STAGE_NUM_TWO 2#define STAGE_NUM_THREE 3#define STAGE_NUM_FOUR 4#define STAGE_NUM_FIVE 5#define STAGE_HEADER "Stage %d\n==========\n" /* stage header format string */ #define MAX_MSG_LENGTH 280 /* maximum message length */#define MAX_NUM_MSGS 100 /* maximum number of messages */#define MAX_EMTCN_LENGTH 50 /* maximum emot. line length */#define MAX_NUM_EMTCN 50 /* maximum number of emot. */ typedef char msg_t[MAX_MSG_LENGTH+1]; /* a message */typedef char emtcn_t[MAX_EMTCN_LENGTH+1]; /* an emoticon */ /****************************************************************/ /* function prototypes */void read_one_msg(msg_t one_msg, int max_len);void print_stage_header(int stage_num);int count_tokens(msg_t one_msg); void stage_one(msg_t one_msg);void stage_two(msg_t msgs[], int *num_msgs);void stage_three(msg_t msgs[], int num_msgs);void stage_four(emtcn_t emtcns[], int *num_emtcns);void stage_five(msg_t msgs[], int num_msgs, emtcn_t emtcns[], int num_emtcns); /* add your own function prototypes here */// check emotion in the dictionaryint emotionexisitence(char string1[], char string2[]); /****************************************************************/ main()Fixed driver: calls the five stages in order
skeleton/* main function controls all the action, do NOT modify this function */int main(int argc, char *argv[]) { /* to hold all input messages */ msg_t msgs[MAX_NUM_MSGS]; /* to hold the number of input messages */ int num_msgs = 0; /* to hold all input emoticons in the dictionary */ emtcn_t emtcns[MAX_NUM_EMTCN]; /* to hold the number of emoticons in the dictionary */ int num_emtcns = 0; /* stage 1: reading the first message */ stage_one(msgs[num_msgs]); num_msgs++; /* stage 2: removing alphanumeric characters */ stage_two(msgs, &num_msgs); /* stage 3: removing extra commas */ stage_three(msgs, num_msgs); /* stage 4: reading the dictionary and finding the longest emoticon */ stage_four(emtcns, &num_emtcns); /* stage 5: removing invalid emoticons with the help of the dictionary */ stage_five(msgs, num_msgs, emtcns, num_emtcns); /* all done; take some rest */ return 0;} read_one_msg()Reads one line from stdin with a length limit
skeleton/* read a line of input into one_msg */void read_one_msg(msg_t one_msg, int max_len) { int i = 0, c; while (((c = getchar()) != EOF) && (c != '\n') && (c != '\r')) { if (i < max_len) { one_msg[i++] = c; } else { printf("Invalid input line, toooooooo long.\n"); exit(EXIT_FAILURE); } } one_msg[i] = '\0';} print_stage_header()Prints the stage banner
skeleton/* print stage header given stage number */void print_stage_header(int stage_num) { printf(STAGE_HEADER, stage_num);} /****************************************************************/ count_tokens()Counts commas to count tokens
stage 1 · Count/* scan a message and count the number of tokens (separated by commas) in it */int count_tokens(msg_t one_msg) { int count = 0; // store number of tokens // condition check: if a line start with commas if (one_msg[0] == ',') { for (int i = 0; i < MAX_EMTCN_LENGTH; i++) { if (one_msg[i] == ',') { count++; } } return count; } // condition check: if a line does not start with commas else { for (int i = 0; i < MAX_EMTCN_LENGTH; i++) { if (one_msg[i] == ',') { count++; } } return 1 + count; }} stage_one()Reads the first message
stage 1 · Count/* stage 1: reading the first message */void stage_one(msg_t one_msg) { /* print stage header */ print_stage_header(STAGE_NUM_ONE); /* read the first message */ read_one_msg(one_msg, MAX_EMTCN_LENGTH); /* count and print the number of tokens */ printf("Number of tokens: %d\n", count_tokens(one_msg)); printf("\n");} stage_two()Reads messages and strips letters and digits
stage 2 · Strip/* stage 2: removing alphanumeric characters */void stage_two(msg_t msgs[], int *num_msgs) { /* print stage header */ print_stage_header(STAGE_NUM_TWO); /* hold temporary msgs */ msg_t tmp_msgs[MAX_NUM_MSGS]; /* start read message & stop while meet the break line */ for (int i = 1; i < MAX_NUM_MSGS; i++) { read_one_msg(tmp_msgs[*num_msgs], MAX_MSG_LENGTH); if (strcmp(tmp_msgs[*num_msgs], "###") == 0) { break; } /* if not meet the break line, update the line */ strcpy(msgs[*num_msgs], tmp_msgs[*num_msgs]); *num_msgs = *num_msgs + 1; } /* create a new 2D array to store lines without alphanumeric characters */ msg_t remove_alphanum[MAX_NUM_MSGS]; for (int i = 0; i < *num_msgs; i++) { int count = 0; // string index in 2D array with index[i] int lenstr = strlen(msgs[i]); // current string length for (int j = 0; j < lenstr; j++) { // append the punctuation if (ispunct(msgs[i][j])) { remove_alphanum[i][count] = msgs[i][j]; count++; } } // update new string; strcpy(msgs[i], remove_alphanum[i]); } /* print out the outcome */ for (int i = 0; i < *num_msgs; i++) { printf("%s\n", msgs[i]); } printf("\n");} stage_three()Removes leading, trailing and repeated commas
stage 3 · Commas/* stage 3: removing extra commas */void stage_three(msg_t msgs[], int num_msgs) { /* print stage header */ print_stage_header(STAGE_NUM_THREE); // create a temporary 2D array to store new string without extra commas msg_t tmp_msgs[num_msgs]; for (int i = 0; i < num_msgs; i++) { int start = 1; // condition start as a new line int count = 0; // index of a string where string is 2D array[i] int lenstr = strlen(msgs[i]); for (int j = 0; j < lenstr; j++) { // remove the commas before the first characters if (start == 1 && msgs[i][j] != ',') { tmp_msgs[i][count] = msgs[i][j]; count++; // index of 2D array [i] start = 0; // while meet the first character } else { // append all characters if (msgs[i][j] != ',') { tmp_msgs[i][count] = msgs[i][j]; count++; // append commas if the next item is a character not a punctuation // && not the end of the string } else if (count != 0 && tmp_msgs[i][count - 1] != ',' && msgs[i][j + 1] != ',' && (j != lenstr - 1)) { tmp_msgs[i][count] = msgs[i][j]; count++; } } } tmp_msgs[i][count] = '\0'; } // update new string into msgs for (int i = 0; i < num_msgs; i++) { strcpy(msgs[i], tmp_msgs[i]); printf("%s\n", msgs[i]); } printf("\n");} stage_four()Reads the dictionary and finds the longest emoticon
stage 4 · Dictionary/* stage 4: reading the dictionary and finding the longest emoticon */void stage_four(emtcn_t emtcns[], int *num_emtcns) { /* print stage header */ print_stage_header(STAGE_NUM_FOUR); // create temporary list to store emotion emtcn_t tmp_emtcns[MAX_EMTCN_LENGTH]; for (int i = 0; i < MAX_EMTCN_LENGTH; i++) { // read emotion and update to temporary emotion list read_one_msg(tmp_emtcns[*num_emtcns], MAX_EMTCN_LENGTH); // break while meet the EOF if (strcmp(tmp_emtcns[*num_emtcns], "") == 0) { break; } *num_emtcns = *num_emtcns+1; } // remove commas and characters for (int i = 0; i <* num_emtcns; i++) { int isComma = 0, lenstr = strlen(tmp_emtcns[i]); for (int j = 0;j < lenstr; j++) { // condition check the current character if (tmp_emtcns[i][j] == ',') { isComma = 1; } // stop append while meet commas if (isComma == 0) { emtcns[i][j] = tmp_emtcns[i][j]; } } } int longEmotionLen = 0, emotionIndex = 0; /* find the longest emotion */ for (int i = 0; i <* num_emtcns; i++) { int lenstr = strlen(emtcns[i]); if (lenstr > longEmotionLen) { emotionIndex = i; longEmotionLen = strlen(emtcns[i]); } } printf("Emoticon total: %d\n", *num_emtcns); printf("Longest: %s\n", emtcns[emotionIndex]); printf("Length: %d\n", longEmotionLen); printf("\n");} emotionexisitence()Hand-written string equality (no string.h)
stage 5 · Validate// check in emtion in the dictionaryint emotionexisitence(char string1[], char string2[]){ int i = 0, issame = 0; while (string1[i] != '\0' && string2[i] != '\0') { if (string1[i] != string2[i]) { issame = 1; break; } i++; } if (issame == 0 && string1[i] == '\0' && string2[i] == '\0') { return 1; } else { return 0; }} stage_five()Tokenises messages and drops unknown emoticons
stage 5 · Validate/* stage 5: removing invalid emoticons with the help of the dictionary */void stage_five(msg_t msgs[], int num_msgs, emtcn_t emtcns[], int num_emtcns) { /* print stage header */ print_stage_header(STAGE_NUM_FIVE); // a new list to store word in msgs[] char list[MAX_NUM_EMTCN][MAX_EMTCN_LENGTH]; // count the number of emotions in emotion list int count = 0; // state the position and string index of each emotion in msgs[] int node = 0, index = 0; for (int i = 0; i < num_msgs; i++) { int strlength = 0; // gain the length of each string for (int k = 0; k < MAX_MSG_LENGTH; k++) { if (msgs[i][k] == '\0') { break; } strlength++; } // separating emotion in msgs[] into a new list for (int j = 0; j < strlength; j++) { if (msgs[i][j] != ',') { list[node][index] = msgs[i][j]; index++; } else if (msgs[i][j] == ',') { list[node][index]='\0'; node++; count++; list[node][0]=','; list[node][1]='\0'; index=0; node++; count++; } if (j == strlength - 1) { list[node][index]='\0'; node++; count++; list[node][0] = '\n'; list[node][1] = '\0'; node++; index=0; count++; } } } // record last emotion comparison status int lastemtionrecord = 0; // comparing each emotion with emotion dictionary for (int i = 0; i < count-1; i++) { int isEmotion = 0; for (int j = 0; j < num_emtcns; j++) { // condition: word is in emotion dictionary if (emotionexisitence(list[i], emtcns[j]) == 1 || list[i][0] == ',') { isEmotion =1; } } // print the results if (isEmotion == 1 && list[i][0] != '\n') { printf("%s", list[i]); } if (list[i][0] == '\n' && lastemtionrecord == 1) { printf("\n"); } lastemtionrecord = isEmotion; } printf("\n");}