【问题标题】:C not detecting EOFC 未检测到 EOF
【发布时间】:2013-02-04 17:46:08
【问题描述】:

我正在编写一个程序,该程序一次读取输入一个字符,并确定它是十进制、八进制还是十六进制,并将其转换为十进制以进行输出。那部分有效,问题是我正在使用while((ch=getchar()) != EOF) 浏览文本,但while 循环永远不会终止。听说EOF相当于-1,使用EOF的方法是control+z结束程序,但我希望它是自动的。我一直在使用标准输入并为其提供 .txt 文本,并且程序不会终止的两种方式。我想知道是否有人可以查看我的代码并查看我哪里出错了。

(长了,不好意思,就是不知道是不是我在案子里做的)

int main (void) 
{
    int ch, chVal, decVal ;

    ch=getchar() ;

    while ((ch != EOF)) 
    {
        switch ( ch ) 
        {
            case ' ' :
                /* Just read until it’s not a space */
                while( ( ch == SPACE ) || ( ch== EOL ) ) 
                        ch=getchar();


            case '0' :
                /* integer, octal or hex possibilities */
                ch=getchar() ;

                /**** HEX ****/

                if ( ( ch=='x' ) || ( ch=='X' ) ) 
                {
                    /* potential hex. So far we have read in 0x.  We need to see what's next. */                
                    ch=getchar() ;

                    if ( ch== SPACE ) 
                    {
                        /* all we had was 0x entered */
                        outputIllegalToken() ;
                        break ; /* we need to end every pass through the switch with a space char (space, eoln or eof) */
                    }

                    decVal=0 ;
                    while ( ( ( '0' <= ch ) && ( ch <= '9' ) ) || ( ( 'a' <= ch ) && ( ch <= 'f' ) ) || ( 'A' <= ch ) && ( ch <= 'F' ) ) 
                    {
                        chVal = DecToHex( ch ) ;
                        decVal*=16 ;
                        decVal+=chVal ;
                        ch=getchar() ;
                    }

                    /* ch is no longer a hex val. */
                    if ( ch == SPACE || ch == EOL || ch == EOF ) 
                    {
                        /* All is good. */
                        outputHex( decVal );
                    } 
                    else 
                    {
                        if ( ch=='l' || ch=='L' ) 
                        {
                            ch=getchar() ;
                            if (( ch== SPACE ) || ( ch== EOL ) || ( ch==EOF )) 
                            {
                                outputLongHex( decVal ) ;
                            } 
                            else 
                            {
                                outputIllegalToken() ;
                                while ( ch!= SPACE && ch!= EOL && ch!= EOF ) 
                                { 
                                        getchar();
                                }
                            }
                        } 
                        else 
                        {
                            outputIllegalToken() ;
                            ch = getchar() ;
                            while ( ( ch!= SPACE ) && ( ch!= EOL ) && ( ch!= EOF ) ) 
                            { 
                                ch=getchar(); 
                            }
                        }
                    }
                    printf("do we come here? \n");
                    count++;
                     break;
                    /* end of the 0x scenario  ch is  a space char */
                }

               /****** 0 *******/

                if ( ch==' ' ) 
                {
                    /* just a 0 */
                    outputDecimal(0);
                    count++;
                    break ; /* end of 0 alone scenario. ch is a space */
                }

                /***** 0L ******/

                if ( ch=='l' || ch=='L' ) {
                    /* if there is space after the l, it's ok. otherwise illegal. */
                    ch=getchar() ;
                    if ( ( ch== SPACE ) || ( ch== EOL ) || (ch==EOF ) ) 
                    {
                        outputLongDecimal(0);
                    } 
                    else 
                    {
                        outputIllegalToken() ;
                        /* read to the next space */
                        ch=getchar() ;
                        while ( ( ch!= SPACE ) && ( ch!= EOL ) & ( ch!=EOF ) ) 
                                { 
                                ch=getchar(); 
                                }
                    }
                    count++;
                    break ;  /* end of 0L scenario.  ch is a space char. */
                }

                /**** Octal ****/

                if ( ( '0'<=ch )&&( ch<='7' ) ) 
                {
                    /* potentially octal  */
                    chVal=DecToHex( ch ) ;
                    decVal=chVal ;
                    ch=getchar() ;
                    while ( ( '0'<=ch )&&( ch<='7' ) ) 
                    {
                        decVal*=8 ;
                        decVal+=DecToHex( ch ) ;
                        ch=getchar() ;
                    }
                    /* no longer octal ch */
                    if ( ch== SPACE || ch== EOL || ch==EOF ) 
                    {
                        outputOctal( decVal ) ;

                    } 
                   else 
                    {
                        if ( ch=='l' || ch=='L' ) 
                        {
                            ch=getchar() ;
                            if (( ch== SPACE ) || ( ch== EOL ) || ( ch==EOF )) 
                            {
                                outputLongOctal(decVal) ;
                            } 
                            else 
                            {
                                outputIllegalToken() ;
                                while ( ch!= SPACE && ch!= EOL && ch!=EOF ) 
                                { 
                                        getchar();
                                }
                            }
                        } 
                        else 
                        {
                            outputIllegalToken() ;
                            ch = getchar() ;
                            while ( ( ch!= SPACE ) && ( ch!= EOL ) && ( ch!=EOF ) ) 
                            { 
                                ch=getchar(); 
                            }
                        }
                    count++;
                    break;/* end octal scenario  ch is a space character. */
                }

                count++;
                break ;

            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                /* potential decimal input */

                chVal=DecToHex( ch ) ;  /* convert the character to a number */
                decVal=chVal ;          /* keep track of the overall number */

                ch=getchar() ;
                while ( ( '0'<=ch ) && ( ch<='9' ) ) 
                {
                    chVal=DecToHex( ch ) ;
                    decVal*=10 ;
                    decVal+=chVal ;
                    ch=getchar() ;
                }

                /* integers have ended.  spaces or l is acceptable. everything else is illegal */
                if ( ( ch== SPACE ) || ( ch== EOL ) || ( ch==EOF )) 
                {
                    outputDecimal( decVal ) ;
                } 
                else if ( ( ch=='l' ) || ( ch=='L' ) ) 
                {
                    /* next char needs to be space in order to be a valid long integer */
                    ch==getchar() ;
                    if ( ( ch== SPACE ) || ( ch== EOL ) || ( ch==EOF ) ) 
                    {
                        outputLongDecimal( decVal ) ;
                    } 
                    else 
                    {
                        outputIllegalToken() ;
                        while ( ( ch!= SPACE) && ( ch!= EOL ) && ( ch!=EOF ) ) 
                        {
                            ch=getchar();
                        }
                    }
                }
                count++;
                break;
        }
    }
}

return 0;
}

