Multiple Layers sum in an array - C - arrays

I have faced with a programming challenge, which I had to calculate the sum of every array which is in my nested array.
In this problem the input is given by the user, and we must start from the must inner array, and then sum it with result of outer arrays.
Sample 1:
{1, 2, {3, {4, 5, {6}}, 7}, 8}
Output 1:
6
15
25
36
Sample 2:
{{12, 23, {4, 0, {1}, {1}}}, 0, {1}}
Output 2:
1
1
6
41
1
42
Sample 3:
{1, {2, {{6}}}, {{{7}}}}
Output 3:
6
6
8
7
7
7
16
My idea was to use the Dynamic Prpgramming strategy for solving this problem, but I am not sure about it, and since the limitations in C are a bit more than the other programming languages, everything gets a bit harder.
Edit
I find a similarity between this question, and implementing a calculator using a Stack data structure.
So I decided to implement a stack of strings, and then add all the { and } characters and also numbers to it. I would ignore the spaces and ,. But when reaching a }, we should calculate the sum.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
/*
https://www.techiedelight.com/stack-implementation/
https://stackoverflow.com/a/1922239/20285050
https://stackoverflow.com/a/1726321/20285050
https://stackoverflow.com/a/8257754/20285050 for converting int to string
https://www.educative.io/answers/how-to-convert-a-string-to-an-integer-in-c
https://stackoverflow.com/a/5099675/20285050
*/
struct stack_entry
{
char *data;
struct stack_entry *next;
};
struct stack_t
{
struct stack_entry *head;
size_t stackSize;
};
struct stack_t *newStack(void)
{
struct stack_t *stack = (struct stack_t*)malloc(sizeof *stack);
if (stack)
{
stack->head = NULL;
stack->stackSize = 0;
}
return stack;
}
char *copyString(char *str)
{
char *tmp = (char*)malloc(strlen(str) + 1);
if (tmp)
strcpy(tmp, str);
return tmp;
}
void push(struct stack_t *theStack, char *value)
{
struct stack_entry *entry = (struct stack_entry*)malloc(sizeof *entry);
if (entry)
{
entry->data = copyString(value);
entry->next = theStack->head;
theStack->head = entry;
theStack->stackSize++;
}
else
{
}
}
int isEmpty(struct stack_t *theStack)
{
if (theStack -> stackSize == 0)
{
return 1;
}
return 0;
}
char *top(struct stack_t *theStack)
{
if (theStack && theStack->head)
return theStack->head->data;
else
return NULL;
}
void pop(struct stack_t *theStack)
{
if (theStack->head != NULL)
{
struct stack_entry *tmp = theStack->head;
theStack->head = theStack->head->next;
free(tmp->data);
free(tmp);
theStack->stackSize--;
}
}
void clear(struct stack_t *theStack)
{
while (theStack->head != NULL)
pop(theStack);
}
void destroyStack(struct stack_t **theStack)
{
clear(*theStack);
free(*theStack);
*theStack = NULL;
}
void evaluate(char expression[], int values[])
{
struct stack_t *operations = newStack();
for (int i = 0; i < 1000; i++)
{
char *expChar;
if (expression[i] == ' ' || expression[i] == ',')
{
continue;
}
else if (expression[i] == '{')
{
expChar = &expression[i];
push(operations, expChar);
}
else if (isdigit(expression[i]))
{
char svalue[5];
int value = 0;
while (i < 1000 && isdigit(expression[i]))
{
value = (value * 10) + (expression[i] - '0');
i++;
}
itoa(value, svalue, 10);
push(operations, svalue);
i--;
}
else if (expression[i] == '}')
{
char sans[5];
int ans = 0;
char openBrace = '{';
expChar = &openBrace;
while (!isEmpty(operations) && top(operations) != expChar)
{
char svalue[5];
strcpy(svalue, top(operations));
pop(operations);
int value = atoi(svalue);
ans += value;
values[i] = ans;
// char op[1];
// strcpy(op, top(operations));
// pop(operations);
}
itoa(ans, sans, 10);
push(operations, sans);
}
else {
}
}
}
int main()
{
printf(" ****** please enter an expression for
evaluating******\n");
char data[1000];
fgets(data, 1000, stdin);
int values[1000] = {0};
evaluate(data, values);
}
I will be grateful for any help and advice.

Related

How to insert element into this struct

I am newer to C and do some practice,in this example,i want construct a table which can contains alot of element which is Symbol type,but i don't konw how to write that part.I want to use malloc to allocate heap memory to Symbol and insert into the table(SymbolTable).
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<string.h>
typedef struct {
char *name;
uint32_t addr;
}Symbol;
typedef struct {
Symbol* tbl;
uint32_t len;
uint32_t cap;
int mode;
} SymbolTable; /*this is the table i want to mantiply*/
SymbolTable* create_table(int mode) {
SymbolTable* st = (SymbolTable*)malloc(sizeof(SymbolTable));
if (st != NULL)
{
st->mode = mode;
st->len = 0;
return st;
}
printf("Memory allocation failed!\n");
return NULL;
}
void free_table(SymbolTable* table) {
int i;
for (i = 0; i < table->len; ++i)
{
free(table->tbl[i].name);
free(&(table->tbl[i]));
}
free(table);
}
int add_to_table(SymbolTable* table, const char* name, uint32_t addr) {
if (addr % 4 != 0)
{
printf("Address alignment erron!\n");
return -1;
}
int table_len = table->len;
if (table->mode == 1)
{
int i;
for (i = 0; i < table_len; ++i)
{
if (*((table->tbl[i]).name) == *name)
{
printf("Name existed!\n");
return -1;
}
`I don't know how to inset element here`
}
}
return 0;
}
int main()
{
SymbolTable * st = create_table(0);
add_to_table(st, "aaa", 4);
add_to_table(st, "bb", 8);
write_table(st, stdout);
free_table(st);
}
There are few problems with your code as it is; also, I had to make a few assumptions since you didn't specify those details in your question:
cap is the capacity of table->tbl, i.e. how much memory we have allocated
When adding a new symbol, we should copy the string containing its name, rather than just assigning that pointer to our new Symbol entry.
You should also pick one coding style and stick to it (braces on same vs new line, T* ptr vs T *ptr etc). Finally, I've removed the cast in create_table; see Do I cast the result of malloc?
Here is a fixed version of your code; in add_to_table, if we don't have enough memory to add a new one, we double the capacity of our Symbol array (calling realloc every single time to add space for one more element would be wasteful). When we extend the capacity of our array, we must take care to set each name pointer to NULL, because if we don't and free_table is called when cap > len, we'd be trying to free an uninitialized pointer (whereas calling free on NULL is perfectly fine and does nothing).
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef struct
{
char* name;
uint32_t addr;
} Symbol;
typedef struct
{
Symbol* tbl;
uint32_t len;
uint32_t cap;
int mode;
} SymbolTable; /*this is the table i want to mantiply*/
SymbolTable* create_table(int mode)
{
SymbolTable* st = malloc(sizeof(SymbolTable));
if (st != NULL)
{
st->tbl = NULL;
st->mode = mode;
st->len = 0;
st->cap = 0;
return st;
}
printf("Memory allocation failed!\n");
return NULL;
}
void free_table(SymbolTable* table)
{
int i;
for (i = 0; i < table->cap; ++i)
{
free(table->tbl[i].name);
}
free(table->tbl);
free(table);
}
int add_to_table(SymbolTable* table, const char* name, uint32_t addr)
{
if (addr % 4 != 0)
{
printf("Address alignment erron!\n");
return -1;
}
int table_len = table->len;
if (table->mode == 1)
{
int i;
for (i = 0; i < table_len; ++i)
{
if (!strcmp(table->tbl[i].name, name))
{
printf("Name existed!\n");
return -1;
}
}
if (table_len + 1 > table->cap)
{
// allocate more memory
uint32_t new_cap = table->cap ? table->cap * 2 : 2;
table->tbl = realloc(table->tbl, new_cap * sizeof(*table->tbl));
if (table->tbl == NULL)
{
// handle the error
}
table->cap = new_cap;
int i;
for (i = table_len; i < new_cap; ++i)
{
table->tbl[i].name = NULL;
}
}
uint32_t name_len = strlen(name);
table->tbl[table_len].name = malloc(name_len + 1);
strncpy(table->tbl[table_len].name, name, name_len);
table->tbl[table_len].name[name_len] = '\0';
table->tbl[table_len].addr = addr;
table->len++;
}
return 0;
}
int main(void)
{
SymbolTable* st = create_table(1);
add_to_table(st, "aaa", 4);
add_to_table(st, "bb", 8);
write_table(st, stdout);
free_table(st);
}
Firstly, I think you need to allocate *tbl and set cap (if he contain the max nb of cell in your table) in create_table().
Next, in add_to_table(), try to malloc(sizeof(struct symbol)) if (len < cap) and allocate memory for *name, and set up to your value (don't forget the \0 at the end of *name). Assign this to tbl[len] and do not forget to increment len.
Try to separate in little function, like int is_in_table(const char *name) who return the index or -1, or symbol new_symbol(const char *name, Uint32 addr) who create and set new symbol.
I hope that I have been useful for you :).
Use the concept of implementing Self-Referential structure.
Giving hints:
typedef struct S{
char *name;
uint32_t addr;
S* next;
}Symbol;
typedef struct {
Symbol* tbl;
uint32_t len;
int mode;
} SymbolTable;
http://www.how2lab.com/programming/c/link-list1.php
self referential struct definition?
Possible Implementation
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<string.h>
#include <stdio.h>
typedef struct S{
char *name;
uint32_t addr;
S* next;
}Symbol;
typedef struct {
Symbol* tbl;
uint32_t len;
int mode;
} SymbolTable; /*this is the table I want to maltiply*/
SymbolTable* create_table(int mode) {
SymbolTable* st = (SymbolTable*)malloc(sizeof(SymbolTable));
if (st != NULL)
{
st->tbl = NULL;
st->mode = mode;
st->len = 0;
return st;
}
printf("Memory allocation failed!\n");
return NULL;
}
void free_table(SymbolTable* table) {
free(table);
}
int add_to_table(SymbolTable* table, char* name, uint32_t addr) {
if (addr % 4 != 0)
{
printf("Address alignment erron!\n");
return -1;
}
int table_len = table->len;
if (table->mode == 1)
{
if (table_len == 0)
{
Symbol *t = (Symbol*)malloc(sizeof(Symbol));
t->name = name;
t->next = NULL;
table->len++;
table->tbl = t;
}
else
{
Symbol *t = table->tbl;
while (t->next != NULL)
{
if (t->name == name)
{
printf("Name existed!\n");
return -1;
}
t = t->next;
}
if (t->name == name)
{
printf("Name existed!\n");
return -1;
}
t->next = (Symbol*)malloc(sizeof(Symbol));
table->len++;
t->next->name = name;
t->next->next = NULL;
}
}
return 0;
}
void write_table(SymbolTable *st)
{
Symbol *t = st->tbl;
while (t != NULL)
{
printf("%s\n",t->name);
t = t->next;
}
printf("\n");
}
int main()
{
SymbolTable *st = create_table(0);
st->mode = 1;// Table mode setting to 1 for importing next value to table.
// You may implement it in your own way.
add_to_table(st, "cc", 8);
st->mode = 1;
add_to_table(st, "bb", 8);
st->mode = 1;
write_table(st);
free_table(st);
}

Double pointer in the function

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).

