scanf() running endlessly, program stops running on a statement - c

This is the code for BFT(breadth first traversal) for a connected graph.
I run the code then I successfully make the adjacency list and also successfully print the adjacency list but after it program stops at when I take input from user to start the BFS from that inputed node.
scanf() is running infinitely or other error I can't able to identify.
#include<stdio.h>
#include<stdlib.h>
typedef struct root //the adjacency list which have all the vertices
{
int info;
struct adjacent *adj;
struct root *next;
} root;
typedef struct adjacent //Linked list which store adjacent nodes of any nodes in adj list.
{
int info;
struct adjacent *adj;
} adjacent;
typedef struct node // to make queue to store nodes to be explored.
{
int info;
struct node *next;
} nodeQ;
void insert(nodeQ **ft,nodeQ **rr,int n) // insert func of Q
{
nodeQ * new=(nodeQ *)malloc(sizeof(nodeQ));
new->info = n;
new->next = NULL;
if(*ft == NULL)
{
*ft=new;
*rr=new;
}
else
{
(*rr)->next = new;
*rr = new;
}
}
int delete(nodeQ **ft,nodeQ **rr) //delete func of Q
{
int value=(*ft)->info;
nodeQ *temp=*ft;
*ft=(*ft)->next;
free(temp);
if(*ft==NULL)
*rr=NULL;
return value;
}
void BFS(int total_nodes,int node_tobe_explored,root *head,nodeQ **ft,nodeQ **rr)
{
printf("ff");
int * visited=(int *)malloc(sizeof(int)*total_nodes);
for(int i=0;i<total_nodes;i++)
visited[i]=0; //initialize all value in visited array with 0
printf("aa");
visited[node_tobe_explored] = 1;
printf("%d",node_tobe_explored);
while(1) // this loop iterates until all nodes are not explored.
{
root *t=head;
while(t->info != node_tobe_explored) // this find the node address(t) of the node_tobe_explored.
t=t->next;
printf("bb");
adjacent * adj_node = t->adj;
while(adj_node)
{
if(visited[adj_node->info] == 0) //if that adjacent node is not visited then also we visit it.
{
int adj_node_val = adj_node->info;
visited[adj_node_val] = 1;
insert(ft,rr,adj_node_val);
printf(", %d",adj_node_val);
}
}
printf("cc");
if(*rr==NULL) //if Q is empty, means all nodes are explored, so we return.
return;
else //otherwise explore first node present in Q
node_tobe_explored = delete(ft,rr);
}
}
int main()
{
char ch;
int no,tot_nodes,start;
nodeQ *front=NULL,*rear=NULL;
printf("enter the no. of nodes: ");
scanf("%d",&tot_nodes);
root *head = NULL;
no = tot_nodes;
while(no!=0)
{ //to make the main chain of adjacency list.
root *new=(root *)malloc(sizeof(root));
new->info = no;
new->adj = NULL;
new->next = head;
head = new;
no--;
}
root *temp = head;
while(temp!=NULL)
{ // to add the adjacent nodes to main chain.
printf("enter the nodes adjacent to %d:\n",temp->info);
do
{
int element;
printf(" enter node: ");
scanf("%d",&element);
adjacent *nw = (adjacent *)malloc(sizeof(adjacent));
nw->info = element;
nw->adj = temp->adj;
temp->adj = nw;
printf("more adjacent nodes y/n: ");
ch=getchar();
ch=getchar();
}while(ch=='Y'||ch=='y');
temp=temp->next;
}
printf("display of the structur of the linked list formed:\n");
root * head1=head;
while(head1) // to display the formed adj. list.
{
printf("%d--",head1->info);
adjacent *t = head1->adj;
while(t)
{
printf("%d,",t->info);
t=t->adj;
}
printf("\n");
head1=head1->next;
}
do
{
printf("enter the node value from which you want to start BFS: ");
printf("before [enter image description here][1]");
int st;
scanf("%d",&st);
printf("after");
BFS(tot_nodes,st,head,&front,&rear); //calling BFS func.
printf("do you want to print more traversals y/n: ");
ch=getchar();
ch=getchar();
}while(ch=='Y'||ch=='y');
}

