/* Return the balance of the user or -1 if the user does not exist. */ double user_balance(Group *group, const char *user_name) { User * prev_user = find_prev_user(group, user_name); if (prev_user == NULL) { return (double)(-1); } if (prev_user == group->users) { // user could be first or second since previous is first if (strcmp(user_name, prev_user->name) == 0) { // this is the special case of first user //LEO MOD: //printf("Balance is %f\n", prev_user->balance); //return 0; return prev_user->balance; } } //LEO MOD: //printf("Balance is %f\n", prev_user->next->balance); //return 0; return prev_user->next->balance; }
/* Add a new user with the specified user name to the specified group. Return zero * on success and -1 if the group already has a user with that name. * (allocate and initialize a User data structure and insert it into the * appropriate group list) */ int add_user(Group *group, const char *user_name) { User *this_user = find_prev_user(group, user_name); if (this_user != NULL) { return -1; } // ok to add a user to this group by this name // since users are stored by balance order and the new user has 0 balance // he goes first User *newuser; if ((newuser = malloc(sizeof(User))) == NULL) { perror("Error allocating space for new User"); exit(1); } // set the fields of the new user node // first allocate space for the name size_t name_len = strlen(user_name); if ((newuser->name = malloc(name_len + 1)) == NULL) { perror("Error allocating space for new User name"); exit(1); } strncpy(newuser->name, user_name, name_len + 1); newuser->balance = 0.0; // insert this user at the front of the list newuser->next = group->users; group->users = newuser; return 0; }
/* Print to standard output the balance of the specified user. Return 0 * on success, or -1 if the user with the given name is not in the group. */ int user_balance(Group *group, const char *user_name) { User *prev_user = find_prev_user(group, user_name); if (prev_user == NULL) { return -1; } else if (strcmp(prev_user->name, user_name) == 0) { printf("BALANCE\n-------\n"); printf("%c%.2f (%s)\n", CURRENCY, prev_user->balance, prev_user->name); return 0; } else { printf("BALANCE\n-------\n"); printf("%c%.2f (%s)\n", CURRENCY, prev_user->next->balance, prev_user->next->name); return 0; } }
/* Remove the user with matching user and group name and * remove all her transactions from the transaction list. * Return 0 on success, and -1 if no matching user exists. * Remember to free memory no longer needed. * (Wait on implementing the removal of the user's transactions until you * get to Part III below, when you will implement transactions.) */ int remove_user(Group *group, const char *user_name) { /* Gets the previous user before the user to be deleted if the to be deleted * user is not a head. If the to be deleted user is a head, the to be deleted * is returned. If the user doesn't exist in the group, NULL is returned. */ User *prev_user = find_prev_user(group, user_name); /* If the user returned is not NULL, this means that user exists in the group, * therefore we check if the returned user is a head or the previous user. * 1) If it is a previous user, we set the previous user next pointer to * the next next user and free space for the deleted user. */ if (prev_user != NULL) { if (strcmp(prev_user->name, user_name) == 0) { group->users = prev_user->next; remove_xct(group, user_name); free_dp(prev_user->name); free_dp(prev_user); return 0; /* 2) If it is a head node, we reset the head to the next user and free * up space for the deleted node. Free space for the user name * and the user, also points the user to NULL to avoid dangling * pointers. */ } else if (strcmp(prev_user->next->name, user_name) == 0) { User *temp = prev_user->next; prev_user->next = prev_user->next->next; remove_xct(group, user_name); free_dp(temp->name); free_dp(temp); } // Return 0 if we the deletion is successful. return 0; /* If the user returned is NULL, that means the user name doesn't exist, no * users are deleted, and -1 is returned. */ } else { return -1; } }
/* Add the transaction represented by user_name and amount to the appropriate * transaction list, and update the balances of the corresponding user and group. * Note that updating a user's balance might require the user to be moved to a * different position in the list to keep the list in sorted order. Returns 0 on * success, and -1 if the specified user does not exist. */ int add_xct(Group *group, const char *user_name, double amount) { User *this_user; User *prev = find_prev_user(group, user_name); if (prev == NULL) { return -1; } // but find_prev_user gets the PREVIOUS user, so correct if (prev == group->users) { // user could be first or second since previous is first if (strcmp(user_name, prev->name) == 0) { // this is the special case of first user this_user = prev; } else { this_user = prev->next; } } else { this_user = prev->next; } Xct *newxct; if ((newxct = malloc(sizeof(Xct))) == NULL) { perror("Error allocating space for new Xct"); exit(1); } // set the fields of the new transaction node // first allocate space for the name size_t needed_space = strlen(user_name) + 1; if ((newxct->name = malloc(needed_space)) == NULL) { perror("Error allocating space for new xct name"); exit(1); } strncpy(newxct->name, user_name, needed_space); newxct->amount = amount; // insert this xct at the front of the list newxct->next = group->xcts; group->xcts = newxct; // first readjust the balance this_user->balance = this_user->balance + amount; // since we are only ever increasing this user's balance they can only // go further towards the end of the linked list // So keep shifting if the following user has a smaller balance while (this_user->next != NULL && this_user->balance > this_user->next->balance ) { // he remains as this user but the user next gets shifted // to be behind him if (prev == this_user) { User *shift = this_user->next; this_user->next = shift->next; prev = shift; prev->next = this_user; group->users = prev; } else { // ordinary case in the middle User *shift = this_user->next; prev->next = shift; this_user->next = shift->next; shift->next = this_user; } } return 0; }
/* Add the transaction represented by user_name and amount to the appropriate * transaction list, and update the balances of the corresponding user and group. * Note that updating a user's balance might require the user to be moved to a * different position in the list to keep the list in sorted order. Returns 0 on * success, and -1 if the specified user does not exist. */ int add_xct(Group *group, const char *user_name, double amount) { /* Allocate space for the new xct that is to be added to the list of * xcts. */ Xct *new_xct = (Xct*) malloc (sizeof(Xct)); /* Checks if malloc failed, if malloc failed, a error message is printed to * standard output and exit code of 256. */ if (new_xct == NULL) { print_exit("ERROR: Malloc failed", 256); /* If malloc didn't fail, the user name and the amount is assigned to the new * xct and the next pointer is set to NULL temporarily. */ } else { int size_to_malloc = (strlen(user_name)+1)*sizeof(char); new_xct->name = (char*) malloc (size_to_malloc); /* Checks if the current malloc failed, if it failed a message is printed * to standard output and exit code of 256 is set. */ if (new_xct->name == NULL) { print_exit("ERROR: Malloc failed", 256); } strncpy(new_xct->name, user_name, size_to_malloc); new_xct->name[size_to_malloc] = '\0'; new_xct->amount = amount; new_xct->next = NULL; } /* Finds the previous user to the user that added a xct in order to change * the user's balance and re-organize the list. */ User *prev_user = find_prev_user(group, user_name); /* If no user was found with the same user name in the list of users, -1 is * returned. */ if (prev_user == NULL) { free_dp(new_xct->name); free_dp(new_xct); return -1; /* Checks if the user returned is the head of the list of users, if it is, * the head is changed so that the user can be moved to its correct location. */ } else if (strcmp(prev_user->name, user_name) == 0) { push_xct(group, new_xct); prev_user->balance += amount; sort_user(group, prev_user, user_name); return 0; /* Checks if the user returned is in the middle of the list of users, the * user is remvoed from its current position and placed in the correct * position in the users of list. */ } else { push_xct(group, new_xct); prev_user->next->balance += amount; sort_user(group, prev_user, user_name); return 0; } }
/* Add a new user with the specified user name to the specified group. Return zero * on success and -1 if the group already has a user with that name. * (allocate and initialize a User data structure and insert it into the * appropriate group list) */ int add_user(Group *group, const char *user_name) { /* Allocates space in memory for the user, and checks if malloc has been * completed successfully. */ User *new_user = (User*) malloc (sizeof(User)); /* If malloc is not completed succesfully, an error message will be printed * out to standard output and program will exit with 256 exit code */ if (new_user == NULL) { print_exit("ERROR: Malloc failed", 256); /* If malloc has been completed successfully, the user name is set to user_name * and set initial balance to 0 */ } else { int size_to_malloc = (strlen(user_name)+1)*sizeof(char); new_user->name = (char*) malloc (size_to_malloc); /* Checks if malloc is completed succesfully, if it is not completed * successfully, and error message will be printed out the screen and exit * code of 256. */ if (new_user->name == NULL) { print_exit("ERROR: Malloc failed", 256); } /* Copies the user_name given to the user name got the newly created * user. */ strncpy(new_user->name, user_name, size_to_malloc); new_user->name[size_to_malloc] = '\0'; /* Sets all other values to either 0.0 if it is double, or NULL if it is * a pointer to another linked list. */ new_user->balance = 0.0; new_user->next = NULL; } // Returns the user if the user already exists in the group. User *prev_user = find_prev_user(group, user_name); /* If prev_user is NULL, meaning no user in the group exists with the same * name. We can add the new user in this case to the specified group. */ if (prev_user == NULL) { prev_user = new_user; User *tmp = group->users; group->users = prev_user; group->users->next = tmp; return 0; /* If prev_user is not NULL, this means that a user with the same name already * exists, so we don't add the new user and just return -1. Free space for * the user name and the user, also points the user to NULL to avoid dangling * pointers */ } else { free_dp(new_user->name); free_dp(new_user); return -1; } }