K&R 1-24. Why isn't my program properly checking for matching single and double quotes?

时间:2015-11-12 11:53:17

标签: c kernighan-and-ritchie

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..

1 个答案:

答案 0 :(得分:2)

遇到换行符时,您忘记将标记inDubQuote重置为0。因此,当出现错误时,标志会转到下一行,并且第一个双引号会重置它,而下一个(正确关闭的一个)将为 行添加错误标志代替。

通过添加简单的逐行调试printf(以及if提出的更简单的结构),看起来这个加法解决了它:

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);
        }
    }

}

使用一些随机输入,它的行为符合预期:

~/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

您可以对单引号执行相同操作,但请注意,它不会使用嵌套级别的单引号和双引号(以及您过多的其他Begin / End标记)正确标记错误。如果你想这样做,你需要一小部分字符,你可以“推”和“弹出”各种各样的字符;那么当你为一对尚未“推”它的时候'弹出一个'时你会标记一个错误 - 并且在一行的末尾,这个堆栈应该是空的。