Creating List using pointers - c

I want to create a linked list and keep two pointers. One for the head and one for the last element. I tried several approaches and just found a solution, but I don't know why my first solution don't work. The pointer in head->next always points on the last element, instead of the correct one.
int main(void){ // first solution
struct pointList *lastElement;
struct pointList *head;
struct pointList headHelp = {.next = NULL, .p.x = 5, .p.y = 5};
head = &headHelp;
int i = 0;
lastElement = &headHelp;
for( i = 8; i < 10; i++){
printf("LastElement: %d/%d\n", lastElement->p.x, lastElement->p.y);
struct pointList *helpPoint;
helpPoint = ((struct pointList*) malloc(sizeof(struct pointList)));
struct pointList newElement = *helpPoint;
newElement.next = NULL;
newElement.p.x = i;
newElement.p.y = i;
lastElement->next = &newElement;
lastElement = &newElement;
}
//printList(head);
printf("LastElement: %d/%d\n", lastElement->p.x, lastElement->p.y);
printf("head -> next: %d/%d\n", head->next->p.x, head->next->p.y);
printf("finish\n");
return 0;
}
output:
LastElement: 5/5
LastElement: 8/8
LastElement: 9/9
head -> next: 9/9
finish
but it should be : head -> next: 8/8
So the "next" pointer of head is changed in every loop execution
The solution which works looks like this:
int main(void){
struct pointList *lastElement;
struct pointList *head;
struct pointList headHelp = {.next = NULL, .p.x = 5, .p.y = 5};
head = &headHelp;
int i = 0;
lastElement = &headHelp;
for( i = 8; i < 10; i++){
printf("LastElement: %d/%d\n", lastElement->p.x, lastElement->p.y);
lastElement->next = ((struct pointList*) malloc(sizeof(struct pointList)));
lastElement->next->next = NULL;
lastElement->next->p.x = i;
lastElement->next->p.y = i;
lastElement = lastElement->next;
}
//printList(head);
printf("LastElement: %d/%d\n", lastElement->p.x, lastElement->p.y);
printf("head -> next: %d/%d\n", head->next->p.x, head->next->p.y);
printf("finish\n");
return 0;
}
used struct:
struct pointList {
struct point p;
struct pointList *prev;
};

The problem with the first code snippet is that you take and use the pointer to a local variable. The variable newElement have its scope inside the loop only, so when the loop iterates the current newElement variable goes out of scope and you are left with a stray pointer. This leads to undefined behavior.
You also allocate memory for helpPoint but you don't actually use it (when you initialize newElement using helpPoint you initialize one uninitialized structure with another uninitialized structure), and you do not free it anywhere leading to memory leaks.

Related

C/C++ Printing stack bottom to top with recursion

