2013-02-04 93 views
0

我正在编写一次读取输入一个字符并确定它是十进制,八进制还是十六进制并将其转换为十进制输出的程序。这部分工作,问题是我使用while((ch=getchar()) != EOF)来通过文本,但while循环永远不会终止。我听说EOF等于-1,使用EOF的方法是控制+ z来结束程序,但我希望它是自动的。我一直在使用标准输入以及为它提供.txt文本,并且这两种方式都不会终止程序。我想知道是否有人可以看看我的代码,看看我哪里出了问题。C没有检测到EOF

(这是很长,我很抱歉,我只是不知道如果这件事情,我的案件中完成与否)

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; 
} 
+0

我不认为你需要三个'while'循环。只需在空间的case语句中放一个do-nothing,让外层的'while'循环发挥它的魔力。 –

+1

我猜你正在读某个地方的EOF,然后是另一个'getchar()'函数,它将会吃掉EOF字符。要么重新构造您的程序,要么在其他'getchar'调用下添加EOF检查。 –

+0

罗伯特你很对。我摆脱了那个while循环。 布尔戈斯如果我使用putchar()来查看外部while循环中的字符循环是什么,它正在给我一个换行符。我不知道这意味着什么,但是当我试图改变while语句以包含(ch!='\ n')时,它也没有帮助。 – Josephine

回答

0

此:

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

会引起如果输入中的最后一个字符是空格,则为无限循环。我认为你的意思只是(ch == SPACE),但用break;替换整个声明也可以。

可能还有其他的bug ...

0

这是一个词法分析器。如果您使用的是flex/lex,那么将不会重建这个复杂的车轮,而是您编写和维护的更简单的程序。这是十六进制柔性变流器,八进制的从零开始,一切的直通:

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

它接受输入的标准输入和输出,直到EOF:

%{ 

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

只编译。

+2

编写代码重新发明方向盘对于灵魂是有益的,它有助于学习。 –

+1

@RobertHarvey那她为什么不开始写她的编译器呢? :)状态机的细节非常难以调试,并且flex做得更好。所以,除非构建这个程序的原因是专门编写一个状态机,否则没有理由这么做。 –