4

Unnecessarily complete source code:

#include <stdio.h>

main()
{
    int c;          //char read from stdin. Type is int to accomodate EOF
    int x;          //generic counter
    int nl_counter = 1; //new line counter
    int parens, brackets, braces, dubQuotes, singQuotes, comments;                                                  //stores number of unmatched pair occurences
    int parenLines[99], bracketLines[99], braceLines[99], dubQuoteLines[99], singQuoteLines[99], commentLines[99];      //stores lines of unmatched pair occurences
    int inParen, inBracket, inBrace, inDubQuote, inSingQuote, inComment;                                    //checks whether reading inbetween a potentially matching pair
    comments = parens = brackets = braces = dubQuotes = singQuotes = inComment = inParen = inBracket = inBrace = inDubQuote = inSingQuote = 0;  //initializes whether in matching pairs to zero
    for(x = 0; x < 99; x++)                                                                 //initialize line occurences with zero
    parenLines[x] = bracketLines[x] = braceLines[x] = dubQuoteLines[x] = singQuoteLines[x] = commentLines[x] = 0;   //


    //Read from stdin
    while((c = getc(stdin)) != EOF)         
    {       
        if(c == '\n')
            nl_counter++;


        if(c == '/' && inComment == 0)          //opens comment
        {
            c = getc(stdin);

            if(c == '*')
            {
                inComment = 1;
                commentLines[comments] = nl_counter;
                comments++;
            }
            else    if(c == '\n')
                nl_counter++;
        }   

        if(inComment == 1)                  //checks for close comment
        {
            if(c == '*')
            {
                c = getc(stdin);

                if(c == '/')
                {
                    inComment = 0;
                    comments--;
                }
                else    if(c == '\n')
                    nl_counter++;
            }
        }


        if(c == '(' && inComment == 0)          //opens parenthesis
        {
            inParen = 1;
            parenLines[parens] = nl_counter;
            parens++;
        }

        if(inParen == 1 && inComment == 0)          //checks for close parenthesis
        {
            if(c == ')')
            {
                inParen = 0;
                parens--;
            }
        }

        if(c == '[' && inComment == 0)          //opens bracket
        {
            inBracket = 1;
            bracketLines[brackets] = nl_counter;
            brackets++;
        }

        if(inBracket == 1 && inComment == 0)        //checks for close bracket
        {
            if(c == ']')
            {
                inBracket = 0;
                brackets--;
            }
        }

        if(c == '{' && inComment == 0)          //opens brace
        {
            inBrace = 1;
            braceLines[braces] = nl_counter;
            braces++;
        }

        if(inBrace == 1 && inComment == 0)          //checks for close brace
        {
            if(c == '}')
            {
                inBrace = 0;
                braces--;
            }
        }

        if(c == '\"' && inComment == 0 && inDubQuote == 0)              //opens dubQuote
        {
            inDubQuote = 1;
            dubQuoteLines[dubQuotes] = nl_counter;
            dubQuotes++;
        }
        else if(inDubQuote == 1 && inComment == 0)      //checks for close dubQuote
        {
            if(c == '\"')
            {
                inDubQuote = 0;
                dubQuotes--;
            }
        }

        if(c == '\'' && inComment == 0 && inSingQuote == 0)             //opens     single quote
        {
            inSingQuote = 1;
            singQuoteLines[singQuotes] = nl_counter;
            singQuotes++;
        }
        else if(inSingQuote == 1 && inComment == 0)     //checks for close             single quote
        {
            if(c == '\'')
            {
                inSingQuote = 0;
                singQuotes--;
            }
        }
    }



    //display collected data
    if(parens > 0)
    {
        for(x = 0; x < parens; x++)
            printf("unmatched parenthesis on line %d\n", parenLines[x]);


        printf("\n");
    }

    if(brackets > 0)
    {
        for(x = 0; x < brackets; x++)
            printf("unmatched bracket on line %d\n", bracketLines[x]);


        printf("\n");
    }

    if(braces > 0)
    {
        for(x = 0; x < braces; x++)
            printf("unmatched brace on line %d\n", braceLines[x]);

        printf("\n");
    }

    if(dubQuotes > 0)
    {
        for(x = 0; x < dubQuotes; x++)
            printf("unmatched double quote on line %d\n", dubQuoteLines[x]);

        printf("\n");
    }

    if(singQuotes > 0)
    {
        for(x = 0; x < singQuotes; x++)
            printf("unmatched single quote on line %d\n", singQuoteLines[x]);

        printf("\n");
    }

    if(comments > 0)
    {
        for(x = 0; x < comments; x++)
            printf("unmatched comment on line %d\n", commentLines[x]);

        printf("\n");
    }


    getc(stdin);        //wait for input before exit
    getc(stdin);        //
}

Less unnecessarily complete source code (to the point):

#include <stdio.h>

