Google Answers Logo
View Question
 
Q: c programming assignment (fread()) ( Answered 4 out of 5 stars,   0 Comments )
Question  
Subject: c programming assignment (fread())
Category: Computers > Programming
Asked by: derekwtp-ga
List Price: $10.00
Posted: 19 Apr 2003 14:05 PDT
Expires: 19 May 2003 14:05 PDT
Question ID: 192776
I need help on an assignment on one of my online classes. This
assignment assumes that I know fread(). (it assumes to much) I really
dont know how to get started on this assignment, which bothers me
because it seems pretty simple, but I have been staring at my laptop
for a century already:)!!. Can someone please help me complete and get
started on this assigment?


The Assignment:
Write a program to read a binary file containing an "image". The image
consists of floating point numbers which represent the intensity of a
star in Watts/cm**2 (who cares what the numbers mean!). You must read
in the intensities to an array and compute 2 averages...

(sum of intensities) / (total number of values) 
and
(sum of intensities) / (total number of non-zero values)



we will call these pixel average and star average respectively. The
idea here is that a non-zero value represents a star. The program
should simply write these two averages to standard output.

You may assume the image is "square" (same number of rows as columns)
and get the size and file name from the command line using your parser
code. Use "star.img" and 256 as defaults if there are no values
entered on the command line. (note: since the image is "square", a
size of 16 would indicate 256 floating point values in the file)
Remember that the input files are binary. Use the file "test.001" (16
x 16) in the "Data" directory to test your program. You should get a
pixel average of 2.47e-12 and a star average of 7.19e-12 (unless I
goofed). Then run the program using test.002 (128 x 128) and show me
your results and source code.
Answer  
Subject: Re: c programming assignment (fread())
Answered By: dogbite-ga on 19 Apr 2003 15:08 PDT
Rated:4 out of 5 stars
 
Hello derekwtp-ga,

  The 'fread()' function, in the <stdio.h> library,
  is well documented.  Try googling for 'fread' or
  'fread example'.  Two that I like are:

http://developer.novell.com/ndk/doc/clib/index.html?page=/ndk/doc/clib/sngl_enu/data/sdk1077.html
  - has a nice, short example

http://www.qnx.com/developer/docs/momentics_nc_docs/neutrino/audio/wavec.html
  - much longer, but gives you a complete program.

  fread takes four arguments:

    - a data pointer where the new data from the
      file will be stored.  you need a pointer to
      a float.
    - the size of each data value to read.  here you
      want a size of a float.
    - the number of items (floats for you) to try to read.
    - pointer to the FILE.  you populate the pointer
      using fopen().

  The following code roughs out what you need.  The
  main loop reads in one floating point value at a time.


#include <stdio.h>

main()
{

  float sum_intensities = 0;
  int   total_values = 0;
  int   total_nonzero_values = 0;

  float new_value;
  int   result;
  FILE  *datafile;

  char  *filename;

  /* ADD CODE TO SET THE filename VARIABLE */

  /* open the file */
  datafile = fopen(filename, "r");

  /* this is the main loop. */
  result = 1;
  while (result) {

    /* fread will return 0 on error or end of file. */
    result = fread(&new_value, sizeof(new_value), 1, datafile);

    /* update the statistics with the new value in new_value */
    if (result == 1) {
      total_values++;
      sum_intensities += new_value;
      if (new_value > 0) {
        total_nonzero_values++;
      }
    }

  }

  /* we read in the entire file and have the statistics */
  /* in total_values, total_nonzero_values and sum_intensities */

}



  Hopefully that is sufficient to complete your assignment.

  dogbite-ga

Request for Answer Clarification by derekwtp-ga on 19 Apr 2003 18:31 PDT
my output looks like this

[root@localhost ten]# ./a.out test.001
avg_values 0.000000
avg_nonzero 0.000000
[root@localhost ten]# ./a.out test.002
avg_values 0.000000
avg_nonzero 0.000000
[root@localhost ten]# ./a.out sunset1.jpg
avg_values 0.000000
avg_nonzero 0.000000


I don't know why im not able to print the output.


#include <stdio.h>

main(int argc, char *argv[])
{

  float sum_intensities = 0;
  int   total_values = 0;
  int   total_nonzero_values = 0;
  int   avg_values = 0;
  int   avg_nonzero = 0;
  
  float new_value;
  int   result;
  FILE  *datafile;

  char  *filename;

  /* SET THE filename VARIABLE */
  filename=(argv[1]);
  
  /* open the file */
  datafile = fopen(filename, "r");

  /* this is the  loop. */
  result = 1;
  while (result) {

    /* fread will return 0 on error or end of file. */
    result = fread(&new_value, sizeof(new_value), 1, datafile);

    /* update the statistics with the new value in new_value */
    if (result == 1) {
      total_values++;
      sum_intensities += new_value;
      if (new_value > 0) {
        total_nonzero_values++;
      }
    }
    
  }
    avg_values= sum_intensities / total_values;
    avg_nonzero= sum_intensities / total_nonzero_values;
    printf ("avg_values %f\n",avg_values);
    printf ("avg_nonzero %f\n",avg_nonzero);

  
}

