how to organize my main file ?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • pereges

    how to organize my main file ?

    By main file, I mean the one which contains the main routine. Can some
    one please provide suggestions as to how I can improve the
    organization of main file ? I have just though about a rough skeleton.

    In my ray tracing project, I have to carry out following task (in
    sequence)

    1. Read the mesh from an ascii file and store it in the mesh data
    structure.
    2. Create a ray list and store it in a ray list.
    3. Create the binary space partitioning tree for fast mesh traversal.
    4. Trace all the rays and calculate the scattered and incident
    electric fields.

    I'm thinking of writing a function for every task.

    #include "main.h"

    static mesh *m; /* pointer to the mesh */
    static bsptree *tree; /* pointer to the bsp tree */
    static ray *raylist; /* pointer to the ray list */

    /* function prototypes */

    int read_mesh(char *);
    int init_plane_wave (void);
    int create_bsp_tree (void);
    int calc_e_fields (void);


    /* Provide the name of the ascii file(from which mesh is to be read)
    as a command line argument eg. main sphere.dat */

    int main(int argc char *argv[])
    {
    if(argc < 2)
    {
    fprintf(stderr, "Insufficie nt argumens\n");
    return -1;
    }

    if(argc 2)
    {
    fprintf(stderr, "Too many arguments\n");
    return -1;
    }

    if(read_mesh(ar gv[1])
    return -1;
    if(init_plane_w ave())
    return -1;
    if(create_bsp_t ree())
    return -1;
    if(calc_e_field s())
    return -1;

    return 0;
    }

    /* I decided to make the above data structures as static global
    because they are needed throughout the program */

    int read_mesh(char *filename)
    {
    FILE *fp;

    fp = fopen(filename, "r");
    if(fp == NULL)
    {
    fprintf(stderr, "Error while opening the file %s\n", filename);
    return -1;
    }
    m = malloc(sizeof *m);
    if(m == NULL)
    {
    fprintf(stderr, "Couldn't allocate memory for the mesh\n");
    return -1;
    }
    /* parse_dat_file returns -1 if error occured while parsing file */
    if(parse_dat_fi le(fp, &m))
    return -1;
    }

    /* This function will initiailize the plane as in read the
    specification related to a plane wave like frequency, electric field
    at reference point, direction of the plane wave etc. It will allocate
    memory for the ray list. After this it will call init_rays which
    initializes a set of parallel rays. A plane wave is being simulated by
    a dense grid of parallel rays */

    int init_plane_wave (void)
    {
    ...
    ...
    }

    /* This function will read the maximum allowable depth for the tree ,
    allocate memory for it*/

    int create_bsp_tree (void)
    {

    }

    /* This function will call the raytrace function and after that it
    will perform some calculations to find out the scattered and incident
    electric fields */

    int calc_e_fields (void)
    {

    }

  • pereges

    #2
    Re: how to organize my main file ?

    I have another question: Is it ok to write a function to destroy all
    the objects(Its not just a simple 'free' call btw, there are lists
    within objects which must be destroyed first)

    Comment

    • Walter Roberson

      #3
      Re: how to organize my main file ?

      In article <66ed9e1f-214a-4706-8321-e2d6e4d47666@y2 2g2000prd.googl egroups.com>,
      pereges <Broli00@gmail. comwrote:
      >I have another question: Is it ok to write a function to destroy all
      >the objects(Its not just a simple 'free' call btw, there are lists
      >within objects which must be destroyed first)
      Sure, why not? As long as the objects are dynamically allocated, that is.
      --
      "MAMA: Oh--So now it's life. Money is life. Once upon a time freedom
      used to be life--now it's money. I guess the world really do change.
      WALTER: No--it was always money, Mama. We just didn't know about it."
      -- Lorraine Hansberry

      Comment

      • Richard Heathfield

        #4
        Re: how to organize my main file ?

        pereges said:
        By main file, I mean the one which contains the main routine. Can some
        one please provide suggestions as to how I can improve the
        organization of main file ? I have just though about a rough skeleton.
        >
        In my ray tracing project, I have to carry out following task (in
        sequence)
        >
        1. Read the mesh from an ascii file and store it in the mesh data
        structure.
        2. Create a ray list and store it in a ray list.
        3. Create the binary space partitioning tree for fast mesh traversal.
        4. Trace all the rays and calculate the scattered and incident
        electric fields.
        >
        I'm thinking of writing a function for every task.
        It seems to me that tasks 1-3 might reasonably be called initialisation.
        Task 4 appears to be the bit that does the useful processing.

        A function for every task is always a good idea, but why not abstract your
        first three tasks into a function called initialise() or something like
        that. It might look something like this:

        #include "whatever.h "

        int initialise(cons t char *infile)
        {
        int rc = read_mesh(infil e); /* change read_mesh() to take const char *
        */
        if(0 == rc)
        {
        rc = init_plane_wave ();
        }
        if(0 == rc)
        {
        rc = create_bsp_tree ();
        }
        return rc;
        }

        and then main would look something like this:

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

        int main(int argc, char **argv)
        {
        int result = EXIT_FAILURE;

        if(argc != 2)
        {
        printf("%s arguments\n", argc < 2 ? "Insufficie nt" : "Too many");
        }
        else
        {
        if(0 == initialise(argv[1]))
        {
        if(0 == calc_e_fields() )
        {
        result = EXIT_SUCCESS;
        }
        }
        }
        return result;
        }

        You might want to put main() and initialise() in one source file (your
        "main file" as you call it), the initialisation routines (read_mesh and
        the other two) in, say, initialise.c, and the calcs in calcs.c - this will
        help to keep each source file down to a manageable size and make things
        easier for you to find.

        Note that a -1 return value from main isn't guaranteed to be meaningful,
        whereas EXIT_FAILURE is.

        <snip>

        --
        Richard Heathfield <http://www.cpax.org.uk >
        Email: -http://www. +rjh@
        Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
        "Usenet is a strange place" - dmr 29 July 1999

        Comment

        • pereges

          #5
          Re: how to organize my main file ?

          On Jun 17, 9:13 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
          It seems to me that tasks 1-3 might reasonably be called initialisation.
          Task 4 appears to be the bit that does the useful processing.
          >
          A function for every task is always a good idea, but why not abstract your
          first three tasks into a function called initialise() or something like
          that. It might look something like this:
          >
          #include "whatever.h "
          >
          int initialise(cons t char *infile)
          {
          int rc = read_mesh(infil e); /* change read_mesh() to take const char *
          */
          if(0 == rc)
          {
          rc = init_plane_wave ();
          }
          if(0 == rc)
          {
          rc = create_bsp_tree ();
          }
          return rc;
          >
          }
          >
          and then main would look something like this:
          >
          #include <stdio.h>
          #include <stdlib.h>
          #include "whatever.h "
          >
          int main(int argc, char **argv)
          {
          int result = EXIT_FAILURE;
          >
          if(argc != 2)
          {
          printf("%s arguments\n", argc < 2 ? "Insufficie nt" : "Too many");
          }
          else
          {
          if(0 == initialise(argv[1]))
          {
          if(0 == calc_e_fields() )
          {
          result = EXIT_SUCCESS;
          }
          }
          }
          return result;
          >
          }
          >
          You might want to put main() and initialise() in one source file (your
          "main file" as you call it), the initialisation routines (read_mesh and
          the other two) in, say, initialise.c, and the calcs in calcs.c - this will
          help to keep each source file down to a manageable size and make things
          easier for you to find.
          Thanks, I think this is a very good idea but I think the calcs.c file
          will not span more than 30-40 lines. But I think it is better this way
          because later on if there is a requirement to calculate some other
          things(eg. surface currents, magnetic fields , whatever etc), then all
          that code can go into this file.
          Note that a -1 return value from main isn't guaranteed to be meaningful,
          whereas EXIT_FAILURE is.
          >
          Why ?
          I have seen that everytime a C program fails, the process returns some
          non zero value(Pelles C compiler reports this). So what is wrong in
          returning -1 ? Is this only applicable to main function or others as
          well ? I usually use

          #define SUCCESS 0
          #define FAILURE -1

          as return values for functions other than main.

          Comment

          • santosh

            #6
            Re: how to organize my main file ?

            pereges wrote:
            On Jun 17, 9:13 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
            <snip>
            >Note that a -1 return value from main isn't guaranteed to be
            >meaningful, whereas EXIT_FAILURE is.
            >
            Why ?
            Because the C standard says so.
            I have seen that everytime a C program fails, the process returns some
            non zero value(Pelles C compiler reports this).
            Perhaps, but what a C program returns to the host system after it has
            finished (or to be more precise, what value your system indicates that
            the program has returned) is not specified by the standard, and
            therefore your observations may not be valid for one or more systems.

            What the standard does specify is what value you can portably use as an
            argument to the exit function or as an expression with the return
            keyword. These are 0 or EXIT_SUCCESS to indicate that the program has
            terminated normally or EXIT_FAILURE to indicate that the program has
            terminated abnormally. Note that the value that the host system may
            report to you as the termination status code of your program need not
            match the value that you supplied to exit or return. The C runtime code
            can perform translations on this value to ensure compatibility with the
            protocols of the host environment.

            IOW, there could exit a system where -1 indicates successful
            termination. This would render your code broken. On the other hand if
            you use EXIT_FAILURE in the place of -1 your program would work
            correctly on all systems which are fully conforming to the C standard.
            So what is wrong in
            returning -1 ? Is this only applicable to main function or others as
            well ?
            Yes.
            I usually use
            >
            #define SUCCESS 0
            #define FAILURE -1
            >
            as return values for functions other than main.
            In C zero is taken as boolean false and any other value is taken as
            boolean true. Your macros above conflict against this, but in this
            respect, so does a lot of C code including portions of the standard
            library. Also the convention for functions is that a return of zero
            indicates successful completion and a non-zero return indicates
            unsuccessful completion.

            I would much rather use C99's bool type rather than these macros, as
            they are much abused and will merely confuse anyone reading your code.

            Comment

            • Mike Wahler

              #7
              Re: how to organize my main file ?

              "pereges" <Broli00@gmail. comwrote in message
              news:6644f7d0-7433-475d-b993-12569ffde6c4@j3 3g2000pri.googl egroups.com...
              On Jun 17, 9:13 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
              >
              >Note that a -1 return value from main isn't guaranteed to be meaningful,
              >whereas EXIT_FAILURE is.
              >>
              >
              Why ?
              I have seen that everytime a C program fails, the process returns some
              non zero value(Pelles C compiler reports this). So what is wrong in
              returning -1 ?
              It's not really 'wrong', it's simply not standard (thus
              not portable). The only return values for main() which
              are guaranteed to be portable (to a standard-conforming
              implementation) are zero (0), or one of the macros
              'EXIT_SUCCESS' or 'EXIT_FAILURE'. These macros are
              defined in standard header <stdlib.h>. Their actual
              values can and do vary among implementations , so you
              could get different behavior with a different implementation
              and/or platform.

              If you're using a compiler which conforms to the most
              recent (1999) C standard, you can omit the return
              statement entirely, whereupon the program will behave
              as if a 'return 0' were written. While perfectly valid,
              many folks still frown upon doing this, and would rather
              see an explicit return statement to make things perfectly
              clear.
              Is this only applicable to main function or others as
              well ?
              The above requirements I cited for a portable return value
              apply to the 'main()' function, and I believe also the
              'exit()' function. You can do whatever you like with your
              own functions (subject, of course, to language rules).

              >I usually use
              >
              #define SUCCESS 0
              #define FAILURE -1
              Don't Do That. You've redefined standard macros. I'm
              not sure what the standard says about the behavior here,
              it could be undefined. Use the 'framework' provided by
              the implementation, e.g. standard constructs such as
              'EXIT_FAILURE'. If you try to circumvent or change their
              intended behavior, imo you've just introduced potential
              problems for no good reason.

              -Mike


              Comment

              • Kenny McCormack

                #8
                Re: how to organize my main file ?

                In article <6-ydnYRLIKsBb8rVn Z2dnUVZ_oTinZ2d @earthlink.com> ,
                Mike Wahler <mkwahler@mkwah ler.netwrote:
                >"pereges" <Broli00@gmail. comwrote in message
                >news:6644f7d 0-7433-475d-b993-12569ffde6c4@j3 3g2000pri.googl egroups.com...
                >
                >On Jun 17, 9:13 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
                >>
                >>Note that a -1 return value from main isn't guaranteed to be meaningful,
                >>whereas EXIT_FAILURE is.
                >>>
                >>
                >Why ?
                >I have seen that everytime a C program fails, the process returns some
                >non zero value(Pelles C compiler reports this). So what is wrong in
                >returning -1 ?
                >
                >It's not really 'wrong', it's simply not standard (thus
                >not portable). The only return values for main() which
                In this newsgroup, "wrong" and "not standard" are synonymous.
                See also "morally bankrupt".

                Comment

                • pereges

                  #9
                  Re: how to organize my main file ?

                  So, EXIT_FAILURE and EXIT_SUCCESS can be used in any function other
                  than main. Mostly I have seen that they are not used outside main.


                  Comment

                  • santosh

                    #10
                    Re: how to organize my main file ?

                    pereges wrote:
                    I have another question: Is it ok to write a function to destroy all
                    the objects(Its not just a simple 'free' call btw, there are lists
                    within objects which must be destroyed first)
                    I assume you will be calling such a function either just before program
                    termination or after a major task has been completed. As long as it
                    does not free memory still in use, or try to free nonexistent memory,
                    it should be functionally okay. Whether such a strategy will suit your
                    application depends on many other factors.

                    Comment

                    • pereges

                      #11
                      Re: how to organize my main file ?

                      On Jun 17, 11:12 pm, santosh <santosh....@gm ail.comwrote:
                      I assume you will be calling such a function either just before program
                      termination or after a major task has been completed.
                      just before the termination. The last function to be called.
                      As long as it
                      does not free memory still in use, or try to free nonexistent memory,
                      it should be functionally okay. Whether such a strategy will suit your
                      application depends on many other factors.
                      like for eg. ? mine is a pretty straight forward numerical computation/
                      simulation program. I was also wondering what is the point in freeing
                      the dynamic memory just before the program terminates because the
                      objects will be destroyed once the program terminates anyways.

                      Comment

                      • santosh

                        #12
                        Re: how to organize my main file ?

                        pereges wrote:
                        So, EXIT_FAILURE and EXIT_SUCCESS can be used in any function other
                        than main.
                        You can do so, as long as you are internally self consistent, but this
                        is rare. It is more common to return either zero or one. Which of these
                        is used to signal success and which one failure really depends on local
                        convention. All that matters is consistency.

                        For example you could have a function return the int value 1 for success
                        and zero for failure. Then you might test a function like this:

                        if (!do_foo()) {
                        /* handle error */
                        }

                        The code for the reverse situation might be like:

                        if (do_foo()) {
                        /* handle error */
                        }

                        Note that this method allows for multiple error codes, which is usually
                        convenient.

                        It's common (and more robust) to define an enumeration for default
                        success and failure and typedef the enum. You can also use #define
                        macros as you did above.

                        You might also want to use C99's bool type.

                        For functions returning pointer values, usually a return of NULL
                        indicates failure.
                        Mostly I have seen that they are not used outside main.
                        No. It's customary for most non-trivial applications to have their own
                        error handling conventions. It's more work up-front, but pays off as
                        the complexity of the program grows.

                        Comment

                        • Mike Wahler

                          #13
                          Re: how to organize my main file ?


                          "pereges" <Broli00@gmail. comwrote in message
                          news:3d7fa0e0-d8a6-4095-8bf5-ecd84db05b53@z2 4g2000prf.googl egroups.com...
                          So, EXIT_FAILURE and EXIT_SUCCESS can be used in any function other
                          than main.
                          That's not what I said, but they could be. They are
                          intended to be used to communicate a program's completion
                          status (i.e. success or failure) to the host system, thus
                          typically used only with 'main()' or 'exit()'. I've never
                          seen them used for anything else, but that doesn't mean
                          someone never did. :-)

                          Mostly I have seen that they are not used outside main.
                          True.

                          -Mike


                          Comment

                          • Mike Wahler

                            #14
                            Re: how to organize my main file ?


                            "pereges" <Broli00@gmail. comwrote in message
                            news:5cb3c33a-bcbd-4c5a-a648-651693d0c172@c1 9g2000prf.googl egroups.com...
                            On Jun 17, 11:12 pm, santosh <santosh....@gm ail.comwrote:
                            >
                            >I assume you will be calling such a function either just before program
                            >termination or after a major task has been completed.
                            >
                            just before the termination. The last function to be called.
                            >
                            >As long as it
                            >does not free memory still in use, or try to free nonexistent memory,
                            >it should be functionally okay. Whether such a strategy will suit your
                            >application depends on many other factors.
                            >
                            like for eg. ? mine is a pretty straight forward numerical computation/
                            simulation program. I was also wondering what is the point in freeing
                            the dynamic memory just before the program terminates because the
                            objects will be destroyed once the program terminates anyways.
                            Most modern operating systems will indeed reclaim allocated memory
                            upon termination of an application, but the language does not
                            guarantee this (it cannot, since C can be implemented on a platform
                            with no OS ('free-standing implementation' ). IMO the best practice
                            is to do as my mother used to tell me, "put things back the way you
                            found them." IOW if you allocate a resource, free it when you're done.

                            -Mike



                            Comment

                            • santosh

                              #15
                              Re: how to organize my main file ?

                              pereges wrote:

                              [ ... ]
                              I was also wondering what is the point in freeing
                              the dynamic memory just before the program terminates because the
                              objects will be destroyed once the program terminates anyways.
                              It will reduce the number of false positives that memory checkers like
                              Valgrind will report. It's also better form, even though it may not be
                              necessary under modern operating systems.

                              Comment

                              Working...