Excerpt from OPs source code:
printf("do you want to print more traversals y/n: ");
ch=getchar();
ch=getchar();
}while(ch=='Y'||ch=='y');
The intention was probably to read a letter (y or n) and the \n which confirmed the input.
So, the 2nd ch=getchar(); (for ENTER) overrides the previously read letter. The following fix would change this:
printf("do you want to print more traversals y/n: ");
ch=getchar();
getchar(); /* ignore the returned value - it's just to consume '\n'. */
}while(ch=='Y'||ch=='y');
Btw. this is something which should have been uncovered by a step-wise debugging of the cited four lines...

Related

What's the problem in this program of Single Linked list?

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct node {
int data;
struct node* nextptr;
} * manode;
void add();
void delete ();
void display();
int main()
{
int choice;
int echoice;
while (choice != 4) {
printf("\n \t ENTER YOUR CHOICE FOR SINGLE LINKED LIST ");
printf("\n \t 1. ADD ELEMENT ");
printf("\n \t 2. DISPLAY ELEMENT ");
printf("\n \t 3. DELETE ELEMENT ");
printf("\n \t 4. EXIT ");
scanf("%d", &choice);
switch (choice) {
case 1:
while (echoice != 0) {
add();
printf("\n DO YOU WANT TO CONTINUE 1/0 ");
scanf("%d", &echoice);
}
break;
case 2:
display();
break;
case 3:
delete ();
break;
case 4:
exit(0);
break;
default:
printf("\n \t WRONG VALUE ENTERED ");
};
}
return 0;
}
#Add function is responsible to add the first node and all the remaining nodes as well.
void add()
{
struct node *tmp, *tmp2;
tmp = malloc(sizeof(struct node));
tmp2 = malloc(sizeof(struct node));
int value;
printf(" ENTER THE VALUE YOU WANT TO ENTER ");
scanf("%d", &value);
if (manode == NULL) {
manode = malloc(sizeof(struct node));
printf(" FIRST ENTRY ");
manode->data = value;
manode->nextptr = NULL;
tmp = manode;
printf("THE DATA %d ", manode->data);
}
else {
if (tmp2 == NULL) {
printf("\n MEMORY ALLOCATION FAILED");
}
else {
tmp2->data = value;
tmp2->nextptr = NULL;
tmp->nextptr = tmp2;
tmp = tmp->nextptr;
}
}
//manode=tmp;
}
void display()
{
struct node* tmp1;
if (manode == NULL) {
printf(" MEMORY ALLOCATION FAILED ");
}
else {
tmp1 = manode;
while (tmp1 != NULL) {
printf("\n%d DATA IS DISPLAY \n", tmp1->data);
tmp1 = tmp1->nextptr;
}
}
}
void delete ()
{
struct node* tmp;
if (manode == NULL) {
printf("NOTHING TO DELETE ");
}
else {
tmp = malloc(sizeof(struct node));
}
}
Kindly copy and compile the code, it's working but it doesn't display the contents in the list. Kindly copy and compile the code, it's working but it doesn't display the contents in the list.Kindly copy and compile the code, it's working but it doesn't display the contents in the list.Kindly copy and compile the code, it's working but it doesn't display the contents in the list.
As I see, there are a number of issues with your code.
do not use conio.h. This thing is from the '80s and adds nothing to a modern program but problems
never try to implement an ADT --- any container such as list, set, map --- as a node. It will only give you trouble: a list is a collection of nodes. Each node has a payload, some data. This data can have a key, something used to compare records. A node is not a list. A node is not the data. A list is not a node. As seen from the list, the data are the nodes. This way you can use anything as data in your list. And this is the purpose of a container: write once, use always. And the list has metadata, some obvious controls such its size, starting addres, ending address and possibly other stuff.
do not use void(). Is a waste, sometimes an error. In your case is an error. All pointers are buried inside the functions and die there. So display() and add() does not work
do not typedef pointers. It is a mess. In you case manode is a pointer. How are someone, even yourself a few days from now, remember what is what? If manode is a typedef for a struct everyone knows that
manode* many_nodes[30]
declare many_nodes as a pointer to an array of structs. The asterisk tells everything: many_nodes is a pointer to manode. BTOS if you bury the * inside the typedef you will always need to refer to the code in the header.
do not mix code of the list with I/O. It will only make your like harder. You have a list of simple int, so declare add() for instance as int add(int item, List* the_list). This way is more readable and you can write a simple loop to fill the list with a few hundred or just one node and start testing.
if you have a menu just write it as a function that returns the user option. But add it later to the program. A menu serves nothing to the list and to the program
scanf() was not written to read input from the keyboard. It is for scan formatted input, hence the name. It will always give you trouble when reading from stdin. But do your part and at least always test the return of scanf(). ALWAYS. rtfm.
do not write \n \t on a printf. Use just tabs or count the spaces.
always initialize all variables. In your code you start testing choice and echoice with no value set.
what is the point of having a loop on option 1, add since anyway the user will need to input an answer and enter 1?
Back to your program
See below your code rearranged using some of the things I wrote above. Compare with your code
Sample Code
#include <stdio.h>
#include <stdlib.h>
typedef struct st_node
{
int data;
struct st_node* nextptr;
} Node;
typedef struct tlist
{
unsigned size;
Node* start;
} List;
int add(int, List*);
int delete (int, List*);
int display(List*);
int menu();
int main(void)
{
List one;
one.size = 0;
one.start = NULL;
int res = menu();
printf("menu returned %d\n", res);
display(&one);
for( int i = 0; i<10; i+=1)
add(i,&one);
display(&one);
return 0;
}
int add(int value, List* l)
{
if ( l == NULL ) return -1;
Node* node = (Node*) malloc(sizeof(Node));
// simplest: insert at the beginning
node->nextptr = l->start;
node->data = value;
l->start = node;
l->size += 1;
return l->size;
};
int display(List* l)
{
if ( l== NULL) return -1;
if ( l->size == 0 )
{
printf("\n\tlist is empty\n\n");
return 0;
}
else
{
printf("\n\t%d elements in the list\n\n", l->size);
};
Node* p = l->start;
for( unsigned i = 0; i< l->size; i+=1)
{
printf("%3d: %11d\n", 1+i, p->data);
p = p->nextptr;
};
return l->size;
}
int delete (int v, List* l)
{
return 0;
}
int menu()
{
int choice = 0;
int res = 0;
printf(
"\n\tENTER YOUR CHOICE FOR SINGLE LINKED LIST:\n\
\n\t\t1. ADD ELEMENT\
\n\t\t2. DISPLAY ELEMENT\
\n\t\t3. DELETE ELEMENT\
\n\t\t4. EXIT\
\n\n\t\tYour choice: ");
while( res != 1 )
{
res = scanf("%d", &choice);
if ( choice >=1 && choice <= 4 ) return choice;
};
return 4;
}
OUTPUT
ENTER YOUR CHOICE FOR SINGLE LINKED LIST:
1. ADD ELEMENT
2. DISPLAY ELEMENT
3. DELETE ELEMENT
4. EXIT
Your choice: 2
menu returned 2
list is empty
10 elements in the list
1: 9
2: 8
3: 7
4: 6
5: 5
6: 4
7: 3
8: 2
9: 1
10: 0
And it is just an example of stuff using a more manageable list.

