Computing leading set (compiler design) I have written this program to compute the leading set of the following productions

E-&gt;E+T
E-&gt;T
T-&gt;T*F
T-&gt;F
F-&gt;(E)
F-&gt;#


Here identifier is taken as '#'

#include&lt;stdio.h&gt;
#include&lt;conio.h&gt;
#include&lt;ctype.h&gt;
struct leadT
{
    int n;
    char lead[5];
};
struct leadT leading[7];
char ip[7][7];
int col,cnt=0;
char Sym[5]={ '+','(',')','*','#','i' };
int isSym(char);
void findLeading(char,int);
void leadTabOp(char,int);
void main()
{
    int i,j,c;
    char b[4];
    for(i=0;i&lt;=5;i++)
    {
        scanf("%s",&amp;ip[i]);
    }
    printf("\n");
     for(i=0;i&lt;6;i++)
       {    c=0;
        for(j=0;j&lt;i+1;j++)
        {
            if(ip[i][0] == b[j])
            {
                c=1;
                break;
            }
        }
        if(c !=1)
        {
          b[cnt] = ip[i][0];
          cnt++;
        }

        }   
    for(i=cnt-1;i&gt;=0;i--)
    {   leading[i].n=0;
        col=1;
        leading[i].lead[0]=b[i];
        findLeading(b[i],i);
    }

    printf("\n");

    for(i=0;i&lt;cnt;i++)
    {
        for(j=0;j&lt;=leading[i].n;j++)
        {
            if(j==0)
            {
                    printf("leading(%c) = { ",leading[i].lead[j]);
             }
           else if(j == leading[i].n)
           {
               printf("%c ",leading[i].lead[j]);
           }
           else
           {
               printf("%c,",leading[i].lead[j]);
           }

        }
        printf("}");
        printf("\n");
    }

}
int isSym(char ip)
{
    int i;
    for(i=0;i&lt;5;i++)
    {
        if(ip==Sym[i])
        {
            return 1;
        }
    }

    return 0;
}
void findLeading(char p,int row)
{
    int i;
    for(i=5;i&gt;=0;i--)
    {
        if(p == ip[i][0])
        {
            if((ip[i][2] == '&gt;') &amp;&amp; (ip[i][4]=='\0'))
            {
                if(isupper(ip[i][3]))
                {
                                leadTabOp(ip[i][3],row);
                }
                else
                {
                                leading[row].lead[col]=ip[i][3];
                                leading[row].n++;
                                col++;
                }
            }
            if( (ip[i][2] == '&gt;') &amp;&amp; ( isupper(ip[i][3]) ) &amp;&amp; ( isSym( ip[i][4] ) ) )
            {
                            leading[row].lead[col]=ip[i][4];
                            col++;
                            leading[row].n++;
            }
            if( ( ip[i][2] == '&gt;') &amp;&amp; ( isSym( ip[i][3] ) ) &amp;&amp; ( isupper( ip[i][4] ) ) )
            {
                            leading[row].lead[col]=ip[i][3];
                            col++;
                                leading[row].n++;
            }
        }
    }   
}
void leadTabOp(char p,int row)
{   int i,j;
    for(i=0;i&lt;cnt;i++)
    {
        if(p == leading[i].lead[0])
        {
            for(j=1;j&lt;=leading[i].n;j++)
            {
                leading[row].lead[col]=leading[i].lead[j];
                col++;
                leading[row].n++;
            }
        }
    }
}


Please review this.
You should structure your code a bit better and improve your naming conventions.

The first loop in main() apparently scans 6 strings into ip. From that I might deduce that ip is supposed to hold your input. So name it input or even inputProductions. Current IDEs support code completion so not using longer names for the sake of less typing is not a valid argument. 

You could also put that code into a separate function readInput(char **result). Later you can adjust how you read your input without changing main.

Then you have a couple of nested loops which compute some values to be stored in b and a value c. Using i and j as loop counter is accepted practice so that's ok but what are b and c supposed to represent? Give them names which express their meaning.

Also your outer loop counter i can go up to 5 and j &lt; i + 1 means j can go up to 5 as well. b is only an array with 4 elements, so the last index you are allowed to access is 3 and b[j] would be out of bounds for any j &gt; 3.

If that nested for loop is supposed to do some pre-processing then put it into a function and give it a sensible name which expresses what it is doing.

You have a variable called cnt - what exactly is it that you are counting? Name the variable accordingly.

Your functions access global variables like cnt or ip. You should pass all data those functions require as parameters. There is not need to create implicit dependencies.

Organize your code so its concerns are separated: input parsing, data processing, output. Your main function should read something like this:

int main()
{
    char input[7][7];
    char b[4];
    int count;

    if (!readInput(input))
    {
         puts("Failed to read input.");
         return -1;
    }

    count = preProcessInput(input, b);
    if (count &lt; 0)
    {
        puts("Failed to pre-process input");
        return -2;
    }

    if (!findLeadingSet(input, b, leadingSet, count))
    {
        puts("Failed to process input");
        return -3;
    }

    printLeadingSet(leadingSet);

    return 0;
}


This makes the structure immediately clear and explains what the steps are without having to read all the code and trying to understand it (apparently preProcessInput should be named as to what it is actually pre-processing).