0

I'm actually writing about the same program as before, but I feel like I've made significant progress since the last time. I have a new question however; I have a function designed to store the frequencies of letters contained within the message inside an array so I can do some comparison checks later. When I ran a test segment through the function by outputting all of my array entries to see what their values are, it seems to be storing some absurd numbers. Here's the function of issue:

void calcFreq ( float found[] ) 
{
    char infname[15], alpha[27];
    char ch;
    float count = 0;
    FILE *fin;

    int i = 0;
    while (i < 26) {
        alpha[i] = 'A' + i++;
    }

    printf("Please input the name of the file you wish to scan:\n");
    scanf("%s", infname);

    fin = fopen ( infname, "r");
    while ( !feof(fin) ) {
        fscanf(fin, "%c", &ch);
        if ( isalpha(ch) ) {
            count += 1;
            i = 0;
            if ( islower(ch) ) { ch = toupper(ch); }
            while ( i < 26 ) {
                if ( ch == alpha[i] ) {
                    found[i]++;
                    i = 30;
                }
                i++;
            }
        }
    }
    fclose(fin);
    i = 0;
    while ( i < 26 ) {
        found[i] = found[i] / count;
    printf("%f\n", found[i]);
        i++;
    }
}

At like... found[5], I get this hugely absurd number stored in there. Is there anything you can see that I'm just overlooking? Also, some array values are 0 and I'm pretty certain that every character of the alphabet is being used at least once in the text files I'm using.

I feel like a moron - this program should be easy, but I keep overlooking simple mistakes that cost me a lot of time >.> Thank you so much for your help.

EDIT So... I set the entries to 0 of the frequency array and it seems to turn out okay - in a Linux environment. When I try to use an IDE from a Windows environment, the program does nothing and Windows crashes. What the heck?

RedMageKnight
  • 187
  • 2
  • 12
  • 3
    have you tried initializing your arrays to start with all 0s? – John3136 Feb 09 '12 at 07:28
  • @John3136 - No, I never thought of that. I figured they didn't need to be initialized since they were going to be filled with values before I called for them. – RedMageKnight Feb 09 '12 at 07:29
  • C#, Java (and others) will automagically be set to 0. C, not so much... – John3136 Feb 09 '12 at 07:31
  • Aside from the fact that this looks to be overly complex, you're not initializing the `found[]` array in this function. If you're not initializing it before calling the function (which maybe you're doing), then there's no telling what will end up in that array. – Michael Burr Feb 09 '12 at 07:32
  • What size is the array you're passing in as "found" and is it cleared out? – Joachim Isaksson Feb 09 '12 at 07:33
  • @JoachimIsaksson - The array is of size 27 that I'm passing in from main(). – RedMageKnight Feb 09 '12 at 07:38
  • @John3136 - I'm trying to run a for loop through all the entries now and setting their values to 0 to see if that helps. – RedMageKnight Feb 09 '12 at 07:38
  • @John3136 - So I initialized all of the array entries to 0 as you suggested and everything seems to calculate at respectable values. Thank you for the tip there! But it only works in a Linux environment (running Debian for the sake of coding). When I try to use a Windows IDE environment to compile and run my program, it does nothing and then eventually crashes. I wonder why that is? – RedMageKnight Feb 09 '12 at 07:47

3 Answers3

1
alpha[i] = 'A' + i++;

This is undefined behavior in C. Anything can happen when you do this, including crashes. Read this link.

Generally I would advise you to replace your while loops with for loops, when the maximum number of iterations is already known. This makes the code easier to read and possibly faster as well.

Is there a reason you are using float for counter variables? That doesn't make sense.

'i = 30;' What is this supposed to mean? If your intention was to end the loop, use a break statement instead of some mysterious magic number. If your intention was something else, then your code isn't doing what you think it does.

You should include some error handling if the file was not found. fin = fopen(..) and then if(fin == NULL) handle errors. I would say this is the most likely cause of the crash.

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • I really don't know why I used 'i=30' to escape the loop as I am familiar with the concept of break statements. I'll be making that change. I also tend to try to avoid while loops for the most part as I think for loops are easier for me to understand anyways, but the way that examples are put in place in environments I don't always understand, I use them to at least try to make my own functioning code to try to understand how it works before I try using other methods (my professor uses while loops all the time it seems). I will put an error check for the file opening and see if that helps. – RedMageKnight Feb 09 '12 at 12:49
1

Here are a few pointers besides the most important one of initializing found[], which was mentioned in other comments.

the alpha[] array complicates things, and you don't need it. See below for a modified file-read-loop that doesn't need the alpha[] array to count the letters in the file.

And strictly speaking, the expression you're using to initialize the alpha[] array:

alpha[i] = 'A' + i++;

has undefined behavior because you modify i as well as use it as an index in two different parts of the expression. The good news is that since you don't need alpha[] you can get rid of its initialization entirely.

The way you're checking for EOF is incorrect - it'll result in you acting on the last character in the file twice (since the fscanf() call that results in an EOF will not change the value of ch). feof() won't return true until after the read that occurs at the end of the file. Change your ch variable to an int type, and modify the loop that reads the file to something like:

// assumes that `ch` is declared as `int`

while ( (ch = fgetc(fin)) != EOF ) {
    if ( isalpha(ch) ) {
        count += 1;
        ch = toupper(ch);

        // the following line is technically non-portable, 
        //  but works for ASCII targets.
        // I assume this will work for you because the way you
        //  initialized the `alpha[]` array assumed that `A`..`Z`
        //  were consecutive.

        int index = ch - 'A';

        found[index] += 1;
    }
}
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • 1
    I really like your suggestion here because I hate using while loops if I can afford not to, and you've explained how to free up 12 lines of needless code. I understood how subtracting the characters returned the integer value of distance, but I was having a hard time knowing the proper syntax for incrementing the array entry. Thank you! (PS - It seems to have also resolved my crashing problem as well) – RedMageKnight Feb 09 '12 at 15:44
0

Check the definition of found[] in the caller function. You're probably running out of bounds.

aqua
  • 617
  • 4
  • 12