Trying to pass and print string into a linked list - c

So, I am trying to create a linked List where i take in strings from user then add them to the list and then delete the data at position 2. But i am having trouble with scanf (clarified in the output section) and also in the printing section. Any help would be appreciated.
The code
#include <stdio.h>
#include <stdlib.h>
struct node {
char *data;
char *begin;
char *end;
char *posi;
struct node *link;
};
struct node *add_begin(struct node *head, char *data) {
struct node *ptr = malloc(sizeof(*ptr));
ptr->data = data;
ptr->link = head;
return ptr;
}
struct node *add_end(struct node *head, char *data) {
struct node *ptr = malloc(sizeof(*ptr));
ptr->data = data;
ptr->link = NULL;
if (head == NULL) {
return ptr;
} else {
struct node *temp = head;
while (temp->link != NULL) {
temp = temp->link;
}
temp->link = ptr;
return head;
}
}
void add_at_post(struct node* head, char *data, int pos){
struct node *ptr=head;
struct node *ptr2=malloc(sizeof(struct node));
ptr2->data=data;
ptr2->link=NULL;
pos--;
while(pos !=1){
ptr=ptr->link;
pos--;
}
ptr2->link=ptr->link;
ptr->link=ptr2;
}
void delete_post(struct node* head, int position){
struct node*current= head;
struct node*previous= head;
if(head==NULL){
printf("is empty\n");
}
else if (position==1){
head=current->link;
free(current);
current=NULL;
}
else{
while(position!=1){
previous=current;
current=current->link;
position--;
}
previous->link=current->link;
free(current);
current=NULL;
}
}
int main() {
struct node *head = NULL;
char *data;
printf("Print at begin");
scanf("%s",data);
head = add_begin(head,data);//print at beginning of list
printf("Print at end");
scanf("%s",data);
head = add_end(head, data);//print at end of list
printf("Print at Position 2");
scanf("%s",data);
add_at_post(head,data,2);//print at position 2
delete_post(head,2);
for (struct node *ptr = head; ptr; ptr = ptr->link) {
printf("%s\n", ptr->data);
}
return 0;
}
The Expected Output
Print at begin
xxx
Print at end
yyy
Print at Position 2
ZZZ
xxx
zzz
The output I get. It calls the first scanf but skips the other 2. Then ends the RUN.
Print at begin
xxx
Print at end
Print at Position 2

This code is invalid in many places:
data does not reference valid memory
char *data;
printf("Print at begin");
scanf("%s",data);
you should allocate memory for ptr->data and copy as data may reference the same location on every call.
You do not check result of the malloc

Related

Assigning NULL to the head node in a linked list in C

