我无法显示循环输出的内容,我是对此的初学者。应该检查输入是字母还是数字并将其存储为标识符,如果运算符将其存储为符号并检查输入中是否包含关键字。

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

最佳答案

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

从总体上看,但是最大的缺点是无法验证文件操作。您必须验证fopen成功--在尝试从中读取字符之前。写入文件后,fclose也是这样,以确保在更近的位置上不存在流错误,这将使字符不被写入文件。 (如果您只是从文件中读取,则通常不保证关闭时进行验证。)

声明字符数组以容纳字符串时,应使用0初始化所有元素(有效地用nul终止字符填充数组,以确保您的字符串始终以nul终止,只要您不写超出数组末尾它很简单而且很短,只需要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以关键字开头。我还在您的代码中留下了其他注释以进行改进。这应该足以让您继续前进,而不必“为您做” :)

关于c - 如何显示不循环输出的输出?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38842868/

10-11 22:57
查看更多