Hi all.. wonder if anyone can guide me. I am writing a program which reads values from a text file, the text file includes both characters and float values, below is a sample of the data..

London 7.24 8.15 6.45 3.24 3.66 2.45 4.71 6.78 6.45 8.61 7.45 6.55

The text file (attached) is supposed to hold a maximum of 12 records and is terminated by the value ZZZZZ - so basically when the compiler see's ZZZZZ it will stop reading the file. Each row needs to have a city name and 12 float values to represent January to December

the data is then put into an array - and a total for individual row is a calculated and an average for individual column should also be calculated - i have got the program reading the values in and doing the row total, so im happy with that, but the average only gives the correct value if there are 12 entries - so i need to know how to get it automatically divide by the number of entries and not by 12 each time...

also i need to do comparison which displays the name of the town and then displays the month with the highest value and the month with the lowest value - i cant figure out how to incorporate the month names into the program and how to do the comparison. I have pasted the code i have so far - so if anyone can help it will be greatly appreciated

#include <string.h>

const int maxrows=12;
const int maxcols=12;
const int maxchar=10;

static char place[maxrows][maxchar];
static char dummy[maxchar];
int month;
float rain[maxrows][maxcols];
float average, annual, wet, dry; 

FILE *fp;

main ()
{
    int i=0;
    if ((fp = fopen("data.txt", "r"))==NULL)
       printf("Error opening file\n");
    else
    {
        do
        {
            printf("\n\n");
            fscanf(fp,"%s",&dummy);
            if (strcmp(dummy, "ZZZZZ") !=0)
            {
                strcpy(place[i],dummy);
                printf("%10s", place[i]);
                annual=0;
                for (int j=0; j<maxrows; j++) 
                {
                    fscanf(fp,"%f",&rain[i][j]);
	                printf("\t%2.2f",rain[i][j]); 
	                annual=annual+rain[i][j];                      
	            }printf("\tAnnual rainfall is %3.2f", annual);
	            i++;   
            }
        } while ((strcmp(dummy,"ZZZZZ") !=0) && (i<maxrows));
        
        printf("\n\nMonthly Average ");
        for (int j=0; j<maxcols; j++)
        {
            annual=0;
            average=0;
            for (int i=0; i<maxrows; i++)
            { 
                annual=annual+rain[i][j];
                average=annual/maxrows;
            }printf("%2.2f\t", average);
        }
    }
    fclose(fp);
    getchar();
}

Dani AI

Generated

Good progress — the symptoms you describe all come from three simple mistakes: not tracking how many city rows you actually read, using the wrong loop bounds when reading the 12 monthly values, and mixing up indices when you search for min/max. was right to tell you to count rows; correctly flagged the j < maxrows read-loop bug — that inner loop must iterate maxcols (12) months, not maxrows.

Practical fixes you can apply immediately:

  • Maintain an int nrows = 0 and increment it only when you successfully read a city name that is not "ZZZZZ". Use nrows everywhere later instead of maxrows or a hard-coded 12.
  • When reading a city: fscanf(fp, "%9s", place[nrows]) then for months do for (int m = 0; m < maxcols; ++m) fscanf(fp, "%f", &rain[nrows][m]); (check each fscanf return).
  • Compute column averages using for (m=0..maxcols-1) { sum = 0; for (r=0..nrows-1) sum += rain[r][m]; avg = sum / nrows; } — divide by nrows, not 12.

Finding wettest/driest per town:

  • For each city row r set iMin = iMax = 0. Then loop months m = 1..maxcols-1 and update if (rain[r][m] > rain[r][iMax]) iMax = m; and similarly for iMin. Use months[iMax] and months[iMin] when printing; print place[r] as the town name (not months[r]).

Extra cautions: avoid magic sentinels like 99999 — initialize min/max to the first month value for that row. Use %9s (or fgets) to avoid buffer overflow and to handle multi-word city names. Check every fscanf return and compile with -Wall to catch common mistakes (shadowed loop variables, wrong pointer use like &dummy). These small changes will make the row totals, column averages and wet/dry month reports correct and robust.

Recommended Answers

All 8 Replies

but the average only gives the correct value if there are 12 entries - so i need to know how to get it automatically divide by the number of entries and not by 12 each time...

The basics...

#include <stdio.h>

int main(void)
{
   static const char filename[] = "data.txt";
   FILE *file = fopen(filename, "r");
   if ( file )
   {
      char line[20][80];
      int j, i = 0;
      while ( fgets(line[i], sizeof line[i], file) != NULL )
      {
         ++i;
      }
      fclose(file);
      printf("i = %d\n", i);
      for ( j = 0; j < i; ++j )
      {
         fputs(line[j], stdout);
      }
   }
   return 0;
}

/* data.txt
London
Manchester
Liverpool
Bristol
*/

/* my output
i = 4
London
Manchester
Liverpool
Bristol
*/

Keep track of how many you read and use that instead of a hard-code value.

