c doubly-linked list display method showing redundant elements - c

I have a small doubly-linked list application. I want to add elements inside the list and then display the list normally. At the output i get my inserted elements allright, but after them i get a bunch of strange numbers( such as .... 28482 -20048 2817 ...... )
I believe it's a problem of space allocation.
Any help is appreciated, thanks in advance!
# include <stdio.h>
# include <conio.h>
# include <string.h>
# include <stdlib.h>
typedef struct elem {
int number;
struct elem * urm;
struct elem * prec;
}nod;
nod *prim=NULL,*ultim=NULL, *local=NULL, *p=NULL;
void insert_element(int numb){
nod *local=(nod *)malloc(sizeof(nod));
local->number = numb;
if (prim==NULL){
prim=local;
ultim=local;
}
else{
ultim->urm = local;
local->prec = ultim;
ultim=local;
}
}
void load_data()
{
int i,n;
nod *c = (nod *)malloc(sizeof(nod));
printf("\n cate elemente va avea lista?");
scanf("%d", &n);
printf("avem %d elemente", n);
for(i=1;i<=n;i++){
printf("\n number: ");
scanf("%d", &c->number);
insert_element(c->number);
}
}
void list_left_to_right()
{
nod *p = (nod*) malloc(sizeof(nod));
p=prim;
while(p){
printf("%d ", p->number);
p=p->urm;
}
printf("\n");
}
int main()
{
int op;
do{
printf("\n1.Enter some data\n");
printf("2.Display left - > right the data\n");
printf("0.Exit\n");
printf("choice : ");
scanf("%d",&op);
switch(op){
case 1: load_data(); break;
case 2: list_left_to_right(); break;
case 0: break;}
}
while (op!=0);
return 0;
}

(1) You have a memory leak in list_left_to_right():
nod *p = (nod*) malloc(sizeof(nod));
p=prim;
This leaks the block returned by malloc().
(2)
void insert_element(int numb) {
nod *local=(nod *)malloc(sizeof(nod));
local->number = numb;
// TODO: set local->urm and local->prec to NULL
if (prim==NULL) {
prim=local;
ultim=local;
OK, so the first time insert_element() is called, the new element is both the head and the tail.
Bug: You need to set the urm and prec fields to NULL. They have undefined values initially.
}
else {
ultim->urm = local;
local->prec = ultim;
ultim=local;
}
}
After that, the subsequent elements are inserted as a new tail (ultim).
Bug: But again you need to make sure that local->urm is set to NULL.

Related

C Programming - Using Parallel Arrays to enter Names, Exercise Marks and Compute Average of Exercise Marks and Display

