[Courses] C Programming For Absolute Beginners, Lesson 5A: All About Functions, Part 2

Carla Schroder carla at bratgrrl.com
Tue Apr 3 14:26:17 UTC 2012


Excellent and practical, thanks!

Carla


On Tuesday, April 03, 2012 11:18:47 PM Jacinta Richardson wrote:
> Adding to the pile.
> 
> On 02/04/12 15:06, Carla Schroder wrote:
> > C Programming For Absolute Beginners, Lesson 5A: All About Functions,
> > Part 2
> > 
> > Functions are called from other functions, and perform specific tasks.
> > If you find that a function you are writing is getting fat and
> > unwieldy, it might be a sign to re-think what you're trying to make it
> > do. Functions make it possible to write nice modular programs that are
> > easier to understand and modify.
> The example I usually share with my students is this.  Think about what
> steps are required to make a cup of instant coffee.  I then ask the
> students to help me brain storm the steps, it usually ends up with
> something like this:
> 
>      1. Assemble everything (cup, spoon, coffee, kettle, milk, water etc)
>      2. Put water in the kettle and boil [*]
>      3. Put coffee in cup
>      4. Pour hot water into cup [*]
>      5. Add milk (if desired) [*]
>      6. Stir [*]
> 
> Here we've broken down the task into 6 steps (we could have a few more or a
> few less).  What is more, the ones which have asterisks all apply to making
> tea, or hot chocolate, too!  So we could write (using pseudo-code):
> 
>     // I know that this is not an appropriate argument for main() it's
>     pseudocode, I'm cheating.
>     yummybeverage main(sometype beverage_selection) {
> 
>          // gather all the things together:
>          sometype kettle;
>          sometype water;
>          sometype boiling_water;
>          sometype cup;
>          sometype milk;
>          sometype spoon;
> 
>          // boil the kettle
>          kettle = add_to(water, kettle);
>          boiling_water = boil(kettle);          // in Australia we have
> electric kettles that sit on your counter top
> 
>          // add stuff to the cup
>          cup = add_to(beverage_selection, cup);
>          cup = add_to(water, cup);
> 
>          if(milk is wanted) {
>              cup = add_to(milk, cup);
>          }
> 
>          // stir and we're done.
>          cup = stir_with(cup, spoon);
>          return cup;
>     }
> 
> 
> So here we'd need to work out what types things are and write a few
> subroutines and we have something that can make tea, coffee or hot
> chocolate.  :)
> > ========================
> > 
> > #include<stdio.h>
> > 
> > void multiplynumbers (int, int);
> > 
> > int main (void)
> > {
> > 
> >    multiplynumbers(10,11);
> >    return 0;
> > 
> > }
> > 
> > void multiplynumbers (int a, int b)
> > {
> > 
> >    int total;
> >    total = a * b;
> >    printf ( "%d times %d equals %d.\n",a,b,total);
> > 
> > }
> > 
> > =========================
> 
> Calling functions for the things they do, rather than the things they
> return, is called "relying on their side-effects".  This isn't inherently
> bad, we rely on the side effects when we call printf() all the time (it
> prints stuff for us, we don't really care what it returns (although perhaps
> we should)).  However, we have to be careful to name our functions to give
> the casual reader of our code a hint of what the side effect we're relying
> on does.  For example, in the code above, "multiplynumbers" doesn't *sound*
> like the kind of function that's going to print something to the screen. 
> So if you were to see the main code, and not be able to immediately see
> multiplynumbers() nearby (perhaps it's in another file), you might wonder
> why it's return value was being ignored, because it looks like a function
> that should be *doing* something and thus *returning* something.
> 
> There is a slightly related issue called "action from a distance" where
> errors (and other interesting conditions) can propagate through your code
> and cause problems in unexpected places.  For example if we open a file,
> and then pass the file handle to a subroutine, without checking that the
> file opened successfully, then in the situation when the file did not open
> successfully, the error will come from within our subroutine (which is a
> distance from where the error occurred).  eg:
> 
>      int main(void) {
>          ...
>          FILE *fh;
>          fh = fopen("somefile.txt", "r"); // fopen returns a false value on
> failure, we really should check it
> 
>          // but we're not going to
>          somefunction(fh);
>          ...
>      }
> 
>      // then later
>      int somefunction(FILE *fh) {
>          char * string;
> 
>          string = fgets(fh);  // This is where the error happens if we
> didn't succeed in opening the file
>          ...
>      }
> 
> It helps to be aware of these issues.
> 
>      J
> _______________________________________________
> Courses mailing list
> Courses at linuxchix.org
> http://mailman.linuxchix.org/mailman/listinfo/courses
-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Carla Schroder
ace Linux nerd
author of Linux Cookbook,
Linux Networking Cookbook,
Book of Audacity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


More information about the Courses mailing list