Failed to add a node to linked list - c

I make the changes but
I can't add more than 2 nodes its will freez but if 1 or 2 node will work well what is the reason??? I gave_up
I can do nothing for that
This is my code till time
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
struct info{
int num;
char name[15];
struct info *next;
};
struct info *first,*current,*new_s;
int struct_num;
void add_struct(void);
int main(){
first=NULL;
add_struct();
puts("done");
add_struct();
puts("done");
add_struct();
puts("done");
return(0);
}
//struct add function
void add_struct(void){
new_s= malloc (sizeof(struct info));
if(!new_s){
puts("error");
exit (1);
}
if(first==NULL){
first = current= new_s;
first->next = NULL;
}else{
current=first;
while(current->next!=NULL){
current=current->next;
}
current->next=new_s;
current=new_s;
}
struct_num++;
}

The problem in your code is
if( first==NULL){
first->next=new_s;
if first is NULL, you should not dererefence it. It is logically wrong, and invokes undefined behaviour.
I think, what you want instead, is something like (pseudo-code)
if(first == NULL){
first = new_s;
first->next = NULL;
That said,
current->next=new_s;
current=new_s;
also looks problematic. The second statement there is wrong and not required, rather, you can add something like
current->next = new_s;
current->next->next = NULL;
Finally, your struct_num variable should be global, as per the current usage.
Note:
The recommended signature of main() is int main(void).
Please do not cast the return value of malloc() and family in C.
Always check for malloc() success before using the returned pointer.

Function add_struct is wrong
For example if first is equal to NULL then you may not write
first->next=new_s;
Take into account that there is no any sense to declare local variable of the function struct_num because it is always destroyed after exiting the function and moreover it even is not initialized in the function.
int struct_num;
If you need a count of nodes in the list then place it outside the function.
The function itself can look the following way
int struct_num;
int add_struct( void )
{
new_s = ( struct info * )malloc( sizeof( struct info ) );
if ( new_s == NULL ) return 0;
// initialize data members num and name of the allocated structure
new_s->next = NULL;
if ( first == NULL )
{
first = new_s;
}
else
{
current->next = new_s ;
}
current = new_s;
++struct_num;
return 1;
}

Related

runtime error: null pointer passed as argument 1, which is declared to never be null

I wrote a program that creates Linkedlists with two values.
It worked when I just had int values in it but now that I added char* this error messages shows
runtime error: null pointer passed as argument 1, which is declared to never be null
As mentioned before this worked fine until I added char* to the constructor and the struct. Not sure where it goes wrong as the error seems to come from different lines in the code everytime I run it... So what do i need to change ?
#include <stdio.h>
#include <cs50.h>
#include <string.h>
typedef struct node {
int val;
char* name;
struct node *next;
} node_t;
void addFirst(int value, char* word, node_t** nd) {
//initialize new node, allocate space, set value
node_t * tmp;
tmp = malloc(sizeof(node_t));
tmp->val = value;
strcpy(tmp->name, word);
//let the new nodes next pointer point to the old head
tmp->next = *nd;
//Make tmp the head node
*nd = tmp;
}
int findItem(int value,char* word, node_t *nd) {
if(nd->val == value)
return 0;
while(nd->next != NULL) {
if(nd->val == value && strcmp(word, nd->name) == 0)
return 0;
if(nd->next != NULL)
nd = nd->next;
}
return -1;
}
int main (void) {
node_t *head = malloc(sizeof(node_t));
head->val = 0;
strcpy(head->name, "");
head->next = NULL;
addFirst(15, "word", &head);
addFirst(14,"word2", &head);
printf("%i \n", findItem(15, "word", head));
}
The problem is in strcpy(head->name, "");. Here, you;re trying to use the memory location pointer to by head->name, but you never assigned a valid memory to it.
You need to make sure that the pointer points to a valid memory location, before you write to / read from that memory location. Attempt to access invalid memory invokes undefined behavior.
This is applicable for other uninitialized instances of name, too.
If you can live with POSIX standard, instead of strcpy(), you can make use of strdup()

Why is my linked list only printing last entry?

I'm trying to read specific lines from a file and add it to a linked list and then print it out.
Code below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list {
int uid;
char* uname;
struct list* next;
}node;
void push(node ** head, int uid ,char* uname) {
node * new_node;
new_node = malloc(sizeof(node));
new_node->uid = uid ;
new_node->uname=uname;;
new_node->next = *head;
*head = new_node;
}
void print_list(node *head) {
node * current = head;
while (current != NULL) {
printf("%u:%s\n", current->uid,current->uname);
current = current->next;
}
}
int main(int argc, char **argv){
node *current=NULL;
FILE *fp=fopen(argv[1],"r" );
if (fp==NULL){
perror("Failed to open file");
exit(EXIT_FAILURE);
}
char s[1024];
const char token[2]=":";
char *stoken;
while(!feof(fp)){
int count=0;
int tempint;
char* tempchar=malloc(sizeof(char));
fgets(s, 1024, fp);
stoken = strtok(s,token);
current=malloc(sizeof(node));
while(stoken != NULL){
if (count==0){
tempchar=stoken;
}
if (count==2){
sscanf(stoken,"%d",&tempint);
}
count++;
stoken=strtok(NULL,token);
}
push(&current,tempint,tempchar);
}
fclose(fp);
print_list(current);
}
My problem is when print_list is ran the only thing who gets printed is the last entry.
For this input :
hello:asd:123:foo:ar
hi:proto:124:oo:br
hey:qwe:321:fo:bar
the only thing which gets printed is
321:hey
is it my push which is wrong or my print_list?
The problem is the way you are treating the result of strtok: you are setting its value right into the node, instead of copying it.
Make a copy of name when adding a node:
void push(node ** head, int uid ,char* uname) {
node * new_node;
new_node = malloc(sizeof(node));
new_node->uid = uid;
new_node->uname=malloc(strlen(uname)+1);
strcpy(new_node->uname, uname);
new_node->next = *head;
*head = new_node;
}
You should also look at the way that you are using tempchar in the main function. You allocate a space for a single character to it, which gets written over with the result of strtok, leaking the malloc-ed memory.
It's because you always overwrite head in the push() function, you should make it NULL initially and then check if it's NULL the first time and assign to it the first node, and then don't reassing anything to it, your program has a memory leak because of this too.
Also you are malloc()ing the node outside the function and then inside the function again,which causes another memory leak.
You should also check if malloc() returns NULL which indicates an error like when the system runs out of memory, dereferencing a NULL pointer is undefined behavior.
And a final note, you must check the return value of scanf() before accessing the target variables, or that would again cause undefined behavior.
change like as follows
char* tempchar;//=malloc(sizeof(char));
fgets(s, 1024, fp);
stoken = strtok(s,token);
//current=malloc(sizeof(node));//don't update like this
while(stoken != NULL){
if (count==0){
tempchar=strdup(stoken);//malloc and strcpy

Why does malloc fail to allocate more than once?

I coded a simple source. It contains a queue and some of the function a queue needs but for some reason malloc() only works once.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define QUEUE sizeof(Queue)
Definition of the Node, which is an element of the list, and the queue.
typedef struct node {
char * value;
struct node * next;
} Node;
typedef struct queue {
Node * head;
Node * tail;
} Queue;
int initialization(void ** list, int type){
int code = -1;
//create an empty list.
//if queue dynamically allocate memory and assign NULL to both properties head and tail.
return code;
}
enqueue() add one element in the queue at a time. but for some reason it can only add one element then the program crashes.
int enqueue(Queue * q, char * instruction){
int code = -1;
if(q != NULL){
printf("Prepare to enqueue!\n");
Node * n = NULL;
n = (Node*)malloc(sizeof(Node));
if(n != NULL){
printf("Node created!\n");
strcpy(n->value, instruction);
n->next = NULL;
//if first value
if(q->head == NULL){
q->head = n;
q->tail = n;
printf("Enqueue first Node\n");
}
else {
q->tail->next = n;
q->tail = n;
printf("Enqueue another Node\n");
}
code = 0;
printf("Node \"%s\" Enqueued\n", instruction);
}
}
return code;
}
int dequeue(Queue * q){
int code = -1;
//dequeuing code here.
return code;
}
int isEmpty(void * list, int type){
int code = 0;
//check if the list is empty
return code;
}
the for loop in the main() function never reaches 3
int main(int argc, char * argv[]){
Queue * queue = NULL;
initialization((void*)&queue, QUEUE);
int i = 0;
for(i = 0; i < 3; i++){
if(enqueue(queue, "some value") != 0){
printf("couldn't add more Node\n");
break;
}
}
while(!isEmpty(queue, QUEUE)){
dequeue(queue);
}
return 0;
}
The initialization function is written this way because it should also be able to initialize stacks (I removed the stack code to reduce the source but even without it the bug persist). I also put printfs to debug the code. And I have more than enough memory to make this simple code run how it should.
Thanks in Advance!
Running this, I crash with a segmentation fault, as I'd expect:
n = (Node*)malloc(sizeof(Node));
n is allocated, it's contents uninitialized and effectively random
if(n != NULL){
n is not NULL, so...
strcpy(n->value, instruction);
And we crash.
See the problem? n->value is a pointer to nowhere. Or, to somewhere, but nowhere known. Nowhere good. And we're just dumping a string into that space.
Either change the Node struct so that value is a char [SOME_SIZE], or use strdup() instead of strcpy(), to actually allocate some memory for the poor thing.
n->value = strdup(instruction);

C function returning structure data through one of the arguments

I have an issue when using pointer parameters in a function to return values. The function correctly loads all values inside the function, but then somehow fails to pass the pointer value to the variable in the arguments.
In my case, i wrote a function witch returns 1 or 0 depending on whether allocation of memory in question failed or not, and as one of the parameters, takes a pointer to a list that needs to be entered. The structure of the list looks like this:
typedef struct sList {
int id;
char first_name[30];
char last_name[30];
struct sList *next;
} tList;
The function looks like this:
int readList(tList *start, int n){
tList *head = NULL;
tList *tail = NULL;
int i;
for (i = 0; i < n; i++){
tList *tmp = malloc(sizeof(tList));
if (tmp == NULL) return 0;
scanf("%d %s %s", &tmp->id, &tmp->first_name, &tmp->last_name);
tmp->next = NULL;
if (!head) head = tmp;
else tail->next = tmp;
tail = tmp;
}
start = head;
return 1;
}
And the main method:
void main(){
tList *start = NULL;
int n;
scanf("%d", &n);
readList(start, n);
tList *tmp = start;
while (tmp){
printf("%d %s %s\n", tmp->id, tmp->first_name, tmp->last_name);
tmp = tmp->next;
}
system("PAUSE");
return;
}
During debugging, i have concluded that the list head and start inside the function have all the entered values, but as soon as I leave the function and return to the main program the start list goes bananas. So, my question is, am I doing something wrong, because, to my knowledge, this should work in theory. Thanks in advance.
If you want to change a variable from within a function, you need to pass a pointer to it and dereference that pointer within said function. That's how C emulates pass-by-reference.
When that variable is itself a pointer, that means you need to pass a pointer to the pointer, such as with:
int readList(tList **pStart, int n){
// blah blah blah, setting up head.
*pStart = head;
return 1;
}
int main(void){
tList *start = NULL;
int n;
scanf("%d", &n);
readList(&start, n); // Note this, using address-of
// more blah
return 0;
}
The text below is an aside to your specific problem but I thought I'd mention it for completeness.
Your main function doesn't conform to the canonical ones allowed by the standard - I've changed it to make that more acceptable but it may not be necessary for your particular implementation, depending on how lax it is. It's still a good idea to follow the standard.
It's also dangerous to assume (in robust code) that scanf() always works. If it returns zero (number of items successfully scanned), n will almost certainly not be what you expect.
You make the same mistake with readList() in that you don't check its return value either. It also has the annoying aspect of causing memory leaks if an allocation fails.

Pointer trouble creating binary trees

I am creating a binary tree from a bitstring in c. ie 1100100 creates a tree:
1
/ \
1 1
I decided to use a recursive function to build this tree however i keep getting the error
Debug assertion failed...
Expression : CrtIsValidHeapPointer(pUserData)
here is a fragment of my code
typedef
struct Node {
char key;
struct Node *left;
struct Node *right;
} Node;
char string[1000];
int i = 0;
void insertRecursivePreorder(Node **node)
{
Node* parent = *node;
if(string[i] == '0')
{
parent = NULL;
i++;
}
else
{
Node *newn = (Node*)malloc(sizeof(Node));
newn->key = string[i];
parent = newn;
i++;
insertRecursivePreorder(&newn->left); //errors occur here
insertRecursivePreorder(&newn->right); //errors occur here
free(newn);
free(parent);
}
}
int main(void)
{
void printTree(Node* node);
Node* root = NULL;
scanf("%s", string);
insertRecursivePreorder(&root);
//... do other junk
}
i was wondering why this error comes about and what i can do to fix it.
The immediate problem is likely to be calling free on a pointer twice. In insertRecursivePreorder, you set parent to newn, and then call free on both. As an example of this, the following program fails (but works if you comment out one of the free(..)s):
#include <stdlib.h>
int main() {
int *a = malloc(sizeof(int)),
*b = a;
free(a);
free(b);
return 0;
}
However, there are several problems with your logic here. You should only call free when you have completely finished with the pointer, so if you are using your tree later you can't free it as you construct it. You should create a second function, recursiveDestroyTree, that goes through and calls free on the tree (from the bottom up!).
And, you probably want *node = newn rather than parent = newn, since the latter is the only one that actually modifies node.
(You could also change your function to return a Node * pointer, and then just go:
root = insertRecursivePreorder();
and
newn->left = insertRecursivePreorder();
newn->right = insertRecursivePreorder();
instead of trying to keep track of pointers to pointers etc.)
(Furthermore, on a stylistic point, using global variables is often bad practice, so you could have your insertRecursivePreorder take int i and char * string parameters and use them instead of global variables.)
The problem was: you were never assigning to the double pointer in 'insertRecursivePreorder', so root always stayed NULL.
#include <stdio.h>
#include <stdlib.h>
typedef
struct Node {
char key;
struct Node *left;
struct Node *right;
} Node;
/* slightly changed the syntax for the str
** ; now '.' indicates a NULL pointer, values represent themselves.
*/
char *string = "12..3.." ;
/* Removed the global index 'i' */
void printTree(Node* node, int level);
unsigned insertRecursivePreorder(Node **pp, char *str);
unsigned insertRecursivePreorder(Node **pp, char *str)
{
unsigned pos =1;
if (!*str) { *pp = NULL; return 0; } /* safeguard for end of string */
if (*str == '.') { *pp = NULL; return pos; }
*pp = malloc(sizeof **pp);
(*pp)->key = *str;
pos += insertRecursivePreorder(&(*pp)->left, str+pos);
pos += insertRecursivePreorder(&(*pp)->right, str+pos);
return pos;
}
void printTree(Node* node, int level)
{
unsigned pos,len;
len = level> 0 ? level : -level;
for (pos =0; pos < len; pos++) putchar (' ');
if (!level) printf ("Root=");
else if (level<0) printf ("Left=");
else printf ("Right=");
if (!node) { printf( "Null\n" ); return; }
printf("Key=%c\n", node->key );
printTree(node->left, -(len+1) ) ;
printTree(node->right, len+1) ;
}
int main(void)
{
Node *root = NULL;
unsigned result = 0;
result = insertRecursivePreorder(&root, string);
printf( "Result=%u\n", result);
printTree(root, 0);
return 0; printTree(root, 0);
}
Output:
Result=7
Root=Key=1
Left=Key=2
Left=Null
Right=Null
Right=Key=3
Left=Null
Right=Null

Resources