I'm doing self-study on C Programming, and I have been recommended the following C Program by my colleagues to study further, where you can enter the Name and Age and it displays and uses Insert, Delete, Display, and Exit menu options.
I'm trying to convert it to my current study stream logic scenario where I need to enter the Name, Exercise Mark 1 (up to 3), and then it computes the Average and gets displayed while employing the Insert, Delete, Display, Update (updating the scores only, not the names), Delete and Exit.
Any guidance please on how to learn this code and understand the logic, and apply it to the 2nd scenario will be much appreciated.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 50
//using parallel arrays as fields in the list
typedef struct list{
char name[MAX][31];
int age[MAX];
int last;
}LIST;
LIST L;//L structure is global
void save();
void retrieve();
void makenull();
void insert(char n[31],int a);
void del(char n[31]);
void display();
int locate(char n[31]);
int isfull();
int isempty();
int menu();
int main(){
char nm[31];
int ag;
makenull();
retrieve();
while(1){
switch(menu()){
case 1: system("cls");printf("Insert Mode\n");
printf("Input Name: ");scanf("%s",nm);
printf("Input Age: ");scanf("%d",&ag);insert(nm,ag);break;
case 2: system("cls");printf("Delete Mode\n");
printf("Input Name: ");scanf("%s",nm);del(nm);break;
case 3: display();break;
case 4: save();exit(0);
default: printf("\n1-4 lang!\n");system("pause");
}
}
return 0;
}
void makenull(){
L.last = -1;
}
void insert(char n[31],int a){
if (isfull()){
printf("List is full.\n");
system("pause");
}
else {
L.last++;
strcpy(L.name[L.last],n);
L.age[L.last]=a;
}
}
void del(char n[31]){
int p;
if (isempty()){
printf("List is empty.\n");
system("pause");
}
else {
p=locate(n);
if (p==-1){
printf("Not found.\n");
system("pause");
}
else{
for(int i = p;i<L.last;i++){
strcpy(L.name[i],L.name[i+1]);
L.age[i]=L.age[i+1];
}
L.last--;
printf("Successful delete operation.\n");
system("pause");
}
}
}
void display(){
int i;
system("cls");
printf(" Name Age \n");
for(i=0;i<=L.last;i++)
printf("%d.) %s %d\n",i+1,L.name[i],L.age[i]);
system("pause");
}
int locate(char n[31]){
int i;
for (i=0;i<=L.last;i++)
if(strcmp(L.name[i],n)==0)
return i;
return -1;
}
int isfull(){
if (L.last==MAX-1)
return 1;
else
return 0;
}
int isempty(){
return(L.last==-1);
}
int menu(){
int op;
system("cls");
printf("MENU\n");
printf("1. Insert\n");
printf("2. Delete\n");
printf("3. Display\n");
printf("4. Exit\n");
printf("\nSelect(1-4): ");
scanf("%d",&op);
return(op);
}
void save(){
FILE *fp;
int i;
fp=fopen("Practice4.dbf","w+");
if (fp==NULL){
printf("File Error.\n");
system("pause");
}
else{
for (i=0;i<=L.last;i++)
fprintf(fp,"%s %d\n",L.name[i],L.age[i]);
}
fclose(fp);
}
void retrieve(){
FILE *fp;
char n[31];
int i,a;
fp=fopen("Practice4.dbf","r+");
if (fp==NULL){
printf("File Error.\n");
system("pause");
}
else {
while(!feof(fp)){
fscanf(fp,"%s %d\n",n,&a);
insert(n,a);
}
}
fclose(fp);
}
Your code isn't properly formatted and there are no comments. I can't give you a direct answer with some code in it, but summing up all my comments (and of course I deleted them), this is what I've to say:
Consider this scenario-
if your .dbf has more than MAX 50 elements, then your while (!feof(fp)) inside retrieve() will keep calling insert() and insert() will keep executing its if () { } block.
You should put something like while (!feof(fp) && L.last < MAX) to prevent that situation and you'll need to further modify your code in insert(). Another thing is, this code doesn't have any update() function and scores variable. You'll need to add scores in your struct as well as there must be scores fields in your .dbf.
Now, for a moment let's say everything else is good to go in your code, then you should follow these following steps:
Declare variables
char nameInput[31];
float ex_marks[3], sum = 0, avr = 0;
in main().
Add another case 5 in your switch () block inside main() and translate and convert the following pseudocode into C code:
Read name in nameInput
locate()
if found then
3.a for i = 0 to 2
Read marks in ex_marks[i]
sum = sum + ex_marks[i]
3.b Calculate avr = sum / 3
3.c Display name and avr
else
Display name is not in the list.
exit
Also read about why is while(!feof()) always wrong?

breadth first search issue

