[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 300
  • Last Modified:

Need help in syntax. No of occurrences

I need help in finding out the problem with my code.

I have displayed here parts of the code for clarification.




/initialisation
char      inchars[200],
      outchars[200], spoutchars[200];
int      acount = 0,count=0,i=0, j = 0, c, letter[26];



//here i am opening a file for writing
outfile = fopen("c:\\nasser\\cprograms\\tout.txt","w");
if (outfile == NULL)
      printf("Cannot find output file");


// some process
//
//
//



// a bunch of capital letters written here
// eg. THIS IS A TEST TO COUNT THE NUMBER OF OCCURENCES OF EACH LETTER
fputs(spoutchars,  outfile);



//initializing array letter to zeros
for (j = 0; j < 26; ++j)
      letter[j] = 0;
      

//reading outfile, and assigning a number of occurences of each letter
while ((c = getc(outfile)) != EOF)
      ++letter[c - 'A'];
      
      
Everything works the way I wanted until I got to this statement
// printing out the array letter.      
for (i = 0; i < 26; i++)
      printf("%d", letter[i]);
      
I was expecting freq of occurrences of each letter here but I get a bunch of 26 zeros.

I am definitely doing something wrong, but not quite sure what it is.

Any help would be appreciated.

Thanks in advance.

Mark.
0
markov123
Asked:
markov123
  • 7
  • 5
  • 3
  • +2
2 Solutions
 
ozoCommented:
I don't see you opening outfile for reading anywhere.

If getc(outfile) is ever anything other than 'A'-'Z' or EOF letter[c - 'A'] will be out of the range of the array.
0
 
markov123Author Commented:
As I mentioned above, I did not post the whole code, here it is.

Outfile contains only 'A'-'Z', so there is no problem there.

#include <stdio.h>

int main()
{


/////////////////////////////////////////////////
/////////// Initialisation //////////////////////
/////////////////////////////////////////////////
FILE  *infile;
FILE      *outfile;
//FILE  *outfile;

//char outchars[200];
char      inchars[200],
            outchars[200], spoutchars[200];
int            acount = 0,count=0,i=0, j = 0, c, letter[26];

// open i/o files

infile = fopen("c:\\markov\\cprograms\\linetest.txt","r");

if (infile == NULL)
      printf("Cannot find input file");



outfile = fopen("c:\\markov\\cprograms\\tout.txt","w");

if (outfile == NULL)
      printf("Cannot find output file");





while (fgets(inchars, 200, infile) !=NULL)
{
      while(inchars[i] !='\n')//scan a line i
      {
            
            outchars[i] = toupper(inchars[i]);  //convert to upper case
            
            outchars[i] = toupper(inchars[i]);  //convert to upper case
            if ((outchars[i] >= 'A' && outchars[i] <= 'Z'))//test within a line
                  spoutchars[i] = outchars[i];
      
           count++;
      
        i++;
      }
      
      
      
      acount++;      
    i=0;
      fputs(spoutchars,  outfile);
   
}

//initialise new array

for (j = 0; j < 26; ++j)
      letter[j] = 9;
      
      
while ((c = getc(outfile)) != EOF)
      ++letter[c - 'A'];
      
for (i = 0; i < 26; i++)
      printf("%d", letter[i]);


//for (j = 0; j < 10; j = j + 1)
//      printf(spoutchars[j]);


//printf("There are %d lines in this file\n", acount);
//printf(" letter a: %d\n", count);
//printf("%s",spoutchars);
fclose(infile);
fclose(outfile);



      return 0;
}
0
 
PaulCaswellCommented:
Some compilers have strange operator precedence. If ozo's suggestion doesnt work, you could try:

letter[c - 'A'] += 1;

because:

++letter[c - 'A'];

could be interpreted as:

(++letter)[c - 'A'];

which would obviously not be what you want.

Paul

0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
PaulCaswellCommented:
>>while ((c = getc(outfile)) != EOF)
You've opened outfile for write only access! This will not work! You cant use 'getc' on an output file.

Paul
0
 
ozoCommented:
I still don't see outfile being opened for reading before trying to getc(outfile)
0
 
markov123Author Commented:
Thanks for your comments, I found my programs too cumbersome, I have therefore re written it in a simpler (hopefully more efficient) way.

While the program removes all non alphabetic characters and doen the capitalization. I still have a problem in getting the occurrences.

So when the file gets executed, these two statements print nothing:
     letter[c - 'A'];
     printf("%c", cap_char);

Again, am posting the code here.


Your help on this is highly appreciated.

Thanks in advance




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

int main()
{
     FILE *rfile;
     
     rfile = fopen("c:\\markov\\cprograms\\t.txt", "r");
     
     long count = 0;

     int in_char,
                 cap_char,
                 letter[26],
                 c;

     if ((rfile) == NULL)
     {
          printf("Cannot open input file\n");
     
     }

     in_char = fgetc(rfile);
     printf("%c", toupper(in_char));

     while (in_char != EOF)  
     {
     
       in_char = fgetc(rfile);
       cap_char = toupper(in_char);
       
       if((cap_char >= 'A') && (cap_char <= 'Z'))
       {
                  letter[c - 'A'];
                  printf("%c", cap_char);
                   
       }
       count++;
   
     }
      
        printf("%s", letter);      
     printf("\nThere are %d characters in the file\n", count);
     fclose(rfile);
     return 0;
}

0
 
NopiusCommented:
1) this statement does nothing:  letter[c - 'A'];
2) is your file 'c:\\markov\\cprograms\\t.txt' populated with chars?
0
 
