#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define n 5
struct node
{
int num;
char *symbol;
char *code;
struct node *left;
struct node *right;
}*root_ptr, *current, *previous;
void form_bst_of_dividing_positions();
void inorderTraversal(struct node *);
int dividing_positions[n], counter = 0;
int main(int argc, char *argv[])
{
//code to populate dividing_positions
//tree structure formation
counter = 0;
root_ptr = malloc(sizeof(struct node));
root_ptr->num = dividing_positions[0];
root_ptr->code = root_ptr->symbol = NULL;
root_ptr->left = root_ptr->right = NULL;
form_bst_of_dividing_positions();
inorderTraversal(root_ptr);
return 0;
}
void form_bst_of_dividing_positions()
{
for(i=1;i<n;i++)
{
if(dividing_positions[i]==-1)
break;
else
{
struct node nodeToAdd;
nodeToAdd.num = dividing_positions[i];
nodeToAdd.code = nodeToAdd.symbol = NULL;
nodeToAdd.left = nodeToAdd.right = NULL;
current = previous = root_ptr;
while(current!=NULL)
{
previous = current;
current = (dividing_positions[i]<(current->num))? current->left : current->right;
}
if(nodeToAdd.num<(previous->num))
previous->left = &nodeToAdd;
else
previous->right = &nodeToAdd;
}
}
}
void inorderTraversal(struct node *no)
{
if(no!=NULL)
{
inorderTraversal(no->left);
printf("%d ", no->num);
inorderTraversal(no->right);
}
}
Above code gives me Segmentation fault .. in Codeblocks the output window prints 4 infinitely. 2, 3, 1, 4 = to be inserted into BST. Ive converted my Java code to C, are there any specifics to be handled in my above code?
Thanks..
Your nodeToAdd is a local variable, its address becomes invalid once you leave that code block. You should use malloc to create new nodes (and free them with free eventually).
Use malloc everytime you add a new node.
Related
So basically what my code does is creates a WaitingRoom as the HEAD of a list and then it adds students in it ordered alphabetically, this works just fine, but when i try to add another watiningroom it gives me seg fault at the insertinRoom function at firts if.
This is my code, but when i run it with only one WaitingRoom created it works perfectly but if i add another one then it gives me segfault.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct studenti{
char name[100];
struct studenti* next;
}studenti;
typedef struct WaitingRoom{
int ID;
char parola[100];
struct WaitingRoom* next;
struct studenti* next_S;
}WaitingRoom;
studenti* CreateStudent(char* name)
{
studenti* S = (studenti*)malloc(sizeof(studenti));
strcpy(S->name,name);
S->next = NULL;
return S;
}
WaitingRoom* createWaitingRoom(int ID, char* parola){
WaitingRoom* WR = (WaitingRoom*)malloc(sizeof(WaitingRoom));
strcpy(WR->parola,parola);
WR->ID = ID;
WR->next = NULL;
return WR;
}
void insertinRoom(WaitingRoom* WR,char* name){
studenti* S;
S = CreateStudent(name);
if(WR->next_S == NULL || strcmp(WR->next_S->name,name)>0){
S->next=WR->next_S;
WR->next_S = S;
}
else{
studenti* current = WR->next_S;
while(current->next !=NULL && strcmp(current->next->name,name)>0)
{
current=current->next;
}
S->next = current->next;
current->next = S;
}
}
void printWaitingRoom(WaitingRoom* WR){
studenti* current = WR->next_S;
printf("Waiting Romom este %d cu parola %s\n",WR->ID,WR->parola);
while(current!=NULL){
printf("%s\n",current->name);
current = current->next;
}
}
void printall(WaitingRoom* WR){
WaitingRoom* current = WR;
while(current!=NULL){
printWaitingRoom(current);
current = current->next;
}
}
int main()
{
WaitingRoom* WR1 = createWaitingRoom(6969,"Muiedinamo");
insertinRoom(WR1,"BOOm1");
insertinRoom(WR1,"AOOm2");
insertinRoom(WR1,"DOOm3");
insertinRoom(WR1,"COOm4");
/*
WaitingRoom* WR2 = createWaitingRoom(1234,"AStae ");
insertinRoom(WR2,"B1");
insertinRoom(WR2,"AO2");
insertinRoom(WR2,"D3");
insertinRoom(WR2,"C4");
WR1->next = WR2;
*/
printWaitingRoom(WR1);
//printall(WR1);
return 0;
}
I was expecting to created my WaitingRoom and then connecting the waitingrooms and printing them 1 by 1 and the the hole list with "PrintAll" function.
I have to make a list that arrange the people in decreasing order of their number('no' for my program). I tryed to make it by modifying the addNode function but I got no result(peoples do not arrange by their number). This is my code:
Header code:
#ifndef __EX__
#define __EX__
typedef struct Person{
char name[10];
float no;
struct Person *pNext;
} NODE, *pNODE, **ppNODE;
void addNode(ppNODE, pNODE);
void travers(pNODE, unsigned int*);
#endif
Functions folder:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include "EX.h"
void addNode (ppNODE ppPrim, pNODE p){
pNODE q = (pNODE)malloc(sizeof(NODE));
assert(q!=NULL);
printf("Add name: \n");
scanf("%s", &q->name);
printf("\nAdd no: ");
scanf("%f", &q->no);
if (p == NULL || q->no < p->no) {
q->pNext = *ppPrim;
*ppPrim = q;
} else {
q->pNext = p->pNext;
p->pNext = q;
}
return;
}
void travers(pNODE pPrim, unsigned int *pLen){
*pLen = 0;
pNODE tmp = pPrim;
while (tmp != NULL){
puts (tmp->name);
fprintf(stdout, " no %.2f\n", tmp->no);
tmp = tmp->pNext;
(*pLen)++;
}
return;
}
Main folder:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include "EX.h"
int main(){
unsigned int len;
pNODE prim = NULL;
int i;
for (i=0; i<=1; i++){
addNode(&prim, prim);
addNode(&prim, prim->pNext);
}
travers(prim, &len);
return 0;
}
When you insert a new node to the list, you must traverse the list until you find a suitable place to insert it. Your code takes a second argument, which isn't really needed and causes confusion, and only looks at that.
The code to insert a code q at the end of a list that is defined by its head is:
Node *prev = NULL;
Node *p = *head;
while (p) {
prev = p;
p = p->pNext;
}
q->pNext = p;
if (prev == NULL) {
*head = q;
} else {
prev->pNext = q;
}
You can get rid of keeping track of the previous node and the distinction between inserting at the head and inserting after that by traversing the list with a pointer to node pointer:
Node **p = &head;
while (*p && (*p)->no < q->no) {
p = &(*p)->pNext;
}
q->pNext = *p;
*p = q;
In this concise code, p holds the address of the head at first and the address of the pNext pointer of the previous node. Both can be updated via *p.
You can now use this code to traverse only as far as the numbers associated with each node are smaller than the one of the node to insert. here's a complete program:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct Node Node;
void addNode(Node **p, const char *name, float no);
void travers(Node *pPrim, unsigned int *pLen);
struct Node {
char name[10];
float no;
Node *pNext;
};
void addNode(Node **p, const char *name, float no)
{
Node *q = malloc(sizeof(*q));
assert(q != NULL);
snprintf(q->name, sizeof(q->name), "%s", name);
q->no = no;
while (*p && (*p)->no < q->no) {
p = &(*p)->pNext;
}
q->pNext = *p;
*p = q;
}
void traverse(const Node *pPrim, unsigned int *pLen)
{
*pLen = 0;
while (pPrim != NULL) {
fprintf(stdout, "%-12s%.2f\n", pPrim->name, pPrim->no);
pPrim = pPrim->pNext;
(*pLen)++;
}
}
int main()
{
unsigned int len;
Node *prim = NULL;
addNode(&prim, "Alice", 0.23);
addNode(&prim, "Bob", 0.08);
addNode(&prim, "Charlie", 0.64);
addNode(&prim, "Dora", 0.82);
traverse(prim, &len);
printf("\n%u entries.\n", len);
return 0;
}
Things to node:
I've used Node * and Node ** instead of the typedeffed pNODE and ppNODE. In my opinion using the C pointer syntax is clearer.
You should separate taking user input from adding a node.
In your code you shouldn't pass the address of the char array when scanning a string, just the char array. (It happens to work, but it isn't correct. The compiler should warn you about that.)
I seem to have created a selfish function which refuses to pass control back to my main function. I've inserted into my code several output statements to ease debugging, and to prove that the program is resting at the end of my 'add_node()' function. I have included the entire program because I am genuinely perplexed as to where the problem may lie.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
/* All-purpose error function */
void kill(char *error)
{
if(errno != 0) {
perror("Error: ");
} else {
printf("%s", error);
}
exit(1);
}
// A link with string data type
typedef struct slink
{
char value[20];
struct node* prev;
struct node* next;
}slink;
// A link with double data type
typedef struct dlink
{
double value;
struct node* prev;
struct node* next;
}dlink;
// Node structure, contains several links
typedef struct node
{
slink name;
dlink weight;
dlink height;
dlink spins; //Place forhead on bat, count spins until fall.
dlink chug; //Open beer, chug. Record time.
}node;
// Creates a new node and populates it with given data arguments
void add_node(char* n, double w, double h, double s, double c)
{
node* this = malloc(sizeof(node));
bzero(this, sizeof(node));
if(!this) kill("Failed to create node.\n");
strncpy(this->name.value, n, 20);
this->weight.value = w;
this->height.value = h;
this->spins.value = s;
this->chug.value = c;
sort_node(this);
printf("returned flow to add_node\n");
}
/*Compares values of this node to the values of all other nodes
and assigns appropriate ptr values to the links*/
int sort_node(node* this)
{
static bool first_sort = true;
static node* head;
if(first_sort){
this->name.prev = NULL;
this->name.next = NULL;
this->weight.prev = NULL;
this->weight.next = NULL;
this->spins.prev = NULL;
this->spins.next = NULL;
this->chug.prev = NULL;
this->chug.prev = NULL;
first_sort = false;
head = this;
printf("first node sorted successfully\n");
} else {
node* current = head;
//Traverse list searching for logical alphabetical neighbors
while(current->name.value < this->name.value) {
if(current->name.next) {
current = current->name.next;
}
}
this->name.next = current;
this->name.prev = current->name.prev;
current->name.prev = this;
}
return 0;
}
int main(void)
{
add_node("Chiis Manly", 195, 66.5, 39, 23);
printf("chiis added");
add_node("Harrie Malaria", 253, 48, 210, 4);
return 0;
}
The output of this program is as follows:
first node sorted successfully
returned flow to add_node
note that 'printf("chiis added");' in my 'main' function is never run. Thank you all greatly for any assistance!
If the following if statement condition is false:
if(current->name.next) {
Then how will your while loop ever terminate? That's your problem.
See this on debugging small programs.
If you add a fflush(stdout); after printf("chiis added"); you'll see that printf is indeed executed and your program gets stuck somewhere else (see #i_am_jorf's answer).
Whatever you pass to printf() is buffered by the standard library to improve the performance of writing to the terminal. You can manually flush the buffer with fflush().
The problem is somewhere in here....
char buffer[80];
char *name;
while (1) {
fgets(buffer, 80, inf); //reads in at most 80 char from a line
if (feof(inf)) //this checks to see if the special EOF was read
break; //if so, break out of while and continue with your main
name = (char *) malloc(sizeof(char)*20);
....
name = strtok(buffer, " ");//get first token up to space
stock = newStock(name,...)
....
}
I'm working in C with generic linked lists. I made a list implementation that I've tested and know works with chars. I'm trying to add stocks (I created a stock struct) to the linked list, with each node of the linked list holding a stock struct, but when I finish reading in the stocks all of the nodes point to the same struct and I can't figure out why. Here's some snippets of my code
list *list = malloc(sizeof(list));
newList(list, sizeof(stock_t));
while(1) {
...
(read from file)
...
stock_t *stock;
stock = newStock(name, closes, opens, numshares, getPriceF, getTotalDollarAmountF,getPercentChangeF,toStringF);
addToBack(list, stock);
}
Here's the newStock function:
stock_t *newStock(char *name, float closingSharePrice, float openingSharePrice, int numberOfShares, getPrice getP, getTotalDollarAmount getTotal, getPercentChange getPercent, toString toStr) {
stock_t *stock = malloc(sizeof(stock));
stock->stockSymbol = name;
stock->closingSharePrice = closingSharePrice;
stock->openingSharePrice = openingSharePrice;
stock->numberOfShares = numberOfShares;
stock->getP = getP;
stock->getTotal = getTotal;
stock->getPercent = getPercent;
stock->toStr = toStr;
return stock;
}
In a way I see what's wrong. newStock returns a new pointer every time, but it always gets stored in the variable 'stock' which is what every node points to, so it's going to be equal to whatever the last pointer newStock returned was...but I don't see the way around this. I tried having newStock return just a stock_t, and doing addToBack(list, &stock), but that didn't solve the problem either.
Any help would be appreciated!
Here is some code from the list:
typedef struct node {
void *data;
struct node *next;
}node_t;
typedef struct {
int length;
int elementSize;
node_t *head;
node_t *tail;
} list;
void newList(list *list, int elementSize) {
assert(elementSize > 0);
list->length = 0;
list->elementSize = elementSize;
list->head = list->tail = NULL;
}
void addToBack(list *list, void *element) {
node_t *node = malloc(sizeof(node_t));
node->data = malloc(list->elementSize);
node->next = NULL; //back node
memcpy(node->data, element, list->elementSize);
if (list->length == 0) { //if first node added
list->head = list->tail = node;
}
else {
list->tail->next = node;
list->tail = node;
}
list->length++;
}
Here's code from the stock struct:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef float (*getPrice)(void *S);
typedef float (*getTotalDollarAmount)(void *S);
typedef float (*getPercentChange)(void *S);
typedef char *(*toString)(void *S);
typedef struct stock{
char *stockSymbol;
float closingSharePrice;
float openingSharePrice;
int numberOfShares;
getPrice getP;
getTotalDollarAmount getTotal;
getPercentChange getPercent;
toString toStr;
}stock_t;
The generic functions probably seem like overkill but this is for homework (if you couldn't tell already) so we were asked to specifically use them. I don't think that has anything to do with the problem though.
Here are the definitions for those functions anyway
float getPriceF(void *S) {
stock_t *stock = (stock_t*)S;
return stock->closingSharePrice;
}
float getTotalDollarAmountF(void *S) {
stock_t *stock = (stock_t*)S;
return ((stock->closingSharePrice) * (stock->numberOfShares));
}
float getPercentChangeF(void *S) {
stock_t *stock = (stock_t*)S;
return ((stock->closingSharePrice - stock->openingSharePrice)/(stock->openingSharePrice));
}
char *toStringF(void *S) {
stock_t* stock = (stock_t*)S;
char *name = malloc(20*sizeof(char));
//sprintf(name, "Symbol is: %s. ", (stock->stockSymbol));
return stock->stockSymbol;
}
void printStock(void *S) {
char *str = toStringF(S);
printf("%s \n", str);
}
And this is how I'm traversing the list:
typedef void (*iterate)(void *); //this is in the list.h file, just putting it here to avoid confusion
void traverse(list *list, iterate iterator) {
assert(iterator != NULL);
node_t *current = list->head;
while (current != NULL) {
iterator(current->data);
current = current->next;
}
}
And then in my main I just called
traverse(list, printStock);
I can't find any problems with your code (that would cause your problem, anyway - there are places where you don't check the return from malloc() and stuff like that, but those are not relevant to this question). You don't supply the definition of stock_t, so I made a new data struct, and a new couple of functions, otherwise I just copied and pasted the code you provided:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/* Your code starts here */
typedef struct node {
void *data;
struct node *next;
}node_t;
typedef struct {
int length;
int elementSize;
node_t *head;
node_t *tail;
} list;
void newList(list *list, int elementSize) {
assert(elementSize > 0);
list->length = 0;
list->elementSize = elementSize;
list->head = list->tail = NULL;
}
void addToBack(list *list, void *element) {
node_t *node = malloc(sizeof(node_t));
node->data = malloc(list->elementSize);
node->next = NULL; //back node
memcpy(node->data, element, list->elementSize);
if (list->length == 0) { //if first node added
list->head = list->tail = node;
}
else {
list->tail->next = node;
list->tail = node;
}
list->length++;
}
/* Your code ends here */
/* I made a new struct, rather than stock, since you didn't supply it */
struct mydata {
int num1;
int num2;
};
/* I use this instead of newStock(), but it works the same way */
struct mydata * newNode(const int a, const int b) {
struct mydata * newdata = malloc(sizeof *newdata);
if ( newdata == NULL ) {
fputs("Error allocating memory", stderr);
exit(EXIT_FAILURE);
}
newdata->num1 = a;
newdata->num2 = b;
return newdata;
}
/* I added this function to check the list is good */
void printList(list * list) {
struct node * node = list->head;
int n = 1;
while ( node ) {
struct mydata * data = node->data;
printf("%d: %d %d\n", n++, data->num1, data->num2);
node = node->next;
}
}
/* Main function */
int main(void) {
list *list = malloc(sizeof(list));
newList(list, sizeof(struct mydata));
struct mydata * data;
data = newNode(1, 2);
addToBack(list, data);
data = newNode(3, 4);
addToBack(list, data);
data = newNode(5, 6);
addToBack(list, data);
printList(list);
return 0;
}
which outputs this:
paul#MacBook:~/Documents/src$ ./list
1: 1 2
2: 3 4
3: 5 6
paul#MacBook:~/Documents/src$
demonstrating that you have a 3 node list, with all nodes different and where you'd expect them to be.
Either there is some other problem in code you're not showing, or for some reason you are thinking each node points to the same struct when it actually doesn't.
One possibility is that you have a char * data member in your stock struct. It's impossible to tell from the code you provided, but it's possible that you really are creating different nodes, but they all end up pointing to the same name, so they just look like they're the same. If you're assigning a pointer to name, you should make sure it's freshly allocated memory each time, and that you're not just, for instance, strcpy()ing into the same memory and assigning the same address to each stock struct.
EDIT: Looks like that was your problem. This:
name = (char *) malloc(sizeof(char)*20);
....
name = strtok(buffer, " ");
should be:
name = (char *) malloc(sizeof(char)*20);
....
strcpy(name, strtok(buffer, " "));
Right now, you malloc() new memory and store a reference to it in name, but then you lose that reference and your memory when you overwrite it with the address returned from strtok(). Instead, you need to copy that token into your newly allocated memory, as shown.
I have the following C program:
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
typedef struct node_t node_t;
struct node_t
{
char *name;
node_t **nodes;
};
node_t* init(int p_n)
{
node_t *node = malloc(sizeof(node_t));
node->name = "_ROOT_";
if(p_n > 0 && p_n < 10)
{
node->nodes = malloc(p_n*sizeof(node_t**));
char nbuffer[9];
int i;
for(i = 0; i < p_n; i++)
{
node_t *child = malloc(sizeof(node_t));
sprintf(nbuffer, "NAME %d", i);
child->name = nbuffer;
node->nodes[i] = child;
}
}
return node;
}
int main(int argc, char *argv[])
{
int n = 3;
node_t *ROOT = init(n);
printf("%sNODE {name:%s [%lu]}\n",
"", ROOT->name, sizeof(ROOT->nodes)/sizeof(ROOT->nodes[0])
);
assert(n == sizeof(ROOT->nodes)/sizeof(ROOT->nodes[0]));
free(ROOT);
return 0;
}
The assertion from the beginning of the main method fails and this is my problem. What I am doing wrong in the evaluation of the length of member nodes?
This post is know by me but from some reason it doesn't work for me. Why?
SK
Assuming a 32 bit pointer.
The sizeof(ROOT->nodes) is going to be 4 bytes. A pointer to a pointer it still a pointer.
The sizeof(ROOT->nodes[0]) is also going to be 4 bytes. It too is a pointer.
Hence 4/4 != 3 and your assert fails.
I'm not sure what your objective is, but if you're wanting to do something like this with dynamically allocated storage you might do something like the following. It can be extended with additional APIs to add, remove, etc. This solution maintains a count of the number of elements in the list.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define NAME_SIZE 32
typedef struct node_s {
char *name;
} node_t;
typedef struct node_list_s {
int count;
node_t *nodes;
} node_list_t;
void init(node_list_t *l, int p_n) {
int i = 0;
char name[NAME_SIZE];
if(!l) return;
memset(l, 0, sizeof(node_list_t));
l->nodes = malloc(p_n*sizeof(node_t));
l->count = p_n;
for(i=0;i<l->count;i++) {
snprintf(name,sizeof(name),"NAME %d",i);
l->nodes[i].name = strdup(name);
}
}
void term(node_list_t *l) {
int i = 0;
if(!l) return;
for(i=0;i<l->count;i++) {
if(l->nodes[i].name) free(l->nodes[i].name);
}
if(l->nodes) free(l->nodes);
}
void print(node_list_t *l) {
int i = 0;
if(!l) return;
for(i=0;i<l->count;i++) {
printf("%d %s\n", i, l->nodes[i].name ? l->nodes[i].name : "empty" );
}
}
int main(int argc, char *argv[]) {
node_list_t list;
init(&list, 3);
print(&list);
term(&list);
return 0;
}