0

My program should print the letter frequency and the sum of the numbers of an input file in another output file. The letter frequency works just fine. The problem is that the sum part is ignored by the compiler so it prints the letter frequency and the sum is 0. I have tried a few things out but I can't figure out where the problem is. Hope u can help :)

So here is the code :

#define MAX_FILE_NAME 100 
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> 



void text_analysis(FILE*,FILE*, int,int freq [] );

int main()
{

FILE *in, *out;
    int frequency[26] = {};
    char filename[MAX_FILE_NAME]; 
    int a, sum = 0;
    int ch = 0;


   //Give the name of the file you want to open
    printf("Enter file name: "); 
    scanf("%s", filename); 

    // Open the file in to read
    in = fopen(filename, "r"); 
    if (in == NULL) 
    { 
        printf("Could not open file %s", 
               filename); 
        return 0; 
     } 

    //Open the file out to write the output 
    out = fopen("output.txt", "w");
    if (out == NULL) 
    {
    printf("Cannot open destination file.\n");
    exit(1);
    }




  do {

    // read each character from input file
    ch = fgetc(in);


  //read all the numbers in the file and calculate the sum
    if( isdigit( (char)ch ) )
        {
            ungetc( (char)ch, in );
            if( fscanf( in, "%8d", &a ) != 1 )
            {
                fprintf( stderr, "fscanf for number failed\n" );

            }
            sum += a;
        }



         //Call the function to analyse the text and return the frequency of the letters in the file
            text_analysis(in,out, ch, frequency);
    } 

    while (!feof(in));


    //Print the sum of the numbers in the file 
    fprintf(out, "\n The sum of all numbers in the file is: %d \n", sum);


    //Close the files
    fclose(out);
    fclose(in);

   return 0;
}



void text_analysis(FILE *in,FILE *out, int c, int freq[]) {

 while ( (c = fgetc(in)) != EOF)
   {
      /** Considering characters from 'a' to 'z' only
          and ignoring others */

      if ('a' <= c && c <= 'z') 
         freq[c-'a']++;
      else if('A' <= c && c <= 'Z')
          freq[c-'A']++;

   }


  //Print the letters a-z and the frequency in the output file 
   fputs("character\t\t\t\tfrequency", out);

   for (c = 0; c < 26; c++)
   {
    fprintf(out, "\n%c\t\t\t\t\t\t%2d", c+'a',freq[c]);

   }

}
f_ozk
  • 5
  • 2
  • So you first read a digit into `ch` and then hope that next 8 characters will be digits as well? – Eugene Sh. Jan 15 '20 at 22:37
  • Reinit sum to be 9 and see if your program prints 9, i assume your not hitting the line where you think you're adding to it. Alternatively printf right above the sum+= line and print every time you add to it. – Bwebb Jan 15 '20 at 22:40
  • 1
    A number can contain 8 digits. for example if I have these two numbers in my file: 1111111 and 23 then the sum should be 1111134 – f_ozk Jan 15 '20 at 22:44
  • 1
    The `text_analysis` function reads the entire contents of the file. So there's nothing left for the loop in `main` to read. – user3386109 Jan 15 '20 at 22:48
  • regarding: `int frequency[26] = {};` This results in the compiler outputting: "untitled1.c:14:25: warning: ISO C forbids empty initializer braces [-Wpedantic]" – user3629249 Jan 16 '20 at 02:18
  • 1
    regarding: `scanf("%s", filename);` 1) when using `%s` and/or `%[...]` always include a max characters modifier that is 1 less than the length of the input buffer because those input format conversion specifiers always append a NUL byte to the input. This avoids any possibility of a buffer overflow and the attendant undefined behavior 2) always check the returned value (not the parameter values) to assure the operation was successful. In the current scenario, any returned value other than 1 indicates an error occurred – user3629249 Jan 16 '20 at 02:22
  • OT: for ease of readability and understanding: 1) please consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces – user3629249 Jan 16 '20 at 02:25
  • regarding: `if( isdigit( (char)ch ) ) { ungetc( (char)ch, in );` the function: `isdigit()` and the function: `ungetc()` are expecting the first parameter to be an `int`, not a `char` so no need to cast – user3629249 Jan 16 '20 at 02:26
  • OT: regarding: `if ('a' <= c && c <= 'z') freq[c-'a']++; else if('A' <= c && c <= 'Z') freq[c-'A']++;` This can be greatly reduced to `if( isalpha( c ) { freq[ tolower( c) -'a']++; }` – user3629249 Jan 16 '20 at 02:30
  • 1
    strongly suggest: move this statement: `text_analysis(in,out, ch, frequency);` prefixed by: `rewind( in );` to just before the comment: `close the files` – user3629249 Jan 16 '20 at 02:37
  • You will want to look at [**Why is while ( !feof (file) ) always wrong?**](https://stackoverflow.com/questions/5431941/why-is-while-feoffile-always-wrong). It's no better in a `do .. while (!feof(in));`. `EOF` will be triggered by `ch = fgetc(in);` – David C. Rankin Jan 16 '20 at 06:55
  • @user3629249 why don't you provide an answer instead of all these comments ? – chmike Jan 16 '20 at 07:40

1 Answers1

1

You didn't provide an example input, so I'm just guessing:

  1. Your input starts with a non-digit character.
  2. Then your do-while() loop in main calls text_analysis(), which reads the entire input by its while loop.
  3. After returning, main's loop ends, giving you a sum of 0.
the busybee
  • 10,755
  • 3
  • 13
  • 30