For an assignment I need to write code that takes a string as input and counts what word is the most used in that string.
We need to implement this using a Binary Search Tree of a structure called "WordCount" that contains a character array and the count of how many times the word appears.
This is how the structure is defined.
struct wordcount {
char word[80];
int count;
};
typedef struct wordcount WordCount;
A binary search tree must have a way to create nodes, this is the code:
BSTnode* createNode(void* item) {
BSTnode* newNode = (BSTnode*) malloc(sizeof(BSTnode));
newNode->item = item;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
When I store the WordCount structure inside of the Binary Search Tree and attempt to access the item, and then access the word, I get a Segmentation Fault.
If I just try to access the item of the tree, I get the char word array. This doesn't make sense because I'm storing the wordCount structure, so I should have to dereference it twice.
int main(int argc, char* argv[]) {
if (argc >= 1) {
WordCount* firstWord = (WordCount*) malloc(sizeof(WordCount));
strcpy(firstWord->word,argv[1]);
firstWord->count = 0;
BSTnode* BST = createNode(firstWord);
printf("%s", BST->item); // should be BST->item->word...but this does not work and says that it cannot find "word" which is apart of
}
/*int i;
char string[80];
for(i = 1; i < argc; i++) {
sscanf(argv[i], "%s", string);
//printf("%s ", string);
//insert(main, argv[i], wordCountCompare);
}*/
}
Any help is greatly appreciated. Let me know if my explanation was entirely vague or incomplete or if I'm overlooking something entirely.
I also want to clarify that the printf statements are merely for debugging only they won't be apart of the actual program...however the point still stands.
Definition of BSTnode:
struct bstnode {
void *item;
struct bstnode *left;
struct bstnode *right;
};
typedef struct bstnode BSTnode;
Your item should be of wordcount type.
struct bstnode {
wordcount *item;
struct bstnode *left;
struct bstnode *right;
};
typedef struct bstnode BSTnode;
You can't be dereferencing void pointers (which lead to the compilation error)
You're likely getting these errors because you're trying to dereference a pointer to NULL. Learn how to use the debugger!. Hint: break in main and step thru the function to see where the segmentation fault occurs
printf("%s", BST->item);
Printf's "%s" expects a string, and item is a structure. Try:
printf("%s" BST->item->word);
Related
I have this assignment where I have to implement a stack to work with the following struct given by my professor. As you know I don't know how to implement a stack using the following struct.
struct elements{
char word;
struct elements *next;
}
I do know how to do that using the struct below...
struct elements{
struct student data;
struct elements *next;
}
To insert the data into the stack I'd use... I know dat the code below is correct. I do understand what is happening there. But I cannot see how I can do that using char word instead of struct student data; Someone could explain it to me? I'm not getting the idea.
int pushStack(Stack* ptr, struct student info){
Elemn* node = (Elemn*)malloc(sizeof(Elemn);
if(node == NULL && ptr == NULL){
printf("error.");
return 0;
}
node->student = info;
node->next = (*ptr);
*ptr = node;
return 1;
}
Have you tried to replace struct student by char?
Of course in the function header, but also in the Elemn class.
Created a basic binary search tree, utilising linkedlists AND also trying to input 'data' into the function (because it requires it).
However, I keep getting the 'unused variable' error even though I'm using it?
Is it because I'm not returning 'data'? If so, how am I supposed to when the function itself is supposed to be creating a new node?
Thanks!
/* Binary search trees in linkedlists!
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct tnode Tnode; //Tree node
struct tnode {
int data;
Tnode *left; //for smaller vals
Tnode *right; //for larger vals
};
Tnode * makeTnode( int data );
int main(int argc, char*argv[]){
int data = 9;
struct tnode new_node;
Tnode * makeTnode( int data );
printf("new_node's data is %d\n", new_node.data);
return 0;
}
Tnode * makeTnode( int data ){
Tnode *new_node =(Tnode *)malloc(sizeof(Tnode));
if(new_node == NULL) {
fprintf(stderr, "Error: memory allocation failed\n");
exit(1);
}
new_node->data = data;
new_node->left = NULL;
new_node->right = NULL;
return(new_node);
}
Your function call to makeTnode in main() is incorrect and any return result would be unused. It looks like what you want to do is save that result as new_node. So change your main function to this:
int main(int argc, char*argv[]){
int data = 9;
Tnode * new_node = makeTnode( data );
printf("new_node's data is %d\n", new_node.data);
free(new_node); //You should also clean up after yourself.
return 0;
}
Tnode * makeTnode( int data );
is a function declaration (and a useless one here, because you've already declared the function)
If you want to actually call it, use:
new_node = makeTnode(data);
and make sure new_node is actually a Tnode* (not a Tnode).
void insert_tree(tree_t *tree, void *name, void *movie){
node_t *new;
new = malloc(sizeof(*new));
assert(new!=NULL);
strcpy(new->name, name);
strcpy(new->movie, movie);
new->left = new->right = NULL;
insert_node(&(tree->root), new);
}
typedef struct node node_t;
struct node{
char name[128];
char movie[422498];
node_t *left;
node_t *right;
};
typedef struct {
node_t *root;
} tree_t;
Code above inserts nodes to a binary search tree. I have been having thing trouble of overflowing while running the binary search tree algorithm with large files with more than 200000 lines.
With the
assert(new!=NULL)
statement, I found that the overflow is occurring in this part of the code.
I'm guessing that it is due to too many nodes being created?
How could I resolve this?
I haven't used realloc and malloc anywhere except in this part of the code.
All of the other codes also do not implement recursion they all use loops.
When the file is small enough it works perfectly with precision when it get larger it fails.
Try instead to make your nodes a bit more space efficient, having such a large array for a movie name (?) is a waste.
Instead declare the structure like this
struct node
{
char* name;
char* movie;
nde_t* left;
node_t* right;
};
then in your insert function:
void insert_tree(tree_t* tree, const char* name, const char* movie)
{
node_t *new = NULL;
// to catch unexpected arguments
assert( tree != NULL && name != NULL && movie != NULL );
new = malloc(sizeof(node_t)); // i prefer this style for sizeof
// don't use assert for runtime errors
if (new!=NULL)
{
new->name = strdup(name); // short form for malloc/strcpy
new->movie = strdup(movie);
new->left = new->right = NULL;
insert_node(&(tree->root), new);
}
else
{
fprintf(stderr, "out of memory");
exit(EXIT_FAILURE);
}
}
You should later free the memory for name and movie for each node.
Basically I have to store words in linked list with each character having its own node. I get really confused with nested structures. How do I go to the next node? I know i'm doing this completely wrong which is why I'm asking.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
char letter;
}NODE;
typedef struct handle
{
NODE **arr;
}HANDLE;
HANDLE * create();
void insert(handle **, char, int);
int main(int argc, char **argv)
{
FILE *myFile;
HANDLE *table = (HANDLE *)malloc(sizeof(HANDLE));
NODE *linked = (NODE *)malloc(sizeof(NODE));
int counter = 0;
linked = NULL;
table->arr[0] = linked;
char c;
myFile = fopen(argv[argc], "r");
while((c = fgetc(myFile)) != EOF)
{
if(c != '\n')
insert(&table, c, counter);
else
{
counter++;
continue;
}
}
}
void insert(HANDLE **table, char c, int x)
{
(*table)->arr[x]->letter = c; //confused on what to do after this or if this
//is even correct...
}
You have a linked list of words with each word being a linked list of characters. Am I right? If so, it is better to use the names for what they are:
typedef struct char_list
{
char letter;
struct char_list * next;
} word_t;
typedef struct word_list
{
word_t * word;
struct word_list_t * next;
} word_list_t;
Now, you can populate the lists as per need.
For a linked-list, you typically have a link to the next node in the node structure itself.
typedef struct node
{
char letter;
struct node *next;
}NODE;
Then from any given node NODE *n, the next node is n->next (if not NULL).
insert should scan the list until it finds an n->next that is NULL, and allocate a new node at the end (make sure to set its next to NULL).
You may want to have a function to initialize a new list given the table index, and a separate function to initialize a new node.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dictionary.h"
#define HASH_SIZE 100
// prototype
int hash(char *word);
// counter
int counter;
// node
typedef struct
{
char *word;
node *next;
} node;
// hash table
node *hashtable[HASH_SIZE];
bool
load(const char *dictionary)
{
// open the dictionary
FILE *dict = fopen(dictionary, "r");
if(dict == NULL)
{
printf("Could not open %s.\n", dictionary);
return false;
}
// set all values in the hash table to null
for(int i = 0; i < HASH_SIZE; i++)
{
hashtable[i] = NULL;
}
// set the counter to 0
counter = 0;
// iterate through the words in the dictionary
while (!feof(dict))
{
// get word into a string
char gotcha[LENGTH];
fscanf(dict, "%s", gotcha);
// declare a node and allocate memory
node n;
n.word = malloc( strlen(gotcha)*sizeof(char) );
// save the word into the node
strcpy(n.word, gotcha);
// hash the word, baby!
int hash_value = hash(n.word);
// start saving addresses to the hashtable
n.next = hashtable[hash_value];
hashtable[hash_value] = &n;
//test
int len = strlen(n.word);
printf("%s\n", n.word);
printf("%i\n", len);
// that's one more!
counter++;
}
fclose(dict);
return true;
}
I am receiving the following two errors on these two lines of code:
n.next = hashtable[hash_value];
hashtable[hash_value] = &n;
dictionary.c:89:16: error: assignment from incompatible pointer type [-Werror]
dictionary.c:90:31: error: assignment from incompatible pointer type [-Werror]
How do I save pointer values in these two places? I am new to this, so please bear that in mind. :)
In your structure, the type node is not yet defined. Change it to use the structure tag:
typedef struct node
{
char *word;
struct node *next;
} node;
This:
typedef struct
{
char *word;
node *next;
} node;
is a syntax error. The node *next; occurs before the end of the typedef that creates node as a type. If your compiler for some reason accepted this, it probably thinks there are 2 different types called "node" now, which explains why one of them isn't compaible with the other. You should give up on that typedef silliness (structs generally shouldn't be typedef'ed) and just use
struct node
{
char *word;
struct node *next;
};
Define typedef names of structs before defining the structs. This allows mutually referring structs without concern for order and doesn't require inconsistent definitions, sometimes with the struct keyword and sometimes without it. Note that in C++ you can do away with the typedef line entirely:
typedef struct node node;
struct node
{
char* word;
node* next;
};