also i need to do comparison which displays the name of the town and then displays the month with the highest value and the month with the lowest value - i cant figure out how to incorporate the month names into the program and how to do the comparison. I have pasted the code i have so far - so if anyone can help it will be greatly appreciated

When you find the month with the highest and lowest, not the index -- this will give you the month.

thanks for this dave - just coudnt understand what you meant by the following!

When you find the month with the highest and lowest, not the index -- this will give you the month.

If rain[month] was the highest, then the highest is in month.

im still not with it... basically this is what i am trying to acheive

screen display of text file - including town name - with a total at the end of each row and a average at the bottom of each column - i have this done.

i now need to display the town name and then wettest month and dryest month.
so London: Wettest Month - October: 8.61 Dryest Month - June: 2.45

so i need to look at the array again and do a comparison of each value in a row to find the highest and lowest and then need to make sure it assigns the correct month value, im sorry i just dont know how to go about doing this

Canned example:

#include <stdio.h>

int main()
{
   static const char *month[] = 
   {
      "January", "February", "March", "April", "May", "June",
      "July", "August", "September", "October", "November", "December"
   };
   static const double rainfall[] =
   {
      7.24, 8.15, 6.45, 3.24, 3.66, 2.45, 4.71, 6.78, 6.45, 8.61, 7.45, 6.55  
   };
   size_t i, most, least; /* indices */
   for ( most = least = i = 0; i < sizeof rainfall / sizeof *rainfall; ++i )
   {
      if ( rainfall[i] > rainfall[most] )
      {
         most = i; /* save index to highest rainfall */
      }
      if ( rainfall[i] < rainfall[least] )
      {
         least = i; /* save index to lowest rainfall */
      }
   }
   printf("Wettest Month - %s : %g Driest month - %s : %g\n", 
          month[most], rainfall[most], month[least], rainfall[least]);
   return 0;
}

/* my output
Wettest Month - October : 8.61 Driest month - June : 2.45
*/

thanks again for your time dave, but im afraid im still not getting it - its really frustrating me, i just cant seem to grasp the concept of the arrays :sad:

here is the code i have got - the rest of the program seems to work fine but i cant display the wet/dry months correctly - it just keeps coming up with london and listing all the months as wet and dry.. :sad:

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

const int maxrows=12;
const int maxcols=12;
const int maxchar=10;

static char place[maxrows][maxchar];
static char dummy[maxchar];
const char *months[12] = {"January","February","March","April","May","June","July","August","September","October","November","December"};
float rain[maxrows][maxcols];
float average, annual, wet, dry, total, lowval, highval, highindex, lowindex; 

FILE *fp;

main ()
{
    int i=0;
    if ((fp = fopen("data.txt", "r"))==NULL)
       printf("Error opening file\n");
    else
    {
        do
        {
            printf("\n\n");
            fscanf(fp,"%s",&dummy);
            if (strcmp(dummy, "ZZZZZ") !=0)
            {
                strcpy(place[i],dummy);
                printf("%10s", place[i]);
                annual=0;
                for (int j=0; j<maxrows; j++) 
                {
                    fscanf(fp,"%f",&rain[i][j]);
	                printf("\t%2.2f",rain[i][j]); 
	                annual=annual+rain[i][j];                      
	            }
	            
				printf("\tAnnual rainfall is %3.2f", annual);
	            i++;   
            }
        } while ((strcmp(dummy,"ZZZZZ") !=0) && (i<maxrows));
        // make a temp varable
        int tmp = i;
        printf("\n\nMonthly Average ");
        //for col 0 to last coll
        for (int j=0; j<tmp; j++)
        {
            annual=0;
            average=0;
            for (int i=0; i<maxrows; i++)
            { 
                annual=annual+rain[i][j];
            }
			average=annual/tmp;
			printf("%2.2f\t", average);
			
        }printf("\n\n");
    }
    for (int i=0; i < maxcols; i++)
    {
        lowval = 99999;
        highval = 0;
        
        if (strcmp("ZZZZZ", place[i])!=0)
        {
         
            for (int j=0; j<maxrows; j++)
            {
                if (rain[i][j] > highval)
                {
                    highval=rain[i][j];
                    highindex = j;    
                }
                
                if (rain[i][j] < lowval)
                {
                    lowval = rain[i][j];
                    lowindex = j;
                }
   
            printf("%10s\n", place[i]);
            printf("\tDry Month   : %s\t\tDry   :%.2f\n",months[i],lowval);
            printf("\tWet Month   : %s\t\tWet   :%.2f\n",months[j],highval);
            }
           } 
           
     
    fclose(fp);
    getchar();
           
 }
}

Just a note...

Is this line correct?
for (int j=0; j<maxrows; j++)
Should it be maxcols instead?

Take care,
Bruce

dello,

I have your code running on my computer. Take a look at how you are calculating the average. Is that what you really want?

Take care,
Bruce

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.