Clarification of Answer by dogbite-ga on 20 Apr 2003 15:49 PDT
Hi derekwtp-ga,

  Sorry for not getting back to you more quickly.

  You should change the avg_values and avg_nonzero
  variable declarations from ints to doubles.  I 
  would also change sum_intensities to a double to
  guard against overflow in the summation.

  So you want:

  double sum_intensities = 0;
  int   total_values = 0;
  int   total_nonzero_values = 0;
  double   avg_values = 0;
  double   avg_nonzero = 0;

  Please let me know if that helps you.

          dogbite-ga

Request for Answer Clarification by derekwtp-ga on 21 Apr 2003 19:29 PDT
Sorry I took so long i been trying to decipher what my instructor
means. Anyhow, he doesnt like the while loop:

  first, the whole point of loading data with an fread() is that
you don't have to convert it from ascii on disk to binary in
memory while the program is running.  So, you don't have to read
the data one at a time.  You read the entire file (array) with
one singe fread().  So get rid of the while loop.


saying:

 if you are reading 16*16 floats with the fread() then the
loop that computes the averages has to execute 16*16 times.
So, you know this ahead of time.
As for which loop, the only difference is that there is less
overhead for the for loop.  If you know ahead of time that
it has to execute 256 times, then you can use a for loop,
and you don't have to worry about incramenting a counter inside
the loop.
  Using a while loop in this case will make the program 
slower and less efficient, because the assembly code generated
for a while loop is uglier and slower.  In our work here it
certainly won't be noticable, but in a bigger program with
more data, it would make a difference.   Also, the for loop
is easier code to follow... all the guts are right there for
you.  And you can use the loop index for the array index.
It works out nice.


I have changed my code to a for loop and it doesnt work. I dont know
how to get it to work while getting the counters to increment.

any help and explanation would be great

Clarification of Answer by dogbite-ga on 21 Apr 2003 19:44 PDT
Hi derekwtp-ga,

  Okay, that's fine.  I made only a few small
  changes, as follows.  I do not have the data
  files that you do, so I cannot be sure that
  it works.  Here is the code though:





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

main(int argc, char *argv[])
{

  double sum_intensities = 0;
  int   total_values = 0;
  int   total_nonzero_values = 0;
  double   avg_values = 0;
  double   avg_nonzero = 0;

  float new_value;
  int   result;
  FILE  *datafile;

  char  *filename;
  int   img_rows;
  int   i;

  /* SET THE filename VARIABLE */
  filename=(argv[1]);
  img_rows=(atoi(argv[2]));


  /* open the file */
  datafile = fopen(filename, "r");

  /* this is the  loop. */
  result = 1;

  for (i = 0; i < img_rows; i++) {

    /* fread will return 0 on error or end of file. */
    result = fread(&new_value, sizeof(new_value), img_rows, datafile);

    /* update the statistics with the new value in new_value */
    if (result == img_rows) {
      total_values++;
      sum_intensities += new_value;
      if (new_value > 0) {
        total_nonzero_values++;
      }
    }
    else {
      printf("invalid file format (result = '%d')\n", result);
      exit(0);
    }


  }
  avg_values= sum_intensities / total_values;
  avg_nonzero= sum_intensities / total_nonzero_values;
  printf ("avg_values %f\n",avg_values);
  printf ("avg_nonzero %f\n",avg_nonzero);


}



       dogbite-ga

Request for Answer Clarification by derekwtp-ga on 23 Apr 2003 15:23 PDT
dogbite,

  I think what he is saying is that the fread() doesnt need to be in a
loop. In order to make that happen the new_value has to be a array.
Now in order to make this work format wise I get an error ten.c:65:
invalid operands to binary +

for sum_intensities += new_value; when I change this to a array. Also,
i couldnt get yours to compile and work right. You could use any image
file I found out. The notes abose said the input number is supposed to
be square.. Which i did but now i think my program still bites and I
dont know why. I am not getting values in my print statement ..instead
i am getting (without the array and w/ the fread() still in the loop)

[root@win186821wks ten]# ./a.out test.001 16
avg_values 0.000000
avg_nonzero 0.000000
Segmentation fault