markov123Author Commented:
1) I have just changed it to letter[cap_char - 'A']


2) yes, my file is just a normal text file.

i need two simple operations.

1. capitalise,
2. count the occurrences,
 for example: C PROGRAMMING IS QUITE FRUSTRATING.

Output: A: 0, B: 0, C: 1, D: 0, E: 1, and so forth.



0
 
PaulCaswellCommented:
>>letter[cap_char - 'A']
This just has a value. If you wish to change the value in that location then you need to do something with it. I suspect you want to add one? You are adding one to 'count' elsewhere in your code, perhaps that is what you need to do here.

Paul
0
 
cwwkieCommented:
Besides the statement which does nothing, there is a logic error in your loop. You are doing this:

    in_char = fgetc(rfile);

    while (in_char != EOF)  
    {
        in_char = fgetc(rfile);

        /* Do something with in_char */
    }

Do you see the error now?
0
 
markov123Author Commented:
Sorry, but I do not see the error here.

I have modified it further:

 while (in_char != EOF)  
     {
     
       in_char = fgetc(rfile);
       cap_char = toupper(in_char);
       
       if((cap_char >= 'A') && (cap_char <= 'Z'))
       {
                  ++letter[cap_char - 'A'];
                  //printf("%d\t", cap_char);
                  printf("%d ", letter[count]);
                  count++;
                   
       }

It compiles and runs, instead of printing the occurences, it prints out large numbers, which I assume are addresses. For example, if the text 5 contains 5 chars, I get a combination of 5 large numbers (maybe one or two small).

Again I appreciate your inputs, would like some more.

Thanks in advance.

Mark
0
 
cwwkieCommented:
> it prints out large numbers

Did you set the counters to 0 before counting?
In your original code you did so, but not in the new code.
0
 
PaulCaswellCommented:
Hi markov123,

I'll try to describe exactly what your program is telling the computer to do. Perhaps that will help.

// Each time around the loop, check if in_char is equal to EOF. If it is, stop.
while (in_char != EOF)  
     {
     // Read a character from the file 'rfile' and set 'in_char' to its value.
       in_char = fgetc(rfile);
     // Set 'cap_char' to the uppercase form of the value of 'in_char'
       cap_char = toupper(in_char);
       // if 'cap_char' is between 'A' and 'Z'
       if((cap_char >= 'A') && (cap_char <= 'Z'))
       {
                // Add one to the value of the letter array entry indicated by 'cap_char' were the zero'th entry would be used if 'cap_char' had value 'A'
                ++letter[cap_char - 'A'];
                //printf("%d\t", cap_char);
                // print the 'count'th entry from the letter array.
                printf("%d ", letter[count]);
                // Add one to 'count'
                count++;
                 
       }

The critical problem is that you are assuming that the 'count'th entry in the letter array has a valid value before you have finished reading all the letters.

You need two loops. One to read the letters in and count them and another loop to print out the results.

Paul
0
 
markov123Author Commented:


I got the program to work. Two problems I had

1. The array was not initialised to zero.
2. The loop for printing out chars was inside the main while loop, when I took it out, the program worked like a charm.

I still cannot figure out why it wont work when the printf is inside the loop.

I like to thank both Paul and cw for your help. You guys have been very patient.

Here is the latest version:


 //ititialise array
        for(i = 0; i < 26; ++i)
              letter[i] = 0;

 while (in_char != EOF)  
     {
     
       in_char = fgetc(rfile);
       cap_char = toupper(in_char);
       
       if((cap_char >= 'A') && (cap_char <= 'Z'))
       {
                  ++letter[cap_char - 'A'];
                  //printf("%d\t", cap_char);
                  //printf("%d ", letter[count]);
                  count++;
                   
       }
       //count++;
   
     }
              
              
        //count freq
        for (int j = 0; j < 26; j++)
              printf(" %c:%d ", 'A' + j, letter[j]);
     printf("\nThere are %d characters in the file\n", count);
     fclose(rfile);
     return 0;
0
 
cwwkieCommented:
Is it working correctly now? In the previous version you would forget to count one character.
0
 
markov123Author Commented:
I have tested it and the count is correct.  The only problem I have is that I need the first line below in order for the progam to work, if I dont incluse that line, it fails. I have no idea why.


     in_char = fgetc(rfile);  //the prog fails if i dont include this line
     printf("%c\n", toupper(in_char));

     while (in_char != EOF)  
     {
     
       in_char = fgetc(rfile);
       cap_char = toupper(in_char);
       
       if((cap_char >= 'A') && (cap_char <= 'Z'))
       {
                  ++letter[cap_char - 'A'];
                      count++;
                   
       }
       //count++;
   
     }
              
              
0
 
PaulCaswellCommented:
Thats because you have to read the first character before checking it dont you?

The normal way to tidy this up is to do something like:

     while ((in_char = fgetc(rfile)) != EOF)  
    {
     
       // in_char = fgetc(rfile); Dont need this anymore because its already been read.
       cap_char = toupper(in_char);
  ...

Paul
0
 
markov123Author Commented:
Thanks Paul, will try and make those changes
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 7
  • 5
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now