Please see the full code below.
I have an initial array named arr.
I'm using a linked list to store some indices via the append function. After I got the indices, I store them in linked list and use clearList to change the corresponding values to 0 (In this example arr[2] and arr[4]).
Finally, I free the memory by calling freeList since i'm done with the linked list.
However, to be able to do same thing again and again, I need to set head to NULL whenever I call freeList. But I cannot. Any idea how to solve this?
Thank you.
#include <stdio.h>
#include "gurobi_c.h"
#include <stdlib.h>
//Gurobi variables
GRBenv *env = NULL;
GRBmodel *model = NULL;
//Gurobi variables
struct Node
{
int data;
struct Node *next;
struct Node *end;
};
void append(struct Node** head_ref, int new_data)
{
struct Node *last = *head_ref;
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = NULL;
new_node->end = new_node;
if (*head_ref == NULL)
{
*head_ref = new_node;
//printf(" ..Init Append %d\n",new_data);
return;
}
last = (*head_ref)->end;
last->next = new_node;
(*head_ref)->end=new_node;
//printf(" ..Append %d\n",new_data);
return;
}
void clearList(struct Node *node, double *arr)
{
int i;
if(node!=NULL)
{
struct Node tmp;
tmp=*(node->end);
while (node != NULL)
{
i=node->data;
arr[i]=0;
//printf(" ..clear %d \n", node->data,(node->end)->data);
node = node->next;
}
}
}
void freeList(struct Node *node)
{
struct Node *tmp,*hd;
hd=node;
while (node != NULL)
{
tmp=node;
node = node->next;
//printf(" ..Free %d \n", tmp->data);
free(tmp);
}
hd=NULL;
}
int main (){
Node *head;
double *arr = (double *) malloc(sizeof(double) * 10);
for(int i=0;i<10;i++)
arr[i]=i;
head=NULL;
printf("Head: %s\n", head);
append(&head,2);
append(&head,4);
clearList(head,arr);
for(int i=0;i<10;i++)
printf("No %d : %.2f\n",i,arr[i]);
freeList(head);
free(arr);
printf("%s", head);
getchar();
return 0;
}
You're already changing the value of head in your append function so you basically need to do the same thing in freeList:
void freeList(struct Node **head_ref)
{
struct Node *tmp,*node;
node=*head_ref;
while (node != NULL)
{
tmp=node;
node = node->next;
//printf(" ..Free %d \n", tmp->data);
free(tmp);
}
*head_ref=NULL;
}
int main (){
/* do stuff */
freeList(&head);
/* do stuff */
}
Just for completeness: Another possible option would be to use a wrapper macro for freeList().
void freeList(struct Node *node)
{
/* ... */
}
#define freeListNull(node) do { \
freeList(node); \
node = NULL; \
} while(0)
int main () {
/* ... */
freeListNull(head);
/* ... */
}
This solution has a similar disadvantage as the version that returns the modified pointer. You can simply forget to use the right call freeListNull(head); and call freeList(head); instead. The best solution is a function freeList() that takes the address of the head pointer as in idk's answer.
I realized it is possible to change the freeList function so that it will return a NULL value. See the updated code below:
#include <stdio.h>
#include "gurobi_c.h"
#include <stdlib.h>
//Gurobi variables
GRBenv *env = NULL;
GRBmodel *model = NULL;
//Gurobi variables
struct Node
{
int data;
struct Node *next;
struct Node *end;
};
void append(struct Node** head_ref, int new_data)
{
struct Node *last = *head_ref;
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = NULL;
new_node->end = new_node;
if (*head_ref == NULL)
{
*head_ref = new_node;
//printf(" ..Init Append %d\n",new_data);
return;
}
last = (*head_ref)->end;
last->next = new_node;
(*head_ref)->end=new_node;
//printf(" ..Append %d\n",new_data);
return;
}
void clearList(struct Node *node, double *arr)
{
int i;
if(node!=NULL)
{
struct Node tmp;
tmp=*(node->end);
while (node != NULL)
{
i=node->data;
arr[i]=0;
//printf(" ..clear %d \n", node->data,(node->end)->data);
node = node->next;
}
}
}
Node* freeList(struct Node *node)
{
struct Node *tmp;
while (node != NULL)
{
tmp=node;
node = node->next;
printf(" ..Free %d \n", tmp->data);
free(tmp);
}
return NULL;
}
int main (){
Node *head;
double *arr = (double *) malloc(sizeof(double) * 10);
for(int i=0;i<10;i++)
arr[i]=i;
head=NULL;
printf("Head: %s -> null as expected\n", head);
append(&head,2);
append(&head,4);
clearList(head,arr);
for(int i=0;i<10;i++)
printf("No %d : %.2f\n",i,arr[i]);
printf("Head: %s -> Not null as linkedlist is not freed\n", head);
head=freeList(head);
printf("Head: %s -> Again null as expected\n", head);
free(arr);
printf("%s", head);
getchar();
return 0;
}

Can't traverse through a C linked list

