0

I'm trying to implement a stack to solve parenthesis problem, but i'm getting confused with the pointers(i'm new to C) here is my code so far:

typedef struct node{
    char data;
    struct node *next;
}node;
typedef struct stack{
    struct node **head;
}stack;
void push(stack *s, char c){
    node *n = (node *)malloc(sizeof(node));
    n->data = c;
    if(*s->head == NULL){
        n->next = *s->head;
        *s->head = n;
    }
    else{
        n->next = *s->head;
        *s->head = n;
    }
}
void pop(stack *s){
    if(s->head->next == NULL){
        *s->head = NULL;
    }
    else{
        node *temp = *s->head;
        *s->head = s->head->next;
        free(temp);
    }
}
bool isStringBalanced(char** sentence, int size){
    stack *s = malloc(sizeof(stack));
    *s->head = NULL;
    for(int i = 0; i < size; i++){
        int j = 0;
        while(sentence[i][j] != '\0'){
            switch(sentence[i][j]){
                case '(' : push(s, '('); break;
                case '[' : push(s, '['); break;
                case '{' : push(s, '{'); break;
                case ')' : 
                    if(*s->head)
                        if(*s->head->data == '(')
                            pop(s);
                        else return false;
                    else return false;
                    break;
                case ']' :
                    if(*s->head)
                        if(*s->head->data == '[')
                            pop(s);
                        else return false;
                    else return false;
                    break;
                case '}' :
                    if(*s->head)
                        if(*s->head->data == '{')
                            pop(s);
                        else return false;
                    else return false;
                    break;
            }
            j++;
        }
    }
    if(!s->head)
        return true;
    else
        return false;
}

when i try to run this, i get error on all the double arrows like s->head->data and s->head->next Help me to understand how to use right double pointer thanks.

5
  • 2
    You need to just make up your mind which syntax to use. If s is defined as stack *s and stack is a struct, you would use either s->member or (*s).member. Refer to the C language reference for details. Commented Feb 5, 2018 at 23:49
  • i never used (*s). i always used -> Commented Feb 5, 2018 at 23:51
  • 1
    Why is head a pointer-to-a-pointer? Commented Feb 5, 2018 at 23:53
  • 2
    In stack, I don't think you need struct node **head;; just a single indirection would do struct node *head;. Furthermore, because of this, I think you are getting confused by the two different ways to reference head and next. Commented Feb 5, 2018 at 23:54
  • When you use s->head->next, it would only work if head is node*, not node** like you have. Commented Feb 5, 2018 at 23:58

1 Answer 1

5

A double pointer is a pointer to a pointer. It is useful for example when you want that a function changes where a pointer is pointing:

void foo(char **str)
{
    *str = "World";
}

void bar(void)
{
    const char *x = "Hello";
    puts(x); // points to "Hello"
    foo(&x);
    puts(x); // points to "World"
}

This would print1:

World
Hello

A double pointer can be used for storing an array of arrays or pointers. This can be used for example for storing matrices.

In your case, the double pointer in stack is not needed, it's inside an structure. Sure you can declare it as a double pointer, but it will make live unnecessarily harder. head is already inside a struct and you usually pass the stack object as whole. So functions altering the pointing location of head can do that without the need of a double pointer, because head is not a variable, it is a member of a struct (see example below).

So you can rewrite it as:

typedef struct stack{
    struct node *head;
}stack;

Then the push can be rewritten as:

int push(stack *s, char c)
{
    node *n = calloc(1, sizeof *n);
    if(n == NULL)
        return 0;

    n->data = c;
    n->next = s->head;
    s->head = n; // see footnote 2
}

As for the question about -> and .: -> and . are used to access the members of a struct. If the variable (or expression) is not a pointer, then you use ., if the variable (or expression) is a pointer, then you use ->. It's as simple as that:

// Note these examples show only how to use -> and .

stack *s;
s->next;             // because s is a pointer
s->next->next;       // because s->next is a pointer
s->next->next->data  // because s->next->next is a pointer

stack s;
s.next;              // because s is not a pointer
s.next->next;        // because s is not a pointer, but s.next is a pointer
s.next->next->data;  // because s is not a pointer, but s.next is a pointer
                     // and s.next->next is also a pointer

fotenotes

1A string literal (the ones in quotes) return the address of where the sequence of characters are stored. In C a string is just a sequence of characters that ends with the '\0'-terminating byte.

When you do

const char *x = "Hello";

your are not copying the string to x, you are assigning the location of the sequence

base = some memory location

base
+---+---+---+---+---+----+
| H | e | l | l | o | \0 |
+---+---+---+---+---+----+

of chars to the pointer x. The value of x is that address base.

2Thanks to user user7231 for pointing out that in this case even the if(n->head == NULL) check is not necessary. I've updated my answer using his/hers lines. Credit goes to user7231.

Sign up to request clarification or add additional context in comments.

4 Comments

Why rewrite push with a loop when it was perfectly fine and shorter in the original code? Also your push pushes to the end of chain, why?
@user7231 you are right, I was more focused on the double-pointer vs single-pointer than the actual meaning of the "push" in a stack. Thanks for the feedback, I've updated my answer.
Instead of if-else it's better to just assign n->next = s->head; s->head = n;
@user7231 right again. Sometimes the fingers are faster than the brain and the examples one provides can be improved. Thanks for the feedback, I've updated my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.