I am trying to create a program to solve the classic problem of brackets balancing.
The program needs to tell the user if an the parantheses appearing in an expression are balanced.
I am very new to C/C++, coming from Python, so please excuse my ignorance and please point me towards the right direction!
What I have up until now is below. When compiled with gcc -o exec program.c then ./exec it outputs: List is: ) ( ] [ } { , rather than what I would expect: List is: { } [ ] ( )
I do not understand why, is there an obvious mistake?
I keep searching for it...
Also, I would be very grateful if you could comment if my logic on how I am designing those functions makes sense and is correct: I feel I actually need to put those pointer variables as arguments to the functions?
Thank you!
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// Parantheses check:
struct Node {
char data;
struct Node* next;
};
struct Node* head_of_listofparans = NULL;
struct Node* head_of_listofparans_open = NULL;
struct Node* head_of_listofparans_close = NULL;
struct Node* insert_at_beginning(char c, struct Node* head) {
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
temp->data = c;
temp->next = head;
head = temp;
return head;
}
void Delete(int n, struct Node* head) { // removes the n-th node (n=1 represents the head node, n=2 represents the second node)
struct Node* temp1 = head;
if (n==1) {
head = temp1->next;
free(temp1);
return;
}
int i;
for (i=0; i<n-2; i++) { // if n=2 (want to delete the 2nd node), this for-loop doesn't get executed.
temp1 = temp1->next;
} // temp1 now points to the n-1 th node. if n=2, temp1 still (correctly) points towards the head (first node)
struct Node* temp2 = temp1->next; // temp2 points towards the n-th node
temp1->next = temp2->next; // n-1 th node now points to the n+1 th node
free(temp2); // delete the n-th node
}
struct Node* createListOfParantheses(char* parants, struct Node* initial_head) {
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
temp->data = parants[0];
temp->next = initial_head;
initial_head = temp; // 1st node created. the link of this node points to NULL now. head of the list points to this newly created 1st node.
int i;
for (i=1; i<=(int)strlen(parants); i++) {
initial_head = insert_at_beginning(parants[i], initial_head);
}
return initial_head;
}
// int ParanthesisCheck(char* parantheses_open, char* parantheses_close, char* expr) {
// int n = int(strlen(expr));
// int i;
// for (i=0; i<=n-1; i++) {
// if (strchr(parantheses_open, expr[i])!=NULL) { // if expr[i] can be found in "{[("
// insert_at_beginning(expr[i]) // ppush(expr[i]);
// }
// else if (strchr(parantheses_close, expr[i])!=NULL) { // if expr[i] can be found in "}])"
// if ((check_emptiness_of_stack()==1) || (get_top_of_stack() != expr[i])) { // || signifies the logical OR
// return 0;
// }
// else {
// Delete(1, head_of_stack); // ppop(), delete the very first node (head node), i.e. the most-recently-introduced node
// }
// }
// }
// return check_emptiness_of_stack()==1 ? 1:0;
// }
void Print_List_Of_Parans(struct Node* head) {
struct Node* temp = head;
printf("List is: ");
while (temp != NULL) {
printf(" %c", temp->data);
temp = temp->next;
}
printf("\n");
}
int main() {
char paras[7] = "{}[]()";
char paras_open[4] = "{[(";
char paras_close[4] = "}])";
char input_expr[20] = "(a+b)";
// int j;
// for (j=0; j<7; j++) {
// scanf("%c", ¶s[j]); // ¶s[j] is equivalent to: paras + j if paras is an array
// printf("%s %d\n", "Iteration number: ", j);
// } // doesn't work because scanf reads 1 character, alright, but adds a \n at its end, so consumes 2 memory locations from the array char paras[7], not 1 as expected.
head_of_listofparans = createListOfParantheses(paras, head_of_listofparans);
head_of_listofparans_open = createListOfParantheses(paras_open, head_of_listofparans_open);
head_of_listofparans_close = createListOfParantheses(paras_close, head_of_listofparans_close);
Print_List_Of_Parans(head_of_listofparans);
// int result = ParanthesisCheck(head_of_listofparans_open, head_of_listofparans_close, input_expr);
// printf("%d\n", result);
return 0;
}
Related
I am a beginner to C and am learning linked lists. I tried making functions to have everything organised but no matter what i do the function print_list doesn't print the values. The output is only START and END. I noticed that if I put the same block of code directly into the function that builds the lists, then it prints correctly. What am I doing wrong? (Also first time asking on stack overflow)
Thank you to whoever answers.
#include <stdlib.h>
#include <stdio.h>
typedef struct nd
{
int val;
struct nd *next;
} node;
typedef node * Lista;
void print_list(node*currnode)
{
printf("START -> ");
while (currnode != NULL)
{
printf("%d -> ", currnode->val);
currnode = currnode->next;
}
printf("END");
}
//reimpilista means "buildlist"
node*riempilista(Lista lis){
node *currentNode, *temp;
int i,n;
printf("how many nodes?\n");
scanf("%d",&n);
for (i = 0; i < n; i++)
{
currentNode = (node *)malloc(sizeof(node));
printf("Enter element %d : ", (i + 1));
scanf("%d", ¤tNode->val);
if (i == 0)
{
temp = currentNode;
}
else
{
temp->next = currentNode;
temp = currentNode;
}
}
temp->next = NULL;
return lis;
}
int main(){
Lista listautente=NULL;
listautente=riempilista(listautente);
print_list(listautente);
return 0;
}
When you build the list you need to return the head of the list as a result. So you need to store the pointer to the first node. Then when adding a new node you need to know the previous node, so you need to store it as well. The last added node should have next field poiting to NULL otherwise you won't be able to determine the end of the list and will get an exception.
Here is your code slightly edited.
#include <stdlib.h>
#include <stdio.h>
typedef struct nd {
int val;
struct nd *next;
} node;
typedef node *Lista;
void print_list(node *currnode) {
printf("START -> ");
while (currnode != NULL) {
printf("%d -> ", currnode->val);
currnode = currnode->next;
}
printf("END");
}
//reimpilista means "buildlist"
node *riempilista() {
node *firstNode = NULL, *currentNode = NULL, *previousNode = NULL;
int i, n;
printf("how many nodes?\n");
scanf("%d", &n);
for (i = 0; i < n; ++i) {
currentNode = (node *)malloc(sizeof(node));
printf("Enter element %d : ", (i + 1));
scanf("%d", ¤tNode->val);
currentNode->next = NULL;
if (i == 0) {
firstNode = currentNode;
}
if (previousNode != NULL) {
previousNode->next = currentNode;
}
previousNode = currentNode;
}
return firstNode;
}
int main() {
Lista listautente = riempilista();
print_list(listautente);
return 0;
}
I tried to fix your program with minimal changes. Here it is:
Change
node *currentNode, *temp;
to
node *currentNode, *temp, *head;
Change
temp = currentNode;
to
temp = currentNode; head = temp;
Change
return lis;
to
return head;
Here is the link to the modified code:
https://onlinegdb.com/8cjqifgl2
I'm new to DSA and currently learning linked-list. I was trying to create an entire linked list in one function. The first scanf in createList function doesn't seem to assign the input to the address provided(i.e. &n). I tried printing n right after scanf. It doesn't print n to console at all.
As a result, the output is not the way I expected. I can't figure out why.
//ENTIRE CODE HERE
#include<stdio.h>
#include<stdlib.h>
struct node {
struct node* prev;
int data;
struct node* next;
};
void print_nodes(struct node* );
struct node* addToEmpty(struct node*, int);
struct node* addAtEnd(struct node*, int);
struct node* createList(struct node*);
int main() {
struct node* head = NULL;
head = createList(head);
print_nodes(head);
}
void print_nodes(struct node* head) {
struct node* ptr = head;
while (ptr != NULL) {
printf("%d ", ptr->data);
ptr = ptr->next;
}
printf("\n");
}
struct node* addToEmpty(struct node* head, int data) {
struct node* temp = malloc(sizeof(struct node));
temp->prev = NULL;
temp->data = data;
temp->next = NULL;
head = temp;
return head;
}
struct node* addAtEnd(struct node* head, int data) {
struct node* tp = head;
struct node* temp = malloc(sizeof(struct node));
temp->prev = NULL;
temp->data = data;
temp->next = NULL;
while (tp->next != NULL) {
tp = tp->next;
}
tp->next = temp;
temp->prev = tp;
return head;
}
struct node* createList(struct node* head) {
int n, data, i;
printf("Enter the number of nodes: ");
scanf("%d ", &n);
if (n == 0)
return head;
printf("Enter the element of node 1: ");
scanf("%d ", &data);
head = addToEmpty(head, data);
for (i = 1; i < n; i++) {
printf("Enter the element of node %d: ", i + 1);
scanf("%d", &data);
head = addAtEnd(head, data);
}
return head;
}
your problem is so simple , instead of scanf("%d ", &n); , just write scanf("%d", &n); by which I mean to remove the wite space after %d as it's producing some strange behavior in your case , as if you refer to scanf() manual page , they say that :
A sequence of white-space characters (space, tab, newline,
etc.; see isspace(3)). This directive matches any amount
of white space, including none, in the input.
which is supposed to ignore any whitespace after the number entered till getting a valid char.
and here is the full code but with this only small modification:
#include<stdio.h>
#include<stdlib.h>
struct node {
struct node* prev;
int data;
struct node* next;
};
void print_nodes(struct node* );
struct node* addToEmpty(struct node*, int);
struct node* addAtEnd(struct node*, int);
struct node* createList(struct node*);
int main() {
struct node* head = NULL;
head = createList(head);
print_nodes(head);
}
void print_nodes(struct node* head) {
struct node* ptr = head;
while (ptr != NULL) {
printf("%d ", ptr->data);
ptr = ptr->next;
}
printf("\n");
}
struct node* addToEmpty(struct node* head, int data) {
struct node* temp = malloc(sizeof(struct node));
temp->prev = NULL;
temp->data = data;
temp->next = NULL;
head = temp;
return head;
}
struct node* addAtEnd(struct node* head, int data) {
struct node* tp = head;
struct node* temp = malloc(sizeof(struct node));
temp->prev = NULL;
temp->data = data;
temp->next = NULL;
while (tp->next != NULL) {
tp = tp->next;
}
tp->next = temp;
temp->prev = tp;
return head;
}
struct node* createList(struct node* head) {
int n, data, i;
printf("Enter the number of nodes: ");
scanf("%d", &n);
if (n == 0)
return head;
printf("Enter the element of node 1: ");
scanf("%d", &data);
head = addToEmpty(head, data);
for (i = 1; i < n; i++) {
printf("Enter the element of node %d: ", i + 1);
scanf("%d", &data);
head = addAtEnd(head, data);
}
return head;
}
and this is the output:
Enter the number of nodes:3
Enter the element of node 1:1
Enter the element of node 2:2
Enter the element of node 3:3
1 2 3
I tried out your code and found issues with the space in the literal string in the "scanf" statements. I see that someone else found that and offered up the solution to that with the cleanup of the "scanf" statements. I would say that if you are to accept an answer, select the first one. However, I just wanted to also offer up my code snippet with a couple of additional tweaks.
#include<stdio.h>
#include<stdlib.h>
struct node
{
struct node* prev;
int data;
struct node* next;
};
void print_nodes(struct node* );
struct node* addToEmpty(struct node*, int);
void addAtEnd(struct node*, int); /* No requirement for a node to be returned as the pointers are all set up in the function */
struct node* createList(struct node*);
int main()
{
struct node* head = NULL;
head = createList(head);
print_nodes(head);
}
void print_nodes(struct node* head)
{
struct node* ptr = head;
while (ptr != NULL)
{
printf("%d ", ptr->data);
ptr = ptr->next;
}
printf("\n");
}
struct node* addToEmpty(struct node* head, int data)
{
struct node* temp = malloc(sizeof(struct node));
temp->prev = NULL;
temp->data = data;
temp->next = NULL;
//head = temp;
return temp; /* Return the pointer to the new struct - no need for update of head here */
}
void addAtEnd(struct node* head, int data)
{
struct node* tp = head;
struct node* temp = malloc(sizeof(struct node));
temp->prev = NULL;
temp->data = data;
temp->next = NULL;
while (tp->next != NULL)
{
tp = tp->next;
}
tp->next = temp;
temp->prev = tp;
return;
}
struct node* createList(struct node* head)
{
int n, data, i;
printf("Enter the number of nodes: ");
scanf("%d", &n);
if (n == 0)
return head;
printf("Enter the element of node 1: ");
scanf("%d", &data);
head = addToEmpty(head, data);
for (i = 1; i < n; i++)
{
printf("Enter the element of node %d: ", i + 1);
scanf("%d", &data);
addAtEnd(head, data);
}
return head;
}
First off, since there is not a need to return a "struct" pointer in the function "addAtEnd", I revised that to be a "void" function return signature. Second, in the "addToEmpty" function, one can just return the pointer value in "temp" instead of placing the value into the input parameter "head"; however, it works either way. It is just a matter of choice.
As a sample, here is some output data at the terminal.
#Una:~/C_Programs/Console/CompleteList/bin/Release$ ./CompleteList
Enter the number of nodes: 4
Enter the element of node 1: 65535
Enter the element of node 2: 2458
Enter the element of node 3: -44
Enter the element of node 4: 3258779
65535 2458 -44 3258779
I would suggest trying out both iterations.
Other answers have pointed at the specific problem you experienced (bad scanf() parameter string).
Going beyond that, however, there are two other "issues(?)".
First is to "create an entire linked list in one function".
In your code, main() calls only one function, but that function uses two "helper" functions to get the job done.
Every line of code is an opportunity for a bug to lurk unseen.
Re-using code is a way to reduce the chances for bugs to appear.
Secondly, the code appears to be correct, but does not prove that the doubly linked list is anything more than a singly linked list.
Both of these matters are addressed below creating (in one function, and later demonstrating) a circular doubly linked list.
Comments explain changes from the original code to this version.
Finally, an additional function is used here to prevent memory leaks.
#include <stdio.h>
typedef struct node { // Using 'typedef' saves lots of typing (and reading
int data;
struct node *next;
struct node *prev; // conventional layout of members
} node_t; // Notice '_t' as conventional suffix for user declared datatypes
node_t *print_nodes( node_t *head ) { // return pointer for use by caller
if( head ) { // insurance against NULL pointer
node_t *pn = head;
printf( "Forward: " ); // exercise circular LL in both directions
do {
printf( "%d ", pn->data );
pn = pn->next; // NB: 'next'
} while( pn != head ); // circular, not linear! One full circuit
puts( "" );
printf( "Reverse: " );
pn = pn->prev; // shift 'back' one node to begin
do {
printf( "%d ", pn->data );
pn = pn->prev; // NB: 'prev'
} while( pn != head->prev ); // circular, not linear! One full circuit
puts( "" );
}
return head;
}
node_t *createList() { // Create "one ring to rule them all"
int n = 0; // ALWAYS initialise variables
do {
printf( "Number of nodes (min 3): ");
scanf( "%d", &n ); // 'while' protects against bad input
} while( n < 3 );
node_t *head = NULL;
for( int i = 0; i < n; i++ ) {
printf( "Enter the element of node %d: ", i + 1 );
node_t *pn = (node_t *)calloc( 1, sizeof *pn ); // 'calloc()' zeros the block
/* check 'pn == NULL' omitted for brevity */
scanf("%d", &pn->data ); // read directly into destination (fewer variables)
if( head == NULL )
head = pn->prev = pn->next = pn; // 1st node, circular
else {
pn->prev = head->prev; // other nodes spliced-in ahead of 'head'
pn->next = head;
head->prev->next = pn;
head->prev = pn;
}
}
return head;
}
void freemem( node_t *head ) { // VERY important to respect "heap" storage!
if( head == NULL ) return;
node_t *pn = head; // traverse releasing nodes along the way
do {
node_t *pdel = pn;
pn = pn->next;
free( pdel );
} while( pn != head );
}
int main() {
// create, print, release, done...
freemem( print_nodes( createList() ) );
return 0;
}
Output
Number of nodes (min 3): 5
Enter the element of node 1: 42
Enter the element of node 2: 56
Enter the element of node 3: 10
Enter the element of node 4: -5
Enter the element of node 5: 256
Forward: 42 56 10 -5 256
Reverse: 256 -5 10 56 42
This code implements and proves a circular doubly linked list. The example can be trivially adapted to a linear dbl-LL by severing the connection between head and head->prev after the ring has been formed, and then making necessary adjustments at other locations to account for the change.
Below is a Minimal Reproducible Example from my code. What I am doing is that I am inserting data in a list of structs and printing them on the console.
I want to print from each link only the first element that is inserted into each list of structs.
But how is that possible when instead of data in my struct I have:
typedef struct Node
{
int rollnumber, src, dst;
double gentime;
struct Node *next;
} Node;
(rollnumber, src, dst,gentime are the information I am reading from text files, but the reading code is not nessacary, so I wrote it with testdata.)
MINIMAL REPRODUCIBLE EXAMPLE
#include <stdio.h>
#include <stdlib.h>
#define N 10
typedef struct Node
{
int data;
struct Node* next;
} Node;
int push_front(Node** head, int data)
{
Node* new_node = malloc(sizeof(Node));
int success = new_node != NULL;
if (success)
{
new_node->data = data;
new_node->next = *head;
*head = new_node;
}
return success;
}
void output(Node* head)
{
for (Node* current = head; current != NULL; current = current->next)
{
printf("%d ", current->data);
}
}
void display(Node** set, int i)
{
output(set[i]);
putchar('\n');
}
int main(void)
{
int testdata = 1;
Node* link[N] = { 0 };
struct Node* head = NULL;
for (int i = 0; i < N; i++) {
push_front(&link[i], testdata++);
push_front(&link[i], testdata++);
}
for (int i = 0; i < N; i++) {
printf("link[%d]:", i);
display(link, i);
}
}
If you only want to print the first element of each link list, just do not loop in output:
void output(Node* head)
{
printf("%d ", head->data);
}
If I am right you want the first element of the list right ??
If so than the way you are working you are pushing the new node in front of old node, so your first node is now the last in the line, so all you need to do is to iterate the list till Node* next == null, and that node will be your answer
Node *getLastInLine( Node *Head){
Node *ptr;
ptr = Head;
if( ptr == NULL) return NULL;
while(ptr-> next != NULL){
ptr = ptr->next;
}
return ptr;
}
I'd like to remove in a linked list all the nodes that have a greater value to their right.
Input: 10 -> 12 -> 15 -> 20 -> 5 -> 16 -> 25 -> 8 -> NULL
Expected output: 20 -> 25 -> 8 -> NULL
Actual Output: 20 -> 25 ->
Kindly help me resolve the bug.
#include <stdlib.h>
#include <stdio.h>
struct node{
int data;
struct node *ptr;
}*start=NULL, *t, *last=NULL;
int i=0;
int main() {
//creation
int size;
printf("Enter size:");
scanf("%d", &size);
while (size--) {
t = (struct node *) malloc(sizeof(struct node));
printf("Enter list:");
scanf("%d", &(t->data));
t->ptr = NULL;
if (start == NULL) {
start = t;
} else
last->ptr = t;
last = t;
}
//display
printf("\n");
t = start;
do {
printf("%d->", t->data);
t = t->ptr;
} while (t != NULL);
printf("NULL\n");
//main objective
struct node *t1,*t2;
t1=start;
t2=t1->ptr;
t=start;
for(t=start;t!=NULL;t=t->ptr){
if(t1->data>t2->data||t->ptr==NULL){
printf("%d->", t->data);
}
t1=t1->ptr;
t2=t2->ptr;
}
printf("NULL\n");
return 0;
}
You can fix the segmentation fault due to illegal memory access by verifying that t2 is not null before attempting to dereference the pointer. This version runs clean after adding guards to t2:
for (t = start; t; t = t->ptr) {
if (!t2 || (t1 && t1->data > t2->data)) {
printf("%d->", t->data);
}
t1 = t1->ptr;
if (t2) {
t2 = t2->ptr;
}
}
Although this shows the correct output, the list isn't actually modified, so we're simply producing a side effect, rendering the routine useless for manipulating the data in memory for other purposes.
A few additional suggestions:
There's no need for global variables in this program.
Avoid unnecessary variables (t and t1 are basically the same, so it's easy to remove one of these. We can also remove t2 and use t->ptr instead).
Give variables descriptive names.
Use spacing around operators.
Separate logical chunks of code into separate functions rather than adding comments in main to delimit them.
Free allocated memory when finished with it.
No need to cast the result of malloc.
Here's a version that modifies the list in-place and implements the above points:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *ptr;
};
void remove_right_larger(struct node **head) {
for (struct node *curr = *head, *prev = NULL;
curr; curr = curr->ptr) {
if (curr->ptr && curr->data < curr->ptr->data) {
if (prev) {
prev->ptr = curr->ptr;
}
else {
*head = curr->ptr;
}
free(curr);
}
else {
prev = curr;
}
}
}
void print_list(struct node *head) {
for (; head; head = head->ptr) {
printf("%d->", head->data);
}
puts("NULL");
}
void free_list(struct node *head) {
while (head) {
struct node *tmp = head;
head = head->ptr;
free(tmp);
}
}
struct node *input_list() {
struct node *start = NULL;
struct node *last = NULL;
int size;
printf("Enter size: ");
scanf("%d", &size);
while (size--) {
struct node *tmp = malloc(sizeof(*tmp));
tmp->ptr = NULL;
printf("Enter list: ");
scanf("%d", &(tmp->data));
if (start) {
last->ptr = tmp;
}
else {
start = tmp;
}
last = tmp;
}
return start;
}
int main() {
struct node *head = input_list();
print_list(head);
remove_right_larger(&head);
print_list(head);
free_list(head);
return 0;
}
You are facing Core Dump/Segmentation fault which is a specific kind of error caused by accessing memory that “does not belong to you.”
The iteration before the last one, you're setting t1 <- 8 & t2 <- NULL. So when you enter the last iteration, you check t1->data with t2->data with in if(), which resutls in accessing NULL->data (you're not allowed).
To fix this, you need to add some extra condition to handle this case.
I'm getting assignment makes pointer from integer without a cast errors on lines 46 and 53, the two lines with double asterisks on either side, and for the life of me, I cannot figure out why. Linked lists are very new to me, I don't know how they work completely yet.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct node_def
{
int data;
struct node_def *next;
};
typedef struct node_def node;
node *makeNode (int a);
node *insertFront(node *head,node *new);
void printList(node *head);
int numNodes = 0;
int main()
{
srand(time(0));
int r = rand() % 10000;
int i = 0;
node *head = NULL;
node *tmp = NULL;
printf("How many nodes? ", numNodes);
scanf("%d", numNodes);
printf("\n");
head = insertFront(head, tmp);
for(i = 0; i < numNodes; i++)
{
makeNode(r);
printList(head);
}
printf("\n");
return 0;
}
node *makeNode (int a)
{
node *new = malloc(sizeof(node));
**new = a;**
return new;
}
node *insertFront(node *head, node *new)
{
**new->data = head;**
new->next = new;
return 0;
}
void printList(node *head)
{
int j = 0;
for(j = 0; j < numNodes; ++j)
{
while (head != NULL)
{
printf(" %4d", head->data);
head = head->next;
}
if(j % 10 == 0)
printf("\n");
}
return;
}
new = a is meant to make new nodes and assign them a random number from 0 - 9999.
You try to assign r to new, but new is a struct.
You make a pointer to struct : node *new
What you want to do is assigning r to new->data, which is an int.
node *insertFront(node *head, node *new)
{
**new->data = head;** // ** is meaningless
new->next = new; // new is a reserved key word, don't use it this way
return 0;
}
What you try to do is to put a NULL pointer as the head of your list.
Just push element into it within your makeNode function.
insert like this :
void createNode(node *head)
{
Node *new_node = malloc(sizeof(Node*));
new_node->data = rand() % 100000;
new_node->next = NULL;
if(head == NULL)
head = new_node;
else if(head != NULL)
//Here you have to adapt your list, search (linked list crud functions)
}
You have a bad understanding about what pointers are.
Hope it helps bro