How to make changes in an array through a function - c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 10
// A hashtable is a mixture of a linked list and array
typedef struct node NODE;
struct node{
int value;
NODE* next;
};
int hash(int);
void insert(int,NODE **);
int main(){
NODE* hashtable[SIZE];
insert(12,&hashtable[SIZE]);
printf("%d\n",hashtable[5]->value);
}
int hash(int data){
return data%7;
}
void insert(int value,NODE **table){
int loc = hash(value);
NODE* temp = malloc(sizeof(NODE));
temp->next = NULL;
temp->value = value;
*table[loc] = *temp;
printf("%d\n",table[loc]->value);
}
The above code prints :
12 and
27475674 (A random number probably the location.)
how do I get it to print 12 and 12 i.e. how to make a change in the array. I want to fill array[5] with the location of a node created to store a value.

The expression *table[loc] is equal to *(table[loc]) which might not be what you want, since then you will dereference an uninitialized pointer.
Then the assignment copies the contents of *temp into some seemingly random memory.
You then discard the memory you just allocated leading to a memory leak.
There's also no attempt to make a linked list of the hash-bucket.
Try instead to initially create the hashtable array in the main function with initialization to make all pointers to NULL:
NODE* hashtable[SIZE] = { NULL }; // Will initialize all elements to NULL
Then when inserting the node, actually link it into the bucket-list:
temp->next = table[loc];
table[loc] = temp;

This is just a simple change which I have made to your program which will tell you what you are actually doing wrong.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 10
// A hashtable is a mixture of a linked list and array
typedef struct node NODE;
struct node {
int value;
NODE* next;
};
NODE *hashtable[SIZE] = { NULL };
int hash(int);
int insert(int); //, NODE **);
int main(void)
{
int loc = insert(12); //, &hashtable[SIZE]);
if (loc < SIZE) {
if (hashtable[loc]) {
printf("%d\n", hashtable[loc]->value);
} else {
printf("err: invalid pointer received\n");
}
}
return 0;
}
int hash(int data)
{
return data%7;
}
int insert(int value) //, NODE *table[])
{
int loc = hash(value);
printf("loc = %d\n", loc);
if (loc < SIZE) {
NODE *temp = (NODE *) malloc(sizeof(NODE));
temp->value = value;
temp->next = NULL;
hashtable[loc] = temp;
printf("%d\n", hashtable[loc]->value);
}
return loc;
}
Here I have declared the hashtable globally just to make sure that, the value which you are trying to update is visible to both the functions. And that's the problem in your code. Whatever new address you are allocating for temp is having address 'x', however you are trying to access invalid address from your main function. I just wanted to give you hint. Hope this helps you. Enjoy!

Related

no effect happening to the program when i am putting r=NULL in function ins()