How to use gets and puts with linked list using pointers

I've written a linked list program and want to take input with spaces but it's not working.It works fine when I simply use "scanf" with %s but since I want to take input with multiple spaces I tried using "gets" and "puts" I've also tried using scanf("%[^\n]*c"); but on the console it gives me random garbage value for scanf("%[^\n]*c"); and for "gets" it reads blank space,
now let me tell you guys some info about the code and how it works
createNode(); function basically just creates a new node to store in the list and returns the address of this newly created node to the insertend(); function where it aligns the new node at the end of the list and in start=t=newnode start is the head pointer which points to the very first node and t is used to traverse the list until t's value becomes NULL,As you could see in the else part of the insertend(); function we're using another pointer t and storing the value of start in it so that we can traverse the list without losing the the address of the first node which is originally kept in the start pointer.
here's the code ->
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct Node
{
char first[20];
struct Node* next;
};
struct Node* start=NULL;
struct Node* t,*u;
int i=1;
struct Node* createNode() //this function creates a newnode everytime it's called
{
struct Node* create=(struct Node*)malloc(sizeof(struct Node));
return create;
}
int length() //to measure the length of the list.
{
int count = 0;
struct Node* temp;
temp=start;
while(temp!=NULL)
{
count++;
temp = temp->next;
}
return count;
}
void insertend() //to insert a node at the end of the list.
{
int l;
struct Node* newnode = createNode();
printf("Enter Name : ");
fgets(newnode->first,sizeof(newnode->first),stdin);
if(start==NULL)
{
start=t=newnode;
start->next=NULL;
}
else
{
t=start;
while(t->next!=NULL)
t=t->next;
t->next=newnode;
t=newnode;
t->next=NULL;
printf("%s successfully added to the list!",newnode->first);
}
l=length();
printf("The length of the list is %d",l);
}
void display() //to display the list
{
struct Node* dis;
dis=start;
if(start==NULL)
{
system("cls");
printf("No elements to display in the list");
}
else
{
system("cls");
for(int j=1;dis!=NULL;j++)
{
printf("%d.) %s\n",j,dis->first);
dis=dis->next;
}
}
}
int menu() //this is just a menu it returns the user input to the main function
{
int men;
printf("Please select a choice from the options below :-\n\n");
printf("1.) Add at the end of the list\n");
printf("2.) Display list\n");
printf("3.) exit\n");
printf(" Enter your choice : ");
scanf("%d",&men);
return men;
}
int main()
{
while(1)
{
system("cls");
switch(menu())
{
case 1 : insertend();
break;
case 2 : display();
break;
case 3: exit(0);
default : system("cls"); printf("Ivalid choice!Please select an appropriate option!");
fflush(stdin);
break;
}
getch();
}
return 0;
}
gets is not to be used, it has been removed from C standard due to it's lack of security.
If you want to know more read Why is the gets function so dangerous that it should not be used?
If you use [^\n] it should work, though it's also problematic since this specifier does not limit the lenght of the stream to be read only that it must stop when finding a newline character.
I suspect the problem might be in the container rather than in the reading, maybe uninitialized memory, If you provide the struct code it'll be easier to diagnose.
You can try:
fgets(newnode->first, sizeof(newnode->first), stdin)
There is a caveat:
If the inputed stream is larger than the container, the extra characters will remain in the input buffer, you might need to discard them.
EDIT:
So the main problem was the fact that through your code you have lingering characters in the buffer, in the particular case of your fgets input it would catch a '\n' left in the buffer, so it would read it before the inputed stream, leaving it, again, in the buffer.
I added a function to clean up buffer, note that fflush(stdin) leads to undefined behaviour so it's a bad option.
I also added a few small tweaks.
- Note that conio.h is windows specific as is system("cls") and getch()(ncurses.h in Linux systems) so I commented it for this sample.
Live sample here
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
struct Node
{
char first[20];
struct Node *next;
};
struct Node *start = NULL;
struct Node *t, *u;
void clear_buf(){ //clear stdin buffer
int c;
while((c = fgetc(stdin)) != '\n' && c != EOF){}
}
struct Node *createNode() //this function creates a newnode everytime it's called
{
struct Node *create = malloc(sizeof(struct Node));
return create;
}
int length() //to measure the length of the list.
{
int count = 0;
struct Node *temp;
temp = start;
while (temp != NULL)
{
count++;
temp = temp->next;
}
return count;
}
void insertend() //to insert a node at the end of the list.
{
int l;
struct Node *newnode = createNode();
printf("Enter Name : ");
clear_buf(); //clear buffer before input
fgets(newnode->first, sizeof(newnode->first), stdin);
newnode->first[strcspn(newnode->first, "\n")] = '\0'; //remove '\n' from char array
if (start == NULL)
{
start = t = newnode;
start->next = NULL;
printf("%s successfully added to the list!", newnode->first);
}
else
{
t = start;
while (t->next != NULL)
t = t->next;
t->next = newnode;
t = newnode;
t->next = NULL;
printf("%s successfully added to the list!", newnode->first);
}
l = length();
printf("The length of the list is %d", l);
}
void display() //to display the list
{
const struct Node *dis;
dis = start;
if (start == NULL)
{
system("cls");
printf("No elements to display in the list");
}
else
{
system("cls");
for (int j = 1; dis != NULL; j++)
{
printf("%d.) %s\n", j, dis->first);
dis = dis->next;
}
}
}
int menu() //this is just a menu it returns the user input to the main function
{
int men;
printf("\nPlease select a choice from the options below :-\n\n");
printf("1.) Add at the end of the list\n");
printf("2.) Display list\n");
printf("3.) exit\n");
printf(" Enter your choice : ");
scanf("%d", &men);
return men;
}
int main()
{
while (1)
{
system("cls");
switch (menu())
{
case 1:
insertend();
break;
case 2:
display();
break;
case 3:
exit(0);
default:
system("cls");
printf("Ivalid choice!Please select an appropriate option!");
clear_buf();
break;
}
getch();
}
return 0;
}