finding a dangling pointer

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.

Hashing, linked list, delete node

My task is to delete a node from a array of pointers which point to structure.
My code doesn't work and I just don't know why:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Jmena4.h"
#define LENGTH 101
#define P 127
#define Q 31
typedef struct node {
char *name;
struct uzel *next;
} NODE;
int hash(const char Name[]) {
int i;
int n = strlen(Name);
int result;
result = Name[0] * P + Name[1] * Q + Name[n - 1] + n;
return result % LENGTH;
}
void Insert(NODE *array[], const char *name) {
NODE *u;
int h;
u = (NODE*)malloc(sizeof(NODE));
u->name = name;
h = hash(name);
u->next = array[h];
array[h] = u;
}
int Search(NODE *array[], const char *name) {
NODE *u;
u = array[hash(name)];
while (u != NULL) {
if (strcmp(u->name, name) == 0) {
printf("%s\n", u->name);
return 1;
}
u = u->next;
}
printf("Name: %s wasn't found\n", name);
return 0;
}
int Delete(NODE *array[], const char *name) {
NODE *current;
NODE *previous;
int position = hash(name);
current = array[position];
previous = NULL;
while (current != NULL) {
if (strcmp(current->name, name) == 0) {
if (previous == NULL) {
array[position] = current->next;
return 1;
} else {
previous->next = current->next;
current = NULL;
return 1;
}
}
previous = current;
current = current->next;
}
return 0;
}
int main() {
int i;
NODE *array[LENGTH];
for (i = 0; i < LENGTH; i++) {
array[i] = NULL;
}
for (i = 0; i < Pocet; i++) {
Insert(array, Jmena[i]);
}
for (i = 0; i < PocetZ; i++) {
Delete(array, JmenaZ[i]);
}
Search(array, "Julie");
system("PAUSE");
return 0;
}
EDIT 1: I changed names of variables and instead of position = array[position] should be current = array[position], but it still doesn't work.
EDIT 2 : In array Jmena is string "Julie" and I can search it after Insert function, but after I delete strings from JmenaZ which not included "Julie" program output is: Name: Julie wasn't found.
For one thing, current isn't initialized before it gets tested in the while loop.

