Functions

February 4 2002

announcements

you should read over the expectations for your labs that are posted on the cs5a website... most importantly, if you don't have a header at the top of your program, you will receive zero points!

you guys have a midterm coming up in a week and a half... there will be a review session at some point. we'll send you email when figure out where and when it will be.

updates to the generic program framework for this class

your programs should look like this:

/* header goes here: author, date, description, etc */

#include<stdio.h>

/* symbolic constants are defined here [#define...] */

/* function prototypes go here */

void main()
{
  /* interesting stuff goes here */
}

/* function definitions go here */

defining functions

here's a simple function:

/* prototype */
int square(int x);

/* function definition */
int square(int x) 
{
  return(x*x);
}

this function takes one integer as input, and returns the number squared. let's go through the parts of this function one piece at a time. the very first int specifies that the function will return an integer. next, we say what our function is called, in this case, square. after that, we specify the inputs to our function. in our case, int x means that we want one integer as input, and we're going to refer to that integer as x in the body of the function. after we specify the inputs, we have the body. the special keyword return tells the computer that the function is to return the value in the parentheses as its output.

note that the computer will stop a function when it processes a return statement. consider the following function:

int get_positive_int()
{
  int x;
  while(1)
  {
    printf("please enter a positive integer: ");
    scanf("%d", &x);
    if(x > 0)
      return(x);
  }

  return(-1);
}

the while(1) is an infinite loop, but the return "breaks out" of the loop and returns x to the caller of the function when x is positive. we put the return(-1) at the end, because the compiler requires us to return something at the end of our function [the compiler isn't smart enough to realize that the while(1) is an infinite loop, unfortunately].

to define a function that takes no inputs, leave the parentheses after the name of the function empty. for example:

/* prototype */
int no_inputs();

/* actual definition */
int no_inputs()
{
  int x;
  scanf("%d", &x);
  return(x*x);
}

this function reads input from the user, instead of whoever called the function.

to define a function that has no output, use void as the return type. for example:

/* prototype */
void no_output(int x);

/* actual definition */
void no_output(int x)
{
  printf("%d", x*x);
}

this function outputs to the user, instead of to whoever called the function. note that return is not needed in function with no output.

using functions

after you define a function, you can use it as many times as you want. for example:

/* prototype */
int square(int x);

void main()
{
  int x;
  int y;
  
  scanf("%d %d", &x, &y);
  printf("%d\n", square(x)+square(y));
}

/* function definition */
int square(int x) 
{
  return(x*x);
}

in this program, we declare the function square, and in main, we call it twice. note that the variable x in main, and the variable x in square are two different variables! each function [main is also a function] has its own set of variables.

so what can functions do for me?

the great thing about functions is that once you define one, you can use it all you want, and you don't have to think about how it works anymore. a great example of this power is printf. we have no clue how printf works [trust me, it's gross, you don't want to know], but we use it all the time, and it's great. functions are the key to building complex programs: if we write functions to do common tasks, we don't have to worry about how to do the common tasks anymore, and we can focus our efforts on programming new things. for example, think about how hard it would be to write last week's lab if you couldn't use printf or scanf. this idea ["set it and forget it"] is called abstraction by computer science people. it's a great word to throw around when you feel the need to impress people.

call by value

c uses call by value for function calls. this means that when a function is called, the function receives copies of the arguments. this is best explained with an example:

void swap(int x, int y);

void main()
{
  int x;
  int y;
 
  scanf("%d %d", &x, &y);
  swap(x, y);
  printf("in main: x=%d y=%d\n", x, y);
}

void swap(int x, int y)
{
  int tmp;
  
  tmp = y;
  y = x;
  x = tmp;
  printf("in swap: x=%d y=%d\n", x, y);
}

suppose we run this program, and we type in 3 4. the program will output

in swap: x=4 y=3
in main: x=3 y=4

because the swap function receives copies of the 3 and the 4, and exchanges the copies. we print the values of the copies at the end of swap. when we return to main, we print the values of the original x and y, which are still 3 and 4.

exercises

write functions that compute exponents and factorials.

write a function display_asterisks that takes an integer as input, and displays that number of asterisks on the screen, all on one line.

write a function display_box that takes two integers, height and width, and displays a box of asterisks on the screen of the appropriate height and width. write the function so it displays a solid box first, then write another version that only draws the borders [top, bottom, left, and right] of the box.