I have a problem with linked list when I add the contacts to the list and print it out it prints out the first list twice rather than the first and the second list. Please let me know what I am doing wrong.
Thanks.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#define true 1
#define false 0
typedef int boolean;
typedef int Position;
typedef int Count;
typedef struct node_def {
int area_code;
char name[30];
char phone_number[8];
struct mode_def *next;
} Node;
typedef struct {
Position currentPos;
Count nodeCount;
Node *head;
Node *current;
Node *tail;
} ListADT;
void initList(ListADT*);
boolean checkEmpty(ListADT*);
void addList(ListADT*, int, char*, char*);
void printList(ListADT*);
int main(void) {
ListADT phoneList;
initList(&phoneList);
Node *firstNode;
addList(&phoneList, 416, "Sam", "1234567");
addList(&phoneList, 416, "Bob", "7654321");
firstNode-> next;
printList(&phoneList);
printList(&phoneList);
return 0;
}
void initList(ListADT* list){
list->currentPos = -1;
list->nodeCount = 0;
list->head = NULL;
list->tail = NULL;
}
boolean checkEmpty(ListADT* list){
return list->nodeCount == 0 ? true : false;
}
void addList(ListADT* list, int areaCode, char* name, char* phoneNum){
Node* newNode = malloc(sizeof(Node));
assert(newNode);
newNode->area_code = areaCode;
strcpy(newNode->name, name);
strcpy(newNode->phone_number, phoneNum);
newNode->next = NULL;
if(list->nodeCount == 0) {
list->head = newNode;
list->tail = newNode;
list->currentPos = 0;
list->nodeCount = 1;
}
else {
list->tail = newNode;
list->current = list->tail;
list->nodeCount++;
list->currentPos = list->nodeCount -1;
}
}
void printList(ListADT* list){
if(!checkEmpty(list)){
Node* newNode = list->head;
printf("The name is %s\n",newNode->name);
printf("The phone number is %i-%s\n",newNode->area_code,newNode->phone_number);
}else
printf("The list is empty.\n");
}
Mean no harm, but based on your question concerning the current code, I suppose you have to get some more experience in programming, particularly in programming in C++, before writing your own abstract data types.
There are a lot of things done only to the half, and actually you are asking "why does my function, which does nothing else than printing out exactly the first element, print the same element twice if I call this function twice.".
Anyway, some hints:
Typo in struct mode_def *next, should be struct node_def *next.
Make sure that next is actually set somewhere, e.g. else {
list->tail->next = newNode; otherwise you won't get a linked list but unlinked nodes
When printing, traverse the nodes through next, i.e something like while(node!=NULL) { ...; node=node->next; }
firstNode-> next; does simply nothing
Related
I have started to learn about linked lists, and I have written this code.
It should be a recursive call to create a new link in a linked list in c.
But, if you’ll check the output, you’ll see it’s passing over the middle links.
I don’t know why I’m losing the middle links.
Btw, I do have a destroy function in my code, I just didn’t write it here.
I do have a different version of a working code, I don’t ask for solutions, I’m only asking why this recursive idea doesn’t work.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct node {
int data;
struct node *next;
}node;
node *create(node **head, int data)
{
if(!*head) {
*head = malloc(sizeof(node));
assert(*head);
(*head)->data = data;
(*head)->next = NULL;
return *head;
}
node *new = NULL;
new = create(&new,data);
(*head)->next = new;
return *head;
}
void display(node *head)
{
assert(head);
node *current = head;
do
{
printf("%d\t",current->data);
current = current->next;
}while(current);
}
int main()
{
int count = 0, data = 0;
node *head = NULL;
printf("Enter list count:\n");
while(count <= 0){
scanf("%d",&count);
if(count <= 0) printf("\nEnter a valid number:\n");
}
while(count){
scanf("%d",&data);
head = create(&head,data);
count--;
}
printf("\nHere are the elements:\n");
display(head);
return 0;
}
As implemented create() either adds a new node to the tail or iterates to the next linked node. Logic changed to affect that. It's confusing that the first argument is called head to changed it to n. Changed main() to retain the head and made the program non-interactive for ease of testing. Recatored display to use a for() loop:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
node *create(node **n, int data) {
if(!*n) {
*n = malloc(sizeof(**n));
assert(*n);
(*n)->data = data;
(*n)->next = NULL;
return *n;
}
node *n2 = (*n)->next;
(*n)->next = create(&n2, data);
return n2;
}
void display(node *head) {
assert(head);
for(node *c = head; c; c = c->next) {
printf("%d\t", c->data);
}
}
int main() {
node *head = NULL;
node *tail = NULL;
for(int i = 0; i < 10; i++) {
tail = create(&tail, i);
if(!head) head = tail;
}
display(head);
return 0;
}
and it displays:
0 1 2 3 4 5 6 7 8 9
If you compile your code with NDEBUG (some folks do that for production) then your code no longer has any error handling.
Thank you all for your answers. I see the problem now, after “explaining to the duck” a thousand times. In function create(), under the if() block, I assigned (*head)->next = new; without first making it point to the last link, so it’s just over write the next link in every call to the function.
The solution is:
Add a “current” pointer points to the head(to not lose it’s value)
Iterate through the list until we find the last link,
assign current->next the value of new.
Here is the fixed section:
node *new = NULL;
new = create(&new,data);
node *current = *head;
while(current->next) current = current->next;
current->next = new;
return *head;
Im a beginner in c and i need to print a linked list contents but the printing function doesnt work and i dont know why. i checked if the function of creating the linked list works by printf some words after using addFirst function and it seems the addFirst function works and the linked list has been created but the printing function doesnt
Here is my code
#include <stdio.h>
#include <stdlib.h>
typedef enum msgtag {
NoTag = 0, Important, Work, Personal, ToDo, Later
} msgtag;
typedef struct MsgID
{
char* id ;
} MsgID;
typedef struct MsgDetails
{
char* id;
msgtag tag;
int year;
int month;
int day;
} MsgDetails;
typedef struct Node
{
void *item;
struct Node* next;
} Node;
Node* addFirst(MsgDetails*ptr,Node* head) {
Node* newHead = ( Node*)malloc(sizeof(Node));
newHead->item = malloc(sizeof(MsgDetails));
((MsgDetails*)newHead->item)->year = ptr->year;
((MsgDetails*)newHead->item)->day = ptr->day;
((MsgDetails*)newHead->item)->month = ptr->month;
((MsgDetails*)newHead->item)->id = ptr->id;
((MsgDetails*)newHead->item)->tag = ptr->tag;
newHead->next = head;
return newHead;
}
void printAll(Node* head) {
Node* current = NULL;
((MsgDetails*)current->item)->year = ((MsgDetails*)head->item)->year;
((MsgDetails*)current->item)->day = ((MsgDetails*)head->item)->day;
((MsgDetails*)current->item)->month = ((MsgDetails*)head->item)->month;
((MsgDetails*)current->item)->id = ((MsgDetails*)head->item)->id;
((MsgDetails*)current->item)->tag = ((MsgDetails*)head->item)->tag;
while (current != NULL) {
printf("%d,%d,%d,%d,%s",((MsgDetails*)current->item)->tag,((MsgDetails*)current->item)->year,((MsgDetails*)current->item)->month,((MsgDetails*)current->item)->day,((MsgDetails*)current->item)->id);
current = current->next;
}
printf("\n");
}
int main()
{
Node* head = NULL;
MsgDetails details;
MsgDetails *ptr =NULL;
int msg_tag;
details.id =(char*)malloc(sizeof(char)*40);
ptr = &details;
printf("\nenter msg metadata (tag,year,month,day,id):");
scanf("%d,%d,%d,%d,%s",&msg_tag,&(details.year),&(details.month),&(details.day),details.id);
details.tag = msg_tag;
head = addFirst(ptr,head);
printAll(head);
}
Your code initialises current to (Node *)NULL, then attempts to dereference the pointer. That's not going to work.
void printAll(Node* head) {
Node* current = NULL;
((MsgDetails*)current->item)->year = ((MsgDetails*)head->item)->year;
The preliminary code that makes assignments to current do not seem necessary. Assign head to current and it will work:
void printAll(Node* head) {
Node* current = head;
while (current) {
printf("%d,%d,%d,%d,%s", ((MsgDetails*)current->item)->tag,((MsgDetails*)current->item)->year,((MsgDetails*)current->item)->month,((MsgDetails*)current->item)->day,((MsgDetails*)current->item)->id);
current = current->next;
}
printf("\n");
}
I'm writing a code to split a circular linked-list to two linked lists with equal number of codes, following is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node *ptr;
struct node {
int element;
ptr prev;
ptr next;
};
typedef ptr list;
typedef ptr position;
int main() {
list L=malloc(sizeof(struct node));
list first=malloc(sizeof(struct node));
list second=malloc(sizeof(struct node));
splitlist(L,first,second);
return 0;
}
void splitlist(list L, list first,list second) {
position p,temp;
p=malloc(sizeof(struct node));
temp=malloc(sizeof(struct node));
p=L;
int count=0;
while ((p)->next != L) {
count++;
}
int c=count;
while (c!=(count/2)-1) {
p=(p)->next;
temp=(p)->next;
}
first=L;
(p)->next=NULL;
second=temp;
c=count;
while (c!=(count/2)-1) {
temp=(temp)->next;
}
(temp)->next=NULL;
}
When compiling my code it gives no errors but I'm not sure if it's working properly.
In order to get more readable and maintainable code, the first step to improve the code could be to create functions which help manipulating lists. Candidate functions are:
ListInitialize()
ListPushFront()
ListPushBack()
ListPopFront()
ListPopBack()
ListGetFirstNode()
ListGetNextNode()
ListGetFront()
ListGetBack()
ListEmpty()
...
With a proper set of arguments and return values of course.
Then you can write your splitlist function using those basic list operation functions and your code will be easier to read and to reason about.
Also, in order to handle an empty list, you should have an extra list type which is not just a pointer to a node.
typedef struct Node_tag { int value; struct Node_tag *next; struct Node_tag *prev } Node, *NodePtr;
typedef struct IntList_tag { NodePtr front; NodePtr back; } IntList;
// Creates an empty list.
void ListInitialize( IntList *pList ) { pList->front = NULL; pList->back = NULL; }
void ListPushFront( IntList *pList, int value )
{ NodePtr newNode = malloc(sizeof(Node));
if(NULL != newNode )
{ newNode->next = pList->front;
newNode->prev = NULL; newNode->value = value;
pList->front = newNode;
if( pList->back == NULL ) pList->back = newNode; // first element...
}
}
// ...
Eventually, using those functions, you can write splitlist() function in a concise and noise-free way:
void splitlist( IntList * source, IntList *target1, IntList *target2 )
{
IntList * currentTarget = target1;
for( NodePtr currentNode = ListGetFirstNode(source); currentNode != NULL; currentNode = ListGetNextNode(currentNode) )
{
ListPushBack(currentTarget, currentNode->value );
if(currentTarget == target1 ) currentTarget = target2;
else currentTarget = target1;
}
}
It might appear that it is much work to create all those other list functions if all you want is splitlist. But in real world applications you will most likely want all those other functions as well (or you have them already). Only in homework situations, this looks a bit funny.
Example code. Using typedef for node to be compatible with Microsoft C compilers (C89). Note sometimes the pointer to a circular list is a pointer to the last node of the circular list, (which contains a pointer to the first node of the circular list), allowing for faster appends. This example assumes list pointers are pointers to first nodes, but could be modified to assume list pointers are to last nodes.
#include <stdlib.h>
typedef struct _node{
struct _node *next;
int data;
}node;
node * splitlist(node * psrc, node ** ppdst1, node ** ppdst2)
{
node *ps = psrc;
node ** ppd1 = ppdst1;
node ** ppd2 = ppdst2;
*ppd1 = *ppd2 = NULL;
if(ps == NULL)
return NULL;
while(1){
*ppd1 = ps;
ps = *(ppd1 = &(ps->next));
if(ps == psrc)
break;
*ppd2 = ps;
ps = *(ppd2 = &(ps->next));
if(ps == psrc)
break;
}
*ppd1 = *ppdst1;
*ppd2 = *ppdst2;
return NULL;
}
main()
{
node a[8] = {{&a[1],0},{&a[2],1},{&a[3],2},{&a[4],3},
{&a[5],4},{&a[6],5},{&a[7],6},{&a[0],7}};
node *pa = &a[0];
node *pb = NULL;
node *pc = NULL;
pa = splitlist(pa, &pb, &pc);
return 0;
}
I'm trying to add items to a linked list. The code compiles OK but when I execute the program, it crashes before adding the first node. The code looks OK to me but I must be missing something.
The code uses a global linked list which is necessary for this problem. I think my usage of it may be what is causing the crash.
main.c
#include <stdio.h>
#include <stdlib.h>
#include "LinkedList.h"
int main (int argc, char* argv[])
{
LinkedList *canQueue;
int ii;
createList();
FILE* f;
f = fopen(argv[1], "r");
if(f==NULL)
{
printf("Error: could not open file");
return 0;
}
for(ii = 0; ii < 10; ii++)
{
TinCan* tempCan = malloc(sizeof(TinCan));
fscanf(f, " label_%d", &tempCan->label); /*Read info from file into label field*/
insertLast(canQueue, tempCan); /*Inserts the new can into linked list*/
}
return 0;
}
LinkedList.h
typedef struct TinCan
{
int label;
} TinCan;
typedef struct Node
{
TinCan* data;
struct Node *next;
} Node;
typedef struct LinkedList
{
Node *head;
} LinkedList;
void insertLast(LinkedList* list, TinCan *newData);
void createList();
extern LinkedList* canQueue;
LinkedList.c
#include <stdio.h>
#include <stdlib.h>
#include "LinkedList.h"
LinkedList *canQueue;
void createList() /*creates empty linked list*/
{
canQueue = malloc(sizeof(LinkedList));
canQueue->head = NULL;
}
void insertLast(LinkedList* list, TinCan *newData)
{
Node* newNode = malloc(sizeof(Node));
newNode->data = newData;
newNode->next = NULL;
if(list->head==NULL)
{
list->head=newNode;
}
else
{
Node* temp;
temp = list->head;
while(temp->next!=NULL)
{
temp = temp->next;
}
temp->next = newNode;
}
printf("Added to end");
}
Based on your response, you need to remove this declaration from main:
LinkedList *canQueue;
It is shadowing the global canQueue, which means later on when you call insertLast:
insertLast(canQueue, tempCan);
you are operating on an unintialized pointer.
I've been stuck on a segmentation fault of a long time. I declared a struct with a pointer to a string. I wrote two functions, create and remove to manipulate values. The struct is as follows:
#include "filename.h"
//*in filename.h:* typedef struct linkNode linkNode_t;
struct linkNode{
struct linkNode *next;
char *value;
};
The create function will first allocate memory for the node, then allocate memory for the value, and then copy the input value into the value field:
linkNode_t* create(char* stuff){
linkNode_t *ptr=malloc(sizeof(linkNode_t));
if(ptr==NULL){
printf("malloc failure");
return NULL;
}
char* tempvalu=malloc(sizeof(char)*strlen(stuff)+1);
if(tempvalu==NULL){
printf("malloc failure");
return NULL;
}
strcpy(tempvalu,stuff);
ptr->next=NULL;
ptr->value=tempvalu;
return ptr;
}
A function is used to insert a node into the linked list:
linkNode_t* insertLast(linkNode_t* start, linkNode_t* newNode){
linkNode_t* current=start;
while(current->next!=NULL){
current=current->next;
}
//now current points to the last element in the linked list
current->next=newNode;
return start;
}
The part causing me problem is as follows:
linkNode_t* removebyValue(linkNode_t* start, char* valu){
/**removes the first instance of a node with a certain value. Return *start after removing.
if linked list becomes empty, return NULL*/
linkNode_t *current=start;
linkNode_t *previous=start;
while(current!=NULL){
if(strcmp(valu,current->value)==0) {//found the node to delete
if(current==start){//removing the head
linkNode_t* retvalue= current->next;
free(current->value);
free(current);
return retvalue;
}
else{ //removing other elements in the linked list
previous->next=current->next;
free(current->value);
free(current);
return start;
}
}
else{
previous=current;
current=current->next;
}
}
return start;
}
In the Main I created a linked list of two elements,1 and 2, and tried to free element 1 when segmentation fault occured.
int main(){
linkNode_t *pt1=create("1");
pt1=insertLast(pt1,create("2"));
removebyValue(pt1,"1"); //Causes seg fault. If I replace "1" by "2" nothing happens
Can someone give some suggestions on this? Thanks in advance
EDIT: I put all the code that could be related since someone said the sections I put on didn't have an error
I think you're over-thinking the removal of a node while maintaining the start pointer properly. Consider a hopefully simpler approach.
typedef struct node_t
{
struct node_t* next;
char* value;
} node_t;
node_t* remove(node_t *start, const char* valu)
{
node_t* current=start;
node_t* prev=NULL;
while(current && strcmp(current->value, valu))
{
prev = current;
current = current->next;
}
if (current)
{
if (prev) // we're not deleting start node
prev->next = current->next;
else // we *are* deleting start node
start = current->next;
// now the node is unlinked. remove it.
free(current->value);
free(current);
}
return start;
}
here's an alternative test code that works fine, take a loot at it and see if it helps.
in addition, you can add
typedef struct node_t {
struct node_t* next;
char* value;
} node;
this may appear simpler to understand, but it isn't because nature of typedef is confusing.
I STRONGLY suggest you take a look at https://github.com/torvalds/linux/blob/master/Documentation/CodingStyle
This is the coding style of the linux kernel, it is very short and simple, not particularly a law, but it is worth noting...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node_t {
struct node_t* next;
char* value;
};
struct node_t* create(const char* istr)
{
struct node_t* ptr = (struct node_t*)malloc(sizeof(struct node_t));
char* tmp = (char*)malloc(sizeof(char) * (strlen(istr) + 1));
strcpy(tmp, istr);
ptr->next = 0;
ptr->value = tmp;
return ptr;
}
struct node_t* remove(struct node_t* start, const char* value)
{
struct node_t* current = start;
struct node_t* prev = start;
while (current != 0) {
if (!strcmp(value, current->value)) {
if (current == start) {
struct node_t* retval = current->next;
free(current->value);
free(current);
return retval;
} else {
/* nothing happens */
return 0;
}
}
}
}
int main(const int argc, const char** argv)
{
struct node_t* pt = create("1");
printf("%s\n", pt->value);
pt->next = create("2");
printf("%s\n", pt->next->value);
remove(pt, "1");
return 0;
}