/***************************************************************************
                          ten.c  -  description
                             -------------------
    begin                : Sat Apr 19 2003
    copyright            : (C) 2003 by Derek S. Winchester
    email                : dswinchester@winchester1.com
 ***************************************************************************/

/***************************************************************************
 *                                                                    
    *
 *   This program is free software; you can redistribute it and/or
modify  *
 *   it under the terms of the GNU General Public License as published
by  *
 *   the Free Software Foundation; either version 2 of the License, or
    *
 *   (at your option) any later version.                              
    *
 *                                                                    
    *
 ***************************************************************************/

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

main(int argc, char *argv[])
{

  double sum_intensities = 0;
  int   total_values = 0;
  int   total_nonzero_values = 0;
  double   avg_values = 0;
  double   avg_nonzero = 0;

  float new_value[400];
  int   result;
  FILE  *datafile;

  char  *filename;
  int   img_rows;
  int   i;
  int   size;

  /* SET THE filename VARIABLE */
  filename=(argv[1]);
  img_rows=(atoi(argv[2]));
  size= img_rows*img_rows;


  /* open the file */
  datafile = fopen(filename, "r");

  /* this is the  loop. */
  result = 1;



   
  for (i = 0; i < size; i++) {

    /* fread will return 0 on error or end of file. */
    result = fread(&new_value, sizeof(new_value), size, datafile);


   
    /* update the statistics with the new value in new_value */
    if (result == size) {
      total_values++;
      sum_intensities += new_value;
      if (new_value > 0) {
        total_nonzero_values++;
      }
    }
    /*else {
      printf("invalid file format (result = '%d')\n", result);
      exit(0);
    }    */


  }
  avg_values= sum_intensities / total_values;
  avg_nonzero= sum_intensities / total_nonzero_values;
  printf ("avg_values %f\n",avg_values);
  printf ("avg_nonzero %f\n",avg_nonzero);


} 

pleaes help..thanks

Clarification of Answer by dogbite-ga on 23 Apr 2003 15:33 PDT
Okay, let me take a look.

  Is there any way you make one
  of your image files web-accessible?
  Can you link one from a webpage?
  Then I could try it for sure.

  Also, this "not using fread() in a 
  loop" is a bit beyond the origional
  question's scope.  I understand the
  wants of professors though.  When we 
  get this all wrapped up, any tips would 
  be greatly appreciated!  :-)

          dogbite-ga

Request for Answer Clarification by derekwtp-ga on 23 Apr 2003 16:17 PDT
Okay dude I got it running. Can you help me w/ my parser code. I have
to add this ini the program..here is my program and the parser example
will follow..thanks in advance dog man.: )

/***************************************************************************
                          ten.c  -  description
                             -------------------
    begin                : Sat Apr 19 2003
    copyright            : (C) 2003 by Derek S. Winchester
    email                : dswinchester@winchester1.com
 ***************************************************************************/

/***************************************************************************
 *                                                                    
    *
 *   This program is free software; you can redistribute it and/or
modify  *
 *   it under the terms of the GNU General Public License as published
by  *
 *   the Free Software Foundation; either version 2 of the License, or
    *
 *   (at your option) any later version.                              
    *
 *                                                                    
    *
 ***************************************************************************/

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

main(int argc, char *argv[])
{

  double sum_intensities = 0;
  int   total_values = 0;
  int   total_nonzero_values = 0;
  double   avg_values = 0;
  double   avg_nonzero = 0;

  float new_value[400];
  int   result;
  FILE  *datafile;

  char  *filename;
  int   img_rows;
  int   i;
  int   size;

  /* SET THE filename VARIABLE */

  
  filename=(argv[1]);
  img_rows=(atoi(argv[2]));
  size = (img_rows*img_rows);




  /* open the file */
  datafile = fopen(filename, "r");

  /* this is the  loop. */
  result = 1;


    /* fread will return 0 on error or end of file. */
    result = fread(&new_value, sizeof(float), size, datafile);


   
  for (i = 0; i < size; i++) {

   
   
    /* update the statistics with the new value in new_value */
    if (result == size) {
      total_values++;
      sum_intensities += new_value[i];
            if (new_value[i] > 0) {
        total_nonzero_values++;
      }
    }
    else {
      printf("invalid file format (result = '%d')\n", result);
      exit(0);
    }    


  }
  avg_values= sum_intensities / total_values;
  avg_nonzero= sum_intensities / total_nonzero_values;
  printf ("avg_values %e\n",avg_values);
  printf ("avg_nonzero %e\n",avg_nonzero);
  printf ("total_values %e\n",total_values);
  printf ("total_nonzero_values %e\n",total_nonzero_values);


} 

