[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