I'm sure this has been asked before, but I cannot find anything on this website or any other about it after searching for quite awhile.
I''m having trouble getting the values of structures that I'm creating and modifying in a function. The code looks something like:
struct node {
char name[35];
int employeeID;
struct node *next;
}
typedef struct node employee;
void insertInOrder(employee *head, employee *curr) {
if (head == NULL) {
*curr->next = *head;
*head = *curr;
} else {
if ((head->employeeID<curr->employeeID)&&(curr->employeeID <head->next->employeeID)) {
*curr->next = *head->next;
*head->next = *curr;
} else {
insertInOrder(head->next, curr);
}
}
}
void addEmployee(char name[], employee *head, employee *curr) {
int id;
scanf("%d", &id);
curr = malloc(sizeof(employee));
strcpy(curr->name, name);
curr->employeeID = id;
insertInOrder(head, curr);
}
int main(void) {
char name[35];
int quit = 1;
employee *head, *curr;
head = NULL;
printf("Enter data about the books: \n");
while (quit) {
scanf("%[^\n]%*c", title);
if (title[0] != '#') {
addBook(name, head, curr);
} else {
quit = 0;
}
}
During my debugging, my code iterates into all of my functions, but once I get back to main after adding all of the data I want, all of the variables are empty. I know it has something to do with the way I'm using or passing pointers, but when I look at the code I keep coming to the logical conclusion that what I have should do what I want. Please, someone point out where my algorithm is flawed.
addBook takes pointers of type Book but you are passing pointers of type Employee
Edit:
So, first you don't need to do things like *curr->next = *head. It should be curr->next = head.
Also, head->next can be null which is not being checked. Finally, head needs to always be pointed at the start of the list.
Edit 2:
Following code should work. head always points to the start of the list. In order to do that, we must pass the address of the head pointer. We need to do this because we will be modifying the address of head.
I've also cleaned up a few things.
void insertInOrder(employee **head, employee *curr) {
if (*head == NULL) {
// We are inserting the first element
*head = curr;
}
else if ((*head)->next == NULL) {
// This is the second element. We either insert it in front of head or before head.
if ((*head)->employeeID < curr->employeeID) {
(*head)->next = curr;
}
else {
curr->next = *head;
*head = curr;
(*head)->next = NULL;
}
}
else {
// We iterate through the list trying to find the best spot to insert curr.
employee *temp = *head;
while (temp->next != NULL) {
if ((temp->employeeID < curr->employeeID) && (curr->employeeID < temp->next->employeeID)) {
curr->next = temp->next;
temp->next = curr;
break;
}
temp = temp->next;
}
// curr has the greatest id so it is inserted at the end
if (temp->next == NULL)
temp->next = curr;
}
}
void addEmployee(char name[], employee **head) {
int id;
printf("Enter id\n");
scanf("%d", &id);
employee *curr = malloc(sizeof(employee));
strcpy(curr->name, name);
curr->employeeID = id;
curr->next = NULL;
insertInOrder(head, curr);
}
int main(void) {
int quit = 1;
employee *head = NULL;
char title[100];
printf("Enter data about the employees: \n");
while (quit) {
scanf("%s", title);
if (title[0] != '#')
addEmployee(title, &head);
else break;
}
return 0;
}
inside the function no need to use *head or *curr ..because -> is made up for pointers only instead directly use head->left & curr->next
thanks
Related
I have written a linked list program which stores data member as void *.
while trying to store annd print using scanf/printf functions, I am getting segmentation fault.
node definition -->
typedef struct node {
struct node *next;
void *data;
}node;
main function -->
head=(node *)malloc(sizeof(node));
if (head==NULL){
printf("error in allocation of memory\n");
exit(EXIT_FAILURE);
}
tail=(node*)create(head);
create function -->
void *create(node *current)
{
int user_choice;
while(current){
printf("\nEnter the data:");
scanf("%s",current->data);
printf("stored at %p\n",(void*)current->data);
printf("%s",(char*)current->data);
printf("\nType '1' to continue, '0' to exit:\n");
scanf("%d",&user_choice);
if(user_choice == 1){
current->next=(node*)malloc(sizeof(node));
current=current->next;
}
else{
current->next=NULL;
}
}
return current;
}
can anyone tell what is the correct argument for scanf & prinf should be..?
working code after incorporating points given in answers...
void *create(node *current)
{
node *temp;
int user_choice;
while(current){
printf("\nEnter the data:");
current->data=(char*)malloc(10*sizeof(char));
scanf("%s",current->data);
printf("stored at %p\n",(void*)current->data);
printf("%s",(char*)current->data);
printf("\nType '1' to continue, '0' to exit:\n");
scanf("%d",&user_choice);
if(user_choice == 1){
current->next=(node*)malloc(sizeof(node));
}
else{
current->next=NULL;
temp=current;
}
current=current->next;
}
return temp;
}
In your code,
scanf("%s",current->data);
is attempt to make use of an unitialized pointer, it invokes undefined behavior.
You need to follow either of bellow approach,
make the pointer point to valid chunk of memory (using malloc() and family for dynamic allocation, for example)
use an array.
You should first initialize data member of structure because
current->data = malloc("passes size here");
For putting data you have to typecast first this data because void is not storage type. void pointer can be used to point to any data type.
Like
*(char *)(current->data) = 1;
As others have said:
scanf("%s",current->data);
Is undefined in C. current->data needs to be pointing somewhere before you can store anything in it.
You should instead:
Accept input from scanf.
Store in temporary buffer.
Insert into linked list
print out whole linked list at the end
free() linked list at the end.
I also feel that your current void *create function is doing too much, and it would be easier to split up your code into different functions, just to make it easier to handle all the pointer operations, inserting etc.
To demonstrate these points, I wrote some code a while ago which does these things, and has been modified to help you with your code. It is not the best code, but it does use these points that will help you with your code.
Here it is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSTRLEN 100
typedef struct node {
void *data;
struct node *next;
} node_t;
typedef struct {
node_t *head;
node_t *foot;
} list_t;
list_t *create_list(void);
node_t *generate_node(void);
list_t *insert_node(list_t *list, char *data);
void print_list(list_t *list);
void free_list(list_t *list);
int
main(int argc, char *argv[]) {
list_t *list;
char data[MAXSTRLEN];
int user_choice;
list = create_list();
while (1) {
printf("Enter the data: ");
scanf("%s", data);
printf("\nType '1' to continue, '0' to exit:\n");
if (scanf("%d",&user_choice) != 1) {
printf("Invalid input\n");
exit(EXIT_FAILURE);
}
if (user_choice == 1) {
list = insert_node(list, data);
} else {
list = insert_node(list, data);
break;
}
}
print_list(list);
free_list(list);
list = NULL;
return 0;
}
/* inserting at foot, you can insert at the head if you wish. */
list_t
*insert_node(list_t *list, char *data) {
node_t *newnode = generate_node();
newnode->data = malloc(strlen(data)+1);
strcpy(newnode->data, data);
newnode->next = NULL;
if (list->foot == NULL) {
list->head = newnode;
list->foot = newnode;
} else {
list->foot->next = newnode;
list->foot = newnode;
}
return list;
}
node_t
*generate_node(void) {
node_t *new = malloc(sizeof(*new));
new->data = NULL;
return new;
}
void
print_list(list_t *list) {
node_t *curr = list->head;
printf("\nlinked list data:\n");
while(curr != NULL) {
printf("%s\n", (char*)curr->data);
curr = curr->next;
}
}
list_t
*create_list(void) {
list_t *list = malloc(sizeof(*list));
if (list == NULL) {
fprintf(stderr, "%s\n", "Error allocating memory");
exit(EXIT_FAILURE);
}
list->head = NULL;
list->foot = NULL;
return list;
}
void
free_list(list_t *list) {
node_t *curr, *prev;
curr = list->head;
while (curr) {
prev = curr;
curr = curr->next;
free(prev);
}
free(list);
}
UPDATE:
Also note how I allocated memory for newnode->data?
Like this:
newnode->data = malloc(strlen(data)+1); //using buffer from scanf
This now means I can store data in this pointer, your current->data will need to do something similar.
working code-->
void *create(node *current)
{
node *temp;
int user_choice;
while(current){
printf("\nEnter the data:");
current->data=(char*)malloc(10*sizeof(char));
scanf("%s",current->data);
printf("stored at %p\n",(void*)current->data);
printf("%s",(char*)current->data);
printf("\nType '1' to continue, '0' to exit:\n");
scanf("%d",&user_choice);
if(user_choice == 1){
current->next=(node*)malloc(sizeof(node));
}
else{
current->next=NULL;
temp=current;
}
current=current->next;
}
return temp;
}
Please try with this
void *create(node *current)
{
int user_choice;
while(true){
if(current == NULL) {
current = (node *)malloc(sizeof(node));
current->data = NULL;
current->next = NULL;
}
printf("\nEnter the data:");
scanf("%s",current->data);
printf("stored at %p\n", (void *)current->data);
printf("%s",current->data);
//printf("%s",(char*)current->data);
printf("\nType '1' to continue, '0' to exit:\n");
scanf("%d",&user_choice);
if(user_choice == 1){
current->next=(node*)malloc(sizeof(node));
current=current->next;
}
else{
current->next=NULL;
tail = current;
current=current->next;
break;
}
}
return current;
}
Note: The element has to be initialized (ie; it has to be alloted with some memory) before we are trying to make use of it.
This is my insertion sort function :
Student *sort(Student* node)
{
if (node == NULL || !node->next)
return node;
Student *sorted = NULL;
while (node != NULL)
{
Student *head = node;
Student **tail = &sorted;
node = node->next;
while (!(*tail == NULL || head->id < (*tail)->id))
{
tail = &(*tail)->next;
}
head->next = *tail;
*tail = head;
}
return sorted;
}
So if this is supposed to sort 3.3, 3.1 and 3.8 , it sorts them such as :
3.3
3.8
I don't know what happens to the first element. If I give it a larger set of text to sort, it misses almost half of the text.
Been trying to figure out why it does this. I'm pretty sure it's the problem with my sorting function.
write function. This function is supposed to simply write the sorted result to a file :
void write(Student* node) {
Student * curr = NULL;
curr = node;
FILE *ptr = fopen("student_out.txt", "w");
if (curr == NULL)
{
printf("Nothing to list. \n");
exit(1);
}
int i=0;
while(curr !=NULL) {
fprintf(ptr,"%d, %s, %s, %s, %.2f\n", curr->id, curr->firstname, curr->lastname, curr->major, curr->gpa);
curr = curr -> next;
}
return;
}
Seems to be working, the problem could be with the print out. Example code to test the case mentioned above, converted to be C89 compatible (since I'm using Visual Studio). I would have swapped the names head and node, but I left them as is to match the original example. I also changed the compare to stop when (*tail)->id > head->id (using <= in the compare instead of <) so that the original order of "equal" nodes is preserved.
#include <stdio.h>
typedef struct Student_{
struct Student_ *next;
double id;
}Student;
Student *sort(Student* node)
{
Student *sorted = NULL;
Student **tail;
Student *head;
if (node == NULL || !node->next)
return node;
while (node != NULL)
{
head = node;
node = node->next;
tail = &sorted;
while (*tail != NULL && (*tail)->id <= head->id)
tail = &(*tail)->next;
head->next = *tail;
*tail = head;
}
return sorted;
}
int main()
{
Student a[3] = {{&a[1],3.3},{&a[2],3.1},{NULL,3.8}};
Student *b;
b = sort(a);
while(b){
printf("%3.1lf ", b->id);
b = b->next;
}
printf("\n");
return 0;
}
I'm having a problem with inserting a node at the end of a linked list. It's not being executed when the start node is not null and I don't understand the problem. Please help me out here. The function is called second time but is not going to the else block.
typedef struct token_Info
{
int linenumber;
char* token;
char value[200];
struct token_Info* next;
} token_Info;
token_Info *tokenlist;
token_Info* insert_at_end( token_Info *list,char *name)
{
printf("token identified \t");
token_Info *new_node;
token_Info *temp,*start;
start = list ;
char *tempname ;
tempname = name;
new_node= malloc(sizeof(token_Info));
new_node->token = malloc(sizeof(strlen(tempname)+1));
strcpy(new_node->token,tempname);
new_node->next= NULL;
// printf("%d",strlen(tempname));
if(new_node == NULL){
printf("nFailed to Allocate Memory");
}
if(start==NULL)
{
start=new_node;
return start;
}
else
{
printf("anvesh");
temp = start;
while(temp->next != NULL)
{
temp = temp ->next;
}
temp->next = new_node;
return temp;
}
}
tokenlist = insert_at_end(tokenlist,"TK_BEGIN");
tokenlist = insert_at_end(tokenlist,"TK_BEGIN1");
UPDATE
I found two bugs, the first was the head of the list was not being returned when appending the list. The other in the memory allocation for the token string which incorrectly used sizeof.
I repositioned the test of the malloc() return value, and added a second one. I removed several unnecessary temporary variables that were cluttering the code. I added two functions, show_list() and free_list(). Finally, remember that the value string field is still uninitialised.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct token_Info
{
int linenumber;
char* token;
char value[200];
struct token_Info* next;
} token_Info;
token_Info* insert_at_end( token_Info *list, char *name)
{
token_Info *new_node, *temp;
new_node= malloc(sizeof(token_Info));
if(new_node == NULL){ // repositioned
printf("\nFailed to allocate node memory\n");
exit(1); // added
}
new_node->token = malloc(strlen(name)+1); // removed sizeof
if(new_node->token == NULL){ // added
printf("\nFailed to allocate token memory\n");
exit(1);
}
strcpy(new_node->token, name);
new_node->next= NULL;
if(list==NULL)
return new_node;
// append
temp = list;
while(temp->next != NULL)
temp = temp->next;
temp->next = new_node;
return list; // original head
}
void free_list( token_Info *list)
{
token_Info *temp;
while (list) {
temp = list->next;
free(list->token);
free(list);
list = temp;
}
}
void show_list( token_Info *list)
{
printf ("\nCurrent list:\n");
while (list) {
printf ("%s\n", list->token);
list = list->next;
}
}
int main(int argc, char **argv)
{
token_Info *tokenlist = NULL;
tokenlist = insert_at_end(tokenlist, "TK_BEGIN");
show_list(tokenlist);
tokenlist = insert_at_end(tokenlist, "TK_SECOND");
show_list(tokenlist);
tokenlist = insert_at_end(tokenlist, "TK_FINAL");
show_list(tokenlist);
free_list(tokenlist);
return 0;
}
Program output:
Current list:
TK_BEGIN
Current list:
TK_BEGIN
TK_SECOND
Current list:
TK_BEGIN
TK_SECOND
TK_FINAL
The question could also be whether you want tokenlist to be a running end of the list, or remain at the start.
As of right now, your first call:
tokenlist = insert_at_end(tokenlist,"TK_BEGIN");
has tokenlist being the only node in the list.
The second call tokenlist = insert_at_end(tokenlist,"TK_BEGIN1"); returns 'temp' which happens to also be the 'TK_BEGIN' node, ( ie, the first node )
If you want the return value to be the last element, you would return new_node instead of temp. If you want to retain the start, you would return start;
All that said:
The calls to it are not part of any function,
I just ran it with the calls in main and got this output:
int main(void){
tokenlist = insert_at_end(tokenlist,"TK_BEGIN");
tokenlist = insert_at_end(tokenlist,"TK_BEGIN1");
return 0;
}
$> ./a.out
token identified token identified anvesh
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void Insert();
void DisplayList();
struct Student
{
char Name[10];
int Marks;
struct Student *Next;
} *Start;
int main()
{
Start = NULL;
int Choise;
while (1)
{
printf("enter number to choose ");
scanf_s("%d", &Choise);
switch (Choise)
{
case 1:
Insert();
break;
case 3:
DisplayList();
break;
default:
printf("Incorrect assignment Press relevant key :");
}
}
}
void Insert()
{
struct Student *Temp, *current=NULL;
Temp = (struct Student *) malloc(sizeof(struct Student));
printf("Enter Name Of Student");
scanf_s("%s",&Temp->Name);
printf("Enter Marks Of Student");
scanf_s("%d", &Temp->Marks);
Temp->Next = NULL;
if (Start == NULL)
{
Start = Temp;
Temp->Next = NULL;
}
else
current = Start;
while (current->Next != NULL)
{
current = current->Next;
current->Next = Temp;
}
}
void DisplayList()
{
struct Student *current, *Temp;
current = Start->Next;
if (Start == NULL)
{
printf("No Element in the list");
}
else
{
for (current = Start; current != NULL; current = current->Next)
{
printf("The List are\n");
printf_s("%d",current->Marks);
}
}
this is a Program written for single linked list.when i display the list it give only one element in the list. Whenever i am trying to print the elements of the linked list, it gives the output only one element
what mistake i do please help?
change
else
current = Start;
while (current->Next != NULL)
{
current = current->Next;
current->Next = Temp;
}
to
else {
current = Start;
while (current->Next != NULL)
{
current = current->Next;
}
current->Next = Temp;
}
and
scanf_s("%s", Temp->Name, sizeof(Temp->Name)); //remove & and add size(see Amnon's answer)
When using scanf_s which is the safe version of scanf, you are expected to pass not only the address of the buffer but also its size as the next parameter, i.e.:
scanf_s("%s", Temp->Name, _countof(Temp->Name));
You can read more about it in http://msdn.microsoft.com/en-us/library/w40768et.aspx
The other issue with the code is that you're initializing current with NULL but then trying to access its Next field.
Change the code here:
else
current = Start;
while (current->Next != NULL)
{
current = current->Next;
current->Next = Temp;
}
to this:
else {
current = Start;
while (current->Next != NULL)
{
current = current->Next;
}
current->Next = Temp;
temp->next=NULL;
}
you forget to add NULL at next pointer and therefore you are getting only single output.
This code adds only one element to the end of list(just creates head element, nothing after that).What is wrong in my program? Should I pass two items in function, head and item or just one?
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct MyList
{
int x;
int y;
struct MyList * next;
}List;
typedef List * Item;
void AddEnd(Item * head);
void PrintList(Item * head);
int main(void)
{
int response;
Item head;
head = NULL;
while(1)
{
printf("1- Print, 2 - Add to End, 3 - exit\n");
scanf("%d", &response);
switch(response)
{
case 1: PrintList(&head); break;
case 2: AddEnd(&head); break;
case 3: return 0;
}
}
return 0;
}
void PrintList(Item * head)
{
Item temp;
temp = *head;
while(temp != NULL)
{
printf("%d %d\n", temp->x, temp->y);
temp = temp->next;
}
}
void AddEnd(Item * head)
{
Item new, temp;
new = (Item)malloc(sizeof(new));
printf("Enter x and y: ");
scanf("%d %d", &new->x, &new->y);
new->next = NULL;
if(*head == NULL)
{
*head = new;
}
else
{
temp = *head;
while(temp != NULL)
{
temp = temp->next;
}
temp = new;
}
}
This code down that I just tried don't work also:
void AddEnd(Item * head, Item * item)
{
Item new, temp;
new = (Item)malloc(sizeof(new));
printf("Enter x and y: ");
scanf("%d %d", &new->x, &new->y);
new->next = NULL;
if(*head == NULL)
{
*head = new;
}
else
{
temp = *head;
while(temp != NULL)
{
temp = temp->next;
}
temp = new;
*item = temp;
}
}
In your AddEnd function in the else clause, when you exit the while loop, temp is now NULL. However, the element before it is still pointing to NULL.
Try something like
temp = *head;
if (temp->next == NULL) {
temp->next = new;
} else {
while((temp->next) != null) {
temp = temp->next;
}
temp->next = new;
}
in your else clause.
(This, and the apparent issue with your understanding of malloc referenced by the others, new should be a Item * and the malloc call should be malloc(sizeof(Item)). You also don't need to cast the return value of malloc (indeed, there are some pitfalls that happen if you do).) Reading your typedefs a little more closely, new should actually be an Item (since it's a pointer to a List struct and you have typedef List* Item). Try new = malloc(sizeof(List)); and just declare new to be of type List *. (The typedef List * Item makes your code hard to read; it becomes less clear what's a pointer and what isn't.)
You need to change this:
new = (Item)malloc(sizeof(new));
To this:
new = (Item *)malloc(sizeof(List));
Hope this helps