[root@win186821wks c]# more parser.c
main(int argc, char** argv)
{
int age,month,maxargs,i;
char name[80];

/*(NOTE:  this may look overkill but please notice how easy
        it will be to add another command line option, or to
        add another 50 options!  If there is something
        you don't undestand, please mail me questions.
        I added the "main" stuff above and the printf()
        at the end, just so you can compile and run the
        program to see how it works.
*/
/*
current command line arguments:

         -n name          User's first name ("Sean" is default)
         -m month         integer month (default is "1" for January)
         -a age           integer age (default is "39" :) )
*/

 maxargs = 7;

/* check for too many command line arguments */
 if (argc > maxargs) {
   printf("Usage:  %s [-n name -m month -a age ]\n",argv[0]);
   exit(1);
 }

/* set default values */
 strcpy(name,"Sean");
 month = 1;
 age = 39;

 for (i=1;i<argc;i+=2) {

/* check for valid flags (first char should be '-' for flags) */
   if (argv[i][0]!='-') {
     printf("bad option character...should be \"-\"\n");
     exit(2);
   }

/* check for valid flag value and take appropriate action */
   switch (argv[i][1]) {
      case 'n': strcpy(name,argv[i+1]);
                break;
      case 'm': month = atoi(argv[i+1]);
                break;
      case 'a': age = atoi(argv[i+1]);
                break;
       default: printf("bad option...should be \"n\" or \"m\" or
\"a\"\n");
                exit(3);
                break;
   }
 }
printf("age = %d, month = %d, name = %s\n",age,month,name);
}

Clarification of Answer by dogbite-ga on 23 Apr 2003 16:18 PDT
Hey derekwtp-ga,

  Here is a new version of the program, 
  sans loop.  Another change is that I 
  added a threshold test for the non-zero
  value.  floats are rarely *zero* on the
  dot, and it seemed that very-near-zero
  values were being incorrectly counted as
  non-zero.

  I tried this on a few image files, and
  it worked for me.  Let me know how it
  works for you.

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

 main(int argc, char *argv[])
{

  double sum_intensities = 0;
  int   total_values = 0;
  int   total_nonzero_values = 0;
  double   avg_values = 0;
  double   avg_nonzero = 0;

  float *new_value;
  int   result;
  FILE  *datafile;

  char  *filename;
  int   img_rows;
  int   i;
  int   size;

  /* SET THE filename VARIABLE and number of image rows */
  filename=(argv[1]);
  img_rows=(atoi(argv[2]));
  size= img_rows*img_rows;

  /* malloc our array of floats */
  new_value = malloc(size * sizeof(float));

  /* open the file */
  datafile = fopen(filename, "r");

  /* this is the  loop. */
  result = 1;

  result = fread(new_value, sizeof(float), size, datafile);

  if (result == size) {
    total_values = size;
    for (i = 0; i < size; i++) {

      sum_intensities += new_value[i];

      //      if (new_value[i] != 0) {
      if ((new_value[i] <  0.0000001) &&
          (new_value[i] > -0.0000001)) {
        total_nonzero_values++;
      }
    }
  }
  else {
    printf("invalid file format (result = '%d')\n", result);
    exit(0);
  }

  //  printf("sum:\t\t%f\n", sum_intensities);
  //  printf("total: %d \nnonzero: %d\n", total_values, total_nonzero_values);
  avg_values= sum_intensities / total_values;
  avg_nonzero= sum_intensities / total_nonzero_values;
  printf ("avg_values\t %f\n",avg_values);
  printf ("avg_nonzero\t %f\n",avg_nonzero);


  /* free the memory we malloced */
  free(new_value);

}


     dogbite-ga

Request for Answer Clarification by derekwtp-ga on 23 Apr 2003 16:34 PDT
thanks dog..im hoping you saw my last input before yours

Clarification of Answer by dogbite-ga on 23 Apr 2003 16:48 PDT
hey derekwtp,

  can you be more specific on what
  you want?  what command line options
  is it supposed to accept?

         dogbite-ga

Request for Answer Clarification by derekwtp-ga on 23 Apr 2003 18:48 PDT
like if I do a ./a.out img.file 16 or if I do a ./a.out 16 img.file
..both would be accepted .. or if I do  just a ./a.out it would take a
default like test.001 file. That is very tough to do i think

Clarification of Answer by dogbite-ga on 23 Apr 2003 20:23 PDT
Hey derekwtp-ga,

  I'd be happy to add some basic command-line
  option handling for you.  Could you please
  post it as another question though?  I feel
  it is too far beyond the scope of this question.
  Just put "For dogbite-ga ONLY" in the title, 
  and I'll grab it.

         dogbite-ga
derekwtp-ga rated this answer:4 out of 5 stars and gave an additional tip of: $5.00

Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy