如何在没有它的情况下显示输出继续循环?

时间:2016-08-09 05:41:01

标签: c

我无法显示循环播放的输出,我是初学者。它应该检查输入是alpha还是数字并将其存储为标识符,如果是运算符,它将存储为符号并检查输入的关键字。

#include <stdio.h> 
#include <string.h>
#include <ctype.h>

void keyword(char str[10])
{
   if(strcmp("for",str)==0||strcmp("while",str)==0||strcmp("do",str)==0||strcmp("int",str)==0||strcmp("float",str)==0||strcmp("char",str)==0||strcmp("double",str)==0||strcmp("static",str)==0||strcmp("switch",str)==0||strcmp("case",str)==0)
      printf("\n%s is a keyword",str);
   else
      printf("\n%s is an identifier",str);
}

main()
{
   FILE *f1,*f2,*f3;
   char c,str[10],st1[10];
   int num[100], lineo=0,tokenvalue=0,i=0,j=0,k=0;
   printf("\nEnter the c program ");
   gets(st1);
   f1=fopen("input","w");
   while((c=getchar())!=EOF)
      putc(c,f1);
   fclose(f1);
   f1=fopen("input","r");
   f2=fopen("identifier","w");
   f3=fopen("specialchar","w");
   while((c=getc(f1))!=EOF)
   {
      if(isdigit(c))
      {
         tokenvalue=c-'0';
         c=getc(f1);
         while(isdigit(c))
         {
            tokenvalue*=10+c-'0';
            c=getc(f1);
         }
         num[i++]=tokenvalue;
         ungetc(c,f1);
      }
      else if(isalpha(c))
      {
         putc(c,f2);
         c=getc(f1);
         while(isdigit(c)||isalpha(c)||c=='_'||c=='$')
         {
            putc(c,f2);
            c=getc(f1);
         }
         putc(c,f2);
         ungetc(c,f1);
      }
      else if(c=='  '||c=='\t')
         printf("");
      else if(c=='\n')
         lineo++;
      else
         putc(c,f3);
   }
   fclose(f2);
   fclose(f3);
   fclose(f1);
   printf("\nThe no. im the program are");
   for(j=0;j<i;j++)
      printf("%d",num[j]);
   printf("\n");
   f2=fopen("identifier","r");
   k=0;
   printf("The keywords and identifiers are: ");
   while((c=getc(f2))!=EOF)
   {
      if(c!='\0')
         str[k++]=c;
      else
      {
         str[k]='\0';
         keyword(str);
         k=0;
      }
   }
   fclose(f2);
   f3=fopen("specialchar","r");
   printf("\nSpecial Characters are: ");
   while((c=getc(f3))!=EOF)
      printf("%c",c);
   printf("\n");
   fclose(f3);
   printf("Total no. of lines are:%d",lineo);
}

1 个答案:

答案 0 :(得分:1)

在整个代码中,语法等都有很多细微的误用。我试图找出所有问题并在评论中注明问题的性质。

从整体的角度来看,但最大的缺点是没有验证您的文件操作。您必须验证fopen成功,---在您尝试从中读取字符之前。对于文件的写入fclose也是如此,以确保没有流错误出现在更接近的文件上。 (如果您只是从文件中读取,则通常不需要对关闭进行验证。)

当声明字符数组保存字符串时,您应该使用0初始化所有元素(使用 nul-terminatedating 字符有效填充数组,以确保您的字符串始终为 nul -terminated ,只要你不写数组的末尾。它简单而简短。只需要char str[10] = "", st1[10] = "";就像你需要的那样简单。(按照惯例,如果你填充第一个元素对于带有值的数组或结构,默认情况下将所有其他值初始化为zero。)

还有其他细微之处。您将getcfgetc混合在一起。虽然这样可以正常工作,但请注意getc通常是作为宏实现的,并不保证fgetc所做的单通行操作。

这就是概述,浏览代码并打开代码。您可能认为它们都是可读的,但是如果您考虑代码中的块之间的空白行,与写入段落的方式相同,那么它确实使流程更易于遵循。

将它们放在一起,您可以执行以下操作:

注意:根据您的评论进行编辑,更正了最初未解决的读取逻辑错误。

#include <stdio.h>
#include <string.h>
#include <ctype.h>

/* use constants, not 'magic numbers' in code */
enum { MAXC = 10, MAXND = 100, MAXFN = 4096 };

void keyword (char *str)
{
    if (strncmp ("for", str, strlen ("for")) == 0 ||
        strncmp ("while", str, strlen ("while")) == 0 ||
        strncmp ("do", str, strlen ("do")) == 0 ||
        strncmp ("int", str, strlen ("int")) == 0 ||
        strncmp ("float", str, strlen ("float")) == 0 ||
        strncmp ("char", str, strlen ("char")) == 0 ||
        strncmp ("double", str, strlen ("double")) == 0 ||
        strncmp ("static", str, strlen ("static")) == 0 ||
        strncmp ("switch", str, strlen ("switch")) == 0 || 
        strncmp ("case", str, strlen ("case")) == 0)
        printf ("  keyword : %s\n", str);
    else
        printf ("  identifier : %s\n", str);
}

int main (void)     /* main() is type int, and returns a value */
{
    FILE *f1, *f2, *f3;
    char str[MAXC] = "", st1[MAXFN] = "";  /* initialize arrays 0 */
    int c, num[MAXND] = {0}, lineo = 0, tokenvalue = 0, i = 0, j = 0, k = 0;

    printf ("\nEnter the c program: ");
    if (!fgets (st1, 10, stdin)) {
        fprintf (stderr, "error: invalid input 'st1'\n");
        return 1;
    }

    if (!(f2 = fopen ("input", "w"))) { /* validate opening */
        fprintf (stderr, "error: file open failed 'input'.\n");
        return 1;
    }
    /*  The while takes input from stdin and writes to f1, but has nothing
     *  to do with the file you opened "input". I'm guessing you want to
     *  read file stream f1 (copy it) into "input" so you can reopen it
     *  in "r" mode and check for identifiers, keywords, etc.
     *
     *  You cannot redirect a file to your code, and then prompt for 
     *  a filename -- fgets will take the code as your filename
     *  (or as much will fit) because stdin is FIFO, not LIFO
     *    
    while ((c = getchar ()) != '\n' && c != EOF)
        fputc (c, f1);
     */

    if (!(f1 = fopen (st1, "r"))) { /* validate opening */
        fprintf (stderr, "error: file open failed '%s'.\n", st1);
        return 1;
    }

    while ((c = fgetc (f1)) != EOF)  /* you should really do this with fgets */
        fputc (c, f2);               /* and read/write a line at a time */

    fclose (f1);

    if (fclose (f2)) {  /* validate close after *write*, stream error */
        fprintf (stderr, "error: on stream close after write 'f2'.\n");
        return 1;
    }

    if (!(f1 = fopen ("input", "r"))) { /* validate opening */
        fprintf (stderr, "error: invalid input 'input'\n");
        return 1;
    }
    if (!(f2 = fopen ("identifier", "w"))) { /* validate opening */
        fprintf (stderr, "error: invalid input 'identifier'\n");
        return 1;
    }
    if (!(f3 = fopen ("specialchar", "w"))) { /* validate opening */
        fprintf (stderr, "error: invalid input 'specialchar'\n");
        return 1;
    }

    while ((c = fgetc (f1)) != EOF) {
        if (isdigit (c)) {
            tokenvalue = c - '0';
            c = fgetc (f1);         /* fgetc guarantees single evaluation */
            while (isdigit (c)) {
                tokenvalue *= 10 + c - '0';
                c = fgetc (f1);
            }
            num[i++] = tokenvalue;
            ungetc (c, f1);
        } else if (isalpha (c)) {
            fputc (c, f2);
            if ((c = fgetc (f1)) && c != EOF)  /* need () around assignment */
                while (isdigit (c) || isalpha (c) || c == '_' || c == '$') {
                    putc (c, f2);
                    c = fgetc (f1);
                }
            fputc (c, f2);
            ungetc (c, f1);
        } else if (c == ' ' || c == '\t')  /* one 'space' for a char */
            putchar (' ');   /* printing empty-char ?, looks like 'space' or 0 */
        else if (c == '\n')
            lineo++;
        else
            putc (c, f3);
    }
    if (fclose (f2)) { /* validate close after *write*, stream error */
        fprintf (stderr, "error: on stream close after write 'f2'.\n");
        return 1;
    }
    if (fclose (f3)) { /* validate close after *write*, stream error */
        fprintf (stderr, "error: on stream close after write 'f3'.\n");
        return 1;
    }
    fclose (f1);

    printf ("\nThe nm. in the program are: ");
    for (j = 0; j < i; j++)
        printf ("%d", num[j]);
    putchar ('\n');     /* no need for printf for a single 'char' */

    if (!(f2 = fopen ("identifier", "r"))) { /* validate opening */
        fprintf (stderr, "error: invalid input 'identifier'\n");
        return 1;
    }
    k = 0;
    printf ("The keywords and identifiers are: ");
    while ((c = fgetc (f2)) != EOF) {
        if (k + 1 < MAXC && c != '\0') /* you must limit chars to str len */
            str[k++] = c;              /* and your logic needs a rework */
        else {
            str[k] = 0;
            keyword (str);
            k = 0;
        }
    }
    putchar ('\n');
    fclose (f2);

    if (!(f3 = fopen ("specialchar", "r"))) { /* validate opening */
        fprintf (stderr, "error: invalid input 'specialchar'\n");
        return 1;
    }
    printf ("\nSpecial Characters are: ");
    while ((c = getc (f3)) != EOF)
        printf ("%c", c);
    putchar ('\n');
    fclose (f3);

    printf ("Total no. of lines are: %d\n", lineo);
}

我已经运行了一个简短的C文件来测试你的逻辑。你还有一些工作要做。编译并运行您的数据,如果您有任何其他问题,请告诉我。显示您仍有工作要做的示例是:

输入文件

$ nl -ba whileit.c
     1  #include <stdio.h>
     2  #include <string.h>
     3
     4  int main (void) {
     5
     6      char a[] = "You are welcome",
     7           b[5][20] = {{0}},
     8           *pch;
     9      int i = 0;
    10
    11      pch = strtok ( a," \t" );
    12
    13      while (i < 5 && pch) {
    14          strcpy (b[i++], pch);
    15          pch = strtok( NULL, " \t\n" );
    16      }
    17
    18      i = 0;
    19      while (*b[i]) {
    20          printf( "b[%d] = %s\n", i, b[i] );
    21          i++;
    22      }
    23
    24      return 0;
    25  }

示例使用/输出

$ ./bin/fopenprob

Enter the c program: whileit.c

The nm. in the program are: 52000500    // nm is correct
The keywords and identifiers are:   identifier : include s
  identifier : dio.h>inc
  identifier : ude strin
  identifier : .h>int ma
  identifier : n void)ch
  identifier : r a[You a
  identifier : e welcome
  identifier : b[pch;int
  identifier : i pch str                // keyword logic needs work
  identifier : ok a,t"wh
  identifier : le i pch)
  identifier : trcpy b[i
  identifier : pch)pch s
  identifier : rtok(NULL
  identifier : t\n"i whi
  identifier : e b[i]pri
  identifier : tf(b[d]s\
  identifier : "i,b[i]i+


Special Characters are: #<.>#<.>(){[]="",[][]={{}},*;=;=(,"\");(<&&){([++],);=(,"\\");}=;(*[]){("[%]=%\",,[]);++;};}
Total no. of lines are: 25

撰写的文件

$ nl -ba input
     1  #include <stdio.h>
     2  #include <string.h>
     3
     4  int main (void) {
     5
     6      char a[] = "You are welcome",
     7           b[5][20] = {{0}},
     8           *pch;
     9      int i = 0;
    10
    11      pch = strtok ( a," \t" );
    12
    13      while (i < 5 && pch) {
    14          strcpy (b[i++], pch);
    15          pch = strtok( NULL, " \t\n" );
    16      }
    17
    18      i = 0;
    19      while (*b[i]) {
    20          printf( "b[%d] = %s\n", i, b[i] );
    21          i++;
    22      }
    23
    24      return 0;
    25  }

(手动换行符为79个字符以便于阅读 - 文件中没有:)

$ cat identifier
include stdio.h>include string.h>int main void)char a[You are welcome"b[pch;int
i pch strtok a,t"while i pch)strcpy b[i+pch)pch strtok(NULL,t\n"i while b[i]pri
ntf(b[d]s\n"i,b[i]i+return

$ cat specialchar
#<.>#<.>(){[]="",[][]={{}},*;=;=(,"\");(<&&){([++],);=(,"\\");}=;(*[]){("[%]=%\
",,[]);++;};}

如您所见,您的关键字和标识符逻辑需要工作。提示,要识别关键字和标识符,您必须确保只向您的keyword函数发送带有标识符的字符串开头。我修改了您的keyword功能以使用strncmp来测试关键字,因此您可以发送,例如"for(i=0"keyword,它会识别"for",但您必须确保str以关键字开头。我还在您的代码中留下了其他注释以进行改进。这应该足以让你在没有“为你做”的情况下前进。 :)