Very weird issue - C & pthreads

I'm having a very strange problem with this bit of code, sorry its pretty messy. Basically its a pagerank algorithm. Each struct webpage is contained in the dynamic array "pages". The pages vector is put through the algorithm until its absolute value (|P|) is smaller than 'epsilon'. Now the issue is with lines 195-201. If i remove the iteration over the array in those lines (i.e. an empty while loop), it works for cases that only require one iteration. However, when i do have the for loop (even for one iteration cases), it throws error6 (line 179, debugging shows e == NULL) without even having run over the inserted loop. Ive set breakpoints etc, and still gives error6 without even having read the extra code. What's going on here? Im pretty new to C and parallel programming so its probably something fundamental. Would appreciate any help!
input format:
number_of_cores
number_of_pages
...
page_names
...
page_links
output format:
...
page_rank
...
code
#include <assert.h>
#include <math.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const double D = 0.85;
static const double EPSILON = 0.005;
int ncores;
int npages;
struct webpage** pages;
int maxdepth;
struct webpage* has(char s[20], int e);
void* threadf(void* ptr);
int quit(void);
double rec(int s, int f, int depth);
struct webpage {
char name[20];
double oldrank;
double rank;
struct node* in;
int incount;
int outcount;
};
struct node {
struct webpage* data;
struct node* next;
};
struct arg {
int s;
int f;
int depth;
double ret;
};
struct webpage*
has(char s[20], int e) {
int p;
for (p=0; p<e; ++p) {
if (strcmp(s, pages[p]->name) == 0) {
return pages[p];
}
}
return NULL;
}
void *
threadf(void* ptr) {
struct arg* curr = (struct arg*)ptr;
curr->ret = rec(curr->s, curr->f, curr->depth);
}
int
quit(void) {
int i;
for(i=0; i<npages; ++i) {
struct node* curr = pages[i]->in;
struct node* next;
while(curr != NULL) {
next = curr->next;
free(curr);
curr = next;
}
free(pages[i]);
}
free(pages);
return 0;
}
double
seq(int s, int f) {
double sum;
sum = 0;
int w;
for (w=s; w<=f; w++) {
struct webpage* curr = pages[w];
double ser;
ser = 0;
struct node* currn = curr->in;
while (currn != NULL) {
struct webpage* n = currn->data;
ser = ser + ((n->oldrank)/(n->outcount));
currn = currn->next;
}
double temp = (((1-D)/npages) + (D*ser));
sum = sum + pow((temp - curr->oldrank), 2);
curr->oldrank = curr->rank;
curr->rank = temp;
}
return sum;
}
double
rec(int s, int f, int depth) {
if (depth == maxdepth ) {
return seq(s, f);
} else {
if (s < f){
int m;
m = (s+f)/2;
struct arg l;
struct arg r;
l.s = s;
l.f = m;
l.depth = depth+1;
r.s = m+1;
r.f = f;
r.depth = depth+1;
pthread_t left, right;
pthread_create(&left, NULL, threadf, (void*) &l);
pthread_create(&right, NULL, threadf, (void*) &r);
pthread_join(left, NULL);
pthread_join(right, NULL);
double res;
res = l.ret + r.ret;
return res;
}
return seq(s, f);
}
}
int
main(void) {
if (scanf("%d", &ncores) != 1) {
printf("error1\n");
return quit();
}
if (scanf(" %d", &npages) != 1) {
printf("error2\n");
return quit();
}
int i;
char n[20];
pages = (struct webpage**)malloc(npages*sizeof(struct webpage*));
for (i=0; i<npages; ++i) {
if (scanf(" %c", n) != 1 || has(n, i) != NULL) {
printf("error3\n");
return quit();
}
pages[i] = (struct webpage*)malloc(sizeof(struct webpage));
struct webpage* curr = pages[i];
strcpy(curr->name, n);
curr->oldrank = 1/npages;
curr->in = NULL;
curr->incount = 0;
curr->outcount = 0;
}
int nedges;
if (scanf(" %d", &nedges) != 1) {
printf("error4\n");
return quit();
}
for (i=0; i<nedges; ++i) {
char f[20], t[20];
if (scanf(" %s %s", f, t) != 2) {
printf("error5\n");
return quit();
}
char from[20], to[20];
strcpy(from, f);
strcpy(to, t);
struct webpage* s = has(from, npages);
struct webpage* e = has(to, npages);
if (s == NULL || e == NULL) {
printf("error6\n");
return quit();
}
s->outcount++;
e->incount++;
struct node* new;
new = (struct node*)malloc(sizeof(struct node));
new->data = s;
if (e->in == NULL) {
e->in = new;
} else {
new->next = e->in;
e->in = new;
}
}
maxdepth = (log(ncores))/(log(2)) + 0.5;
while (sqrt(rec(0, npages-1, 0)) > EPSILON){
int c;
for (c=0; c<npages; ++c) {
struct webpage* curr = pages[c];
curr->oldrank = curr->rank;
}
}
int z;
for (z=0; z<npages; ++z) {
struct webpage* curr = pages[z];
printf("%s %.4lf\n", curr->name, curr->rank);
}
return quit();
}
sample input:
8
4
a
b
c
d
4
a a
output:
error6
char n[20];
[ ... ]
if (scanf(" %c", n) != 1 || has(n, i) != NULL) {
The %c format specifier for scanf reads only one character. So n consists of the character you typed plus whatever garbage happened to be on the stack before you called scanf(). If you use %s, it will consist of the character you typed plus a NUL byte for terminating the string plus garbage you don't care about.
Also note that you can limit the amount of characters scanf() reads by using a width specifier, as in:
scanf("%19s", n)
(meaning: read 19 characters and add a NUL byte). Otherwise, your buffer could overflow, possibly leading to arbitrary code execution (or at least a crash when used by non-malicious users).

Resources