Thread: Help with variable scope in C !!

  1. #1
    Registered User
    Join Date
    Sep 2014
    Posts
    51

    Help with variable scope in C !!

    I wanted to find out the factors of a number. I decided later that i'd store all the factors of the number in a linked list so that i could get more familiar with them instead of using an array.
    Here's the code
    Code:
    #include<stdlib.h>
    #include<stdio.h>
    int nextPrime(int num)
        {
            if(num==1 || num ==0)
                return 2;
            num++;
            int i;
            int flag;
            for(i=2;i<=num/2;++i)
            {
                if(num%i==0)
                {
                    flag=0;
                    break;
                }
            }
            if(flag==0)
                return nextPrime(num);
            else
                return num;
        }
        struct Node
        {
            int data;
            struct Node *link;
        };
        //typedef struct Node Node;
    void append(struct Node *start,int value)
    {
        while(start->link != NULL)
        {
            start=start->link;
        }
        start->link = (struct Node *)malloc(sizeof(struct Node));
        start=start->link;
        start->data=value;
        start->link=NULL;
    }
    void traverse(struct Node *start)
    {
        while(start != NULL)
        {
            printf("%d\n",start->data);
            start=start->link;
        }
    }
    void calculateFactors(int number)
    {
        int Den,reminder;
        Den = nextPrime(0);
        while(number > 1 )
        {
            reminder = number % Den;
            if(reminder != 0)
                Den=nextPrime(Den);
            else
               {
                 number=number / Den;
                 append(start,Den);   // Error here. Start undeclared first use in function.
               }
        }
    }
    void main()
    {
        int number, i;
        struct Node *head, *start;
        head->link = NULL;
        start=head;
        scanf("%d",&number);
        calculateFactors(number);
        //append(start,10);
        //traverse(head);
    }
    I was wondering why it shows such an error as I have already initialized the node in the main program. Should it not be available in the functions as well? Can someone explain how to fix this and the scope of variable in this context
    Last edited by thebenman; 10-23-2014 at 12:59 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,898
    > struct Node *head, *start;
    > head->link = NULL;
    You need to initialise head before doing head->link.

    Also main returns an int, not void.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Sep 2014
    Posts
    51
    I don't get it , By doing
    Code:
     head->link =NULL
    don't we initialize it?. Can you elaborate a bit more?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,377
    By doing that, you provide head->link with an initial value. What is the value of head?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    Quote Originally Posted by thebenman View Post
    I was wondering why it shows such an error as I have already initialized the node in the main program. Should it not be available in the functions as well? Can someone explain how to fix this and the scope of variable in this context
    Actually, it has not been declared yet; the program may begin at main(), but the compiler does not. At the point the errror occured, "start" has not yet been declared.

    You could make it a global structure and declare it outside main, and before it is ever referenced.

    -

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,377
    Quote Originally Posted by megafiddle
    At the point the errror occured, "start" has not yet been declared.
    Good catch, I missed the comment.

    Quote Originally Posted by megafiddle
    You could make it a global structure and declare it outside main, and before it is ever referenced.
    NO! Do not do that. Rather, remove the declaration of start from the main function since it serves no purpose there: the head variable already does its job. Rather, change the declaration of the calculateFactors function to add another parameter named start, then change how you call that function in the main function.

    Personally, I would pick either head or start as the naming convention then stick to it. You can have a local variable named head in the main function and also have a parameter named head in the calculateFactors function. Since the pointer is supposed to point to the head (or start) node either way, keeping the name consistent would be a good idea.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    Quote Originally Posted by laserlight View Post
    NO! Do not do that. Rather, remove the declaration of start from the main function since it serves no purpose there: the head variable already does its job. Rather, change the declaration of the calculateFactors function to add another parameter named start, then change how you call that function in the main function.
    Yes, but that structure is needed elsewhere in other functions.

    -

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,377
    Quote Originally Posted by megafiddle
    Yes, but that structure is needed elsewhere in other functions.
    That is why a pointer to the head is passed as an argument. This was done for the other functions that needed that pointer.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    The function "traverse()" is called from main (currently commented out). If it were actually called, how would main have access to the struct "start"? (or "head" if that replaced the "start")

    -

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,377
    Quote Originally Posted by megafiddle
    The function "traverse()" is called from main (currently commented out). If it were actually called, how would main have access to the struct "start"? (or "head" if that replaced the "start")
    Looking at the implementation of traverse and the clue given by its name, main already has access to the struct Node object, i.e., via the head pointer. It is traverse that needs access to that object by say, passing head as an argument when calling it from main (which is what was commented out).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    Ok, so the call within main(), to calculateFactors(), passes the address of "head" and then within calculateFactors(), "head" is passed on in the call to append()?

    I missed that.

    -

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,377
    Quote Originally Posted by megafiddle
    Ok, so the call within main(), to calculateFactors(), passes the address of "head" and then within calculateFactors(), "head" is passed on in the call to append()?
    Yes. There's a problem in that when the linked list is empty, then the very first append should change the head node unless it is a dummy, but that's related to the problem that Salem noted in post #2.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Sep 2014
    Posts
    51
    I have modified the code to take care of head data and link pointing to NULL.
    Code:
    #include<stdlib.h>
    #include<stdio.h>
    typedef struct Node Node;
    typedef struct Set Set;
    
    
    struct Node
    {
        int data;
        struct Node *link;
    };
    
    
    struct Set
    {
        struct Node *head;
    };
    Set *set_create()
    {
        Set *set = malloc(sizeof(*set));
    
    
        if(set ==NULL)
        {
            printf("Sorry !! Memory Full :)");
        }
        else
            set->head = NULL;
        return set;
    }
    Node *append(Set *set,int value)
    {
        Node *node;
        node = malloc(sizeof(*node));
    
    
        node->data=value;
        node->link=NULL;
    
    
        if(set->head == NULL)
        {
            set->head = node;
        }
        else
        {
            Node *iter = set->head;
            while(iter->link)
            {
                iter=iter->link;
            }
            iter->link=node;
        }
        return node;
    }
    void traverse(Set *set)
    {
        const Node *node = set->head;
        while(node)
        {
            printf("%d\n",node->data);
            node=node->link;
        }
    }
    int nextPrime(int num)
        {
            if(num==1 || num ==0)
                return 2;
            num++;
            int i;
            int flag;
            for(i=2;i<=num/2;++i)
            {
                if(num%i==0)
                {
                    flag=0;
                    break;
                }
            }
            if(flag==0)
                return nextPrime(num);
            else
                return num;
        }
    void destroy(Set *one)
    {
        Node *node = one->head;
    
    
        while(node)
        {
            Node *next = node->link;
            free(node);
            node=next;
        }
    }
    void calculateFactors(int number, Set *one)
    {
        int Den,reminder;
        Den = nextPrime(0);
        while(number >1 )
        {
            reminder = number % Den;
            if(reminder != 0)
            {
                Den=nextPrime(Den);
                //printf("%d\n",Den);
            }
    
    
            else
               {
               // printf("%d\t",Den);
                 number=number / Den;
                 //printf("%d\n",Den);
                 append(one,Den);
               }
        }
    }
    void main()
    {
        int number;
        scanf("%d",&number);
        Set *factors=set_create();
        calculateFactors(number,factors);
        traverse(factors);
        //destroy(factors);
    }
    Thep program just prints out the factors of a number. I wanted to use a linked list so that I could be more familiar with it.

    The program works just fine for most of the inputs I'e tried but fails unexpectedly for a few one.

    Suppose i give the input as 157, for which the program needs to find out the factors, the program fails. I tried with print statements in the calculateFactors function to check if the values are correctly calculated. Turns out all the values are calculated fine but fails in the append statement in the calculateFactors function. Any guesses as to why this happens?

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,377
    Since you are appending to the Set, I suggest that you keep track of the tail of the linked list as it will be far more efficient that way.

    Instead of set_create, I suggest a set_init function. The difference is that your set_create function calls malloc to create the set, whereas set_init will assume that the memory for the set has already been allocated, so it just initialises the set by setting the head (and tail) to a null pointer. This way, you can create a set local to the main function without using malloc, or use malloc in the main function if you wish. At the moment, your set_destroy function fails to call free for the set, but if you have set_init instead then it would be correct.

    Quote Originally Posted by thebenman
    Turns out all the values are calculated fine but fails in the append statement in the calculateFactors function.
    Where exactly does it fail in append, and what do you mean by fail?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    Registered User
    Join Date
    Sep 2014
    Posts
    51
    When i run this program with 128 it prints the factors correctly as 2 2 2 2 2 2 2. But when i try it with the input as 157 the program exists abruptly without printing anything. I tried printing the factors(the commented printf statements in the calculateFactor() function) with the append statement commented , it printed the factors correctly. But when i uncomment the append statement and try it for 157 as input the program exits without printing anything.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. scope of a variable
    By Satya in forum C Programming
    Replies: 3
    Last Post: 05-21-2014, 07:54 AM
  2. Replies: 8
    Last Post: 02-14-2010, 04:14 PM
  3. variable scope
    By happyclown in forum C Programming
    Replies: 4
    Last Post: 03-02-2009, 06:48 AM
  4. Variable Scope
    By Matty_Alan in forum C Programming
    Replies: 3
    Last Post: 11-23-2008, 03:28 PM
  5. Variable scope
    By Axel in forum C Programming
    Replies: 2
    Last Post: 09-19-2005, 08:41 PM