While working with the pointers we are working on address, right?
So when a struct node pointer n is passed to t(struct node *t=n) and later if t is assigned NULL shouldn't n also become NULL?
ps-: it's a program of a binary tree
#include<stdio.h> //check at third line of ins() function
#include<stdlib.h>
struct node{
int data;
struct node* left,*right;
};
struct node* n(int dat){
struct node *x=(struct node*)malloc(sizeof(struct node));
x->data=dat;
x->left=NULL; x->right=NULL;
return x;
};
void ins(struct node* n,struct node* r){
struct node* t=r,*y=NULL; //ok so when i put r=NULL in this next line should this block of memory go
//r=NULL; //NULL
while(t!=NULL){
y=t;
if(t->data>n->data)
{
if(t->left==NULL)
{t->left=n;
t=NULL;
}
else
t=t->left;
}
else {
if(t->right==NULL){
t->right=n;
t=NULL;
}else
t=t->right;
}
}
}
void inorder(struct node* n){
if(n!=NULL){
inorder(n->left);
printf("%d ",n->data);
inorder(n->right);
}}
void main(){
struct node *a,*b,*c,*d,*e,*f,*g,*h;
a=n(32); b=n(20); c=n(100); d=n(16);
e=n(25); f=n(50); g=n(144); h=n(19);
a->left=b; a->right=c;
b->left=d; b->right=e;
c->left=f; c->right=g;
ins(h,a);
inorder(a);
}```
With struct node* t=r you are creating a new and independent variable t that points to the same location as r (lets call that A).
This means any changes to *r are reflected in *t as they both point to the same location A.
when assigning NULL to r, the t variable still points to location A, but r no longer does.
A small example:
int A = 0;
int *r = &A;
int *t = r;
// *r==0, *t==0, point to same location
*r = 55;
// *r==55, *t==55 (same location)
r = NULL;
// *t==55 (*r is no longer valid as r is NULL)

How to initialize struct values and output the struct correctly

I'm attempting some homework and not sure where to go from here, or if I'm on the right path to doing this correctly. This program was given to me with the goal of creating a function to create a new node with an array large enough to hold the input "count". From there I assume I'm supposed to output the created node.
I've tried setting up the node multiple ways with different pointers, I'm not sure how to initialize the 'newnode' correctly though. And every time I try to use the input 'count' such as 'newnode->array_length = count;' I get a segmentation fault, I don't understand why though, if count is input into the function, isn't it usable in the scope of it?
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<assert.h>
typedef struct node {
struct node* previous;
struct node* next;
int array_length;
int* values;
} node;
//creates a new node with an array large enough to hold `count` values
node* create_node(int count) {
//your code here:
node* newnode;
newnode = (node*) malloc(sizeof(node));
newnode->array_length = count;
newnode->values;
newnode->next=NULL;
newnode->previous=NULL;
return newnode;
}
void append(node* a, node* b) {
assert(a);
assert(b);
a->next = b;
b->previous = a;
}
int main() {
node* a = create_node(10);
assert(a->array_length == 10);
assert(a->next == NULL);
assert(a->previous == NULL);
node* b = create_node(20);
assert(b->array_length == 20);
assert(b->next == NULL);
assert(b->previous == NULL);
append(a, b);
assert(a->next == b);
assert(b->previous == a);
assert(a->previous == NULL);
assert(b->next == NULL);
for(node* cur = a; cur != NULL; cur = cur->next) {
for(int i = 0; i < cur->array_length; i++) {
cur->values[i] = i;
}
}
}
Compilation Errors:
problem2.c: In function ‘create_node’:
problem2.c:20:30: warning: implicit declaration of function ‘size’ [-Wimplicit-function-declaration]
newnode->values = malloc(size(int) * count);
^~~~
problem2.c:20:35: error: expected expression before ‘int’
newnode->values = malloc(size(int) * count);
^~~
You're not allocating memory for values. It's set by default to whatever memory was there before, which was probably an invalid pointer. This would cause a segfault when you tried to access values.
//creates a new node with an array large enough to hold `count` values
node* create_node(int count) {
//your code here:
node* newnode = malloc(sizeof(node));
newnode->array_length = count;
newnode->values = malloc(sizeof(int) * count); // malloc memory for values
newnode->next = NULL;
newnode->previous = NULL;
return newnode;
}

Segmentation Fault (singal 11 sigsegv) with linked list

Was writing a program to practice before with linked lists and pointers before pset5 and am left with two memory errors that i have not been able to remedy.
#include <stdio.h>
#include <stdlib.h>
//define struct for Nodes
typedef struct list
{
int data;
int key;
struct list* next;
}Node;
//function declarations
Node* create(int a, int *counter);
void insert(int a, int *counter);
void delete_list();
void printlist();
//global pointers
Node* Head = NULL;
Node* Current = NULL;
int main()
{
int *keycounter =(int*)malloc(sizeof(int));
int value = 20;
keycounter = 0;
Head=create(value, keycounter);
value = 30;
insert(value, keycounter);
value = 40;
insert(value, keycounter);
printlist();
delete_list();
free(keycounter);
return 0;
}
// VV functions VV
void delete_list()
{
free(Head);
free(Current);
}
Node* create(int a, int *counter)
{
Node* ptr=malloc(sizeof(Node));
if(!ptr)
{
printf("ERROR-NOT ENOUGH MEMORY\n");
free(ptr);
return 0;
}
ptr->data=a;
ptr->key=*counter;
counter++;
return ptr;
}
void insert(int a, int *counter)
{
Node* ptr=malloc(sizeof(Node));
if(!ptr) {
printf("ERROR-NOT ENOUGH MEMORY\n");
free(ptr);
}
ptr->data=a;
ptr->key=*counter;
//point next field to old head
ptr->next=Head;
//assign current node as head of singly linked list
Head=ptr;
counter++;
}
//Thank you guys over at tutorialspoint for this neat idea for testing this.
//https://www.tutorialspoint.com/data_structures_algorithms/linked_list_program_in_c.htm
void printlist()
{
Node* ptr=Head;
printf("TESTING\n");
while(ptr != NULL) {
printf("%p*NODE* KEY:%i VALUE:%i PTR NEXT:%p\n \n", ptr, ptr->key, ptr->data, ptr->next);
ptr=ptr->next;
}
}
Here is my valgrind output:
Still learning so alot of the valgrind output is pretty arcane to me and threads on stack exchange regarding the "signal 11 (SIGSEGV)" error are difficult to comprehend as well.
Also, any tips or advice on my code would be appreciated.
There is a problem in your code. See the below lines:
int main()
{
int *keycounter =(int*)malloc(sizeof(int));
int value = 20;
keycounter = 0; ===> You are setting the pointer to NULL effectively nullifying the effect of your malloc call above
So, in your create function, when you try to access counter, it is leading to NULL pointer dereference
Node* create(int a, int *counter)
{
Node* ptr=malloc(sizeof(Node));
if(!ptr)
{
printf("ERROR-NOT ENOUGH MEMORY\n");
free(ptr);
return 0;
}
ptr->data=a;
ptr->key=*counter; ==> Here it will lead to NULL pointer dereference
If your key member in the struct is just an integer, then no need to pass a pointer (counter is a pointer), you can as well pass an integer and set it.

Making of linked list by head and node

here's my code in C for making of linked list. Its giving runtime error after the while loop gets executed for one time. Plz help me in correcting my code. (totally confused that where's the error.) I am making a head node first and then adding child nodes to it.
#include <stdio.h>
#include <stdlib.h>
typedef struct node nd;
typedef nd *link;
struct node{
int data;
link next;
};
typedef struct {
int size;
link head;
}list;
void create(link temp)
{
link new;
new=(link)malloc(sizeof(nd));
printf("enter data: ");
scanf("%d",new->data);
temp->next=new;
temp=temp->next;
}
list createlist()
{
list sl;
sl.size=0;
sl.head=0;
return sl;
}
int main()
{
list sl;
sl=createlist();
link temp;
temp=sl.head;
char c;
while (1)
{
printf("Add node?: ");
scanf(" %c",&c);
if (c=='y')
{
create(temp);
sl.size++;
}
else
break;
}
return 0;
}
your createlist() function is returning a reference to a local variable that goes out of scope after it returns. You should instead return a heap based value:
list* createlist() {
list* sl = (list*)malloc(sizeof(list));
sl->size=0;
sl->head=0;
return sl;
}
Initially temp points to NULL. temp = sl.head;
In create(temp) temp->next = new;
You are dereferencing a NULL, address 0x0. I get a segmentation fault when I do that.
Need to change the algorithm.
A debugger shows this problem immediately.
You could use a pointer to pointer for temp. It would be easier to read if you didn't use a typedef for a pointer to node. I haven't tested this, but it should be close:
nd ** create(nd **temp)
{
nd *new;
new=(nd *)malloc(sizeof(nd)); /* this cast shouldn't be needed */
printf("enter data: ");
scanf("%d",&(new->data));
new->next = NULL;
*temp = new;
return &(new->next);
}
/* ... */
int main()
{
nd **temp;
temp = &(sl.head);
/* ... */
temp = create(temp);
/* ... */
}

Trouble with insertion of C string into linked list

I am writing a program to read a file and then store the data into a linked List.
linkedList.h
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
struct linked_list
{
char *stock_name;
double stock_price;
struct linked_list *next;
};
typedef struct linked_list NODE;
NODE* insert(NODE *head, double stock_price, char *stock_name);
void printList(NODE *head);
linkedList.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#include"linkedList.h"
void printList(NODE *head)
{
NODE *this = head;
while(this != NULL)
{
printf("stock name:%s , stock price:%lf\n", this->stock_name, this->stock_price);
this = this->next;
}
}
NODE* insert(NODE *head, double stock_price, char *stock_name)
{
NODE *newNode = malloc(sizeof(NODE));
if(head == NULL)
{
newNode->stock_price = stock_price;
newNode->stock_name = stock_name;
head = newNode;
}
else
{
newNode->stock_price = stock_price;
newNode->stock_name = stock_name;
newNode->next = head;
head = newNode;
}
return head;
}
main.c
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "linkedList.h"
NODE *head;
bool headNode = true;
void insertIntoLinkedList(char *stock_name, double stock_price);
int main ( int argc, char *argv[] )
{
head = malloc(sizeof(NODE));
double stock_price;
char stock_name[100];
int stock_name_counter = 0;
**..then I read the file..**
stock_name[stock_name_counter] = '\0'; //to end my C string
stock_name_counter = 0; //this is used for reading char
insertIntoLinkedList(stock_name, stock_price); //I double checked here,the name and price is correct
**......**
printList(head); //**Not the output I want**
fclose( file );
void insertIntoLinkedList(char *m_stock_name, double m_stock_price)
{
if(headNode == true)
{
head = insert(NULL, m_stock_price, m_stock_name);
headNode = false; //this is used to insert data to my linked list for the first time
}
else
{
head = insert(head, m_stock_price, m_stock_name);
}
}
Here is the problem: if the file contains:
YAHOO 120
GOOGLE 10
APPLE 199
my printList() gave me this:
APPLE 120
APPLE 10
APPLE 199
I have been trying to debug for hours and still cannot figure why the name is not stored in my linked list properly(but the price is store properly..)...any help will be appreciate :)
The address of stock_name in main is always constant through out the program and you store that address to newNode->stock_name and so you will always get the last stored string in stock_name.
Modification
NODE* insert(NODE *head, double stock_price, char *stock_name)
{
NODE *newNode = malloc(sizeof(NODE));
newNode->stock_name = malloc(strlen(stock_name)+1);
if(head == NULL)
{
newNode->stock_price = stock_price;
strcpy(newNode->stock_name, stock_name);
head = newNode;
}
else
{
newNode->stock_price = stock_price;
strcpy(newNode->stock_name, stock_name);
newNode->next = head;
head = newNode;
}
return head;
}
Don't forget to free the allocated memory.
You need to make a copy of the string stored in stock_name when you call insert. As is, all the nodes point to the same buffer, and every time you read a new line, you overwrite the buffer. In the end, this means that all of the nodes have the text APPLE because that's the last content that's read into the shared buffer. If you either copy the buffer's contents (instead of just the pointer to the buffer) or allocate a new buffer every time you read from the file, this will be fixed.
Your basic problem is that C does not have a "String" type. A string is simple an array of characters, and an array "decays" to a pointer when used as an argument to a function. Based on the way you're using it, your insert() function should do a second malloc() to allocate storage for the string and use strdup() or similar to store it.
Your other problem is that you've got a logic flaw in the insert() function. You aren't initializing newNode->next if head is NULL. You should be doing newNode->next = head either way. If it's NULL, good. Your list tail will then not be pointing at an indeterminate place.

Resources