I am trying to insert strings in the binary search tree.
So what I am to trying is,
parsing strings from a file(contains instruction set) and then inserting in the function
insertOpcodeFromFile().
So this function will execute
(*node) = Node_insert(&node,instruction).
the node will be the root of binary tree which is located in main function.
So in simple way to explain, I want to manipulate(insert) the root pointer in the main function by using double pointer in the other function contain insert function.
I have a simple understanding about the pointer, but in this situation, I need to use more than double pointer I think.
please explain me about the double pointer clearly using this example.
Here is my code(I commenting out insert_node)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef BINARYTREE_H_
#define BINARYTREE_H_
typedef struct node *NodePtr;
typedef struct node {
char *word;
int count;
NodePtr left;
NodePtr right;
} Node;
NodePtr Node_alloc();
NodePtr Node_insert(NodePtr node_ptr, char *word);
void clearArray(char a[]);
void insertOpcodeFromFile(FILE *opcodeFile, NodePtr *node);
void Node_display(NodePtr);
char *char_copy(char *word);
#endif
int main(int argc, const char * argv[]) {
FILE * opFile;
FILE * progFile;
struct node *root = NULL;
if ( argc != 4) { // # of flag check
fprintf(stderr, " # of arguments must be 4.\n" );
exit(1);
}
opFile = fopen ( argv[1], "r");
if(opFile == NULL)
{
fprintf(stderr,"There is no name of the opcode file\n");
exit(1);
}
progFile = fopen ( argv[2], "r");
if(progFile == NULL)
{
fprintf(stderr,"There is no name of the program file \n");
exit(1);
}
insertOpcodeFromFile(opFile, &root);
//Node_display(root);
}/* main is over */
void insertOpcodeFromFile(FILE *opcodeFile, NodePtr *node)
{
int fsize = 0;
int lengthOfInst = 0;
int c;
int i;
char buffer[100];
fsize = getFileSize(opcodeFile);
enum flag {ins,opc,form};
int flag = ins;
char instruction[6];
unsigned int opcode = 0;
unsigned char format;
while (c != EOF)
{
c = fgetc(opcodeFile);
buffer[i++] = c;
if (c == 32){
switch (flag) {
case ins:
flag = opc;
memcpy(instruction,buffer,i);
instruction[i] = '\0';
clearArray(buffer);
i = 0;
// printf("인스트럭션 : %s\n",instruction );
break;
case opc:
flag = form;
opcode = atoi(buffer);
clearArray(buffer);
i = 0;
// printf("옵코드 : %d\n",opcode );
break;
default:
break;
}/* end of switch */
}/* end of if(space) */
if((c == 10) || (c == EOF))
{
if (flag == form)
{
format = buffer[0];
clearArray(buffer);
i = 0;
// printf("포멧: %c\n", format);
}
flag = ins;
//node = Node_insert(node,instruction);
}
}
//Node_display(node);
}
int getFileSize(FILE *opcodeFile)
{ int fsize = 0;
fseek(opcodeFile,0, SEEK_SET);
fseek(opcodeFile,0, SEEK_END);
fsize = (int)ftell(opcodeFile);
fseek(opcodeFile,0, SEEK_SET);
return fsize;
}
int countUntilSpace(FILE *opcodeFile, int currentPosition)
{ char readword[1];
char *space = " ";
char *nextLine = "/n";
int i = 0;
//printf("현재: %d\n",currentPosition );
while(1)
{
fread(readword, sizeof(char),1,opcodeFile);
i++;
if(strcmp(readword,space) == 0 || strcmp(readword,nextLine) == 0)
{
//printf("break\n");
break;
}
}
fseek(opcodeFile,currentPosition ,SEEK_SET);
//printf("끝난 현재 :%d\n",ftell(opcodeFile) );
//printf("%I : %d\n",i );
return i - 1;
}
void clearArray(char a[])
{
memset(&a[0], 0, 100);
}
NodePtr Node_alloc()
{
return (NodePtr) malloc(sizeof(NodePtr));
}
NodePtr Node_insert(NodePtr node_ptr, char *word)
{
int cond;
if (node_ptr == NULL) {
node_ptr = Node_alloc();
node_ptr->word = char_copy(word);
node_ptr->count = 1;
node_ptr->left = node_ptr->right = NULL;
} else if ((cond = strcmp(word, node_ptr->word)) == 0) {
node_ptr->count++;
} else if (cond < 0) {
node_ptr->left = Node_insert(node_ptr->left, word);
} else {
node_ptr->right = Node_insert(node_ptr->right, word);
}
return node_ptr;
}
void Node_display(NodePtr node_ptr)
{
if (node_ptr != NULL) {
Node_display(node_ptr->left);
printf("%04d: %s\n", node_ptr->count, node_ptr->word);
Node_display(node_ptr->right);
}
}
char *char_copy(char *word)
{
char *char_ptr;
char_ptr = (char *) malloc(strlen(word) + 1);
if (char_ptr != NULL) {
char_ptr = strdup(word);
}
return char_ptr;
}
In this case, in main(),
Node *root;
Why do you need to use a "double" pointer ( Node ** ) in functions that alter root is because root value as to be set in these functions.
For instance, say you want to allocate a Node and set it into root.
If you do the following
void alloc_root(Node *root) {
root = malloc(sizeof (Node));
// root is a function parameter and has nothing to do
// with the 'main' root
}
...
// then in main
alloc_root( root );
// here main's root is not set
Using a pointer to pointer (that you call "double pointer")
void alloc_root(Node **root) {
*root = malloc(sizeof (Node)); // note the *
}
...
// then in main
allow_root( &root );
// here main's root is set
The confusion comes probably from the Node *root in main, root being a pointer to a Node. How would you set an integer int i; in a function f? You would use f(&i) to call the function f(int *p) { *p = 31415; } to set i to the value 31415.
Consider root to be a variable that contains an address to a Node, and to set its value in a function you have to pass &root. root being a Node *, that makes another *, like func(Node **p).
Related
I'm attempting to insert stdin strings into a binary search tree, and then output the inorder and postorder traversals. My problem is it seems like older nodes are being overwritten by the most recent, but I can't figure out why. So my inorder/postorder methods return the last inserted string how many times there are nodes in the tree.
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <ctype.h>
#include "bstsort.h"
/* Case Sensitive String Comparison */
int strcmpCase(char* string1, char* string2) {
while(*string1 && (*string1==*string2)) {
string1++;
string2++;
}
return *string1 - *string2;
}
/* Case Insensitive String Comparison */
int strcmpNoCase(char* string1, char* string2) {
int i;
char a[100];
char b[100];
strcpy(a, string1);
strcpy(b, string2);
for (i = 0; a[i]; ++i) {
a[i] = tolower(a[i]);
}
for (i = 0; b[i]; ++i) {
b[i] = tolower(b[i]);
}
return strcmpCase(a, b);
}
/* Inserts a Node into the Binary Search Tree */
void insert(struct Node **node, char *keyStr, int cflag) {
// Creates new node
if (*node == NULL) {
*node = (struct Node*) malloc (100);
strcpy((*node)->key, keyStr);
(*node)->left = NULL;
(*node)->right = NULL;
(*node)->count = 1;
return;
}
// Compares Strings
int compareResult;
if (cflag == 1){
// Case sensitive
compareResult = strcmpCase(keyStr, (*node)->key);
} else {
// Case insensitive
compareResult = strcmpNoCase(keyStr, (*node)->key);
}
// Moves down branches of BST to insert node in correct order
if (compareResult < 0) {
insert(&((*node)->left), keyStr, cflag);
} else if (compareResult > 0) {
insert(&((*node)->right), keyStr, cflag);
}
(*node)->count++;
return;
}
/* Outputs in-order traversal or BST */
void inorder(Node* root) {
if (root != NULL) { // if current node is not null
inorder(root->left); // travel down left child, recursively
printf("%s", root->key); // prints key of current node, the root
inorder(root->right); // travel down right child after root printed, recursively
}
}
void postorder(Node* root) {
printf("Postorder: \n");
if (root != NULL) { // if current node is not null
postorder(root->left); // travel down left child, recursively
postorder(root->right); // travel down right child, recursively
printf("%s", root->key); // prints key of current node, the root
}
}
int main(int argc, char **argv) {
extern char *optarg;
extern int optind;
int c, err = 0, i = 0, numRead, isfirst = 1;
int cflag = 0, oflag = 0;
char *inName = NULL; // Input filename
char *outName = NULL; // Output filename
static char usage[] = "Usage: bstsort [-c] [-o output_file_name] [input_file_name]\n";
FILE* inFile = NULL;
FILE* outFile = NULL;
char *line;
char tmp[100] = "";
struct Node *root = NULL;
while ((c = getopt(argc, argv, "co:")) != -1)
switch (c) {
case 'c':
cflag = 1;
break;
case 'o':
oflag = 1;
outName = optarg;
break;
case '?':
err = 1;
break;
}
if (err) {
fprintf(stderr, usage, argv[0]);
exit(1);
}
/* see what we have */
printf("cflag: %d\n", cflag);
printf("oflag: %d\n", oflag);
printf("Output Filename: \"%s\"\n", outName);
/* these are the arguments after the command-line options */
if (optind < argc) {
for (; optind < argc; optind++) {
inName = argv[optind];
printf("Input Filename: \"%s\"\n", inName);
}
} else {
printf("No input filename provided.\n");
}
/* Reads stdin one line at a time when input filename not provided*/
line = (char*) malloc (100);
if (inName == NULL) {
printf("\nEnter one line at a time:\n");
fflush(stdout);
fgets(line, 100, stdin);
insert(&root, line, cflag);
while (strcmp(line, "\n") != 0) {
fflush(stdout);
fgets(line, 100, stdin);
if (strcmp(line, "\n") != 0) {
insert(&root, line, cflag);
}
}
}
inorder(root);
postorder(root)
free(line);
free(root);
fclose(inFile);
exit(0);
}
Here's my Node struct
#ifndef BSTSORT_H
#define BSTSORT_H
/* Binary Search Tree Node Struct */
typedef struct Node {
char *key;
int count;
struct Node *left;
struct Node *right;
} Node;
void insert(Node **node, char *keyStr, int cflag);
void inorder(Node* root);
void postorder(Node* root);
void display_tree(Node* nd);
#endif
Any tips would be great.
I'm trying to build a binary search tree , that store word/definition pairs.
so my struct is like this :
struct BinarySearchTree_t
{
char *word,*def;
struct BinarySearchTree_t *left;
struct BinarySearchTree_t *right;
};
typedef struct BinarySearchTree_t BinarySearchTree;
So I've been blocked in insertWord function that inserts a word/definition pair in a binary search tree. Neither the word nor the definition may be NULL. NULL is considered as a special value. If the word already exists then this function replaces the current definition by the new one and returns the old one.
This is the function:
char* insertWord(BinarySearchTree *tree, char *word, char *definition)
{
int r;
char* a;
if((tree==NULL))
{
BinarySearchTree* tmp;
tmp = malloc( sizeof( BinarySearchTree ) );
tmp->word= malloc((strlen(word)+1)*sizeof(char));
tmp->def = malloc((strlen(definition)+1)*sizeof(char));
strcpy(tmp->word, word);
strcpy(tmp->def , definition);
tmp->left = NULL;
tmp->right = NULL;
*tree = *tmp;
return NULL;
}
else
{
a= tree->word;
r= strcmp(a,word);
if(r = 0)
{
char* ret= tree->def;
strcpy(tree->word, word);
strcpy(tree->def , definition);
return ret;
}
else if(r<0)
return insertWord((tree->right),word,definition);
else
return insertWord((tree->left),word,definition);
}
}
What is the problem?
Edited : the correct function:
char* insertWord(BinarySearchTree **tree, char *word, char *definition)
{
int r;
char* a;
if(((*tree)==NULL) || ((*tree)!=NULL && (*tree)->mot==NULL))
{
BinarySearchTree* tmp;
tmp = malloc( sizeof( BinarySearchTree ) );
tmp->left = NULL;
tmp->right = NULL;
tmp->mot = malloc((strlen(word)+1)*sizeof(char));
tmp->def = malloc((strlen(definition)+1)*sizeof(char));
strcpy(tmp->mot , word);
strcpy(tmp->def , definition);
*tree = tmp;
return NULL;
}
else
{
a= (*tree)->mot;
r= strcmp(a,word);
if(r == 0)
{
char* ret= (*tree)->def;
strcpy((*tree)->mot , word);
strcpy((*tree)->def , definition);
return ret;
}
else if(r<0)
return insertWord(&((*tree)->right),word,definition);
else
return insertWord(&((*tree)->left),word,definition);
}
}
So, you are trying to initialize the pointer to root of your SearchTree, the first time it's accessed, right? The problem is that you are modifying a local copy of the pointer *tree and not the actual pointer that's present in the parent (calling) function. If you plan to modify the pointer to your SearchTree inside the called function, you should pass a pointer to the *tree in call to insertWord (i.e. a pointer to pointer).
You should change the definition to:
char* insertWord(BinarySearchTree **tree, char *word, char *definition)
Accordingly you should modify all accesses of tree inside your insertWord function.
Alternative working code — given a clean bill of health by valgrind:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct BinarySearchTree_t
{
char *word, *def;
struct BinarySearchTree_t *left;
struct BinarySearchTree_t *right;
};
typedef struct BinarySearchTree_t BinarySearchTree;
static void freeTree(BinarySearchTree *root);
static void dump_tree(BinarySearchTree *root);
extern char *insertWord(BinarySearchTree **ptree, char *word, char *definition);
char *insertWord(BinarySearchTree **ptree, char *word, char *definition)
{
if (*ptree == NULL)
{
BinarySearchTree *tmp = malloc(sizeof(*tmp));
tmp->word = strdup(word);
tmp->def = strdup(definition);
tmp->left = NULL;
tmp->right = NULL;
*ptree = tmp;
return tmp->def;
}
else
{
BinarySearchTree *tree = *ptree;
int r = strcmp(tree->word, word);
if (r == 0)
{
free(tree->def);
tree->def = strdup(definition);
return tree->def;
}
else if (r < 0)
return insertWord(&tree->right, word, definition);
else
return insertWord(&tree->left, word, definition);
}
}
int main(void)
{
char *word_defs[][2] =
{
{ "cat", "feline" },
{ "dog", "canine" },
{ "box", "carton" },
{ "cat", "purring critter" },
};
BinarySearchTree *root = 0;
for (size_t i = 0; i < sizeof(word_defs) / sizeof(word_defs[0]); i++)
{
printf("%zu: Add %s => %s\n", i, word_defs[i][0], word_defs[i][1]);
char *def = insertWord(&root, word_defs[i][0], word_defs[i][1]);
dump_tree(root);
printf("New definition: %s\n", def);
}
freeTree(root);
return 0;
}
static void freeTree(BinarySearchTree *root)
{
if (root != 0)
{
freeTree(root->left);
freeTree(root->right);
free(root->word);
free(root->def);
free(root);
}
}
static void dump_tree(BinarySearchTree *root)
{
if (root->left != 0)
dump_tree(root->left);
printf("%p: %s => %s\n", (void *)root, root->word, root->def);
if (root->right != 0)
dump_tree(root->right);
}
This version reports the new definition of the word. The original code may have been reporting the old definition; it is not hard to fix this code so that it reports the old definition (but it requires a modicum of care to ensure that the old definition is actually released, and null pointers aren't printed).
I have a problem with my code. I am getting a segmentation fault error, which I understand is a dangling pointer problem(generally) or a faulty allocation of memory. The compiler dose not show at what line the problem might be, so my question is how do I detect these problems for further concern? and where would my problem be in the code?
here is my code:
`#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])
#define ALPHABET_SIZE (256)
#define CHAR_TO_INDEX(c) ((int)c - (int)'a')
#define LEVELS 255
// trie node
struct n
{
char value,level,isLeaf;
struct n* children[ALPHABET_SIZE];
struct n* failLink;
};
typedef struct n node;
//trie
struct t
{
node *root;
int count;
};
typedef struct t trie;
void bytesCpy(char *to, char *from, int len)
{
int i;
for(i=0;i<len;i++)
{
to[i]=from[i];
}
}
// Returns new trie node (initialized to NULLs)
node *getNode(trie *t, char value,char level)
{
node *pNode = NULL;
pNode = (node *)malloc(sizeof(node));
if (pNode)
{
printf("ok\n");
int i;
for (i = 0; i < ALPHABET_SIZE; i++)
{
pNode->children[i] = NULL;
}
pNode->failLink = t->root;
pNode->value=value;
pNode->level=level;
pNode->isLeaf=0;
}
else
printf("error\n");
return pNode;
}
// Initializes trie (root is dummy node)
void initialize(trie *t)
{
t->root = getNode(t, '[', 0);
//t->count = 0;
}
// If not present, inserts key into trie
// If the key is prefix of trie node, just marks leaf node
void insert(trie *t, char key[], int len)
{
int level;
char value;
node *node = t->root;
for (level = 0; level<len; level++)
{
value = key[level];
printf("value: %c\n",value);
if (node->children[value] == NULL)
{
node->children[value] = getNode(t, value, level+1);
}
node = node->children[value];
}
node->isLeaf=1;
}
// Returns non zero, if key presents in trie
int search(trie *t, char key[])
{
int level;
int length = strlen(key);
int value;
node *node;
node = t->root;
for (level = 0; level < length; level++)
{
value = key[level];//CHAR_TO_INDEX(key[level]);
if (!node->children[value])
{
node = node->failLink;
return 0;
}
node = node->children[value];
}
return (0 != node);// && node->value);
}
void search1(trie *t, char *c, int len)
{
node *curNode = t->root;
int i;
for(i=0; i<=len; i++)
{
printf("i=%d curnode=%p\n",i,curNode);
if(curNode->isLeaf) //leaf: cuvant gasit
{
printf("if1 curGasit \n");
do{
curNode=curNode->failLink;
if(curNode->isLeaf)
printf("if1 curGasit \n");
else break;
}while(1);
continue;
}
else //nu e gasit inca
{
if(curNode->children[c[i]]==NULL) //fail
{
printf("if2\n");
curNode = curNode->failLink;
continue;
}
else //litera gasita: go on
{
printf("el2\n");
curNode=curNode->children[c[i]];
}
}
}
printf("end of search\n");
}
node* searchAux(trie *t, node *curRoot, char cuv[], char len, int level ,int failLevel)
{
char cuvAux[1024];
bytesCpy(cuvAux,cuv,len);
printf("searchAux level:%d cuvAux:%s curRootLevel:%d\n",level,cuvAux,curRoot->level);
if(cuvAux[level+1] == '\0') //got to the end of cuvAux
{
printf("1st if\n");
return curRoot;
}
if(curRoot->children[cuvAux[level+1]] == NULL) //fail: letter not found
{
printf("3rd if\n");
return searchAux(t, t->root, &cuvAux[failLevel+1], len, 0, failLevel+1);
}
else //letter found: go on
{
printf("3rd else\n");
if(cuvAux[level+2] == '\0') //the found letter was the last of the string
{
printf("4th if\n");
return curRoot->children[cuvAux[level+1]]; //return final pointer
}
else //the found letter was not the last of the string: continue with the next one
{
printf("4th else\n");
return searchAux(t, curRoot->children[cuvAux[level+1]], cuvAux, len, level+1, failLevel);
}
}
}
void createFailLinks(trie *t, node* curRoot, char cuv[], int level)
{
int i;
char cuvAux[1024];
bytesCpy(cuvAux,cuv,1024);
if(curRoot == NULL)
return;
for(i=0;i<ALPHABET_SIZE/*curRoot->children[i] != NULL*/;i++)
{
if(curRoot->children[i] == NULL)
continue;
else
{
cuvAux[level] = curRoot->children[i]->value;
printf("createFailLinks %c%d\n",cuvAux[level],curRoot->children[i]->level);
curRoot->children[i]->failLink = searchAux(t, t->root, cuvAux, level+1, 0, 0);
createFailLinks(t,curRoot->children[i],cuvAux,level+1);
}
}
printf("got\n");
}
void printTrie(node *curRoot)
{
int i;
if(curRoot == NULL)
return;
printf("%c: ", curRoot->value);
for(i=0;i<ALPHABET_SIZE;i++)
if(curRoot->children[i] != NULL)
{
printf("%c ", i);
}
printf("\n");
for(i=0;i<ALPHABET_SIZE;i++)
if(curRoot->children[i] != NULL)
{
printTrie(curRoot->children[i]);
}
}
void checkLinks(node* curRoot)
{
int i;
if(curRoot == NULL)
return;
printf("node %c%d: ",curRoot->value,curRoot->level);
for(i=0;i<256;i++)
if(curRoot->children[i] != NULL)
printf("\n\t%c%d:%c%d",curRoot->children[i]->value, curRoot->children[i]->level, curRoot->children[i]->failLink->value,curRoot->children[i]->failLink->level);
printf("\n");
for(i=0;i<256;i++)
if(curRoot->children[i] != NULL)
checkLinks(curRoot->children[i]);
}
int mai()
{
FILE *fd = fopen("VirusDatabase.txt","r");//O_RDONLY);
int i;
char c;
for(i=0;i<1000;i++)
{
fscanf(fd, "%c", &c);
printf("%c",c);
}
}
int main()
{
// Input keys (use only 'a' through 'z' and lower case)
char keys[][1024] = { "he", "she", "her", "his", "heres"};
char cuv[] = {'\0','\0','\0','\0','\0','\0'};
trie t;
char output[][32] = { "Not present in trie", "Present in trie" };
int i;
char text[]={"andreiherutshevlastashecristihiskatjaheres"};
initialize(&t);
// Construct trie
for (i = 0; i < ARRAY_SIZE(keys); i++)
{
insert(&t, keys[i], strlen(keys[i]));
}
createFailLinks(&t, t.root, cuv, 0);
printTrie(t.root);
printf("\n\n");
checkLinks(t.root);
search1(&t, text, strlen(text));
return 0;
// Search for different keys
printf("%s --- %s\n", "abcd", output[search(&t, "abcd")]);
printf("%s --- %s\n", "ab", output[search(&t, "ab")]);
printf("%s --- %s\n", "ccdd", output[search(&t, "ccdd")]);
printf("%s --- %s\n", "thaw", output[search(&t, "thaw")]);
return 0;
char a = getchar();
}`
Do you have access to a debugger? I ran your code in a debugger and get a memory access violation at line 157 here:
return searchAux(t, t->root, &cuvAux[failLevel+1], len, 0, failLevel+1);
You seem to be recursively calling searchAux. ie you have:
node* searchAux(trie *t, node *curRoot, char cuv[], char len, int level ,int failLevel)
{
char cuvAux[1024];
...
return searchAux(t, t->root, &cuvAux[failLevel+1], len, 0, failLevel+1);
...
Anyway, eventually the buffer size variable failLevel exceeds the size of your buffer so you are attempting to access memory outside the bounds of your array which is why you get an access violation.
The easiest way to debug is use an interactive debugger. On Windows there is a free version of Visual Studio with a very good debugger. On linux you can use GDB.
Failing that you can embed print statements to print out variables before the crash.
You can add print statements at lines of code.
#include <iostream>
std::cout << "At Line: " << __LINE__ << endl;
putting that at various lines of code, you can see what lines got executed, and find where it crashes.
This is for C++. My bad. Same idea, but put printf() statements and see where it stopped executing to narrow down the crash location.
I want to be able to use my getNextWord function to return a pointer to the next word in the file. I think I'm getting the seg fault while inserting but I just can't figure it out. Any help on this would be excellent. Also, I should probably find a better way of getting my hash_table_size than increasing a count for the total number of words in the file then rewinding. How can I make the size grow automatically?
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
int hash_table_size;
char* getNextWord(FILE* fd) {
char c;
char buffer[256];
int putChar = 0;
while((c = fgetc(fd)) != EOF) {
if(isalnum(c)) break;
}
if(c == EOF) return NULL;
buffer[putChar++] = c;
while((c = fgetc(fd)) != EOF) {
if(isspace(c) || putChar >= 256 -1) break;
if(isalnum(c))
buffer[putChar++] = c;
}
buffer[putChar] = '\0';
return strdup(buffer);
}
struct node {
struct node *next;
int count;
char* key;
};
struct list {
struct node *head;
int count;
};
struct list *hashTable = NULL;
/*
* djb2 hash function
*/
unsigned int hash(unsigned char *str) {
unsigned int hash = 5381;
int c;
while(c == *str++)
hash = ((hash << 5) + hash) + c;
return (hash % hash_table_size);
}
struct node* createNode(char *key) {
struct node *new_node;
new_node = (struct node *)malloc(sizeof(struct node));
strcpy(new_node->key, key);
new_node->next = NULL;
return new_node;
}
void hashInsert(char *str) {
int hash_dex = hash(str);
struct node *new_node = createNode(str);
if(!hashTable[hash_dex].head) {
hashTable[hash_dex].head = new_node;
hashTable[hash_dex].count = 1;
return;
}
new_node->next = (hashTable[hash_dex].head);
hashTable[hash_dex].head = new_node;
hashTable[hash_dex].count++;
return;
}
void display() {
struct node *current;
int i;
while(i < hash_table_size) {
if(hashTable[i].count == 0)
continue;
current = hashTable[i].head;
if(!current)
continue;
while(current != NULL) {
char tmp[256];
strcpy(tmp, current->key);
printf("%s", tmp);
current = current->next;
}
}
return;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: ./hashFile textfile\n");
}
else {
FILE *file = fopen(argv[1], "r");
if(file == 0) {
printf("Could not open file\n");
}
else {
char *new_word;
while((new_word = getNextWord(file)) != NULL) {
hash_table_size++;
}
rewind(file);
hashTable = (struct list *)calloc(hash_table_size, sizeof(struct list));
while((new_word = getNextWord(file)) != NULL) {
hashInsert(new_word);
}
display();
fclose(file);
}
}
return 0;
}
int c;
while(c == *str++)
hash = ((hash << 5) + hash) + c;
c is not initialized here. As is i in display function. Please enable all the compiler warnings and fix them.
Also:
char c;
char buffer[256];
int putChar = 0;
while((c = fgetc(fd)) != EOF) {
if(isalnum(c)) break;
}
c has to be of type int not char.
change
while(c == *str++)
to
while(c = *str++)
I was reading about how to implement a DPDA and found this code in the following Internet address: http://code.zhoubot.com/, This c file implements a simple pushdown automata. The automata will read in a description of their transition function and input, perform its computation on the input, and then print their output.
The input format is like:
e01:e0$:000111:a:ad:aeeb$:b0eb0:b10ce:c10ce:ce$de
The input is separated by a semicolon “:”, first section is “input alphabet”, second is “stack alphabet”, then “input” and the last whole bunch are transition functions.
/* This C file implements a Deterministic Pushdown Automata
* author: Kevin Zhou
* Computer Science and Electronics
* University of Bristol
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct stack {
char content;
struct stack *next;
} Stack;
typedef struct transistion {
char current_state;
char input_symbol;
char pull;
char new_state;
char push;
} Transistion;
/* list of transistion functions */
typedef struct list {
Transistion *content;
struct list *next;
} List;
typedef struct pda {
char *input_alpha;
char *stack_alpha;
char *input;
char start;
char *accept;
List *transistion;
} PDA;
/* create a new empty stack */
Stack *create_stack( void ) {
Stack *s = calloc(1,sizeof(Stack));
if(s==NULL) {
printf("Out of Memory!");
exit(1);
}
return s;
}
/* test if the stack is empty */
int isempty( Stack *s ) {
return (s->next==NULL)? 1:0;
}
Stack *push_stack (Stack *s, char c) {
Stack *new = calloc(1,sizeof(Stack));
if(new ==NULL) {
printf("Out of Memory!");
exit(1);
}
new -> content = c;
new -> next = s;
return new;
}
Stack *pull_stack (Stack *s) {
Stack *head;
if(isempty(s)) {
return '\0';
}
head = s;
s = head -> next;
return s;
}
/*return the top elememt in the stack */
char top (Stack *s) {
return s->content;
}
/* replace a value 'ontop' which on top of the stack with a newvalue 'newvalue'
epsilon represents an empty element*/
Stack *replace(Stack *sta, char ontop, char newvalue, char epsilon) {
if(ontop == epsilon && newvalue == epsilon) return sta;
if(ontop == epsilon && newvalue != epsilon) {
sta = push_stack(sta,newvalue);
return sta;
}
if(ontop != epsilon && newvalue == epsilon) {
if(ontop != top(sta)) return NULL;
sta = pull_stack(sta);
return sta;
}
if(ontop != top(sta)) return NULL;
sta = pull_stack(sta);
sta = push_stack(sta,newvalue);
return sta;
}
/* turn the input string into transistion fields */
Transistion *get_transistion(char *s) {
Transistion *t = calloc(1,sizeof(Transistion));
t->current_state = s[0];
t->input_symbol = s[1];
t->pull = s[2];
t->new_state = s[3];
t->push = s[4];
return t;
}
/* turn the string into transitions and add into list */
List *insert_list( List *l, char *elem ) {
List *t = calloc(1,sizeof(List));
List *head = l;
while(l->next!=NULL)
l = l->next;
t->content = get_transistion(elem);
t->next = NULL;
l->next = t;
return head;
}
/* insert a transistion into a list */
List *insert_list_transistion( List *l, Transistion *tr) {
List *t = calloc(1,sizeof(List));
List *head = l;
while(l->next!=NULL)
l = l->next;
t->content = tr;
t->next = NULL;
l->next = t;
return head;
}
/*test if the char c is in the string s */
int contains ( char c, char *s ) {
int i=0;
while(1) {
if(c== s[i]) return 1;
if(s[i] == '\0') return 0;
i++;
}
}
/* test if the input is a valid input */
int is_valid_input( char *input_alpha, char *input ) {
int i=0;
char c;
while(1) {
c = input[i];
if(c == '\0') break;
if(!contains(c,input_alpha)) return 0;
i++;
}
return 1;
}
/* test if the input is a valid transistion */
int is_valid_transistion ( List *l, PDA *m) {
Transistion *t;
while(1) {
if(l==NULL) break;
t = l->content;
if(!contains(t->input_symbol,m->input_alpha)) return 0;
if(!contains(t->pull,m->stack_alpha)) return 0;
if(!contains(t->push,m->stack_alpha)) return 0;
l = l->next;
}
return 1;
}
/* create a pushdown automata */
PDA *createPDA (char *input) {
PDA *m = calloc(1,sizeof(PDA));
List *tr = calloc(1,sizeof(List));
char *buffer;
char *epsilon = calloc(1,sizeof(char));
/*read input alphabet of PDA*/
buffer = strtok(input,":");
if(buffer == NULL) {
printf("Error in reading input alphabet!\n");
exit(1);
}
m->input_alpha = buffer;
epsilon[0] = m->input_alpha[0];
/*read stack alphabet*/
buffer = strtok(NULL,":");
if(buffer == NULL) {
printf("Error in reading stack alphabet!\n");
exit(1);
}
m->stack_alpha = buffer;
/*read input sequence*/
buffer = strtok(NULL,":");
if(buffer == NULL) {
printf("Error in reading input sequence!\n");
exit(1);
}
if(!is_valid_input(m->input_alpha,buffer)) {
printf("Error! Input contains some invalid characters that don't match the input alphabet!\n");
exit(1);
}
m->input = buffer;
/*read start state*/
buffer = strtok(NULL,":");
if(buffer == NULL) {
printf("Invalid string!\n");
exit(1);
}
m->start = buffer[0];
/*read accept state*/
buffer = strtok(NULL,":");
if(buffer == NULL) {
printf("Invalid string!\n");
exit(1);
}
m->accept = buffer;
/*read transistion function*/
while(1) {
buffer = strtok(NULL,":");
if(buffer == NULL) break;
tr = insert_list(tr,buffer);
}
if(!is_valid_transistion(tr->next,m)) {
printf("Error! Invalid transistion functions!\n");
exit(1);
}
m->transistion = tr->next;
return m;
}
/*print a stack */
void print_stack2(Stack *s) {
if(s==NULL) {
return;
}
print_stack2(s->next);
printf("%c",s->content);
}
void print_stack(Stack *s) {
print_stack2(s);
printf("\n");
}
/* find a proper transition function for the current state */
Transistion *find_transistion(List *list,char input,char current,char e) {
Transistion *t;
while(1) {
if(list==NULL) return NULL;
t = list -> content;
if(t->current_state == current && t->input_symbol == input)
return t;
if(t->current_state == current && t->input_symbol == e)
return t;
list = list->next;
}
}
int isAccept(char current, char* accept) {
int i=0;
while(1) {
if(accept[i]=='\0') return 0;
if(accept[i]==current) return 1;
i++;
}
}
/*simulate the Pushdown automata */
void simulate(PDA *m) {
/* first symbol in input symbol used to represent the usual */
const char epsilon = m->input_alpha[0];
char current_state = m->start;
char input;
int i=0;
Stack *sta = create_stack();
Transistion *current_transistion;
Stack *backup;
while(1) {
/*get input*/
input = m->input[i];
if(input == '\0'&&isAccept(current_state,m->accept)) {
printf("Accept\n");
print_stack(sta);
break;
}
/*get transistion function*/
current_transistion = find_transistion(m->transistion,input,current_state,epsilon);
if(current_transistion==NULL) {
printf("Reject\n");
print_stack(sta);
break;
}
current_state = current_transistion->new_state;
backup = sta;
sta = replace(sta, current_transistion->pull, current_transistion->push,epsilon);
if(sta == NULL) {
printf("Reject\n");
print_stack(backup);
break;
}
if(current_transistion->input_symbol != epsilon&¤t_transistion->input_symbol != '\0')
i++;
}
}
void print(PDA *m) {
printf("input alphabet:%s\n",m->input_alpha);
printf("stack alphabet:%s\n",m->stack_alpha);
printf("input sequence:%s\n",m->input);
printf("start state:%c\n",m->start);
printf("accept state:%s\n",m->accept);
}
int main(void) {
char s[300];
PDA *p;
scanf("%s",s);
p = createPDA(s);
simulate(p);
return 0;
}
When trying to compile, the compiler tells me the following error:
Line 41: "error: invalid conversion from 'void *' to 'Stack *'
how I can fix this error, since I'm trying to understand
code?
You are likely using a C++ compiler instead of a C one. In C it's not required (it's actually discouraged) to cast void *. In C++ it's mandatory.
Incidentally, this C FAQ answers your problem. This one explains why casting void * can be problematic.