I have created a program which should read the number of vertices to be there in the graph and I have a problem in creating the links between the vertices using link list. I get it to create the vertices and it creates links between some of the nodes but for some reason, it crashes when I try to enter certain vertex as the link.
for example
if I give the number of vertices as 4
and enter inputs as 1 2 3 4 then next the vertex to link I enter 1
and the vertices to link with as -1 2 3
It crashes after I enter 3, why?
when I enter 2 as the vertex I could link with any vertices.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct BFS_node
{
int data,vis;
struct BFS_node *linknodes;
};
typedef struct BFS_node node;
node *head,*N=NULL;
int num;
void create_node(node **Node)
{
if(*Node==NULL)
{
*Node=(node*)malloc(sizeof(node));
head=*Node;
}
else
*Node=*Node+1;
printf("%d enter the value \n",*Node);
scanf("%d",&(*Node)->data);
(*Node)->linknodes=(node *)malloc(num*sizeof(node));
printf(" %d \n",(*Node)->linknodes);
}
node * search_node(int num,node *head2)
{
while(head2)
{
if(head2->data==num)
return head2;
head2++;
}
}
void linking()
{
node *Dnode,**Lnode;
int num,i=0;
char Snum[10];
printf("enter the number you want to link ");
scanf("%d",&num);
Dnode=search_node(num,head);
printf("%d",Dnode);
while(getchar() != '\n' && getchar()!=EOF);
Lnode=Dnode->linknodes;
printf("enter the linked numbers");
while(fgets(Snum,sizeof(Snum),stdin))
{
if(sscanf(Snum,"%d",&num)!=1)
break;
*Lnode=search_node(num,head);
printf("%d %d",Lnode,*Lnode);
Lnode++;
}
}
BFStraversal()
{
int num,i=0;
node *queue[10],*link;
printf("enter the starting number");
scanf("%d",&num);
queue[i]=search_node(num,head);
link=queue[i]->linknodes;
printf("%d",link->data);
queue[i]->vis=1;
while(queue[i]!=NULL)
{
int j=1;
link=queue[i]->linknodes;
printf("%d",queue[i]->linknodes->data);
while(link->data !=NULL)
{
if(link->vis!=1)
{
queue[i+j]=link;
link->vis=1;
j++;
}
link++;
}
printf("%d",queue[i]->data);
i++;
}
}
int main()
{
printf("enter the number of vertices \n ");
scanf("%d",&num);
for(int i=0;i<num;i++)
create_node(&N);
for(int i=0;i<num;i++)
linking();
BFStraversal();
return 0;
}
here is the complete working code .feels so relieved ,this was starting to annoy.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct BFS_node
{
int data,vis;
struct BFS_node *linknodes;
};
typedef struct BFS_node node;
node *head,*N=NULL;
int num,i=0,count=-1;
int queue[20];
void create_node(node **Node)
{
if(*Node==NULL)
{
*Node=(node*)malloc(num*sizeof(node));
head=*Node;
}
else
*Node=*Node+1;
printf(" enter the value \n");
scanf("%d",&(*Node)->data);
(*Node)->vis=1;
(*Node)->linknodes=(node *)malloc(num*sizeof(node));
printf("address- %d link- %d \n",*Node,(*Node)->linknodes);
}
node * search_node(int num,node *head2)
{
while(head2)
{
if(head2->data==num)
return head2;
head2++;
}
}
void linking()
{
node *Dnode,**Lnode;
int num2,i=0;
char Snum[10];
printf("enter the number you want to link ");
scanf("%d",&num2);
Dnode=search_node(num2,head);
while(getchar() != '\n' && getchar()!=EOF);
Lnode=Dnode->linknodes;
printf("enter the linked numbers\n");
while(fgets(Snum,sizeof(Snum),stdin))
{
node *head2=head;
if(sscanf(Snum,"%d",&num2)!=1)
break;
*Lnode=search_node(num2,head);
printf(" linknode-%d link-%d\n ",Lnode,*Lnode);
Lnode++;
}
*Lnode=0;
}
BFStraversal(int vertex)
{
node *node,*head2=head,**links;
node=search_node(vertex,head);
links=node->linknodes;
node->vis=0;
printf(" %d ",vertex);
while(*links!=0)
{
if((*links)->vis)
{
queue[i]=(*links)->data;
(*links)->vis=0;
i++;
}
links++;
}
if(++count<i)
BFStraversal(queue[count]);
}
int main()
{
printf("enter the number of vertices \n ");
scanf("%d",&num);
for(int i=0;i<num;i++)
create_node(&N);
for(int i=0;i<num;i++)
linking();
printf("enter the source vertex");
int source;
scanf("%d",&source);
BFStraversal(source);
return 0;
}
enter code here

