1

So I have this program where it asks the user for a filename to read, and a filename to save the output to. This program basically counts the frequency of a letter inside the txt file. Here is the program...

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

int main(void)
{
    char letter[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", FileName[50], SaveFile[50], print[256], stry[50], scount[50], point;
    int i, j, count = 0;
    FILE * readFile, *saveFile;
    printf("Enter a file to read: ");
    gets(FileName);
    printf("Enter a filename to save results: ");
    gets(SaveFile);
    printf("Letter Frequency\n\n");
    saveFile = fopen(SaveFile, "wb");

    for(i = 0; i <= strlen(letter)-1; i++)
    {
        readFile = fopen(FileName, "r");
        while(!feof(readFile))
        {
            fgets(print, 256, readFile);
            for(j = 0; j <= strlen(print); j++)
            {
                if(toupper(print[j]) == toupper(letter[i]))
                {
                    count++;
                }
            }
            point = letter[i];
            stry[0] = point;
            sprintf(scount, "%d", count);
            if(feof(readFile) && count > 0)
            {
                printf("%s %d\n", stry, count);
                fprintf(saveFile, stry);
                fprintf(saveFile, " ");
                fprintf(saveFile, scount);
                fprintf(saveFile, "\n");
            }
        }
        count = 0;


    }
    fclose(readFile);
    return 0;
}

I input a txt file named readme.txt that I modified. It contains

aaa
bbb
ccc
ddd

But when I run it, and used readme.txt to be read, the output is

A 3
B 3
C 3
D 6

The frequency of letter D must be only 3. I further modified the content of the readme.txt file, and figured out that value of the variable count is doubled when reading the last line. For example, the content of the txt file is

hello mama
hihihi
maria maria
woohoo

the output will be

A 6
E 1
H 6
I 5
L 2
M 4
O 9
R 2
W 2

I read my program so many times already, and I still can't find my wrong doings. I hope you can help me fix this problem. Your help will be very much appreciated!

EDIT:

This is what my code looks like after making the changes that were recommended in the comments section:

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

int main(void)
{
    char letter[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", FileName[50], SaveFile[50], print[256], stry[50], scount[50], point;
    int i, j, count = 0;
    FILE * readFile, *saveFile;
    printf("Enter a file to read: ");
    gets(FileName);
    printf("Enter a filename to save results: ");
    gets(SaveFile);
    printf("Letter Frequency\n\n");
    saveFile = fopen(SaveFile, "wb");

    for(i = 0; i < strlen(letter); i++){
        readFile = fopen(FileName, "r");
        while(fgets(print, 256, readFile) != NULL)
            {
            fgets(print, 256, readFile);
            for(j = 0; j <= strlen(print); j++)
            {
                if(toupper(print[j]) == toupper(letter[i]))
                {
                    count++;
                }
            }
            point = letter[i];
            stry[0] = point;
            sprintf(scount, "%d", count);
            if(feof(readFile) && count > 0)
            {
                printf("%s %d\n", stry, count);
                fprintf(saveFile, stry);
                fprintf(saveFile, " ");
                fprintf(saveFile, scount);
                fprintf(saveFile, "\n");
            }
        }
        count = 0;


    }
    fclose(readFile);
    return 0;
}
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
PABLO1403
  • 11
  • 4
  • 4
    `while(!feof(readFile))` is always wrong --> https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – pmg Feb 18 '22 at 13:36
  • 2
    Anybody know why `while(!feof(fp))` is still so rampantly popular? It used to be the influence of Pascal, but I don't get the impression that Pascal is taught so much these days. – Steve Summit Feb 18 '22 at 13:39
  • 1
    @PABLO1403 the `while(!feof(readFile))` issue seems not to be the problem here. The overall approach you've taken is overly complicated and wrong. You read the file 26 times in a row. This task can be achieved by readign it only it only _once_. – Jabberwocky Feb 18 '22 at 13:46
  • Side note: Instead of `i <= strlen(letter)-1`, you can simply write `i < strlen(letter)`. – Andreas Wenzel Feb 18 '22 at 13:49
  • @SteveSummit yes, that is _one_ problem, but it's not the main issue. The main issue is the wrong overall approach. – Jabberwocky Feb 18 '22 at 13:52
  • 1
    When `fgets` returns `NULL`, it means that it was unable to provide any further input. In that case, you still attempt to process this non-existant input, by reading the input buffer `print`, which still contains the input of the previous line. That is why the last line gets processed twice. Instead, you should move the `fgets` function call into the loop condition, by changing `while(!feof(readFile))` to `while( fgets(print, 256, readFile) != NULL )`. – Andreas Wenzel Feb 18 '22 at 13:57
  • @AndreasWenzel putting the ```fgets``` as a condition in the ```while``` function didn't work for me. I dunno why – PABLO1403 Feb 18 '22 at 13:59
  • @Jabberwocky I missed the *second* call fo `feof`. Hoo, boy. You're right, not quite the usual mistake. – Steve Summit Feb 18 '22 at 14:01
  • @PABLO1403 You also need to, at the very lest, move the `fprintf(saveFile)` code out of the inner loop. – Steve Summit Feb 18 '22 at 14:02
  • @PABLO1403 I'd throw this code away and rethink the problem. General approach: read the file once char by char. Use each char read as an index into an array, where each array position contains the number of occurences of the char, e.g. `array[0]` would contain the number of As, `array[1]` would contain the number of Bs etc. Your code will be far more efficient and much simpler (less than half the number of lines you have now). – Jabberwocky Feb 18 '22 at 14:07
  • @PABLO1403: In my comment, I recommended that you **move** the `fgets` line into the loop condition. However, you seem to have **added** an extra call to `fgets`, instead of **moving** it. In other words, you should delete the line `fgets(print, 256, readFile);` after moving it into the loop condition. – Andreas Wenzel Feb 18 '22 at 14:10
  • 1
    @SteveSummit I have no empirical data, but I suspect `feof(fp)` is common because of Cargo Cult programming and people's resistance to change. Someone learns C poorly through examination of the corpus of terrible code available on the internet and learns to use it. Once the pattern is ingrained in their mind, they refuse to unlearn it. And then that person becomes an instructor. (But this is not unique to `feof(fp)`!) – William Pursell Feb 18 '22 at 14:10
  • Also, as already pointed out by @SteveSummit, you should move the content of the `if` block `if(feof(readFile) && count > 0)` outside the loop. – Andreas Wenzel Feb 18 '22 at 14:15
  • @AndreasWenzel I did all the things that you pointed out, including the one from SteveSummit, and it already worked!! Thank you so much guyss!! – PABLO1403 Feb 18 '22 at 14:19
  • @SteveSummit `if (!feof(fp))` is common because it makes sense in English. "While not at end of file." Too bad `feof` doesn't work that way. Its name is misleading because it was written back in the days when we had function names like `creat`. – Raymond Chen Feb 18 '22 at 14:25

0 Answers0