Search code examples
cfileuppercaselowercase

C: Counting the number of Upper/Lower case chars out of a file


Well I'm trying to read a text from a file and then write to another one how many upper and lower case characters there are, as well as how many numbers.

#include <stdio.h>

int main()
{
    int *p;
    int caps, low, num, i;
   caps = low = num = 0;

    FILE *fin, *fout;

    fin = fopen("input.txt","r");
    fout = fopen("output.txt","w");

    if (fin == NULL)
    {
       printf("FILE ERROR\n");
       return 1;
    }
    else
        printf("BABE THIS WORKS\n");

    i=0;

    while(fscanf(fin, "%s", p) != EOF)
      {
              if(p[i] >= 'a' && p[i] <= 'z')                
                         low++;         
              if(p[i] >= 'A' && p[i] <= 'Z')                
                         caps++;  
              if(p[i] >= '0' && p[i] <= '9')                
                         num++;                               
      }

    fprintf(fout,"Lower: %d, Caps: %d, Numbers: %d", low, caps, num);

    fclose(fin);
    fclose(fout);

 system("pause");   
 return 0;   
}

However, when I run this, it just "crashes" and doesn't write anything in the output.txt file.

What did I miss?


Solution

  • Since you are comparing characters, the simplest case for your read is to use character-oriented input. The library provides several character-oriented input functions, (e.g. getchar() (reading from stdin) or getc and fgetc reading from a FILE* stream). This prevents having to step through any array checking each char after your read.

    A short example using your approach would be as follows. The only tweak was to include a ternary operator that either read/writes to the filenames given as arguments to the program (or from the default stdin and stdout if no filenames are given). It just prevents hardcoding the filenames in the file. To use the program on input.txt and output.txt, simply call the program as ./programname input.txt output.txt:

    #include <stdio.h>
    
    int main (int argc, char **argv)
    {
        int p, caps, low, num;
        p = caps = low = num = 0;
    
        FILE *fin, *fout;
    
        /* read from filename argv[1] (default: stdin), 
           write to  filename argv[2] (default: stdout) */
        fin  = argc > 1 ? fopen (argv[1], "r") : stdin;
        fout = argc > 2 ? fopen (argv[2], "w") : stdout;
    
        if (fin == NULL) {
            fprintf (stderr, "input file open failed.\n");
            return 1;
        }
        if (fout == NULL) {
            fprintf (stderr, "output file open failed.\n");
            return 1;
        }
    
        while ((p = fgetc (fin)) != EOF)
        {
            if ('a' <= p && p <= 'z') low++;         
            if ('A' <= p && p <= 'Z') caps++;  
            if ('0' <= p && p <= '9') num++;                               
        }
    
        fprintf (fout, "\n Lower: %d, Caps: %d, Numbers: %d\n\n", low, caps, num);
    
        if (fin  != stdin)  fclose(fin);
        if (fout != stdout) fclose(fout);
    
        //system("pause");   
    
        return 0;   
    }
    

    Example Input File

    $ cat ../dat/captnjack.txt
    This is a tale
    Of Captain Jack Sparrow
    A Pirate So Brave
    On the Seven Seas.
    

    Output (reading/writing to default stdin/stdout)

    $ ./bin/countltrs <../dat/captnjack.txt
    
     Lower: 47, Caps: 12, Numbers: 0
    

    Let me know if you have further questions.