-------------------------------------------------------------------------- * * * AMIGA 'C' FOR BEGINNERS * * * * TYPED IN BY RAZOR BLADE OF ALLIANCE . * * * * GREETS TO :- VIPER , BLACKBEARD , ARAMIS , CHAOS , MIT , SHADOWFAX * * AND THE ALCHEMIST. * *------------------------------------------------------------------------* -------------------------------------------------------------------------- --------------------------------------------------------------------------- CHAPTER 12 - FUNCTIONS. You read in the introduction that a C program sometimes consists of many different functions. Up to now only one has been defined (the MAIN function). Its time to start writing programs which contain several functions developed by you. FUNCTION STRUCTURE First the formal structure of a function definition. You must specify the function name, preceeded by the data type returned by the function. The name must correspond to the usual rules for variable name. Parenthesis containing the arguments follow the name. If no such values exist (e.g. the MAIN function) none can be indicated. If such arguments are expected, these variables must be declared. The values are important since most functions get information from other functions which are then processed. Then follow the executable commands, also enclosed in parenthesis. Let's look again at a simple version of the MAIN function : main() { .. .. } The first item to be encountered according to the specification is the data type which the function returns. Since the MAIN function doesnt return any values to the calling program, the data type is omitted. The word VOID usually appears preceeding a function that returns nothing. Next the function name (main) is specified, followed by a pair of parenthesis. Since no values are passed to the main program, no data appears between the parenthesis. The variable declaration is also omitted, since nothing is passed. Then follow the other executable instructions within the braces, which up to now was the complete executable program. PAGE 105 -------------------------------------------------------------------------- 12.1 FUNCTIONS WITH ARGUMENTS. The next step is to dissect the program into individual tasks. You can write a short function for every partial task. For example, a function to compute the square of a value requires no great mathematical training : double square(x) float x; { double q_number; printf("The square of %f\n is ", x); q_number = x * x; return q_number; } THE SQUARE FUNCTION : The above routine defines a function named SQUARE which in turn returns a double value to the calling program. As a parameter to be passed, a FLOAT value called x is required. At the end of the routine a new C keyword appears, the RETURN keyword. It delivers the required result of the specified data type to the caller and also ends the function. It is important that no semi-colon follows the function name. There must be a semi-colon after each parameter declaration. This differentiates a function definition (without semicolon) from a function call (with semicolon). The following line identifies that a function named square is to be used by the main program : double square(); main() { float value = 3.0; double result; ............ ............ result = square(value) } The names of the parameters passed by the calling function need not be identical to those of the called function. However, the data types must be the same. Notice that the line in which the square function is declared as a function which returns a DOUBLE value. PAGE 106 --------------------------------------------------------------------------- The declaration can be omitted if integer values are returned. The same is true for the definition of a function. If the function returns integer values, a data type need not preceed the function name. This is only possible with the data type INT. All other types must be declared and supplied with the proper data type during the definition. If one of these data types is contradictory (perhaps because the declaration forgot a DOUBLE function) the resulting values will be wrong. While the C language permits much freedom to the programmer, this can cause much trouble. PAGE 107 --------------------------------------------------------------------------- 12.2 FUNCTIONS WITHOUT RETURN VALUES. Some functions return no values. These functions can be declared as VOID, if the compiler has implemented this keyword. This can improve the speed somewhat since the parameters need not be prepared for the calling function. Even that may be omitted, which is the reason why some C compilers dont define the VOID type. /* key.c 12.2 */ void key(string) /* without return value -- void */ char string[80]; { int i; for (i=0; string[i] > 0;i++) printf("%c", string[i]+1); /* from 'a' makes 'b'*/ } void main() { char text[81]; void key(); printf("please input some text\n"); scanf("%80s",text); key(text); printf("in the original it was %s\n",text); } The new defined functions are called exactly like the routines from the libraries. In this example the MAIN function stands at the end of the file. The routine names KEY is declared as a function which returns nothing or VOID. That is important since the definitions would contradict themselves during usage in MAIN. If the function had not been declared the compiler would assume that it should return INT objects. It returns nothing. PAGE 108 --------------------------------------------------------------------------- 12.3 OTHER FUNCTIONS. Another function which does not require a result is STRCPY. This routine copies strings, and performs general string handling. Even though its included in every C compilers library file, it is interesting to see how it can be programmed. 12.3.1 STRCPY - VERSION 1 This copies one string to another. Unlike the previous example, you dont know how many entries are in each string. This can be omitted. It is enough for the compiler to know that it will get a string. In the routine itself, a counter tests all entries. They are copied until the routine reaches the EOS character (the end character which must also be transmitted). #define EOS '\0' strcpy(to,from) char to[], from[]; { int i = 0; while((to[i] = from[i]) != EOS) i++; } The function is indifferent to the memory requirements of the array, since it doesnt have to set aside any memory. The STRCPY works directly with the strings passed to it from the calling function. The strings may be of different lengths. What do you think of the terminiation conditions in the WHILE loop?. The position of the parenthesis makes the processing clear. First it is the assignments of from[i] to to[i]. The expression in the parenthesis also has the value from[i], and also the character which was copied. This is now compared with the end code character. If you copy the EOS, the condition is no longer true and the loop terminates. Otherwise it increments the current counter and remains in the loop. PAGE 109 -------------------------------------------------------------------------- The actual loop body has only a peripheral role. The main action occurs in the ending conditions. Experiment with this function. Notice that the string into which the copy is stored appears first. Here is a complete example program : /* copysrt.c 12.3.1 */ #define EOS '\0' #define MAXLEN 81 strcpy(to,from) char to[], from[]; { int i = 0; while((to[i] = from[i]) != EOS) i++; } void main() { char s1[MAXLEN], s2[MAXLEN], s3[MAXLEN]; printf("Your name please\n"); scanf("%40s",s1); strcpy(s3,s1); strcpy(s2, "TEXT in s2"); printf("Therefore %s, in s2 is \"%s\".", s1,s2); printf("I hope %s, that everything is clear!\n",s3); } The STRCPY function can be used to initialise strings since the following expression is not permitted in C : WRONG: main() { char text[20] = "This_is_text!"; . . . . . . } RIGHT: main() { char text[20]; strcpy(text,"This_is_text!"); . . . . . } This copies the complete string into the variable text. PAGE 110 -------------------------------------------------------------------------- 12.3.2 STRLEN. You used the STRLEN function earlier in this book. It is simple to write and return a value. The passed length of the string is a whole number and should be an integer value. strlen(string) char string[]; { int i = 0; while(string[i]) i++; return(i); } A nice short function! The expression string[i] is always the content of this element. This means that the expression is only 0 (false) when the end character \0 (EOS) has been reached. The counter which corresponds to the length of the string passes to the calling function as an integer value through a return directive. This function doesnt have to be declared in the calling function because it returns an INT value. If the return directive passes data, it must be assured that the value has the proper data type. If the function definition states that the routine returns a CHAR element, there should be a variable or constant of the CHAR type. Some compilers will not tolerate such mistakes and will issue an errror message. Others are indifferent and convert the result into the data type indicated in the definition. Its better to do it right in the first place. PAGE 111 -------------------------------------------------------------------------