Hey I am trying to print a "stack" from bottom to top using recusion. Everything in the code is as should and only the print function should be modified. I am not getting any recursion print and unfortunately I do not know why.
struct element{
int i;
element *next;
};
struct stack{
element *top;
};
void print(stack *st);
int main(){
element *e5 = (element*) malloc(sizeof(element));
element *e4 = (element*) malloc(sizeof(element));
element *e3 = (element*) malloc(sizeof(element));
element *e2 = (element*) malloc(sizeof(element));
element *e1 = (element*) malloc(sizeof(element));
e5->i = 5; e5->next = NULL;
e4->i = 4; e4->next = e5;
e3->i = 3; e3->next = e4;
e2->i = 2; e2->next = e3;
e1->i = 1; e1->next = e2;
stack start;
start.top = e1;
element *e;
print(&start);
return 0;
}
void print(stack *st){
stack nxt;
nxt.top = st->top->next;
if (st->top != NULL){
print(&nxt);
printf("%i\n", st->top);
}
else
printf("%i\n", st->top->i);
}
Thank you for your input!
In your else you have a possible crash on this line:
printf("%i\n", st->top->i); //<-- possible crash here
You should be more clear about what errors you see from you program.
It looks to me like this will crash the program before anything is printed.
There are other problems (see Botje's comment), but also:
printf("%i\n", st->top);
What is the type of st->top? What happens if you print it with format %i?

how to initializing a hash table in C

I have a program in C that creates a hash table.
memset is Okay but, i want to initialize with for loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HSZ 127
#define HASHING(x) ((x)%HSZ)
struct node_t{
int val;
struct node_t *next;
};
struct node_t *hash_table[HSZ];
void init(void){
int i;
//memset(hash_table,0,sizeof(hash_table));
for(i=0; i<HSZ; i++){
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
}
void insert_hash(int value){
int key = HASHING(value);
struct node_t *newNode = (struct node_t*)malloc(sizeof(struct node_t));
newNode->val = value;
newNode->next = NULL;
if(hash_table[key] == NULL){
hash_table[key] = newNode;
} else {
newNode->next = hash_table[key];
hash_table[key] = newNode;
}
}
int delete_hash(int value){
int key = HASHING(value);
if (hash_table[key] == NULL)
return 0;
struct node_t *delNode = NULL;
if (hash_table[key]->val == value){
delNode = hash_table[key];
hash_table[key] = hash_table[key]->next;
} else {
struct node_t *node = &hash_table[key];
struct node_t *next = hash_table[key]->next;
while (next){
if (next->val == value){
node->next = next->next;
delNode = next;
break;
}
node = next;
next = node->next;
}
}
return 1;
free(delNode);
}
void PrintAllHashData()
{
printf("###Print All Hash Data###\n");
for (int i = 0; i < HSZ; i++){
if (hash_table[i] != NULL){
printf("idx : %d ", i);
struct node_t *node = hash_table[i];
while (node->next){
printf("%d ", node->val);
node = node->next;
}
printf("%d\n", node->val);
}
}
}
int main(void){
init();
insert_hash(1);
insert_hash(3);
insert_hash(128);
PrintAllHashData();
}
look at this code.
for(i=0; i<HSZ; i++){
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
The IDE I am using does not throw up a compilation error when I compile the code, but during the execution the code faults and is terminated/haulted. I tried debugging the code, it faults at this line and is stopped, I think BAD ACCESS points to Segmentation Error.
then, I changed this line to
for(i=0; i<HSZ; i++){
hash_table[i].val = 0;
hash_table[i]->next = NULL;
}
but, then I got the compilation error stating 'structure type require instead of 'struct node_t *'
I think that I don't understand clearly about struct in C.
How to fix this problem?
What you are dealing with is Undefined Behavior.
See, struct node_t *hash_table[HSZ];
So, hash_table is an array of HSZ (127) pointers of the data type struct node_t.
When you do,
for(i=0; i<HSZ; i++){
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
hash_table[0] to hash_table[126] pointers are not pointing to anything.
So, each of them (or all of them) should be initialized first to point to an object of the type struct node_t and then you can initialize them. For that matter, Using a memset does not cause a problem because memset is filling the contents of the pointers with all zeros. There is difference between filling the pointers with all zeros and filling all zeros to the memory pointed by pointers.
Trying this,
for(i=0; i<HSZ; i++){
hash_table[i].val = 0;
hash_table[i]->next = NULL;
}
is plain wrong.
To fix the issue you are facing, you need to allocate memory dynamically using malloc. You can do the in your for loop.
for(i = 0; i < HSZ; i++)
{
//Allocate memory of the size struct_node_t
hash_table[i] = malloc(sizeof(struct node_t)); //Do not cast!
//Check if memory is allocated
if(hash_table[i] == NULL)
{
//Memory not allocated, set some error state to handle and break
break;
}
//Initialize to zero
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
struct node_t{
int val;
struct node_t *next;
};
struct node_t *hash_table[HSZ];
when you have *hash_table[HSZ], this varible hash_table is a pointer. so whatever your action is , use hash_table-> ,syntax for pointer, mean point to somewhere.
a suggestion that when you use pointer you should always allocate memory hash_table[i] = malloc(sizeof(struct node_t));
struct node_t hash_table;
but if you initilize your varible like this, you can use hash_table.val = 0
so the way of assign value depend on how you declare your varibles
struct node_t *hash_table[HSZ];
gives you an array of pointers that are unset (i.e. not pointing to anything)
void init(void) {
int i;
// memset(hash_table,0,sizeof(hash_table));
for (i = 0; i < HSZ; i++) {
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
tries writing to your invalid pointers which gives undefined behavior.
Either make the array an array of structs (instead of pointers):
struct node_t hash_table[HSZ];
...
/* note use of . instead of -> since we have structs not pointers */
hash_table[i].val = 0;
or allocate the necessary structs so the array points to something:
for (i = 0; i < HSZ; i++) {
hash_table[i] = malloc(sizeof(struct node_t));
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}

C Linked List from Array

In the function, I created an array of size two which will hold two PolyTerms. Then, within the function, i created a List. After that, i want to pass the array elements into the List as linked list.
I'm getting an error after the if statement
head->next = nodePtr; (Bad Access).
Thanks.
Part of my code:
struct Fraction {
int num;
int denom;
};
struct PolyTerm {
int ex;
struct Fraction coe;
};
typedef struct PolyTerm PTerm;
typedef struct PolyTerm* PTermPtr;
struct PolyListNode {
PTermPtr termAddr;
struct PolyListNode* next;
};
typedef struct PolyListNode PList;
typedef struct PolyListNode* PNodeAddr;
typedef struct PolyListNode* PolyList;
PolyList sortPoly(void);
PolyList sortPoly() {
int arraySize = 2;
int i = 0;
//Array of PTermPtr. Each element holds ex, num and denom.
//Populating 2 elements for arrayTerm
PTermPtr arrayTerm;
arrayTerm = (PTermPtr) malloc(arraySize);
((arrayTerm) + 0)->ex = 2;
((arrayTerm) + 0)->coe.num = 2;
((arrayTerm) + 0)->coe.denom = 2;
((arrayTerm) + 1)->ex = 3;
((arrayTerm) + 1)->coe.num = 2;
((arrayTerm) + 1)->coe.denom = 2;
PNodeAddr nodePtr; //To create nodes
PolyList head = 0; //New List
PNodeAddr current; //To store Address of List Head
current= head; //Store address of head of list
while (i < arraySize) {
nodePtr = (PNodeAddr) malloc(sizeof(PList));
nodePtr->termAddr = (arrayTerm + i);
nodePtr->next = 0;
if (current == 0) {
head->next = nodePtr; //ERROR. Bad Access
} else {
while (current != 0) {
current = current->next;
}
current->next = nodePtr;
}
i++;
}
free (arrayTerm);
return head;
}
Just think about what is going on the first time the code goes thru the loop:
PolyList head = 0; //New List
Head is now 0 (or null).
current= head; //Store address of head of list
Current and head are now 0
if (current == 0) {
It is.
head->next = nodePtr; //ERROR. Bad Access
Try to access head which is 0 and null. you are accessing null
It should also be noted the sizes you pass in to malloc are wrong. You are passing in the size of the arrays you want to create not the size of memory needed.
For example you are need a 2 element array of type mytype you want this code:
newarray = malloc(2 * sizeof(mytype));
then
newarray[0]
and
newarray[1]
have space for a mytype.

Swapping linked list items issue C

i'm trying to invert the "info" field of the in a list like the one below
struct nodo {
int info;
struct nodo *next;
struct nodo *prev;
} ;
typedef struct nodo nodo;
Here is the main, the two output should be the original list of n mebmers, and the inverted list (First value go n , second n-1 and so on)
int main(int argc, const char * argv[]) {
struct nodo *p;
p = CreateList();
PrintList(p);
IvertList(p);
Printlist(p);
return 0;
}
Here is InvertList(): (Count() function just returns dimension of the list, i know it is a messy way but i'm focused on result for now)
void InvertList (struct nodo *p) {
int tmp = 0, num = 0, i = 0;
num = (Count(p));
tmp = num;
for (i=1; i!=tmp; i++) {
Swap(p,num);
num--;
}
}
And here is Swap(), this should bring a value (int info) to the first place of the list, to the last swapping with each:
void Swap (struct nodo *p, int n) {
int *tmp1 = NULL, *tmp2 = NULL;
int i;
for ( i = 1; i != n && p != NULL; i++) {
tmp1 = &p->info;
p = p->succ;
tmp2 = &p->info;
p->info = *tmp1;
p->prec->info = *tmp2;
}
}
Now the output i got printed is:
Value: 1
Value: 2
Value: 3
Value: 4
Value: 5
Value: 1
Value: 1
Value: 1
Value: 1
Value: 1
Where the last 5 values should be 5-4-3-2-1.
The bug(s) in your code not withstanding, you're not reversing your physical list at all, which I can all-but-guarantee is the point of the exercise in the first place.
Inversion of a linked list means all the pointers switch directions and the old tail becomes the new head. You seem to be avoiding that and trying to swap node info values instead.
To invert your list using simple pointer swapping:
// note head pointer passed by address
void InvertList(node **pp)
{
node *cur = *pp;
while (cur)
{
node *tmp = cur->prev;
cur->prev = cur->next;
cur->next = tmp;
*pp = cur;
cur = cur->prev;
}
}
And invoke from main() as:
InvertList(&p);
Note that no info values need be swapped, copied, etc. The node pointers simply switch direction and their enumeration will start at the other end. A full working example appears below:
#include<stdio.h>
#include<stdlib.h>
struct node
{
int info;
struct node *next;
struct node *prev;
};
typedef struct node node;
static void PrintList(const node *head)
{
while (head)
{
printf("%d: this=%p, prev=%p, next=%p\n",
head->info, head, head->prev, head->next);
head = head->next;
}
}
static void InvertList(node **pp)
{
node *cur = *pp;
while (cur)
{
node *tmp = cur->prev;
cur->prev = cur->next;
cur->next = tmp;
*pp = cur;
cur = cur->prev;
}
}
int main()
{
node *prev = NULL, *head = NULL, **pp = &head;
for (int i=1; i<=5; ++i)
{
*pp = malloc(sizeof **pp);
(*pp)->info = i;
(*pp)->prev = prev;
prev = *pp;
pp = &(*pp)->next;
}
*pp = NULL;
PrintList(head); // prints 1,2,3,4,5
InvertList(&head);
PrintList(head); // prints 5,4,3,2,1
}
Output (addresses vary, obviously)
1: this=0x1001054b0, prev=0x0, next=0x1001054d0
2: this=0x1001054d0, prev=0x1001054b0, next=0x1001054f0
3: this=0x1001054f0, prev=0x1001054d0, next=0x100105510
4: this=0x100105510, prev=0x1001054f0, next=0x100105530
5: this=0x100105530, prev=0x100105510, next=0x0
5: this=0x100105530, prev=0x0, next=0x100105510
4: this=0x100105510, prev=0x100105530, next=0x1001054f0
3: this=0x1001054f0, prev=0x100105510, next=0x1001054d0
2: this=0x1001054d0, prev=0x1001054f0, next=0x1001054b0
1: this=0x1001054b0, prev=0x1001054d0, next=0x0
There is a bug in your Swap fcn:
p->info = *tmp1;
p->prev->info = *tmp2;
But what are tmp1 and tmp2 at that time? Well, after we advanced p, tmp1 points at p->prev->info, while tmp2 = &p->info; So we could rewrite these assignments in effect as:
p->info = p->prev->info;
p->prev->info = p->info;
So, we could rewrite them again, in effect, as:
p->info = p->prev->info;
p->prev->info = p->prev->info;
So, the second assignment doesn't change anything in effect. Therefore, the first call to Swap in InvertList takes the value of the first element (1) and sets all the values in the list equal to it. The subsequent calls to Swap act similarly but have no effect as the list already contains all 1's.
Here's a simple way to rewrite Swap:
void Swap(struct nodo *p, int n)
{
if (n <= 1)
return;
int tmp = p->info;
for (int i = 1; i != n; ++i, p = p->next)
p->info = p->next->info;
p->info = tmp;
}
Note, however, that the way you've written InvertList is doing theta(n^2) work. The first loop iteration shifts the first element n-1 spots, the second iteration shifts the first element n-2 spots, the third iteration shifts the first element n-3 spots, and so on, down to shifting the first element 1 spot. So, you end up doing something like n * (n - 1) / 2 total shifts to reverse the list.
A linked list can be reversed / inverted in theta(n) work. See if you can figure out a better way to do this. If you had a pointer to both the beginning and the end of the list (which you often want anyway), then you could do something similar to reversing the characters in a string, for example.

Creating a linked list with a for loop

Here is my struct
struct ListItem{
int data;
struct ListItem *next;
};
Assuming the first node of the linked list will have data = 0, I want to write a for loop that creates a linked list of size 5 but I'm not sure how to work
I tried the following
int main(int argc, char* argv[]){
struct ListItem a;
a.data = 0;
for (int i = 1; i < 5; i++){
struct ListItem *pointer = &a;
struct ListItem nextnode;
nextnode.data = i;
a.next = &nextnode;
pointer = pointer->next;
}
}
But the result is
a.data = 0
and a.next->data = 4
Don't modify a. Take a temp node starting as a. Make it's next point to the new node and then set temp node to the new node. Also allocate dynamically in heap. Otherwise the memory will get deallocated after every loop run
struct ListItem a[5] = { {0, NULL}};
struct ListItem *pointer = &a[0];
for (int i = 0; i < 5; i++){
a[i].data = i;
if(i != 5 -1)
a[i].next = &a[i+1];
}

Resources