How can i solve the logical error in following code

I Have a Problem in following code
#include<stdio.h>
#include<stdlib.h>
struct linked
{
int val;
struct linked *before;
struct linked *next;
};
void get(struct linked *var);
void printforward(struct linked *var);
void printbackward(struct linked *var);
int main()
{
struct linked *ptr,*temp;
ptr=(struct linked*)malloc(sizeof(struct linked));
if(ptr==NULL)
{
printf("NOT ENOUGH MEMOREY");
exit(2);
}
ptr->before=NULL;
get(ptr);
printf("\nForward:\n");
printforward(ptr);
for(temp=ptr;temp->next;temp=temp->next)
{
temp->next->before=(struct linked*)temp;
}
printf("\nBackward:\n");
printbackward(temp->before);
}
void get(struct linked *var)
{
printf("Enter the number (-99) to quit:");
scanf("%d",&var->val);
if(var->val==-99)
{
var->next=NULL;
return;
}
else
{
var->next=(struct linked*)malloc(sizeof(struct linked));
if(var->next==NULL)
{
printf("NOT ENOUGH MEMOREY");
exit(2);
}
get(var->next);
}
}
void printforward(struct linked *var)
{
if(var->next==NULL)
{
return;
}
else
{
printf("\n%d",var->val);
printforward(var->next);
}
}
void printbackward(struct linked *var)
{
if(var->before==NULL)
{
printf("\n%d",var->val);
return;
}
else
{
printf("\n%d",var->val);
printforward(var->before);
}
}
output:
Enter the number (-99) to quit:1
Enter the number (-99) to quit:2
Enter the number (-99) to quit:3
Enter the number (-99) to quit:4
Enter the number (-99) to quit:5
Enter the number (-99) to quit:6
Enter the number (-99) to quit:7
Enter the number (-99) to quit:8
Enter the number (-99) to quit:9
Enter the number (-99) to quit:0
Enter the number (-99) to quit:-99
Forward:
1
2
3
4
5
6
7
8
9
0
Backward:
0
9
0
Process returned 0 (0x0) execution time : 22.297 s
Press any key to continue.
Expected output:
Enter the number (-99) to quit:1
Enter the number (-99) to quit:2
Enter the number (-99) to quit:3
Enter the number (-99) to quit:4
Enter the number (-99) to quit:5
Enter the number (-99) to quit:6
Enter the number (-99) to quit:7
Enter the number (-99) to quit:8
Enter the number (-99) to quit:9
Enter the number (-99) to quit:0
Enter the number (-99) to quit:-99
Forward:
1
2
3
4
5
6
7
8
9
0
Backward:
0
9
8
7
6
5
4
3
2
1
Let me know What's problem in the code,I am learning linked list in c language,I want to write a code for double way linked list But I a have a logical error in above problem,I did not get clear idea Why The above code did not work,so I am request to clear the doubt.
Why you're doing this with recursion, I have no idea, but in that spirit, consider this.
You're invoking printforward from printbackward, which makes no sense.
Your casts are not helping, and in fact, they're masking the real problems. Memory allocations, nor like-pointer or to/from void-pointer casting is required, nor recommended, in C. Read here for why
All four operations can be done recursively, and in fact, you don't even need the "before" pointer but I kept it nonetheless. You can:
Build your list
Forward-print your list
Backward-print your list
Cleanup your list
... all using recursion (I leave why you would want to as a different issue).
Code
#include <stdio.h>
#include <stdlib.h>
struct linked
{
int val;
struct linked *before;
struct linked *next;
};
struct linked *get(struct linked *before);
void printforward(struct linked const *var);
void printbackward(struct linked const *var);
void cleanup(struct linked *lst);
int main()
{
struct linked *ptr = get(NULL);
printf("Forward: ");
printforward(ptr);
fputc('\n', stdout);
printf("Backward: ");
printbackward(ptr);
fputc('\n', stdout);
cleanup(ptr);
}
struct linked *get(struct linked *before)
{
printf("Enter the number (-99) to quit:");
int value = -99;
if (scanf("%d", &value) != 1 || value == -99)
return NULL;
struct linked *p = malloc(sizeof *p);
if (p != NULL)
{
p->before = before;
p->val = value;
p->next = get(p);
}
return p;
}
void printforward(struct linked const *var)
{
if (var)
{
printf("%d ", var->val);
printforward(var->next);
}
}
void printbackward(struct linked const *var)
{
if (var)
{
printbackward(var->next);
printf("%d ", var->val);
}
}
void cleanup(struct linked *lst)
{
if (!lst)
return;
cleanup(lst->next);
free(lst);
}
Console
Enter the number (-99) to quit:1
Enter the number (-99) to quit:2
Enter the number (-99) to quit:3
Enter the number (-99) to quit:4
Enter the number (-99) to quit:5
Enter the number (-99) to quit:-99
Forward: 1 2 3 4 5
Backward: 5 4 3 2 1
here is an example of a simple double linked list construction with basic operation on it, such as addition and insertion of a node, and iteration in both directions.
Basically, node is simple structure with two pointers on previous and next node in list, and simple data variable in form of an integer. Key point on operations is proper manipulation of prev-next pointers in a node and head-last pointers in list structure.
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
typedef struct tagNode
{
int data;
struct tagNode *next; /* pointer to previous node */
struct tagNode *prev; /* pointe to next node */
} NODE;
/* head of list */
typedef struct tagList
{
NODE *head; /* pointer to first node in list */
NODE *last; /* pointer to last node in list */
} LIST;
/* func proto's */
NODE* create_node(int data);
NODE* insert_node(LIST* l,NODE *p);
NODE* add_node(LIST* l, NODE *p);
void print_node(NODE *p);
int main()
{
LIST list = {NULL,NULL}; /* init list with NULLs */
/* add some nodes to list */
for( int i = 0; i < 6 ; i++ )
{
add_node(&list, create_node(i*5) );
}
/* print forward */
printf("Forward:\n");
NODE* p = list.head;
for( ;p != NULL; p = p->next )
{
print_node(p);
}
/* print backward */
printf("Backward\n");
for(p = list.last;p != NULL; p = p->prev )
{
print_node(p);
}
/* insert some nodes */
printf("Insert some nodes\n");
insert_node(&list, create_node(33));
insert_node(&list, create_node(23));
insert_node(&list, create_node(13));
/* print forward -list after inserts */
printf("Print forward after insert\n");
for(p = list.head; p != NULL; p = p->next )
{
print_node(p);
}
/* print backward */
printf("print backward after insert\n");
for( p = list.last;p != NULL; p = p->prev )
{
print_node(p);
}
}
NODE* create_node(int data )
{
NODE *p = malloc(sizeof(NODE));
p->next = NULL;
p->prev = NULL;
p->data = data;
}
/* add node to end of list */
NODE* add_node(LIST* list, NODE* p)
{
if(list->last == NULL )
{
printf("add first node into list\n");
list->last = p;
list->head = p;
p->next = NULL;
p->prev = NULL;
}
else
{
printf("add num %d\n", p->data);
list->last->next = p;
p->prev = list->last;
list->last = p;
p->next = NULL; /* terminate list */
}
return list->last;
}
void print_node(NODE *p)
{
printf("node data: %d\n",p->data);
}
/* insert a node into list,
* position depends on value of data
**/
NODE* insert_node(LIST* l, NODE *q)
{
/* scan list ... */
for( NODE* p = l->head;p != NULL; p = p->next )
{
if( p->next != NULL )
{
if( p->next->data > q->data )
{
q->next = p->next;
q->prev = p;
p->next->prev = q;
p->next = q;
return q; /* indicate success */
}
}
}
return NULL; /* indicate failure */
}

