I want to create a program in C that differentiates between a number or a character and put them into a linked list, then output the list. The issue is that when I input anything into it, it only outputs 10. In the results down below 1+2+3, I need it to separate the char and the nums. Help will be greatly appreciated
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
// define a union to overlay an integer with a char
union DataType{
int operand;
char operate;
};
// typedef to rename DataType
typedef union DataType Data;
// create a structure for a node
typedef struct NodeType{
Data data;
struct NodeType* next;
}Node;
Node* top = NULL;
// typedef to rename NodeType
void displayNode();
void addNode() {
Node * newNode = malloc(sizeof(Node));
char expression[64];
// get the stuff
printf("Enter expression: ");
fgets(expression, 64, stdin);
//char array , int size, stdin
for (int i = 0; i < strlen(expression); i++) { //checks individual character
if (isdigit((expression[i]))){ // if digit add it to operate
(*newNode).data.operate = (expression[i]); // how
}else //else add it to operand
newNode->data.operand = (expression[i]); //how
}
if (top == NULL)
top = newNode; // update headPtr in main
else {
Node *currPtr = top;
// find last Node
while (currPtr->next != NULL)
currPtr = currPtr->next;
// insert new Node
currPtr->next = newNode;
}
}
void popNode()
{
if(top != NULL)
{
Node * temp = top;
top = top->next;
free(temp);
}
}
void displayNode()
{
if(top == NULL)
{
printf("Error");
return;
}
Node * curr = top;
// while(curr -> next != NULL){
printf("\n+---------------------------------+");
printf("\nOperator stack: ");
printf("%c ", curr->data.operate);
printf("\nOperand stack: ");
printf("%d ", curr->data.operand);
printf("\n+---------------------------------+");
curr = curr->next;
// }
}
int main()
{
int menu = 1;
do {
//call an array in main
addNode(&top);
displayNode(&top);
char cont;
printf("\nDo you want to enter another expression (Y/N)?");
scanf(" %c", &cont);
if (cont == 'n'|| cont == 'N') { // if not close menu
menu = 0;
}
}while(menu == 1);
return 0;
}
Enter expression:1+2+3
+---------------------------------+
Operator stack:
Operand stack: 10
+---------------------------------+
Do you want to enter another expression (Y/N)?
Testing out your code quickly indicated that the addNode function was only creating one initial node. That is why you only see one operator stack output. With that I moved the node creation line of code along with the node linkage loop inside the for loop.
Following is a revised version of your code with the noted changes in the addNode function.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
// define a union to overlay an integer with a char
union DataType
{
int operand;
char operate;
};
// typedef to rename DataType
typedef union DataType Data;
// create a structure for a node
typedef struct NodeType
{
Data data;
struct NodeType* next;
} Node;
Node* top = NULL;
// typedef to rename NodeType
void displayNode();
void addNode()
{
char expression[64];
// get the stuff
printf("Enter expression: ");
fgets(expression, 64, stdin);
//char array , int size, stdin
for (int i = 0; i < strlen(expression); i++) //checks individual character
{
Node * newNode = malloc(sizeof(Node)); /* Moved this line of code here to build multiple nodes */
if (isdigit((expression[i]))) // if digit add it to operate
{
(*newNode).data.operate = (expression[i]); // how
}
else //else add it to operand
newNode->data.operand = (expression[i]); //how
/* Moved this block of code inside the for loop to create the linked list */
if (top == NULL)
top = newNode; // update headPtr in main
else
{
Node *currPtr = top;
// find last Node
while (currPtr->next != NULL)
currPtr = currPtr->next;
// insert new Node
currPtr->next = newNode;
}
}
}
void popNode()
{
if(top != NULL)
{
Node * temp = top;
top = top->next;
free(temp);
}
}
void displayNode()
{
if(top == NULL)
{
printf("Error");
return;
}
Node * curr = top;
while(curr -> next != NULL){
printf("\n+---------------------------------+");
printf("\nOperator stack: ");
printf("%c ", curr->data.operate);
printf("\nOperand stack: ");
printf("%d ", curr->data.operand);
printf("\n+---------------------------------+");
curr = curr->next;
}
}
int main()
{
int menu = 1;
do
{
//call an array in main
addNode();
displayNode();
char cont;
printf("\nDo you want to enter another expression (Y/N)?");
scanf(" %c", &cont);
if (cont == 'n'|| cont == 'N') // if not close menu
{
menu = 0;
}
}
while(menu == 1);
return 0;
}
Following was the output at the terminal utilizing your test expression.
#Dev:~/C_Programs/Console/Diff/bin/Release$ ./Diff
Enter expression: 1+2+3
+---------------------------------+
Operator stack: 1
Operand stack: 49
+---------------------------------+
+---------------------------------+
Operator stack: +
Operand stack: 43
+---------------------------------+
+---------------------------------+
Operator stack: 2
Operand stack: 50
+---------------------------------+
+---------------------------------+
Operator stack: +
Operand stack: 43
+---------------------------------+
+---------------------------------+
Operator stack: 3
Operand stack: 51
+---------------------------------+
Do you want to enter another expression (Y/N)?
I suspect that there is some more refinement that you would probably do but this gets your code to the point of creating multiple nodes and linking them. Give that a try and see if it meets the spirit of your project.
Related
I am having trouble figuring out how to do this correctly. I have a linked list of nodes then those nodes have pointers put into an array contained in that node. These nodes make up a sort of one-way graph between the nodes. I must then traverse the nodes randomly until the node "Home" is reached.
The main issue I'm having is assigning the graph nodes into the list nodes. I want the function to take in the head of the list, the names of the nodes and the weight (cost to travel between nodes). I'm not sure how to do this correctly and I don't know what I did but I think there's an infinite loop somehow. Any help is greatly appreciated.
The input file is structured as such:
Applebees
GroundRound
BlueMoose
DrunkenNoodle
Home
STOP
Applebees BlueMoose 10
Applebees DrunkenNoodle 13
GroundRound Applebees 2
GroundRound DrunkenNoodle 7
GroundRound Home 52
STOP STOP 0
GroundRound
Ignore the print statements in graphInsert() those are me trying to debug the loops.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
struct graphNode {
char name[100]; // Establishment name
int arcCnt; // Number of outgoing arc from this node
int weights[10]; // Weights of each outgoing arc from this node
struct graphNode* arcs[10]; // Holds other graph nodes that are connected to this node (this node is source)
};
struct listNode {
char name[100]; // Establishment name
struct listNode* next;
struct graphNode* graph; // Pointer into graph
};
void listInsert(struct listNode **head, char name[100]) {
// setup new nodes
struct graphNode* newGraph = (struct graphNode*)malloc(sizeof(struct graphNode));
for (int i = 0; i < 100; i++) {
newGraph->name[i] = name[i];
}
for (int i = 0; i < 10; i++) {
newGraph->arcs[i] = NULL;
}
newGraph->arcCnt = 0;
struct listNode* newNode = (struct listNode*)malloc(sizeof(struct listNode));
for (int i = 0; i < 100; i++) {
newNode->name[i] = name[i];
}
newNode->next = NULL;
newNode->graph = newGraph;
// check if head is NULL
if (*head == NULL) {
*head = newNode;
return;
}
// if the list is populated then add the node to the end
struct listNode* current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
void graphInsert(struct listNode** head, char src[100], char dst[100], int weight) {
struct listNode* srcNode = *head;
printf("CALL:");
while (srcNode->next != NULL) { // loop through list to find src
printf("%s %s", srcNode->name, src);
if (strcmp(srcNode->name, src) == 0) { // when it finds the name, find the dst update the graph node data
printf("FOUND");
struct listNode* dstNode = *head;
while (dstNode->next != NULL) { // this loop is to find the pointer to the dst node
printf(" %s %s", dstNode->name, dst);
if (strcmp(dstNode->name, src) == 0) { // when it finds name finally update all the info
printf("FOUND");
// assign the new arc to the right spot based on arcCnt (how many arcs there are), then return to exit the loops
srcNode->graph->arcs[srcNode->graph->arcCnt] = dstNode->graph;
srcNode->graph->weights[srcNode->graph->arcCnt] = weight;
srcNode->graph->arcCnt++;
return;
}
dstNode = dstNode->next;
}
}
srcNode = srcNode->next;
}
}
int main(){
srand(2021);
// setup variables
struct listNode* head = NULL;
struct graphNode* sourceNode = NULL;
FILE* data = fopen("./hw10.data", "r");
int i = 0;
int section = 1; // flag to read the file correctly
// this loop reads the file
while (1) {
char name[100];
char name2[100];
int weight = 0;
if (section == 1) { // reads the first section
fscanf(data, "%100s", name);
if (strcmp(name, "STOP") == 0) { // if end of section then increment section counter
section++;
} else { // if its not the end of the section then add the name to the linked list
listInsert(&head, name);
}
} else if (section == 2) { // reads the first section and builds the graph
fscanf(data, "%100s %100s %d", name, name2, &weight);
if (strcmp(name, "STOP") == 0) { // if end of section then increment section counter
section++;
} else {
//graphInsert(&head, name, name2, weight);
}
} else if (section == 3) { // this section only reads one line and gets the
char tmp[100];
fscanf(data, "%100s", tmp);
struct listNode* current = head;
while (current->next != NULL) { // loop through to find the right node for the name
if (strcmp(current->name, tmp) == 0) { // if names are equal update the node
sourceNode = current->graph;
break;
}
current = current->next;
}
}
if (feof(data)) break;
i++;
}
// debug print data
printf("\n");
struct listNode* current = head;
while (current != NULL) {
printf("%s\n", current->name);
current = current->next;
}
printf("\n");
// starting node
printf("%s ", sourceNode->name);
// now walk through the graph from sourceNode until we reach the node "Home"
int totalWeight = 0;
i = 0;
while (i < 100) {
char* tmp = sourceNode->name;
if (strcmp(tmp, "Home") == 0) { // if were home then exit program
// ending node and cost
printf("%s %d", sourceNode->name, totalWeight);
return 0;
} else { // if were not home then keep looping
int index = (rand() % sourceNode->arcCnt); // Generates random number between 0 and sourceNode->arcCnt
sourceNode = sourceNode->arcs[index];
//printf("Going to: %s, Index: %d", sourceNode->name, totalWeight);
}
i++;
}
return 0;
}
My goal is to create a linked list and store elements inside that list.
struct node
{
int a;
struct node *b;
} p,*temp,*head;
void create ( struct node *temp)
{
char c;
temp = malloc (sizeof(struct node));
printf("enter data\n");
scanf(" %d",&temp->a);
printf("do you want to insert another node y/n\n");
scanf("%s", &c);
if (c=='y')
{
create(temp->b);
}
else if ( c=='n')
{
temp->b= NULL;
temp=&p;
return;
}
}
void traverse ( struct node *head)
{
while(head != NULL)
{
printf("%d ",head->a);
head=head->b;
}
}
int main ()
{
int i,j,k,l,m,n;
do{
if(i==1)
{
printf("enter data\n");
scanf("%d",&p.a);
create (p.b);
}
else if ( i==2)
traverse(temp);
}
while(i!=3);
printf("%d",temp->a);
}
I can't recover the elements once i've stored them. When I try to traverse the list, it only gives me the first element of the list and nothing else.
In main
do {
if(i==1)
{
...
}
else if ( i==2)
traverse(temp);
}
while(i!=3);
must be something like
do {
if (scanf("%d", &i) != 1)
break;
if(i==1)
{
...
}
else if ( i==2)
traverse(temp);
}
while(i!=3);
to know what the user want (i not initialized in your code)
in create
scanf("%s", &c);
is wrong because c is a char rather than a string
Do not mix read of int and char because you will read newline and space when reading a character, so read a string for c, for instance
char c[2];
...
scanf("%1s", &c);
if (*c == 'y')
...
else if (c == 'n')
...
the return in else branch is useless, and in case the answer is not 'y' or 'n' you do nothing so you do not set temps, probably you have to just check if 'y' and all other answers must be considered to be 'n', or you need to ask again for the choice
in create you assign the local variable temps, that has no effect on p.b in main, you need to get a node** for instance
in main temp is used but never set elsewhere, and the variables j,k,l,m,n are useless. You also ask for the data in main while you also do in create, must not be done in main. The way you manage your variables do not allow you to modify/print the list
I encourage you to not use global variables the must you can, and to not use the same name for a global and local variable like you do for temp and head because that do not help the reader of your code
A proposal solving the problems :
#include <stdlib.h>
#include <stdio.h>
struct node
{
int a;
struct node * b;
};
/* flush input up to the end of the line */
void flush()
{
int c;
while ((c = getchar()) != '\n') {
if (c == EOF)
exit(-1);
}
}
void create (struct node ** l)
{
/* go to the end of the list */
while (*l != NULL)
l = &(*l)->b;
for (;;) {
char c[2];
int v;
printf("enter data\n");
if (scanf("%d", &v) != 1) {
puts("invalid value");
flush();
}
else {
*l = malloc (sizeof(struct node));
(*l)->a = v;
(*l)->b = NULL;
l = &(*l)->b;
for (;;) {
printf("do you want to insert another node y/n\n");
scanf("%1s", c);
if (*c == 'y')
break;
else if (*c == 'n')
return;
}
}
}
}
void traverse ( struct node *head)
{
while(head != NULL)
{
printf("%d ",head->a);
head = head->b;
}
putchar('\n');
}
int main ()
{
int i;
struct node *head = NULL;
for (;;) {
puts("enter choice : 1 to create new node, 2 to print list, 3 to exit");
if (scanf("%d", &i) != 1)
flush();
switch(i) {
case 1:
create(&head);
break;
case 2:
traverse(head);
break;
case 3:
return 0;
default:
break;
}
}
}
Compilation and execution :
/tmp % gcc -pedantic -Wextra -Wall t.c
/tmp % ./a.out
enter choice : 1 to create new node, 2 to print list, 3 to exit
2
enter choice : 1 to create new node, 2 to print list, 3 to exit
1
enter data
11
do you want to insert another node y/n
y
enter data
22
do you want to insert another node y/n
n
enter choice : 1 to create new node, 2 to print list, 3 to exit
2
11 22
enter choice : 1 to create new node, 2 to print list, 3 to exit
1
enter data
3
do you want to insert another node y/n
n
enter choice : 1 to create new node, 2 to print list, 3 to exit
2
11 22 3
enter choice : 1 to create new node, 2 to print list, 3 to exit
4
enter choice : 1 to create new node, 2 to print list, 3 to exit
3
I encourage you to add the free of the list
There are several issues here:
struct node
{
int a;
struct node *b;
} p,*temp,*head;
Why do you declare global variables and use it as function parameters ? Global variables are available globally, there is no need to pass them into functions. On the other hand, global variables should be avoided and used with care, so it would be better to create local variables (e.g. in main function) and pass them as parameters into next functions.
void create ( struct node *temp)
{
char c;
temp = malloc (sizeof(struct node));
printf("enter data\n");
scanf(" %d",&temp->a);
printf("do you want to insert another node y/n\n");
scanf("%s", &c);
if (c=='y')
{
create(temp->b);
}
else if ( c=='n')
{
temp->b= NULL;
temp=&p;
return;
}
}
This function looks wrong. temp function parameter is actually an internal function's variable, that is not an in/out parameter. In that case you can assign to the temp variable, but it will not for a list. Also temp function parameter shadows temp global variable. It is also a good think to return status of operation, usually '0' means no error, any other error value.
Another thing is to keep things as simple as possible. This will allow for more reuseability and goes with single responsibility principle. If function actually performs two tasks it should be split into two functions.
One more thing, you allocate memory dynamically but never free the memory. This will lead into memory losses.
A possible implementation of your list could be:
#include <stdio.h>
#include <stdlib.h>
typedef struct _node_t
{
int a;
struct _node_t * next;
} node_t;
static node_t * head = NULL;
static node_t * tail = NULL;
node_t * create(void)
{
node_t * temp = malloc(sizeof(node_t));
if (NULL == temp)
{
return NULL;
}
printf("Enter data\n");
scanf("%d", & temp->a);
return temp;
}
void append(node_t * data)
{
if (NULL == head)
{
head = tail = data;
}
else
{
tail->next = data;
tail = tail->next;
}
tail->next = NULL;
return;
}
int add_data(void)
{
node_t * data = NULL;
char answer = 'y';
data = create();
if (NULL == data)
{
return 1;
}
append(data);
return 0;
}
void traverse(void)
{
node_t * current = NULL;
for (current = head; current != NULL; current = current->next)
{
printf("%d ", current->a);
}
printf("\n");
return;
}
void cleanup(void)
{
node_t * current = head;
while (NULL != current)
{
head = head->next;
free(current);
current = head;
}
return;
}
int main(int argc, char ** argv)
{
int option = 3;
do
{
printf("Enter option:\n 1 - add data\n 2 - traverse list\n 3 - exit\n\n");
scanf("%i", & option);
switch (option)
{
case 1:
if (0 != add_data())
{
printf("ERROR:: Cannot allocate memory.\n");
cleanup();
return 1;
}
break;
case 2:
traverse();
break;
default:
if (option > 3)
{
printf("ERROR:: Improper option, try again.\n");
}
break;
}
}
while (option != 3);
cleanup();
return 0;
}
I tried making it as simple as possible and keeping your logic there.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
// create a new node
struct node* create(int data)
{
struct node *n = malloc(sizeof(struct node));
n->data = data;
n->next = NULL; // by default its not NULL, so we must set it
return n;
}
void traverse(struct node *head)
{
struct node *tmp = head;
while(tmp != NULL)
{
printf("%d\t",tmp->data);
tmp = tmp->next;
}
}
void cleanup(struct node *head)
{
struct node *cur = head;
struct node *next;
while(cur != NULL)
{
next = cur->next;
free(cur);
cur = next;
}
}
int main ()
{
int data;
struct node *head, *tmp;
// head node is always created
printf("enter data\n");
scanf("%d",&data);
head = tmp = create(data);
if(head == NULL) return -1;
// now we loop until we don't want to create any more nodes
while(1)
{
char another;
printf("do you want to insert another node y/n\n");
scanf(" %c", &another); // ignore all the previous whitespace
if(another == 'y')
{
printf("enter data\n");
scanf("%d",&data);
tmp->next = create(data);
tmp = tmp->next;
}
else break;
/*
// anything but 'y' breaks the loop, but it can be set to continue if neither 'y' nor 'n' was read:
else if(another == 'n') break;
else continue;
*/
}
traverse(head);
cleanup(head);
}
EDIT: as #Diodacus stated, i added cleanup and checking if malloc returned NULL
I've searched this question and the previous ones do not seem to be related to my problem. I seem to have a disconnect on passing a node into a function, for some reason I keep getting this error when attempting to compile.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char c;
int titleCount;
int authorCount;
char bookTitle[35];
char author[35];
/* Create Struct */
typedef struct bookData {
char bookTitle[35];
char author[35];
int book_stock;
float retail_price;
int wholesale_purchased;
int customer_purchased;
struct bookData *book;
} new_book;
/*Create Node */
typedef struct Node {
new_book books;
struct Node *next;
} node_t;
/* We are GUARANTEED at least 1 input value, so go ahead and initialize the head */
node_t *head = NULL; /*Initalize head to NULL since it is empty */
head = malloc(sizeof(node_t));
if(head == NULL) {
printf("allocation failed");
return 0;
}
head -> next = NULL;
/*Memory allocation successful */
/*Might as well populate the head with data from the user */
titleCount = 0;
authorCount = 0;
printf("Enter Title\n");
while(( c = getchar()) != '\n') {
bookTitle[titleCount++] = c;
}
bookTitle[titleCount] = '\0';
printf("%s\n", bookTitle);
strcpy(head -> books.bookTitle, bookTitle);
printf("Enter Author\n");
while(( c = getchar()) != '\n') {
author[authorCount++] = c;
}
author[authorCount] = '\0';
strcpy(head -> books.author, author);
printf("Bookstock #:\n");
scanf("%d", &(head -> books).book_stock);
printf("Enter retail price $:\n");
scanf("%f", &(head -> books).retail_price);
printf("Enter Wholesale purchased quanity:\n");
scanf("%d", &(head -> books).wholesale_purchased);
printf("Enter quantity sold:\n");
scanf("%d", &(head -> books).customer_purchased);
printf("%s\n", head -> books.bookTitle);
printf("%s\n", head -> books.author);
printf("%d\n", head -> books.book_stock);
printf("%.2f\n", head -> books.retail_price);
printf("%d\n", head -> books.wholesale_purchased);
printf("%d\n", head -> books.customer_purchased);
takeUserInput(head);
}
/*Now populate all other nodes, until user enters END_DATA */
void takeUserInput(node **head) {
int titleCount;
int authorCount;
char bookTitle[35];
char author[35];
int flag = 0;
while(1) {
titleCount = 0;
authorCount = 0;
node_t *temp = NULL;
temp = malloc(sizeof(node_t));
temp -> next = NULL;
printf("Enter Title\n");
while(( c = getchar()) != '\n') {
bookTitle[titleCount++] = c;
}
bookTitle[titleCount] = '\0'
if(bookTitle == "END_DATA") {
flag = 1;
break;
}
strcpy(temp -> books.bookTitle, bookTitle);
printf("Enter Author\n");
while(( c = getchar()) != '\n') {
author[authorCount++] = c;
}
author[authorCount++] = '\0';
strcpy(temp -> books.author, author);
printf("Bookstock #\n");
scanf("%d", &(temp - > books).book_stock);
printf("Enter retail Price in $\n:");
scanf("%.2f", &(temp -> books).retail_price);
printf("Enter wholesale purchased\n:");
scanf("%d", &(temp -> books).wholesale_purchased);
printf("Enter customer purchased\n:");
scanf("%d", &(temp -> books).customer_purchased);
if(temp -> books.book_stock < head -> books.book_stock) {
void pushToFront(head, temp);
} else {
void insert(head,temp);
}
}
if(flag == 1) {
free(temp);
}
}
void pushToFront(node_t **head, node_t *temp) {
temp -> next = *head;
*head -> temp;
}
void insert(node_t *head, node_t *temp) {
node_t *current = head;
while(current -> next -> new_book.book_stock < temp -> new_book.book_stock || current -> != NULL) {
current = current -> next;
}
if(current -> next = NULL) {
current -> next = temp;
}
node_t *xtraNode = current -> next
current -> next = temp;
temp -> next = xtraNode;
}
Error:
lab3p1.c:114: error: expected ‘)’ before ‘*’ token
lab3p1.c:180: error: expected ‘)’ before ‘*’ token
lab3p1.c:188: error: expected ‘)’ before ‘*’ token
To my understanding, I only need to pass in a double pointer when I'm adjusting which node the head points to pushToFront. So on insert(), I'm not actually adjusting the head pointer, just the next pointer of a particular node and the node being inserted. So I'm a little confused as to why this error is occurring.
I have spent a bit time to try compile your code but the number of errors is astonishing. Your code requires your serious attention.
Start with the simple things first.
First move the declaration of the structures before main:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Create Struct */
typedef struct bookData{
char bookTitle[35];
char author[35];
int book_stock;
float retail_price;
int wholesale_purchased;
int customer_purchased;
struct bookData *book;
}new_book;
/*Create Node */
typedef struct Node{
new_book books;
struct Node *next;
}node_t;
void takeUserInput(node_t **head);
void pushToFront(node_t **head, node_t *temp);
void insert(node_t *head, node_t *temp);
int main(){
//...
}
and put your function prototypes before main as well.
void takeUserInput(node **head){
should be:
void takeUserInput(node_t **head){
and
takeUserInput(head);
should be:
takeUserInput(&head);
and
void takeUserInput(node_t **head){ // node_t not node sg7
int titleCount;
int authorCount;
char bookTitle[35];
char author[35];
int c; // declaration was missing sg7!
later
bookTitle[titleCount] = '\0' // missing ;
if(bookTitle == "END_DATA"){ // this is NOT the way to compare strings
I also noticed that you have not accepted a single answer, yet.
I have stopped here and I let you continue yourself. Good luck. Everyone has to carry his own cross.
I'm trying to write a program that enqueue, dequeue, delete a chosen number and print the list. I have problems with the dequeue that i think is because of the menu part when you write a number, I've tried to fix it but the it removes the last number and not the first. The print shows the wrong number and when I tried to solve that problem I got the same problem as I had in dequeue. It's sometinhg wrong in delete but i cant figure it out.
I appreciate all the help i can get
edit:
I've changed it a lot and now everything else works except delete. I want delete to find the number i enter and delete it.
queue.c
#include <stdio.h>
#include <stdlib.h>
#include<conio.h>
struct node
{
int info;
struct node *ptr;
int next;
}*first, *last, *temp, *first1;
void enq(int data);
void deq();
void empty();
void display();
void create();
void delete_queue();
int count = 0;
void main()
{
int no, ch;
printf("\n 1 - Enqueue");
printf("\n 2 - Dequeue");
printf("\n 3 - Delete");
printf("\n 4 - Display");
printf("\n 5 - Exit");
create();
while (1)
{
printf("\n Enter choice : ");
scanf_s("%d", &ch);
switch (ch)
{
case 1:
printf("Enter data : ");
scanf_s("%d", &no);
enq(no);
break;
case 2:
deq();
break;
case 3:
printf("Enter data : ");
scanf_s("%d", &no);
delete_queue(no);
case 4:
display();
break;
case 5:
exit(0);
default:
printf("Wrong choice, Please enter correct choice ");
break;
}
}
}
void create()
{
first = last = NULL;
}
void enq(int data)
{
if (last == NULL)
{
last = (struct node *)malloc(1 * sizeof(struct node));
last->ptr = NULL;
last->info = data;
first = last;
}
else
{
temp = (struct node *)malloc(1 * sizeof(struct node));
last->ptr = temp;
temp->info = data;
temp->ptr = NULL;
last = temp;
}
count++;
}
void display()
{
first1 = first;
if ((first1 == NULL) && (last == NULL))
{
printf("Queue is empty");
return;
}
while (first1 != last)
{
printf("%d ", first1->info);
first1 = first1->ptr;
}
if (first1 == last)
printf("%d", first1->info);
}
void deq()
{
first1 = first;
if (first1 == NULL)
{
printf("\n Error: Trying to display elements from empty queue");
return;
}
else
if (first1->ptr != NULL)
{
first1 = first1->ptr;
printf("\n Dequed value : %d", first->info);
free(first);
first = first1;
}
else
{
printf("\n Dequed value : %d", first->info);
free(first);
first = NULL;
last = NULL;
}
count--;
}
void delete_queue()
{
int retval = -1;
if (first)
{
struct node *temp = first;
first = first->next;
if (!first) { last = first; }
retval = temp->next;
free(temp);
}
return retval;
}
void empty()
{
if ((first == NULL) && (last == NULL))
printf("\n Queue empty");
else
printf("Queue not empty");
}
Let me start with a few points of advice about design and style:
I do not recommend this:
typedef struct node {
int data;
struct node *next;
} node;
you are typedefing struct node to node. while it is not illegal, it is confusing. I would recommend
typedef struct _node {
int data;
struct _node *next;
} node;
Additionally, I do not recommend use of global variable with static storage class to keep track of your queue, instead you should create a queue in your main. Use global variables only when you have compelling reasons to do so.
Do remember that when you get rid of your global variable, you will need to rewrite your enqueue dequeue delete etc... functions to take in a queue_c * as parameter (because it wont have access to queueref any more)
Now for the reason that your code is not working properly and #Weather Vane alluded to:
you have a big problem in your delete function.
int delete(int data)
{
int result = 0;
node *curr_ptr; //pointer just created and not initialized
node *prev_ptr; //not initialized
node *temp_ptr; //not initialized
while (curr_ptr != NULL)
//curr_ptr was just created, where is it pointing? fatal error here
{
//inside this block lets imagine curr_ptr is pointing to a valid
//node in the global queue
if (curr_ptr->data == data)
{
result = 1;
if (curr_ptr->next != NULL)
{
temp_ptr = curr_ptr;
//both pointers point to the same thing
destroy_node(temp_ptr);
//now you just destroyed both nodes
prev_ptr->next = curr_ptr->next;
//the first time this block runs prev_ptr is uninitialized
//so prev_ptr->next will most likely seg fault
//this happens for example if you call this function
//for the first time with a long queue
}
else
{
temp_ptr = curr_ptr;
queueref.last = prev_ptr;
prev_ptr->next = NULL;
destroy_node(temp_ptr);
//again you are destroying both curr_ptr and temp_ptr
}
}
curr_ptr = curr_ptr->next;
prev_ptr = prev_ptr->next;
return result;
}
}
Perhaps it would be better if you think edge cases very carefully and rethink some of the logic from scratch. (test edge cases as you go)
i am confused with the code below. why does the input overwrite the elements in the stack.
for example i enter "abc" first
then the stack will be "123"
but when i enter another string, let's say "234"
the stack will be "234" "234"
but when i used int data type instead of char for my input, there's no error.
thanks!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node{
char* info;
struct node *ptr;
}*top,*top1,*temp;
int count = 0;
/* Push data into stack */
void pushy(char* data){
if (top == NULL)
{
top =(struct node *)malloc(1*sizeof(struct node));
top->ptr = NULL;
strcpy(top->info, data);
}
else
{
temp =(struct node *)malloc(1*sizeof(struct node));
temp->ptr = top;
strcpy(temp->info, data);
top = temp;
}
count++;
}
/* Display stack elements */
void display(){
top1 = top;
if (top1 == NULL)
{
printf("Stack is empty");
return;
}
while (top1 != NULL)
{
printf("%s ", top1->info);
top1 = top1->ptr;
}
}
/* Pop Operation on stack */
void pop(){
top1 = top;
if (top1 == NULL)
{
printf("\n Error : Trying to pop from empty stack");
return;
}
else
top1 = top1->ptr;
printf("\n Popped value : %s", top->info);
free(top);
top = top1;
count--;
}
/* Return top element */
char* topelement(){
return(top->info);
}
int main()
{
int ch=0;
printf("\n 1 - Push");
printf("\n 2 - Pop");
printf("\n 3 - Top");
printf("\n 4 - Display");
printf("\n 5 - Exit");
top = NULL;
while (1)
{
char no[10]={NULL};
char* e;
printf("\n Enter choice : ");
scanf("%d", &ch);
if(ch==1){
printf("Enter data : ");
scanf("\n\n%s", &no);
pushy(no);
}
else if(ch==2){
pop();
}
else if(ch==3){
if (top == NULL)
printf("No elements in stack");
else
{
e = topelement();
printf("\n Top element : %d", e);
}
}
else if(ch==4)
display();
else if(ch==5)
exit(0);
else
printf("Invalid");
}
}
At least function pushy has undefined behaviour beacuse it tries to overwrite memory that was not allocated by the function
void pushy(char* data){
if (top == NULL)
{
top =(struct node *)malloc(1*sizeof(struct node));
top->ptr = NULL;
strcpy(top->info, data);
^^^^^^^^^^^^^^^^^^^^^^^
}
//...
You should at first allocate memory that will be pointed to by data member top->info where you are going to copy the string pointed to by parameter data
For example
void pushy(char* data){
if (top == NULL)
{
top =(struct node *)malloc(1*sizeof(struct node));
top->ptr = NULL;
top->info = malloc( ( strlen( data ) + 1 ) * sizeof( char ) );
strcpy(top->info, data);
}
//...
The function could be written the following way
void pushy( const char* data )
{
temp = ( struct node * )malloc( sizeof( struct node ) );
temp->ptr = top;
temp->info = ( char * )malloc( ( strlen( data ) + 1 ) * sizeof( char ) );
strcpy( temp->info, data );
top = temp;
++count;
}
Of cpurse you have to free also the memory allocated for top->info when you will free the node itself in function pop().
Take into account that there is no need to declare variables top1 and temp like global.
Also in this call
scanf("\n\n%s", &no);
the second argument shall be specified simply like no instead of &no
And in this call
printf("\n Top element : %d", e);
you have to use format specifier %s instead of %d
scanf("\n\n%s", &no);
Remove '&' from the above statement.
Also, as per you code better to take info as char array instead of char *
struct node{
char info[20];
struct node *ptr;
}*top,*top1,*temp;
No memory is being allocated for the string in the node:
top =(struct node *)malloc(1*sizeof(struct node));
top->ptr = NULL;
strcpy(top->info, data);
When strcpy is called top->info pointer is invalid. You will have to allocate the memory, assing it to the pointer top->info and then copy the string into that memory.
Don't forget to free the memory held my info pointer before you free the entire node.