main()
{
    int c;          //char read from stdin. Type is int to accomodate EOF
    int x;          //generic counter
    int nl_counter = 1; //new line counter
    int dubQuotes, singQuotes;                                  //stores number of unmatched pair occurences
    int dubQuoteLines[99], singQuoteLines[99];                      //stores lines of unmatched pair occurences
    int inDubQuote, inSingQuote;                                    //checks whether reading inbetween a potentially matching pair
    dubQuotes = singQuotes = inDubQuote = inSingQuote = 0;              //initializes whether in matching pairs to zero
    for(x = 0; x > 99; x++)                                     //initialize line occurences with zero
        dubQuoteLines[x] = singQuoteLines[x] = 0;                   //


    //Read from stdin
    while((c = getc(stdin)) != EOF)         
    {       
        if(c == '\n')
            nl_counter++;



        if(c == '\"' && inDubQuote == 0)                //opens dubQuote
        {
            inDubQuote = 1;
            dubQuoteLines[dubQuotes] = nl_counter;
            dubQuotes++;
        }
        else if(inDubQuote == 1)                    //checks for close dubQuote
        {
            if(c == '\"')
            {
                inDubQuote = 0;
                dubQuotes--;
            }
        }

        if(c == '\'' && inSingQuote == 0)               //opens single quote
        {
            inSingQuote = 1;
            singQuoteLines[singQuotes] = nl_counter;
            singQuotes++;
        }
        else if(inSingQuote == 1)                   //checks for close single quote
        {
            if(c == '\'')
            {
                inSingQuote = 0;
                singQuotes--;
            }
        }
    }



    //display collected data
    if(dubQuotes > 0)
    {
        for(x = 0; x < dubQuotes; x++)
            printf("unmatched double quote on line %d\n", dubQuoteLines[x]);

        printf("\n");
    }

    if(singQuotes > 0)
    {
        for(x = 0; x < singQuotes; x++)
            printf("unmatched single quote on line %d\n", singQuoteLines[x]);

        printf("\n");
    }

    getc(stdin);        //wait for input before exit
    getc(stdin);        //
}

I haven't gotten to writing for escape sequences just yet, but still, I don't see why all the brackets and braces work, but if I put a " and then after pressing enter and ^z(EOF), it doesn't display my "unmatched double quote on line 1" message. I compensated for the fact that theyre the same character with an if-else, and the additional && inSingQuote == 0 / && inDubQuote == 0 in the initial checking for an opening quote. I just don't see any holes in the logic..

JawiMmm
  • 61
  • 4
  • An observation, probably not the solution as I haven't taken the time, but I would have used the ascii values (0x22 and 0x27) for your quote characters myself. It's just easier to read. – pedwards Nov 12 '15 at 13:55
  • 1
    Simplify the code so it shows only the problem (and verify that the problem still exists with that shorter code). It should be much shorter and more readable. Try printing the variables you check in conditions. – domen Nov 12 '15 at 14:53
  • @user3121023 "for(x = 0; x > 99; x++)" A-whoops! – JawiMmm Nov 12 '15 at 21:47
  • Please say up front what the problem is and give minimal code to reproduce it. – poolie Nov 12 '15 at 21:52
  • "int parenLines[99], bracketLines[99], braceLines[99], dubQuoteLines[99] = singQuoteLines[99], commentLines[99];" this was actually a mistake in editing actually. I accidentally erased the comment and got confused – JawiMmm Nov 12 '15 at 22:00

1 Answers1

2

You forget to reset the flag inDubQuote to 0 when a newline is encountered. Therefore, when there is an error, the flag carries over to the next line, and in that the first double quote resets it and the next (a correctly closing one) will add an error flag for that line instead.

With simple, line by line debugging printfs added (and a proposed simpler structure for the if), it looks like that addition solves it:

printf ("(%d)", nl_counter);

//Read from stdin
while((c = getc(stdin)) != EOF)         
{       
    if(c == '\n')
    {
        inDubQuote = 0;
        nl_counter++;
        printf ("(%d)", nl_counter);
    }


    if(c == '\"')
    {
        if (inDubQuote == 0)                //opens dubQuote
        {
            inDubQuote = 1;
            dubQuoteLines[dubQuotes] = nl_counter;
            printf ("I just set #%d to %d!\n", dubQuotes, nl_counter);
            dubQuotes++;
        }
        else                    //checks for close dubQuote
        {
            inDubQuote = 0;
            dubQuotes--;
            printf ("I just reset counter to #%d!\n", dubQuotes);
        }
    }

}

With some random input, it behaves as expected:

~/Documents $ ./a.out
(1)a"bc"d
i just set #0 to 1!
i just reset counter to #0!
(2)e"f"g"h
i just set #0 to 2!
i just reset counter to #0!
i just set #0 to 2!
(3)i"j"k"l"m
i just set #1 to 3!
i just reset counter to #1!
i just set #1 to 3!
i just reset counter to #1!
(4)n"o"p"q
i just set #1 to 4!
i just reset counter to #1!
i just set #1 to 4!
(5)r"s"t"u"v
i just set #2 to 5!
i just reset counter to #2!
i just set #2 to 5!
i just reset counter to #2!
(6)^D
unmatched double quote on line 2
unmatched double quote on line 4

You can do the same for single quotes but do note that it will not flag errors correctly with nested levels of single and double quotes (and your plethora of other Begin/End markers). If you want to do that, you need a smallish stack of characters on which you 'push' and 'pop' all of the various characters; then you'd flag an error when you 'pop' one for a pair where you did not yet 'push' it – and at the end of a line, this stack ought to be empty.

Jongware
  • 22,200
  • 8
  • 54
  • 100
  • so, I can't have matching double quotes across lines? – JawiMmm Nov 12 '15 at 22:58
  • @JawiMmm: then you can nver tell *on which line* the double quotes are unbalanced - with your setup it will always report the very last line with a doible quote. But my proposed stack based approach will be able to do this. – Jongware Nov 13 '15 at 07:33