-3

I can't display the output it keeps on looping, I'm a beginner on this. It is supposed to check whether the input is alpha or digits and store it as identifier and if operator it will store as symbol and check the input for keywords.

#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);
}
halfer
  • 19,824
  • 17
  • 99
  • 186
  • 2
    As the link http://linux.die.net/man/3/gets says : Never use gets() – Saurav Sahu Aug 09 '16 at 05:56
  • Why is this tagged C++? This is clearly C code. Btw; `main()` is not a valid signature for the main function - `void main()` is. – Jesper Juhl Aug 09 '16 at 05:58
  • You must have `int c` as `EOF` is an `integer` value (generally `-1`). – David C. Rankin Aug 09 '16 at 07:46
  • @JesperJuhl: See [What should `main()` return in C and C++](http://stackoverflow.com/questions/204476/) for a discussion of why `void main()` is only valid with Microsoft compilers. It is not generally valid; the return type should be `int`. – Jonathan Leffler Aug 09 '16 at 15:04
  • @Jonathan Leffler Whoa, did I really write that? That's a total brain-fart. I obviously meant `int main()` - my *bad*. I don't know what amount of drugs I were on when I wrote that - definately eiter too few or too many ;-) – Jesper Juhl Aug 09 '16 at 15:06
  • Im so sorry guys if its a C, but can anybody debug or edit to make it run okay? The objective is in above. Thanks a lot. ^_^ i hope its a challenge to someone hehehe – adamz susa Aug 10 '16 at 14:09

1 Answers1

1

There are a whole lot of subtle misuses of syntax, etc. throughout your code. I've tried to identify all and note in comments the nature of the problem.

From an overall standpoint, but biggest shortcomings were not validating your file operations. You must validate a fopen succeeded, --- Before you attempt to read characters from it. The same goes for fclose following a write to the file to insure no stream errors are present on closer that would leave characters unwritten to the file. (If you are just reading from a files, then no validation on close is generally warranted.)

When declaring character arrays to hold strings, you should initialize all elements with 0 (effectively filling the array with nul-terminating characters to insure your string will always be nul-terminated as long as you do not write beyond the end of your array. It is simple and short. Something as simple as char str[10] = "", st1[10] = ""; is all you need. (by convention, if you fill the first element of an array or struct with a value, all others are initialized to zero by default.)

There are other subtleties. You mix getc and fgetc throughout. While that will work fine, just be aware that getc is generally implemented as a Macro and doesn't guarantee single-pass operation where fgetc does.

That's pretty much the overview, go through the code, and open your code up. You may think it is readable all crammed together, but if you think about a blank line between blocks in code, the same way paragraphs in writing, it sure makes the flow easier to follow in both.

Putting that together, you could do something like the following:


Note: edited per your comment, corrected read logic errors not addressed originally.

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

I have run a short C file through to test you logic. You still have some work to do. Compile it and run your data and let me know if you have any additional questions. An example showing where you still have work to do is:

Input File

$ 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  }

Example Use/Output

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

files written

$ 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  }

(Manual line breaks at 79 chars for readability here - none in file:)

$ 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
#<.>#<.>(){[]="",[][]={{}},*;=;=(,"\");(<&&){([++],);=(,"\\");}=;(*[]){("[%]=%\
",,[]);++;};}

As you can see, your keyword and identifier logic needs work. Hint, to identify keyword and identifiers you must insure you send only strings beginning with identifiers to your keyword function. I have modified your keyword function to use strncmp to test for keywords, so you can send e.g. "for(i=0" to keyword and it will identify "for", but you must insure str starts with the keyword. I have also left additional comments in your code for improvements. This should be more than enough to get you going without 'doing it for you' :)

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Thank You sir. I've tried your code above but it still didnt displays the output i dont know what the condition is to stop and displays the output. Sorry sir im a beginner hehe – adamz susa Aug 10 '16 at 14:00
  • Im so sorry guys if its a C, but can anybody debug or edit to make it run okay? The objective is in above. Thanks a lot. ^_^ i hope its a challenge to someone hehehe – adamz susa Aug 10 '16 at 14:08
  • Adam, I'm happy to, but what would really help is if you posted a small snippet of the input you are using. That way I can validate all reads, etc. on your data. I can feed the code keywords and others all day long, but if there is something strange in the format of the data you are using, it will never show up on my end -- unless I have a copy of what you are using. Just edit your question and add it to the end and let me know. – David C. Rankin Aug 10 '16 at 19:17