Task is to create a linked list consisting of objects. User inputs data for each individual Node in the main and then the object is being passed to push, which creates the list.
The problem comes in the printList function, where the condition for a break is never met.
For some reason the line head = head->next doesn't do anything, as the address of next with every iteration remains the same.
typedef struct Node {
int a;
char asd[30];
struct Node *next;
}Node;
Node *head = NULL;
void push(Node**head, struct Node* object);
void printList(Node *head);
int main() {
struct Node {
int oA;
char oAsd[30];
struct Node *next;
};
struct Node *object = malloc(sizeof(struct Node));
int c = 0;
while (1) {
printf("This int will be stored in Node %d.\n", ++c);
scanf("%d", &object->oA);
getchar();
if (!object->oA) {
break;
}
printf("This string will be stored in Node %d.\n", c);
gets_s(object->oAsd, 30);
if (!(strcmp(object->oAsd, "\0"))) {
break;
}
push(&head, object);
}
printList(head);
return 0;
}
void push(Node ** head, struct Node* object)
{
Node *tmp = malloc(sizeof(Node));
tmp = object;
tmp->next = (*head);
(*head) = tmp;
}
void printList(Node *head) {
if (head == NULL) {
puts("No list exists.");
exit(9);
}
while (1) {
printf("-------------------------------\n");
printf("|Int: <%d> |||| String: <%s>.|\n", head->a, head->asd);
printf("-------------------------------\n");
if (head->next) {
printf("\n\n%p\n\n", head->next);
head = head->next;
}
else {
break;
}
}
}`
There are two major problems in your code:
You define struct Node both outside main and inside main
Here tmp = object; you copy the value of a pointer to another pointer but you really want to copy the value of a struct to another struct, i.e. *tmp = *object;.
Besides that - don't put head as a global variable.
So the code should be more like:
typedef struct Node {
int a;
char asd[30];
struct Node *next;
}Node;
void push(Node**head, struct Node* object);
void printList(Node *head);
int main() {
Node *head = NULL;
struct Node *object = malloc(sizeof(struct Node));
int c = 0;
while (1) {
printf("This int will be stored in Node %d.\n", ++c);
scanf("%d", &object->a);
getchar();
if (!object->a) {
break;
}
printf("This string will be stored in Node %d.\n", c);
gets_s(object->asd, 30);
if (!(strcmp(object->asd, "\0"))) {
break;
}
push(&head, object);
}
printList(head);
return 0;
}
void push(Node ** head, struct Node* object)
{
Node *tmp = malloc(sizeof(Node));
*tmp = *object; // Copy the struct
tmp->next = (*head);
(*head) = tmp;
}
void printList(Node *head) {
if (head == NULL) {
puts("No list exists.");
exit(9);
}
while (1) {
printf("-------------------------------\n");
printf("|Int: <%d> |||| String: <%s>.|\n", head->a, head->asd);
printf("-------------------------------\n");
if (head->next) {
printf("\n\n%p\n\n", head->next);
head = head->next;
}
else {
break;
}
}
}

Calling insert function in c from a header file

My professor send me a library to insert,delete and search elements in a linked list:
#include <stdlib.h>
struct NODE
{
char AM[12];
char name[40];
int semester;
struct NODE *head;
struct NODE *next;
struct NODE *prev;
};
void init(struct NODE **head)
{
*head=NULL;
}
struct NODE *Search (struct NODE *head,char CODE[],struct NODE **prev)
{
struct NODE *tmp;
*prev=NULL;
tmp=head;
while (tmp!=NULL && tmp->AM<CODE)
{
*prev=tmp;
tmp=tmp->next;
}
if (tmp==NULL)
return NULL;
if (tmp->AM==CODE)
return tmp;
return NULL;
}
struct NODE *Search2 (struct NODE *head,char name[],struct NODE **prev)
{
struct NODE *tmp;
*prev=NULL;
tmp=head;
while (tmp!=NULL && tmp->name<name)
{
*prev=tmp;
tmp=tmp->next;
}
if (tmp==NULL)
return NULL;
if (tmp->name==name)
return tmp;
return NULL;
}
int Insert (struct NODE **H,struct NODE P)
{
struct NODE *cur,*prev;
cur=Search(*H,P.AM,&prev);
if (cur)
return 0;
cur=(struct NODE *)malloc(sizeof P);
*cur=P;
if (prev==NULL)
{
cur->next=*H;
*H=cur;
}
else
{
cur -> next = prev -> next;
prev -> next = cur;
}
return 1;
}
int Delete (struct NODE **H,char AM[])
{
struct NODE *cur,*prev,*next;
cur=Search(*H,AM,&prev);
if (!cur)
return 0;
if (prev==NULL)
cur=next;
else
prev->next=cur->next;
free(cur);
return 1;
}
void traverse (struct NODE *head)
{
struct NODE *cur;
cur=head;
while (cur)
{
printf ("%p\n",cur);
cur=cur->next;
}
}
Now here is a piece of code from the source file that i created in an attempt to insert an element in the linked list:
case 1:printf ("Input AM,name and semester of student: ");
tmp=(struct NODE *)malloc(sizeof(struct NODE));
if (tmp==NULL)
exit(1);
scanf("%s %s %d",tmp->AM,tmp->name,&tmp->semester);
_flag=Insert(&head,*tmp);
if(_flag)
printf ("Student inserted succesfully!\n");
free(tmp);
break;
When i insert the element i get the "Student inserted succesfully" message,but when i call the search function to find that element,it returns NULL (meaning that the element is not in the list).How should i call the Insert function from the header file? (I assume the problem must be in the Insert function).Also in main() i have declared the following two:
struct NODE *head;
struct NODE *tmp;
Should i change something regarding those two?
I think your problem is in the Search() and Search2() functions, where you've got things like this:
while (tmp!=NULL && tmp->AM<CODE)
and
if (tmp->AM==CODE)
return tmp;
You're comparing the pointers, rather than the contents of the strings. If you want to compare the strings, or find which is first alphabetically, use strcmp().
while (tmp!=NULL && strcmp(tmp->AM, CODE) < 0)
and
if (!strcmp(tmp->AM, CODE))
return tmp;
The same goes for the comparison between tmp->name and name in Search2().

Create a new node for each entry in a .txt file

Okay so I've been doing a program which would read elements of a txt file using scanf (cmd input redirection). A new node must be created for every entry in the file and add it at the end of the list. Here's my code so far:
struct Elem{
int Atnum;
char Na[31];
char Sym[4];
};
struct nodeTag {
struct Elem entry;
struct nodeTag *pNext; // pointer to the next node
};
typedef struct nodeTag Node;
The function that would initialize it is this:
Node *
InitializeList(Node *pFirst, int n)
{
int i;
Node *head, *temp = 0;
pFirst = 0;
for (i=0; i<n; i++){
head = (Node *)malloc(sizeof(Node));
scanf("%d", &head->entry.AtNum);
scanf("%s", head->entry.Na);
scanf("%s", head->entry.Sym);
if (pFirst != 0)
{
temp->pNext = head;
temp = head;
}
else
{
pFirst = temp = head;
}
fflush(stdin);
temp->pNext = 0;
}
return pFirst;
}
and lastly, print it
void
Print( Node *pFirst )
{
Node *temp;
temp = pFirst;
printf("\n status of the linked list is\n");
while (temp != 0)
{
printf("%d %s %s", temp->entry.AtNum, temp->entry.Na, temp->entry.Sym);
temp = temp -> pNext;
}
}
Now, I can't get the program to run properly. No run-time errors though but the output seems to be garbage. I've been working for hours for this and I cant' get my head around it. Thank you for your help!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Elem
{
int AtNum;
char Na[31];
char Sym[4];
};
struct nodeTag
{
/* entry must be a pointer in order to not lose the values
and/or encounter memory conflicting errors
*/
struct Elem *entry;
struct nodeTag *pNext;
};
typedef struct nodeTag Node;
// insert node at the first location
Node *insertFirst(Node *head, struct Elem *data)
{
Node *node = (Node *) malloc(sizeof(Node));
// fill in data
node->entry = data;
/* point it to old first node
in simple words: "put this node before the head"
*/
node->pNext = head;
// point first to new first node
head = node;
return head;
}
Node *InitializeList(int n)
{
int i;
Node *head = NULL;
struct Elem *data;
for (i = 0; i < n; i++)
{
// allocate memory for the struct Elem of each node
data = (struct Elem*) malloc(sizeof(struct Elem));
scanf("%d", &data->AtNum);
scanf("%s", data->Na);
scanf("%s", data->Sym);
head = insertFirst(head, data);
}
return head;
}
//display the list
void printList(Node *head)
{
Node *ptr = head;
printf("\nStatus of the linked list is:\n");
//start from the beginning
while(ptr != NULL)
{
printf("%d %s %s", ptr->entry->AtNum, ptr->entry->Na, ptr->entry->Sym);
printf("\n");
ptr = ptr->pNext;
}
}
int main(int argc, char *argv[])
{
Node *head;
head = InitializeList(3);
printList(head);
return 0;
}
I hope I didn't come too late! If not, please check this answer as the solution, thanks! :-)

Appending Linked List in C seg fault errors

I am having some trouble adding integers to the end of my linked list. I am very new to C and had part of my program working properly (the push function). I want to return a pointer to a struct node, and I am not quite sure where I am going wrong in my append function.
~Thanks.
enter code here
//node.h
#ifndef NODE_H
#define NODE_H
struct node{
int val;
struct node *next;
};
int length(struct node *);
struct node* push(struct node *, int); //adds integer to front of list.
struct node* append(struct node *, int); //adds integer to back of list.
void print(struct node *, int);
#endif
//node.c
#include "./node.h"
#include<stdlib.h>
#include<stdio.h>
int length(struct node *current){
if(current->next != NULL)
return 1 + length(current->next);
else
return 1;
}
struct node* push(struct node *head, int num){
struct node *temp = malloc(sizeof(struct node));
temp->val = num;
temp->next = head;
head = temp;
temp = NULL;
return head;
}
struct node* append(struct node *current, int num){
if(current != NULL){
append(current->next, num);
}
else{
struct node* temp = malloc(sizeof(struct node));
temp->val = num;
temp->next = NULL;
current = temp;
return current;
}
}
void print(struct node* head, int size){
printf("The list is %i", size);
printf(" long \n");
struct node* temp;
temp = head;
while(temp != NULL){
printf("%d", temp->val);
printf(" ");
temp = temp->next;
}
printf(" \n");
}
//Main
#include "./node.h"
#include<stdlib.h>
#include<stdio.h>
int main(){
char ans[2];
int num;
struct node* head = NULL;
do{
printf("Enter a integer for linked list: ");
scanf("%d", &num);
head = append(head, num);
printf("Add another integer to linked list? (y or n) ");
scanf("%1s", ans);
}while(*ans == 'y');
print(head, length(head));
return 0;
}
I think what is missing is that the recursive part of the function needs to set current->next. This has the effect of setting every node's next pointer to what it was until you get to the end of the list, when it is set to the newly malloced node.
struct node* append(struct node *current, int num){
if(current != NULL){
current->next = append(current->next, num);
return current;
}
else {
struct node* temp = malloc(sizeof(struct node));
if (temp == NULL) abort();
temp->val = num;
temp->next = NULL;
return temp;
}
}

Resources