Why the array not continue where the last number insert?

My idea is to make this program to first queue the number (start from 1001)until 10 loop.But at the same time every twice loop. i want it to delete the first number insert.Then it continue insert number after the last number insert. For example. (0) insert 1001,(1) insert 1002,(2) delete 1001,(3) insert 1003,(4) insert 1004,(5)delete 1002. This is what i imagine and the desire output. But now. When it delete it reset to the initial number.
#include <stdio.h>
#define MAX 10 /* The maximum size of the queue */
#include <stdlib.h>
void insert(int queue[], int *rear, int value)
{
if(*rear < MAX-1)
{
*rear= *rear +1;
queue[*rear] = value;
printf("\n%d queue at counter 1",value);
}
else
{
printf("\nThe queue is full can not insert a value\n");
exit(0);
}
}
void delete(int queue[], int *front, int rear, int * value)
{
if(*front == rear)
{
printf("\nThe queue is empty can not delete a value\n");
exit(0);
}
*front = *front + 1;
*value = queue[*front];
printf("\n%d left counter 1",*value);
}
int main()
{
int queue[MAX];
int iCounter,front,rear,loop=0,a,b,c;
front=rear=-1;
a=1001;
do{
printf("\n------------------------------");
printf("\n\tWelcome!!\n");
printf("\n------------------------------");
printf("\nPress which counter you prefer");
printf("\n1-Pay bill");
printf("\n2-Check up");
printf("\n3-QnA");
printf("\n------------------------------\n");
scanf(" %d",&iCounter);
loop++;
switch(iCounter)
{
case 1:
insert(queue,&rear,a);
a++;
break;
default:
printf("\nError input!");
break;
}
while(loop==2)
{
delete(queue,&front,rear,&a);
loop=0;
}
}while(rear<MAX-1);
return 0;
}
Your delete function take the address of a and writes the deleted value into it. So it will get set to the value you deleted.
You could just remove
*value = queue[*front];
and change
printf("\n%d left counter 1",*value);
to
printf("\n%d left counter 1",queue[*front]);
and also remove the whole parameter and then I think it does what you want it to do.
your delete() function pass a as pass by reference that's why you did not get what you want
delete(queue,&front,rear,&a);
For your design you should pass a as pass by value
delete(queue,&front,rear,a);
void delete(int queue[], int *front, int rear, int value)

Linked list sort from smallest to biggest

I am trying sort a number in a linked list from small to big.
But its not working !
the debugger says there are a problem when i put the second number into the
list ( in main )but i dont know why .
Any help ?
#include<stdio.h>
#include<stdlib.h>
typedef struct list list;
struct list{
int a;
list *nxt;
};
void sort(list *l){
int temp,tp;
list *AIDE,*k;
k=AIDE=(list*)malloc(sizeof(list));
while (l->nxt!= NULL)
{
while (l->nxt->a < l->a)
{
temp=l->a;
l=l->nxt;
l->nxt->a=temp;
l=l->nxt;
while (l->a < AIDE->nxt->a )
{
tp=AIDE->a;
AIDE->a=l->a;
AIDE->nxt->a=tp;
AIDE=AIDE->nxt;
}
}
l=l->nxt;
}
while (k->nxt!= NULL)
{
l->a=k->a;
l=l->nxt;
k=k->nxt;
}
l->nxt=NULL;
}
int main() {
list *t,*s;
int n,i,c=0;
printf("\n how many number you need to enter? ");
scanf("%d",&n);
s=t=(list*)malloc(sizeof(list)*n);
while (c!=n)
{
printf("\n Donner le nb %d :",c+1);
scanf("%d",&t->a);
t=t->nxt;
c++;
}
t->nxt=NULL;
sort(s);
while (t->nxt!=NULL)
{
printf("%d",t->a);
}
return 0;
}
In the loop where you have the problem, what do you think the expression t=t->nxt would do?
When you enter the loop, t is pointing to allocated but uninitialized memory, therefore dereferencing e.g. t->nxt will lead to undefined behavior.
A simple solution would be to e.g. do
t->nxt = t++ + 1;

