I have a program where three values are inserted into linked lists. When I try to iterate through the list I only get the first value printed. Sorry if the function names are confusing I'm still new to c and I'm trying to use the function and variable names gave me just to make my life easier when taking a test. I'm also pretty unfamiliar with debugger and how I would use it to find out what is going on here. Thanks in advance.
void program_header(char i[]);
Node *allocateNode(int iNewInfo);
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes);
Node *insertLL(Node **ppHead, int iNewInfo);
void printLL(Node *pHead);
int main(int argc, char *argv[])
{
program_header(argv[0]);
insertLL(&pHead, 84);
insertLL(&pHead, 45);
insertLL(&pHead, 81);
printLL(pHead);
return 0;
}
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct Node
{
int iInfo;
struct Node *pNext;
}Node;
Node *pHead = NULL;
Node *pNew = NULL;
Node *pPrecedes = NULL;
Node *allocateNode(int iNewInfo)
{
// to allocate a new node
pNew = malloc(sizeof(Node));
if (pNew == NULL)
printf("Memory allocation error");
pNew->iInfo = iNewInfo;
pNew->pNext = NULL;
return pNew;
}
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes)
{
Node *p;
for (p = pHead; p != NULL; p = p->pNext)
{
if (iMatch == p->iInfo)
printf("Found! %d\n", iMatch);
return p;
if (iMatch < p->iInfo)
return NULL;
*ppPrecedes = p;
}
return NULL;
}
Node *insertLL(Node **ppHead, int iNewInfo)
{
Node *pFind;
// see if it already exists
pFind = searchLL(*ppHead, iNewInfo, &pPrecedes);
if(pFind != NULL)
return pFind;
// Doesn't already exist. Allocate a node and insert it
pNew = allocateNode(iNewInfo);
if(pPrecedes == NULL)
{ //insert at head
pNew->pNext = *ppHead;
*ppHead = pNew;
}
else
{ //insert after a node
pNew->pNext = pPrecedes->pNext;
pPrecedes->pNext = pNew;
}
return pNew;
}
void printLL(Node *pHead)
{
Node *p;
printf("iInfo Values\n");
for (p = pHead; p != NULL; p = p->pNext)
{
printf("%d\n", p->iInfo);
}
p = pHead;
}
void program_header(char i[])
{
int j, n = strlen(&i[2]);
char *name = &i[2], border[n], dash = '-';
// loads dashes into array
for(j = 0; j < n; j++)
border[j] = dash;
border[j] = '\0';
// print header
printf("\n~%s~\n~%s~\n~%s~\n\n"
, border, name, border);
}
I believe your problem is in your search method. I have reformatted it to show the way that it is currently behaving. To help in making your code more readable and to avoid these type of errors you should get in the habit of using braces in your if statements even if they are only one line.
This is your current code
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes)
{
Node *p;
for (p = pHead; p != NULL; p = p->pNext)
{
if (iMatch == p->iInfo)
{
printf("Found! %d\n", iMatch);
}
return p;
if (iMatch < p->iInfo)
{
return NULL;
}
*ppPrecedes = p;
}
return NULL;
}
Notice in the for loop that no matter if a match is found or not you are always returning p which is really pHead. Then in your insert code you are checking to see if the item is found in the list. Since you always return head it thinks that the item is in the list and never adds a new item.
I haven't tested this, but I believe this is the change you would need to make. You are expecting the search to return a node if the value is already in the list. So you want to return p if there is a match, otherwise you want to return NULL:
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes)
{
Node *p;
for (p = pHead; p != NULL; p = p->pNext)
{
if (iMatch == p->iInfo)
{
printf("Found! %d\n", iMatch);
return p;
}
if (iMatch < p->iInfo)
{
return NULL;
}
*ppPrecedes = p;
}
return NULL;
}
correct this
Node *allocateNode(int iNewInfo)
{
// to allocate a new node
pNew = malloc(sizeof(Node));
if (pNew == NULL)
printf("Memory allocation error");
pNew->iInfo = iNewInfo;
pNew->pNext = NULL;
return pNew;
}
to this
Node *allocateNode(int iNewInfo)
{
// to allocate a new node
pNew = malloc(sizeof(Node));
if (pNew){
pNew->iInfo = iNewInfo;
pNew->pNext = NULL;
}else{
printf("Memory allocation error");
}
return pNew;
}
Related
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node* next;
}
node;
int main(void){
node* list = NULL;
node *n = malloc(sizeof(node));
if(n==NULL){
return 1;
}
n->number = 2;
n-> next = NULL;
list = n;
n = malloc(sizeof(node));
if(n == NULL){
free(list);
return 1;
}
n->number = 3;
n->next = NULL;
list->next = n;
n = malloc(sizeof(node));
if(n == NULL){
free(list->next);
free(list);
}
n->number = 4;
n->next = NULL;
list->next->next =n;
n = malloc(sizeof(node));
if(n!=NULL){
n->number = 0;
n->next = NULL;
n->next = list;
list = n;
}
for( node* tmp = list; tmp != NULL; tmp->next){
printf("%i\n" , tmp->number);
}
while(list!=NULL){
node*tmp = list->next;
free(list);
list=tmp;
}
}
was trying linked list.
expected when running the code:
0
1
2
3
4
$
//asdoihasidashiofdhiohdfgdiwheifiopioioiophfaifjasklfhafiashfauiosfhwuiohwefuiowhfaslfidasdaskdasjdlaksdjqwfiqpweiojfkldfjsdfklwhefiowefweopfiosfkosid;fjwdfp;fdasiopfjew[0fowejfwepfojmofejmiwrfgj;wdfjewio;fijwefjsdp;jfkl;wjw
Actually you are not changing the pointer
for( node* tmp = list; tmp != NULL; tmp->next){
You need to write
for( node* tmp = list; tmp != NULL; tmp = tmp->next){
It will be even better to write
for ( const node* tmp = list; tmp != NULL; tmp = tmp->next ){
because within the loop the list is not being changed.
Also in this code snippet
if(n!=NULL){
n->number = 0;
n->next = NULL;
n->next = list;
list = n;
}
the statement
n->next = NULL;
is redundant.
In this loop, tmp->next has no effect because you don't assign it to anything.
for (node* tmp = list; tmp != NULL; tmp->next) {
printf("%i\n", tmp->number);
}
You must do tmp = tmp->next:
for (node* tmp = list; tmp != NULL; tmp = tmp->next) {
// ^^^^^
printf("%i\n", tmp->number);
}
Also, you can't expect 1 to be in the output because you never create a node with that number. With the above change the program will therefore output:
0
2
3
4
Sidenote: Your program is full of repetition which makes it hard to find errors and it's also what makes it harder to see that you forgot to add the node with the number 1. If you instead make functions of the things that you do repeatedly it'll be much clearer. You can also make functions with descriptive names to make the whole program easier to read and maintain.
If your program was rewritten to make use of functions, it could look like below - and then it'll be very obvious that the node with the number 1 is missing.
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
struct node {
int number;
node* next;
};
node *create_node(int number, node *next) {
node *nn = malloc(sizeof *nn);
if(!nn) exit(1);
// assign values to the new node:
*nn = (node){.number = number,
.next = next};
return nn;
}
void insert_first(node **list, int number) {
*list = create_node(number, *list);
}
void insert_last(node **list, int number) {
// find the last "next" pointer (the one pointing at NULL):
while(*list) list = &(*list)->next;
// make the pointer pointing at NULL now point at the new node:
*list = create_node(number, NULL);
}
void free_all(node **list) {
for(node *tmp; *list; *list = tmp) {
tmp = (*list)->next;
free(*list);
}
}
void print_all(const node *list) {
for (; list; list = list->next) {
printf("%d\n", list->number);
}
}
int main(void) {
node* list = NULL;
insert_last(&list, 2);
insert_last(&list, 3);
insert_last(&list, 4);
insert_first(&list, 0);
print_all(list);
free_all(&list); // list == NULL after this
}
void
LInsert (LIST * l, int x, int pos)
{
struct Node *new, *p; // p: previous node
// create a new node
new = (struct Node *) malloc (sizeof (struct Node));
new->val = x;
if (pos == 0)
{ // insert to start
new->next = l->head;
l->head = new;
}
else
{
// insert after p
p = l->head;
while (p != NULL && pos > 1)
{
p = p->next;
--pos;
}
if (p == NULL)
{
printf ("LInsert: Position not possible\n");
return;
}
new->next = p->next;
p->next = new;
}
l->size++;
}
This is a function of inserting a node to a linked list. I don't understand a few lines in this program.
In the first if condition there is a line new->next=l->head; From my thinking it means that in the "next" part of the new node it will store the what's in the head node(an address probably), but why?. It makes the linked list a circular linked list but this is just a simple linked list.
Also near the end new->next=p->next what does this mean.It makes the linked list circular again.
Hope the indentation is correct I always get people yelling at me for wrong indentation
Here is the complete code which includes struc declaration and stuff
#include <stdio.h>
#include <stdlib.h>
struct Node {
int val;
struct Node *next;
};
struct List {
struct Node *head;
int size;
};
// LIST is new name for "struct List"
typedef struct List LIST;
void LInit(LIST *l){ // Initialize list to empty
l->head = NULL; // pointer to first node
l->size = 0; // number of nodes
}
int LGetPos(LIST *l, int x) {
struct Node *p;
int i=0;
// go through all nodes
for (p=l->head; p!=NULL; p=p->next)
if (p->val == x) return i; // found
else i++; // next
return -1; // not found in the list
}
int LGetAt(LIST *l, int pos) {
struct Node *p=l->head;
int i;
// go to position
for(i=0; p!=NULL && i<pos; i++) p = p->next;
if(p) return p->val; // if exists, return it
else { printf("LDelete: Position not exist\n"); return -99; }
}
void LInsert(LIST *l, int x, int pos) {
struct Node *new, *p; // p: previous node
// create a new node
new = (struct Node *) malloc(sizeof(struct Node));
new->val = x;
if(pos==0) { // insert to start
new->next = l->head;
l->head = new;
}
else { // insert after p
p = l->head;
while(p!=NULL && pos>1) { p = p->next; --pos; }
if(p==NULL) { printf("LInsert: Position not possible\n"); return; }
new->next = p->next;
p->next = new;
}
l->size++;
}
void LDelete(LIST *l, int pos) {
struct Node *p, *d; // p: previous
if(l->head == NULL) return;
if(pos==0) { // delete first node
d = l->head;
l->head = d->next;
}
else { // delete after p
p = l->head;
while(pos>1 && p) { p = p->next; --pos; }
if(p==NULL) { printf("LDelete: Position not exist\n"); return; }
d = p->next;
p->next = p->next->next;
}
l->size--;
free(d);
}
int LIsEmpty(LIST * l){
return (l->size == 0);
}
int LSize(LIST * l){
return (l->size);
}
void LDisplay(LIST *l) {
struct Node *p;
printf("List: ");
for(p=l->head; p!=NULL; p=p->next)
printf("--> %d ", p->val);
printf("\n");
}
int LHeadOf(LIST *l) {
if (!LIsEmpty(l)) return l->head->val;
else {
printf("LHeadOf: Linked list empty\n");
return -99;
}
}
int main() {
LIST list;
LInit(&list);
LDisplay(&list);
LInsert(&list, 3, 0);
LInsert(&list, 4, 0);
LInsert(&list, 5, 2);
LDisplay(&list);
printf("Value at 1: %d\n", LGetAt(&list, 1));
printf("Location of 4: %d\n", LGetPos(&list, 4));
LDelete(&list, 1);
LDisplay(&list);
return 0;
}
I don't understand a few lines in this program
Okay - let's take a look of those lines...
here is a line new->next=l->head; From my thinking it means that in the "next" part of the new node it will store the what's in the head node(an address probably), but why?
That line is used to insert the new element in front of the current head element. So
new->next=l->head; // Make the new element point to current head
l->head = new; // Change head to point to the new element as it is now the front element
Also near the end new->next=p->next what does this mean.It makes the linked list circular again.
Well, it doesn't make the list circular. It simply insert the new element somewhere in the middle of the list.
new->next = p->next; // Make new point to the element after p
p->next = new; // Make p point to new
// In this way new has between inserted after p and
// before the element that folloed p
I am creating a HashTable in C that uses a Node double pointer and using separate chaining to resolve collisions, but when I run my code it does not place collisions into the linked list.
HTable *createTable(size_t size, int (*hashFunction)(size_t tableSize,
int key),void (*destroyData)(void *data),void (*printData)(void
*toBePrinted)){
HTable * h = malloc(sizeof(HTable));
h->size = size;
h->destroyData = destroyData;
h->hashFunction = hashFunction;
h->printData = printData;
h->table = malloc(h->size * sizeof(Node*));
for(int i = 0; i < h->size; i++){
h->table[i] = malloc(sizeof(Node));
h->table[i]->key = 0;
h->table[i]->data = NULL;
h->table[i]->next = NULL;
}
return h;
}
Node *createNode(int key, void *data){
Node * n = malloc(sizeof(Node));
n->key = key;
n->data = data;
n->next = NULL;
return n;
}
void insertData(HTable *hashTable, int key, void *data){
if(hashTable != NULL){
Node * n = createNode(key, data);
int index = hashTable->hashFunction(hashTable->size, key);
if(hashTable->table[index] != NULL)
if(hashTable->table[index]->key == key){
if(hashTable->table[index]->next != NULL){
n->next = hashTable->table[index]->next;
hashTable->table[index] = n;
}
else
hashTable->table[index] = n;
}
else{
if(hashTable->table[index]->next != NULL){
Node * itr = hashTable->table[index];
while(itr->next != NULL){
itr = itr->next;
}
itr->next = n;
}
else
hashTable->table[index] = n;
}
else{
hashTable->table[index] = n;
}
}
}
and the HTable struck and Node struck look like this:
typedef struct Node
{
int key;
void *data;
struct Node *next;
} Node;
typedef struct HTable
{
size_t size;
Node **table;
void (*destroyData)(void *data);
int (*hashFunction)(size_t tableSize, int key);
void (*printData)(void *toBePrinted);
}HTable;
I am thinking I am running into a problem in my insertData function when I use the iterator to find the last item in the linked list. That or I am misunderstanding the proper use of a double pointer to a node.
I figured out why the data was not chaining. If the keys did not match it would go to the else statement and the first if statement in that block was asking if hashTable->table[index]->next was not NULL when it should have been asking if hashTable->table[index] was NULL. This is because there could have been one node and its next would be pointing to NULL and the data would then have been overridden. Thanks for the responses and i have added comments which was great advice because it helped me find the error. so thank you #wildplasser
Here is the code if anyone is wondering:
void insertData(HTable *hashTable, int key, void *data){
if(hashTable != NULL){
Node * n = createNode(key, data);
int index = hashTable->hashFunction(hashTable->size, key);
//Check if hashTable table node contains data
if(hashTable->table[index]->data != NULL)
//Check if the key at that index matches the incoming key
if(hashTable->table[index]->key == key){
//checks if there is more than one node in the chain and replaces the
//first piece of data in the chain
if(hashTable->table[index] != NULL){
n->next = hashTable->table[index]->next;
hashTable->table[index] = n;
}
}
//if the keys do not match
else{
//check if their is one node in the chain
if(hashTable->table[index] != NULL){
Node * itr = hashTable->table[index];
//iterate through the chain to last node
while(itr->next != NULL){
itr = itr->next;
}
//insert node into end of chain
itr->next = n;
}
}
//if there is no data in the node insert the data
else
hashTable->table[index] = n;
}
}
Well, i have a code that inserts a new struct in a list in alphabetically order but i'm with a little problem. I just can make it work has a function and when i call i make head = Insert(frota* head, char name). The code is the fallowing
typedef struct robot {
int bateria;
char nome[3];
int pos_x;
int pos_y;
int target_x;
int target_y;
int limpos;
int percorridos;
struct robot * next;
}frota;
frota* Insert(frota* head, char name){
frota* temp = (frota*)malloc(sizeof(frota));
if(temp == NULL){
printf("Unable to allocate memory for new node\n");
exit(-1);
}
temp->nome[0] = 'R';
temp->nome[1] = name;
int* prevtemp = head;
int* nexttemp = head;
if(head != NULL)
{
// Corner Case: First on the list
if(temp->nome[1] <= prevtemp->nome[1])
{
head = temp;
temp->next = prevtemp;
}
else
{
// CASE: Somewhere between the first and the list
while(nexttemp->next != NULL)
{
nexttemp = nexttemp->next;
if(temp->nome[1] >= prevtemp->nome[1] && temp->nome[1] <= nexttemp->nome[1])
{
prevtemp->next = temp;
temp->next = nexttemp;
break;
}
prevtemp = prevtemp->next;
}
// Corner Case: end of list
if(nexttemp->next == NULL)
{
nexttemp->next = temp;
}
}
}
else
{
// Corner Case: We had an empty list
head = temp;
}
}
My question is how to make the code to work and changing the value directly of the value head, making this way this function a procedure. The code that i tried is this:
void Insert(frota* head, char name){
frota* temp = (frota*)malloc(sizeof(frota));
if(temp == NULL){
printf("Unable to allocate memory for new node\n");
exit(-1);
}
temp->nome[0] = 'R';
temp->nome[1] = name;
int* prevtemp = *head;
int* nexttemp = *head;
if(*head != NULL)
{
// Corner Case: First on the list
if(temp->nome[1] <= prevtemp->nome[1])
{
*head = temp;
temp->next = prevtemp;
}
else
{
// CASE: Somewhere between the first and the list
while(nexttemp->next != NULL)
{
nexttemp = nexttemp->next;
if(temp->nome[1] >= prevtemp->nome[1] && temp->nome[1] <= nexttemp->nome[1])
{
prevtemp->next = temp;
temp->next = nexttemp;
break;
}
prevtemp = prevtemp->next;
}
// Corner Case: end of list
if(nexttemp->next == NULL)
{
nexttemp->next = temp;
}
}
}
else
{
// Corner Case: We had an empty list
*head = temp;
(*head)->next = NULL;
}
}
This way i cal the procedure as Insert(&head,name). Any help would be appreciate. When i run the code it appears segmentation fault and is not na memory error
PS: The code isn't entirely my responsible, found some part online....
Grateful
For starters:
Change
int* prevtemp;
to be
struct robot * prevtemp;
(same for nexttemp)
Change all
head
to
(*head)
Change all
frota
to
struct robot
The following is a simple code segment in C to create a linked list and print all elements contained in the list.
User is asked to input integer data till a zero is entered which marks the termination of user input; Once data is saved in the linked list, the program prints all elements stored in the list and then completes its execution.
I can't make it run, every time it gives a "Segmentation fault" error, please check and tell me where I'm wrong (using gcc 4.8.2)
Code :
struct node
{
int data;
struct node * next;
};
struct node * createLinkedList()
{
int x;
struct node * start;
start = NULL;
printf("Input 0 to end, Insert elements :\n");
for(scanf("%d", &x); x ;scanf("%d", &x))
{
struct node * temp = (struct node *) malloc(sizeof(struct node));
if (temp)
{
temp->data = x;
temp->next = NULL;
if(start == NULL) {
start = temp;
} else {
start->next = temp;
start = temp;
}
}
}
return start;
}
void printLinkedList(struct node * start)
{
if (start == NULL) {
printf("Linked List is empty!\n");
} else {
printf("\nPrinting Linked List : \n");
struct node * s;
s = start;
while(s != NULL)
{
printf("%d\n", s->data);
s = s->next;
}
}
}
int main(int argc, char const *argv[])
{
struct node * start;
start = NULL;
start = createLinkedList();
printLinkedList(start);
return 0;
}
This part of code
if(start == NULL) {
start = temp;
} else {
start->next = temp;
start = temp;
}
is invalid. There has to be
if(start == NULL) {
start = temp;
} else {
temp->next = start;
start = temp;
}
Also you need to have a function that deletes all nodes of the list.