/* * names9.c - read in a list of names from stdin * (derived from names5.c, to use a 'bag' to store names) * * usage: names < infile * stdin: list of names, one per line * stdout: list of names, one per line * * compile: gcc -o names names9.c readlinep.c * * CS50, Fall 2022 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include "readlinep.h" /* the items in a bag */ typedef struct bagnode { void *item; struct bagnode *next; } bagnode_t; bagnode_t *bagnode_new(void *item); /* the bag as a whole */ typedef struct bag { bagnode_t *head; } bag_t; bag_t * bag_new(void); bool bag_insert(bag_t *bag, void *item); void *bag_extract(bag_t *bag); void bag_print(bag_t *bag, void (*printfunc)(void *item)); void printname(void* item) { char *name=item; printf("%s", name); } /* ********************************************************* */ int main() { int n = 0; // number of names read char *name; bag_t *bag = bag_new(); if (bag == NULL) exit(1); // read the list of names - any number of names! while (!feof(stdin)) { name = readlinep(); if (name != NULL) { if (bag_insert(bag, name)) { n++; // only increment if no error } } } printf("%d names:\n", n); bag_print(bag, printname); putchar('\n'); // here we are lazy and do not free the bag. return 0; } /* ************************************************* * bag_new: create a new bag. * Return a pointer if success, NULL if failure. */ bag_t * bag_new(void) { bag_t *bag = malloc(sizeof(bag_t)); if (bag != NULL) { bag->head = NULL; } return bag; } /* ************************************************* * bag_insert: insert the given name into the bag. * Return true if success, false if failure. */ bool bag_insert(bag_t *bag, void *item) { bagnode_t *node = bagnode_new(item); if (bag == NULL || node == NULL) { return false; } else { // insert the new node at head of the list node->next = bag->head; bag->head = node; } return true; } /* ************************************************* * bagnode_new: create a new node to store the given name. * Returns pointer to new node, if successful, else returns NULL. * The pointer 'name' is assumed to be malloc storage, and is not copied. * Caller is responsibe for later deleting 'name'. */ bagnode_t *bagnode_new(void *item) { // allocate memory for the new node bagnode_t *node = malloc(sizeof(bagnode_t)); if (node == NULL) { return NULL; } else { // initialize node contents node->next = NULL; node->item = item; } return node; } /* ************************************************* * bag_extract: extract an item (any item) from the bag. * Return NULL if bag is empty or if some failure. */ void *bag_extract(bag_t *bag) { if (bag == NULL) { return NULL; } else if (bag->head == NULL) { return NULL; } else { // pull off the node at head of the list bagnode_t *node = bag->head; void *item = bag->head->item; bag->head = node->next; free(node); return item; } } /* ************************************************* * bag_print: print a bag, calling the func on each item. */ void bag_print(bag_t *bag, void (*printfunc)(void *item)) { if (bag == NULL) { return; } else { printf("{"); for (bagnode_t *node = bag->head; node != NULL; node = node->next) { if (printfunc != NULL) (*printfunc)(node->item); printf(", "); } printf("}"); } }