C stack array problem

My function code for peek is not working? why is that? can anyone help me with my peek function?
#include<stdio.h>
#include<stdlib.h>
#define maxsize 10
int stack[maxsize];
int stacktop=0;
void instructions();
int process();
int push(int value);
int pop();
void display();
void peek();
int main()
{
process();
getch();
}
int process()
{
int val;
int choice;
do
{
instructions();
printf("Enter Your Choice: ");
scanf("%d",&choice);
switch( choice )
{
case 1:
printf("\nElement to be Pushed : ");
scanf("%d",&val);
push(val);
break;
case 2:
val=pop();
if(val!=-1)
{
printf("Popped Element : %d\n",val);
}
break;
case 3:
peek();
break;
case 4:
display();
break;
case 5:
break;
}
}while(choice !=5);
}
void instructions()
{
printf("Enter Your choice for the following process\n");
printf("\n[1]Push a Node on top of the list");
printf("\n[2]Pop a node off the list");
printf("\n[3]Peek The Top Node");
printf("\n[4]Display The Whole list");
printf("\n[5]Exit The Program\n");
}
int push(int val)
{
if(stacktop<maxsize)
{
stack[stacktop++]=val;
}
else
{
printf("Stack is full");
}
}
int pop()
{
int a;
if(stacktop>0)
{
a=stack[--stacktop];
return a;
}
}
void display()
{
int i;
i = 0;
if(stacktop>0)
{
printf("Elements are:");
while(i<stacktop)
{
printf("\n%d--\n",stack[i++]);
}
}
}
void peek()
{
printf("%d",stacktop);
}
Is it supposed to be:
printf("%d\n", stack[stacktop - 1]);
Print the contents, rather than the size of the stack?
Obviously you'd also need to bounds check to make sure you're not printing outside of the range of your stack (when it's empty)
I know this isn't Code Review, but I thought I would give you a few bits of advice.
When you call scanf, always check the result. For example, if the user enters something other than a decimal number, your code will end up putting an indeterminate value into the choice or val variables. The scanf function returns the number of items that were successfully read. If you asked for one item, and scanf returns 1, then you can rely on the value of that object:
int choice;
if (scanf("%d", &choice) != 1)
// handle error, can't rely on value of "choice"
else
// continue onwards, can rely on value of "choice"
Usually, the \n escapes go at the end of the string literal, not at the beginning. It is more common to do it this way, but it doesn't mean it should always go at the end.
printf("Enter Your choice for the following process\n\n");
printf("[1]Push a Node on top of the list\n");
printf("[2]Pop a node off the list\n");
printf("[3]Peek The Top Node\n");
For outputting simple strings, consider just using the puts function, which automatically appends the new-line character for you:
puts("Enter Your choice for the following process");
puts("");
puts("[1]Push a Node on top of the list");
puts("[2]Pop a node off the list");
puts("[3]Peek The Top Node");
Your display method is a perfect example of when to use a for loop instead of a while loop. Generally speaking, use a for loop when you know exactly how many items you have and you want to iterate over each of them:
void display()
{
int i;
puts("Elements are:");
for (i = 0; i < stacktop; i++)
printf("\n%d--\n", stack[i]);
}
To reverse the order of the stack, simply start at the top and go backwards:
void display()
{
int i;
puts("Elements are:");
for (i = stacktop - 1; i >= 0; i--)
printf("\n%d--\n", stack[i]);
}

Resources