Why am I getting a segmentation fault when using scanf("%lf", GPA) if I am using a pointer for GPA, and scanf("%lf", &GPA) if it is not a pointer?

void fillQueueWithStudents(Queue *q)
{
int counter = 1;
char answer = 'Y';
//this signifies the current variables that
//are being dealt with
char *currName;
double GPA;
student stud;
while((answer != 'N') || (answer != 'n'))
{
printf("Please enter the info for student %i \n",counter);
//Gets the name of the current student being entered
printf("Name: ");
scanf("%s", currName);
printf("\n");
//Gets the gpa of the current student being entered
printf("GPA: ");
scanf("%lf", &GPA);
//somewhere here is the problem
printf("\n");
//makes our student have the current variables
stud.name = currName;
stud.gpa = GPA;
//enqueues this student
enQueue(q,stud);
//increments to the next student
counter++;
//This sees if the user wants to enter another student
printf("Do you want to enter another student. Enter 'N' or 'n' for
no. \n");
scanf("%c", &answer);
printf("\n");
}
}
I printed hello before and after the scanf and they both printed. It does not let me enter a value for GPA. I am wondering if it is scanning the entire newline or something like that. I do not understand why it will not let me put in a value. I am guessing it is trying to put too much into the GPA variable.
Below is the complete program.
#include <stdlib.h>
#include <stdio.h>
typedef struct
{
char *name;
float gpa;
}student;
//This struct will represent a node in the queue
typedef struct Node
{
student *stud;
struct Node *next;
}QNode;
//This struct will identify the queue
//It will store the front and rear values to make
//it easier to enqueue and dequeue
typedef struct
{
QNode *front, *rear;
}Queue;
/*
This creates a new node with some data k.
It then sets its next value to NULL.
Then it returns the new node
Note: This node is not yet known to the queue. I will
use a separate function to do that
*/
QNode* newNode (student *stud)
{
QNode *temp = (QNode*)malloc(sizeof(QNode*));
temp->stud->gpa = stud->gpa;
temp->stud->name = stud->name;
temp->next = NULL;
return temp;
}
//Creats a empty queue
Queue* createQueue()
{
Queue *q = (Queue*)malloc(sizeof(Queue*));
q->front = q->rear = NULL;
return q;
}
/*
Uses the newNode function to make a new node in our linked list.
Then it puts that node in the correct place in the queue. This
is at the back
*/
void enQueue(Queue *q, student stud)
{
QNode *temp = newNode(&stud);//this creats a new node
/*
Checks if queue is empty, and if it is sets
our new node temp to rear and front. Then it
ends the function
*/
if(q->rear == NULL)
{
q->front = q->rear = temp;
return;
}
//sets the current rears next to our new node temp
q->rear->next = temp;
//this makes temp the new rear
q->rear = temp;
}
/*
This function serves/dequeues a node.
As always nodes are dequeued from the front of the
queue
*/
QNode *deQueue(Queue *q)
{
//if the queue is empty tell the user by
//returning NULL
if(q->rear == NULL)
{
return NULL;
}
/*
I will return front to the user in case they want
to use the data included in it. I have to save
front first to do that. So I save it hear
*/
QNode *temp = q->front;
//Now I make front equal to its next
q->front = q->front->next;
/*
This makes rear NULL if front is NULL
This means the list is empty and we have dequeued the last
node.
*/
if(q->front == NULL)
{
q->rear == NULL;
}
printf("The element dequeued was %s \n",temp->stud->name);
//This returns the node we have dequeued
return temp;
}
void printQueue(Queue *q)
{
//Check is the queue is empty and if it is stop the
//function
if(q->rear == NULL)
{
return;
}
/*
I will now print out each node out one by one.
To do this I create a QNode pointer and make it equal to the
front. I will then print all contents of front
and make temp equal to the next print and repeat this
till the end.
*/
QNode *temp = q->front;
while(temp != NULL)
{
int counter = 1;
printf("Student %i: Name: %s GPA: %f \n",
counter, temp->stud->name, temp->stud->gpa);
//increment the counter to display next student
counter++;
//Get the next node
temp = temp->next;
}
}
/*
This function keeps adding students to the queue until the
user enters 'N' that signifies they are done
*/
void fillQueueWithStudents(Queue *q)
{
int counter = 1;
char answer = 'Y';
//this signifies the current variables that
//are being dealt with
char *currName;
float GPA;
student stud;
while((answer != 'N') || (answer != 'n'))
{
printf("Please enter the info for student %i \n",counter);
//Gets the name of the current student being entered
printf("Name: ");
scanf("%s", currName);
printf("\n");
//Gets the gpa of the current student being entered
printf("GPA: ");
scanf("%f", &GPA);
printf("\n");
//makes our student have the current variables
stud.name = currName;
stud.gpa = GPA;
//enqueues this student
enQueue(q,stud);
//increments to the next student
counter++;
//This sees if the user wants to enter another student
printf("Do you want to enter another student. Enter 'N' or 'n' for no. \n");
scanf("%c", &answer);
printf("\n");
}
}
int main()
{
Queue *q = createQueue();
fillQueueWithStudents(q);
QNode *temp;
do {
temp = deQueue(q);
free(temp);
printQueue(q);
} while(temp != NULL);
return 0;
}
This:
scanf("%s", currName);
is undefined behavior, since currName is not initialized. Using scanf() with plain %s to read in a name is not a good idea. Use a buffer (!) and then tell scanf() the buffer size:
char currName[128];
if(scanf("%127s", currName) == 1)
{
}
... and check the return value, as shown.
Note that %s stops at the first whitespace character, so you won't be able to read a name containing spaces.

Inserting element in linked list after the biggest element in the list

I've been smashing my head here to see if I could find a solution but after few infinite loops, here's the code I'd like to be reviewed:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TREE_STRING 100
typedef struct Node {
char val;
struct Node *next;
} node;
node *create_list(char *list_string) {
node *momentary=NULL, *new=NULL, *head;
int i;
for(i=0; i<strlen(list_string); i++) {
new = (node *)malloc(sizeof(node));
new->val = list_string[i];
new->next = NULL;
if (!momentary) head = new;
else momentary->next = new;
momentary = new;
}
return head;
}
int print_list(node *head) {
node *momentary;
if(!head) return -1;
for(momentary=head; momentary!=NULL; momentary=momentary->next)
printf("%c ", momentary->val);
printf("\n");
return 0;
}
node *find_biggest(node *head) {
node *momentary=NULL, *biggest=head;
if (head==NULL) return NULL;
for (momentary=head; momentary!=NULL; momentary=momentary->next) {
if (momentary->val > biggest->val) biggest = momentary;
}
return biggest;
}
void insert_after_biggest(node **head, node **biggest, char val) {
node *p = *head, *temp=NULL;
*head = p->next;
if(*head!=NULL){
if(p->val==(*biggest)->val){
temp=p;
p->next=temp;
p->val=temp->val;
p->next=NULL;
*biggest=p;
p->next=(*biggest);
p->val=(*biggest)->val;
//*biggest=p;
p->next=NULL;
//temp=p;
p->next=temp;
p->val=temp->val;
}
else if(p->val<(*biggest)->val){
*head = p->next;
}
}
}
int main () {
node *head=NULL, *biggest=NULL;
int menu_choice;
char c, val, list_string[MAX_TREE_STRING];
setbuf(stdout, NULL);
do {
menu_choice = 0;
printf("\n1 Create list \n2 Print");
printf("\n3 Insert after biggest");
printf("\n4 exit\n");
scanf("%d", &menu_choice);
switch (menu_choice) {
case 1:
if (head) {
printf("List exist.\n");
break;
}
printf("Enter list as digits without spaces: ");
scanf(" %s", list_string);
head = create_list(list_string);
break;
case 2:
print_list(head);
break;
case 3:
scanf(" %c", &val);
insert_after_biggest(&head, &biggest, val);
break;
case 4:
break;
default:
while((c=getchar())!='\n' && c!=EOF);
}
} while(menu_choice!=4);
return 0;
}
Now the task here is:
Write a function "insert_after_biggest" so that the new elements are
put behind the element with the highest value and complexity of the
function must be O (1). In other words, the function "find_biggest"
that has complexity of O (n) can be called only if the "biggest" has
not yet been defined. If the list has no elements , it still needs to
be first.
Here's a console example to have clearer picture:
1|<-Insert into linked list option|
Enter list as digits without spaces: 683 |<-Prompt and entered value|
3 |<-Option(the function)|
2 |<-Number to be inserted|
2 |<-Print option|
6 8 2 3|<-Output|
3 |<-Option|
8 |<-Number to be inserted|
2 |<-Print option|
8 |<-Output|
I've been typing this code myself and I have no idea anymore how to look at this.
I would humbly ask if someone can help me to solve this, the code compiles but executing the option 3 in the console only makes it run in infinite loop, resulting in crashing the console.
The specific: how to solve it (step by step) and how it should look like(the done code, possibly included here?).
Thank you.
If you can assume that
1) You don't need to remove elements
You merely need to keep an extra pointer that points to the node with the largest value at all times. It's nice that you are allowed to scan the list for the largest if you've never called
insert_after_biggest, but that's not even necessary. Call that node max, and the pointer to max p_max.
For each insertion
a) The value you're about to insert is larger than the value held by max, in which case you insert the new value, and change p_max = p_new.
n_new->next = p_max;
p_max = p_new;
b) The value you're about to insert is larger than the value held buy max, in which case simply insert and leave p_max unchanged.
For insert_after_max
you explicitly do
p_new->next = p_max->next;
p_max->next = p_new;
Or if the new value is larger then do as described above.
Since you don't have to scan the list to insert, the complexity of insertion is O(1)

Resources