Download presentation
Presentation is loading. Please wait.
1
Discussion 6 HW4 and Libraries
2
Let’s talk Assignment 4 Builds on Assignment 3 concepts
The goal of HW3 is to complete the implementation of a program that performs a simple search for some strings (given on the command line) in a file (read from standard input). In particular, the program searches for up to 50 different strings, and for each string counts the number of times it occurs in the standard input. Once standard input is exhausted, it prints each string and its number of occurrences to the standard output. cat test/flicka.txt | ./count-strings my friend flicka
3
Let’s talk Assignment 4 Builds on Assignment 3 concepts
Now, you have to build a glossary. The goal of HW4 is to complete the implementation of a program that performs a simple glossary analysis. In particular, the program extracts words from a text file and prints to the console the list of those words and their frequencies. For example, a working implementation will allow you to run the program wordfreq like this: cat books/aladdin.txt | ./wordfreq
4
Pointer to pointer int** x; int* y = (int*)malloc(sizeof int); x=&y;
We know we can have a pointer to another pointer. Y is a pointer that points to 4 bytes allocated in memory using malloc. And x is pointer to pointer. X points to y.
5
Explanation of search()
struct WordSet { int size; WordNode *head; }; One task is to implement searching the WordNode for a given word in a set data structure. The implementation of the set is simply a linked list of WordNode objects. size: the number of elements in the linked list. Head: the starting node in the linked list.
6
Explanation of search()
struct WordSet { int size; WordNode *head; }; struct WordNode { int freq; char *word; WordNode *next; }; A WordNode object contains a word, its frequency and the next word node in the list.
7
Explanation of search()
WordNode “Start” 2 WordNode “by” 3 WordNode “possible” 1 *next *next *next NULL p *head struct WordSet { int size; WordNode *head; }; WordSet struct WordNode { int freq; char *word; WordNode *next; }; P=&head, *p=head, (*p)->word=“start”, (*p)->next=pointer to 2nd node P=&(pointer to 2nd node), *p=pointer to 2nd node, (*p)->word=“by”, (*p)->next=pointer to 3rd node P=&(pointer to last node), *p=pointer to last node, (*p)->word=“possible”, (*p)->next=NULL P=&(NULL pointer), *p=NULL pointer,
8
Explanation of search()
WordNode “Start” 2 WordNode “by” 3 WordNode “possible” 1 *next *next *next NULL p *head struct WordSet { int size; WordNode *head; }; WordSet struct WordNode { int freq; char *word; WordNode *next; }; P=&head, *p=head, (*p)->word=“start”, (*p)->next=pointer to 2nd node P=&(pointer to 2nd node), *p=pointer to 2nd node, (*p)->word=“by”, (*p)->next=pointer to 3rd node P=&(pointer to last node), *p=pointer to last node, (*p)->word=“possible”, (*p)->next=NULL P=&(NULL pointer), *p=NULL pointer,
9
Explanation of search()
WordNode “Start” 2 WordNode “by” 3 WordNode “possible” 1 *next *next *next NULL p *head struct WordSet { int size; WordNode *head; }; WordSet struct WordNode { int freq; char *word; WordNode *next; }; P=&head, *p=head, (*p)->word=“start”, (*p)->next=pointer to 2nd node P=&(pointer to 2nd node), *p=pointer to 2nd node, (*p)->word=“by”, (*p)->next=pointer to 3rd node P=&(pointer to last node), *p=pointer to last node, (*p)->word=“possible”, (*p)->next=NULL P=&(NULL pointer), *p=NULL pointer,
10
Explanation of search()
WordNode “Start” 2 WordNode “by” 3 WordNode “possible” 1 *next *next *next NULL p *head struct WordSet { int size; WordNode *head; }; WordSet struct WordNode { int freq; char *word; WordNode *next; }; P=&head, *p=head, (*p)->word=“start”, (*p)->next=pointer to 2nd node P=&(pointer to 2nd node), *p=pointer to 2nd node, (*p)->word=“by”, (*p)->next=pointer to 3rd node P=&(pointer to last node), *p=pointer to last node, (*p)->word=“possible”, (*p)->next=NULL P=&(NULL pointer), *p=NULL pointer,
11
Explanation of search()
WordNode “Start” 2 WordNode “by” 3 WordNode “possible” 1 *next *next *next NULL p *head struct WordSet { int size; WordNode *head; }; WordSet struct WordNode { int freq; char *word; WordNode *next; }; P=&head, *p=head, (*p)->word=“start”, (*p)->next=pointer to 2nd node P=&(pointer to 2nd node), *p=pointer to 2nd node, (*p)->word=“by”, (*p)->next=pointer to 3rd node P=&(pointer to last node), *p=pointer to last node, (*p)->word=“possible”, (*p)->next=NULL P=&(NULL pointer), *p=NULL pointer,
12
i-clicker question Suppose p points to a pointer to a WordNode, how do we access the WordNode’s word? p->word (*p)->word (**p)->word struct WordNode { int freq; char *word; WordNode *next; };
13
i-clicker question Suppose p points to a pointer to a WordNode, how do we access the word of the WordNode’s immediate successor? (*((*p)->next)).word ((*p)->next).word ((*p)->next)->word (*((*p)->next))->word struct WordNode { int freq; char *word; WordNode *next; };
14
Return value of search static WordNode **search (WordSet *wset, char *word) { found a matching wordNode Notice the search function returns a pointer to a pointer. Search would return the pointer to pointer to a matching wordNode or reaching the end of the linked list.
15
Return value of search static WordNode **search (WordSet *wset, char *word) { found a matching wordNode When finding a matching WordNode, strcmp((*p)->word, word)==0, return the address of the pointer that points to the matching WordNode, or the address of the matching node’s immediate predecessor’s next field. If the first node is the matching node, search returns a pointer to the head field of the WordSet struct. If we have nodes with "A", "B", and "C" that are arranged "A" --> "B" --> "C", and we are looking for "B", we would return a pointer to "A"->next
16
Return value of search static WordNode **search (WordSet *wset, char *word) { found a matching wordNode Reached the end of linked list When reaching the end of the linked list, return &(pointer to NULL), which is also the address of last node’s next field.
17
Return value of search static WordNode **search (WordSet *wset, char *word) { found a matching wordNode Reached the end of linked list And also, the pointer to pointer never points to the actual WordNode, but it points the pointer referencing that WordNode.
18
Return value of search static WordNode **search (WordSet *wset, char *word) { found a matching wordNode Reached the end of linked list Can be used for adding and removing a WordNode Add: let *return points to the newly created node if a maching wordNode is not found Search, add and remove are closely related together. If search messes up a next-pointer chain or something, add and remove operation can fail. So when u cannot add or remove a node, it may be due to a problem in the search function. return value can be used for ... Return=&(pointer to NULL), which is also the address of last node’s next field.
19
Return value of search static WordNode **search (WordSet *wset, char *word) { found a matching wordNode Reached the end of linked list Can be used for adding and removing a WordNode Add: let *return points to the newly created node if a maching wordNode is not found Remove: let *return points to the next node of the given word node’s immediate successor if a matching wordNode is found Return is the address of the pointer that points to the matching WordNode, or the address of the matching node’s immediate predecessor’s next field. Let's say we have some list with the following nodes: a -> b -> c and want to remove b. p is initially set to the link between a and b. Using p, we can easily link a to c. How do I express the immediate successor of the given word node? WordNode *w = (*prev); (*prev) = w->next;
20
Return value of search static WordNode **search (WordSet *wset, char *word) { found a matching wordNode Reached the end of linked list Can be used for adding and removing a WordNode Add: let *return points to the newly created node if a maching wordNode is not found Remove: let *return points to the next node of the given word node’s immediate successor if a matching wordNode is found Fast Add: first remove, then add at the beginning Sometimes when I use the time command to test the run-times, wordfreq-fast's run-times are indeed faster than those for wordfreq ... but, other times, wordfreq-fast actually ends up taking a little longer rather than shorter. So this is normal. You get a better test on the larger files. When I cat together all the files in books (cat books/*.txt | wordfreqxxx) I get wordfreq-fast completing on about 60% of the time that wordfreq takes. "Your mileage may vary."
21
words_next_word Two loops
Its job is to read in characters from standard input until it encounters a "non-word" character. I think the easiest approach is two loops. The first one will skip the non-word characters (but stop at EOF and return EOF), and the second will process the word characters.
22
words_next_word Two loops
Skip over leading non-alphanumeric characters Isalnum: <ctype.h> ch != EOF && !isalnum(ch)
23
words_next_word Two loops
Skip over leading non-alphanumeric characters Isalnum: <ctype.h> Store all alphanumeric characters into buf before calling make_string Do I call make_string with an empty buffer? Do I need to null-terminate in buf? Store all alphanumeric characters into a character array buf before calling make_string. No need to null-terminate in buf -- make_string gets told how many actual characters there are. If you reach end of file with an empty buffer, don't call make_string with a count 0, return NULL instead.
24
words_next_word Two loops Use getchar() to read more characters
Skip over leading non-alphanumeric characters Isalnum: <ctype.h> Store all alphanumeric characters into buf before calling make_string Do I call make_string with an empty buffer? Do I need to null-terminate in buf? Use getchar() to read more characters The result of getchar can be EOF, alphanumeric characters, and non-alphanumeric characters
25
words_next_word Two loops Use getchar() to read more characters
Skip over leading non-alphanumeric characters Isalnum: <ctype.h> Store all alphanumeric characters into buf before calling make_string Do I call make_string with an empty buffer? Do I need to null-terminate in buf? Use getchar() to read more characters Hand simulate the function on various cases Hand simulate the function on various cases that might be presented to it. For example, what about the case where there are no word characters left, zero one or more non-word characters followed by EOF.
26
Wset_free Free nodes in the linked list Free the word set
Wset_free is to deallocate WordSet objects. One common mistake is not freeing nodes in the linked list. You just free the word set without freeing nodes in the linked list. You would first need to deallocate word nodes in the linked list first, then deallocate the word set itself
27
Group Activity What is linking? What is the purpose of linking?
Could you compare static linking and dynamic linking? Suppose foo.c calls functions in libx.a; libx.a calls functions in liby.a; liby.a calls functions in libx.a; libx.a calls functions in foo.c. What is the gcc command line that will allow the static linker to resolve all symbol references? What is the difference between a definition and a declaration? When do we use extern?
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.