【问题讨论】:

  • 我认为您不需要三个 while 循环。只需在你的 case 语句中为空间添加一个 do-nothing,然后让外部 while 循环发挥它的魔力。
  • 我猜你正在某处阅读 EOF,然后是另一个 getchar() 函数,它将吃掉 EOF 字符。要么重组你的程序,要么在其他 getchar 调用下添加对 EOF 的检查。
  • 罗伯特你说得对。我摆脱了那个while循环。 Burgos 如果我使用 putchar() 来查看在外部 while 循环中循环的字符是什么,它给了我一个换行符。我不知道这意味着什么,但是当我尝试将 while 语句更改为包含 (ch != '\n') 时,它也没有帮助。
  • 尝试重构您的代码,使其只有一个循环,只调用一次 getchar。它将帮助您控制阅读。内码可以形成为状态机。从 IDLE 状态开始,当您识别类型时移至 HEX、OCT 或 DEC 状态。如果您在不同的上下文中,对 0、空格和其他字符的处理会有所不同

标签: c


【解决方案1】:

这个:

            while( ( ch == SPACE ) || ( ch== EOL ) ) 
                    ch=getchar();

如果输入的最后一个字符是空格,将导致无限循环。我想你的意思只是( ch == SPACE ),但是用break; 替换整个语句也可以。

可能还有其他错误...

【讨论】:

    【解决方案2】:

    这是一个词法分析器。如果您使用flex/lex,它将是一个更容易编写和维护的程序,而不是重建这个复杂的轮子。这是一个用于十六进制、从零开始的八进制以及其他所有内容的 flex 转换器:

    %{
    
    %}
    %option 8bit outfile="scanner.c"
    %option nounput nomain noyywrap
    %option warn
    
    %%
    
    0x[0-9]+ { fprinf(yyout, "%d", yytext); /* hex conversion */ }
    0[0-9]+  { fprintf(yyout, "%d", yytext); /* octal conversion */ }
    .|\n { ECHO; /* print everything else out unmodified */ }
    
    %%
    int main(int argc, char **argv);
    
    int main (argc,argv)
    int argc;
    char **argv;
    {
    yylex();
    return 0;
    }
    

    只需编译:

    flex -Cf scanner.l 
    gcc -O -o wordConverter scanner.c
    

    它在标准输入上接受输入并在 EOF 之前输出。

    【讨论】:

    • 编写代码重新发明轮子对灵魂有益,有助于学习。
    • @RobertHarvey 那她为什么不开始编写她的编译器呢? :) 众所周知,状态机的细节很难调试,而 flex 做得更好。所以,除非构建这个程序的原因是专门写一个状态机,否则真的没有理由这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 2017-01-17
    • 1970-01-01
    相关资源
    最近更新 更多