I am working for a C exam and while trying to insert an element to a linked list, I am encountering with a runtime problem. My only purpose is adding 4 elements to list and then printing the list. However, it gives an error. I already looked some insertion codes and my code seems right. Can't see the error. Any assistance would be appreciated.
#include <stdio.h>
#include <stdlib.h>
struct ders{
char kod;
struct ders *next;
}*header;
typedef struct ders Ders;
void add(Ders*,Ders*);
void print(Ders*);
int main(void)
{
header = NULL;
Ders *node = NULL;
int i = 0;
char c;
while(i<4)
{
scanf("%c",&c);
node = (Ders*)malloc(sizeof(Ders));
node->kod = c;
node->next = NULL;
add(header,node );
i++;
}
print(header);
return 0;
}
void add(Ders *header, Ders *node)
{
if(header == NULL){
header = node;
header->next = NULL; }
else{
node->next = header;
header = node;
}
}
void print(Ders *header)
{
Ders *gecici = header;
while(gecici != NULL){
printf("%c\n",gecici->kod);
gecici = gecici->next;
}
}
As nihirus stated,
"The pointer is passed by value. Thus you can change the memory it points but you can't change the actual pointer, i.e. make it point to something else."
Your modification resulted in error *header is not member of struct
because
->
has a higher precedence than
*
Try using
(*header)->next = NULL
instead.
C operator precedence:
http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm
Related
I'm trying to create an N-ary tree where I have a char array ex: {A,B,C,D} to insert to a tree.
I set the root to be "/"
if the command is mkdir /A/B/C => create node A at root, then B at A and C at B. if the command is mkdir B/C/D =>create node D inside C, etc... I simplified the code below so hopefully, there won't be any typo here. Anyway, upon debugging with gdb, it looks like the upon reaching search function will give me a segmentation fault, I made the code below, I'm really sure the insert function will have the same error as well but I haven't been able to test it out yet.
head.c
#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define len 128
#define num 128
typedef struct tree{
char name;
char type;
struct node *child, *sibbling, *parentNode;
}node;
char *baseName[64];
node *root, *cwd;
tree.c
node *createNode(node * newNode, char ch, char ty){
node *curNode = (node*)malloc(sizeof(node));
curNode->name = ch;
curNode->type = ty;
curNode->parentNode = newNode;
curNode->sibbling = curNode->child=NULL;
return curNode;
}
node * insertNode(node *parent, char name, char type){
if(parent->child == NULL){
parent->child=parent;
createNode(parent->child,name,type);
}
else{
parent->sibbling = parent;
createNode(parent->sibbling,name,type);
}
}
node *searchNode(node *curNode, char name){
if(curNode->name ==name){ <------------error here
return curNode;
}
if(name != curNode->name && curNode->sibbling != '\0'){
searchNode(curNode->sibbling, name);
}
if(name != curNode->name && curNode->child != '\0'){
searchNode(curNode->sibbling, name);
}
return 0;
}
void mkDir(){
int index = 0;
int flag =0;
int baseFlag=0;
node *pwd = root;
///// insert
while(dirName[index] !='\0'){
if(searchNode(root,dirName[index]) != NULL){ <-- error in this searchNode function //no node exist
// insertNode(pwd,"A","D"); <---this probably error too
printf("found A");
}
else{
//node exist
cwd = searchNode(root,dirName[index]);
insertNode(cwd,dirName[index],"D");
}
index++;
}
}
memset(dirName,'\0',sizeof(dirName));
}
I suspect you are passing in a null node reference to the searchNode function, hence when you try to access the property name you are getting a segfault.
I would recommend testing for and handling for null references in your code.
function createNode return type is node*.In function insertNode you must store the address of new node in some other variable of type node*.
node *r
r=createNode(parent->child,name,type);
....
...
In the function searchNode you must check
if(curnode!=NULL) {
if(curNode->name ==name){
return curNode;
}
}
In the last line you are returning 0 but return type is node*
return either NULL or (node*)0.
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'm working on assignment for an operating systems class. We are given code to use to help us with our assignment, but I have little programming experience with C, and I can't figure out how to use it. What I'm trying to do is print the information at the head of the list. The list is a list of structs defined as
typedef struct
{
char name[NAME_MAX];
int lifetime;
} pcb_t;
int
List_head_info ( List_t *list, void **data )
{
int all_ok = 0;
*data = NULL;
if ((list != NULL) && (list->head != NULL)) {
*data = list->head->data;
all_ok = 1;
}
return all_ok;
}
I tried to display them with:
printf("test: %s", List_head_info(&processes, (void *)pcb)->name);
but I am given the error invalid type argument a->a when compiling.
When you call List_head_info(), you will get back two things:
A pointer (void *) to the head data, or NULL.
A status indicating whether the pointer is non-NULL.
If it returns successfully, you can convert (coerce, or cast) the void * to a pcb_t * and then use that to print the data.
How would I do that specifically?
Probably something a bit like this:
List_t list;
...code to initialize and maybe add things to the list...
void *head_data = 0;
if (List_head_info(&list, &head_data))
{
pcb_t *item = (pcb_t *)head_data;
printf("Lifetime: %.2d; Name: %s\n", item->lifetime, item->name);
}
Strictly, the initialization of head_data is superfluous; the code in List_head_info() always sets the value at least once (to NULL or 0) and sometimes twice (the second time to the data component of the head item on the list).
This is 'example code' with enough information in it to compile. I've 'reverse engineered' the list structures enough to make sense; the actual implementation will be different, of course. This compiles cleanly under fairly stringent GCC warning levels, with GCC 4.1.2 and 4.7.0 on Mac OS X 10.7.4. AFAICS, it avoids some complex issues related to 'strict aliasing' which you really don't want to have to worry about at this stage.
#include <stdio.h>
enum { NAME_MAX = 40 };
typedef struct Node Node;
struct Node
{
void *data;
Node *next;
};
typedef struct
{
Node *head;
Node *tail;
} List_t;
typedef struct
{
char name[NAME_MAX];
int lifetime;
} pcb_t;
extern int List_head_info(List_t *list, void **data);
extern void another_func(List_t processes);
void another_func(List_t list)
{
void *head_data = 0;
if (List_head_info(&list, &head_data))
{
pcb_t *item = (pcb_t *)head_data;
printf("Lifetime: %.2d; Name: %s\n", item->lifetime, item->name);
}
}
int
List_head_info ( List_t *list, void **data )
{
int all_ok = 0;
*data = NULL;
if ((list != NULL) && (list->head != NULL)) {
*data = list->head->data;
all_ok = 1;
}
return all_ok;
}
I've been trying to add a new node into a linked list of profiles (for ex. facebook profiles), and I'm getting a runtime error while launching. This is what I got :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
typedef struct friend {
char *name;
int age;
char gender;
struct friend* next;
} friend;
void node_add(friend* new);
int main(int argc, char *argv[]) {
friend amit;
friend *new;
amit.name = "amit";
amit.age = 16;
amit.gender = 'm';
node_add(new);
new->name = "amit";
printf ("name: %s\n", new->name);
system("PAUSE");
return 0;
}
void node_add(friend* new) {
new = (friend* )malloc(sizeof(friend));
friend* head = new;
new -> next = head;
}
I'm trying now to create a delete node function. I tried to find which node does the user wants to delete, and then delete it by doing
delete -> next = delete -> next -> next
The problem is, I need to get for the first node in the list.
Here is what I wrote:
void node_delete(friend* delete) {
friend *temp;
char name[256];
int i = 0, j = 0;
printf ("Please enter the friend's name you want to delete: \n");
fgets (name, 256, stdin);
fgets (name, 256, stdin);
while (0 == (strcmp(temp -> next -> name, delete -> next -> name))) {
temp = friend -> next;
}
temp -> next = temp -> next -> next;
free (delete);
}
Edit:
It seems my test was a mite too quick, because there is in fact a pretty serious problem with this code, but it's subtle:
In main() you are never actually pointing new at anything. It's just a garbled pointer out into memory space, which might sometimes work, and most of the time, is just terrible.
friend *new; // here's your problem; change this to:
friend *new = malloc(sizeof(friend));
Also, never cast the results of malloc.
Reedit:
How a very simple linked list implementation might look:
typedef struct _node node;
struct _node {
void *payload;
node *next;
};
node *create_node () {
node *retval = malloc(sizeof(node));
retval->payload = NULL;
retval->next = NULL;
return retval;
}
node *add_node (node *target) {
if (target->next)
return;
node *next = create_node();
node->next = next;
}
node *node_search (node *haystack, void *needle) {
while (haystack) {
if (!compare(needle, haystack->payload)) {
return haystack;
} else {
haystack = haystack->next;
}
}
return NULL;
}
Implementation of deletion and insertion are left as an exercise to the reader.
Of course, you alloc memory and assign it to local variable.
If you want to change pointer, pass pointer with one more asterix.
And, by the way, do not name anything like friend or new. Its keywords in C++,
and it create not needed problems.
You should have friend *head global.
And in the
void node_add(friend* new)
{
new = (friend* )malloc(sizeof(friend));
new->next = head;
head = new;
}
You should use a double-pointer.
void node_add(friend **new) {
*new = malloc(sizeof(friend));
/* etc */
}
The issue is in the following line:
amit.name = "amit";
You should be a malloc and doing a strcpy()
I tried to implement a binary search tree for the purpose of (re-)learning C. The problem is that the this current = new; does not work as desired because the tree.root is still a null pointer after adding two nodes. What's wrong with that?
#include <stdlib.h>
#include <stdio.h>
typedef struct BinaryNode {
int key;
double value;
struct BinaryNode *left;
struct BinaryNode *right;
} BinaryNode;
typedef struct BinaryTree {
struct BinaryNode *root;
} BinaryTree;
static void binary_tree_insert_recursive(BinaryNode *current, BinaryNode *new) {
if (current == NULL || current->key == new->key) {
current = new;
} else if (current->key > new->key) {
binary_tree_insert_recursive(current->left, new);
} else if (current->key < new->key) {
binary_tree_insert_recursive(current->right, new);
}
}
void binary_tree_insert(BinaryTree *tree, int key, double value) {
BinaryNode *new = (BinaryNode *) malloc(sizeof(BinaryNode));
new->key = key;
new->value = value;
binary_tree_insert_recursive(tree->root, new);
}
int main(void) {
BinaryTree tree;
binary_tree_insert(&tree, 5, 123);
binary_tree_insert(&tree, 10, 123);
printf("%p\n", tree.root);
return 0;
}
Thank you!
I believe the problem with current = new; is that you are changing your local copy of current. After the function is done, this modification is not visible.
I suspect you want something like:
static void binary_tree_insert_recursive(BinaryNode **current, BinaryNode **new)
{
if (*current == NULL || (*current)->key == (*new)->key) {
*current = *new;
/* ... */
Well explained in the C FAQ.
current is a pointer to a node. When you pass it to binary_tree_insert_recursive from binary_tree_insert the value of the pointer is passed. So although it is changed inside the called function, the change is not reflected in the calling function. You need to modify the function to take the address of the pointer you wish to change:
static void binary_tree_insert_recursive(BinaryNode **current, BinaryNode *new)
{
if (*current == NULL || (*current)->key == new->key) {
*current = new;
all that current = new does is make it so that the variable current points at the thing that new is pointing at. No copying takes place, and the function has no effect on that codepath.
new is a keyword. Choose a different variable name.