Example : The following prints the sine table or the cosine table,
#include <stdio.h>
#include <math.h>
int main()
{ double (*fa)();
double x, dumx;
char buffer[1000];
int iwhich;
char *ptr[2]={"sin", "cos"};
L20:
printf("Do you want to print the sine table (1) or cosine table (2) ? ");
gets(buffer);
sscanf(buffer,"%d",&iwhich);
if (iwhich != 1 && iwhich != 2)
{printf("\n *** Enter 1 or 2 please ***\n\n");
goto L20;
}
if (iwhich == 1)
{fa = sin;
}
else
{fa = cos;
}
printf("\n Degree %s\n\n", ptr[iwhich-1] );
for (x=0.; x<= 90.; x+=1.)
{dumx = x/180.*PI;
printf(" %3.0f %10.4f\n", x, (*fa)(dumx));
}
return;
}
It can be seen that to declare a pointer for function, we use, e.g.
double (*fa)();
Exercise : How to declare "fb" to be pointer for a function returning an integer ?
Ans :
int (*fb)();
Exercise : Are the following declarations the same
(a) double (*fa)();
double x, b[100], *ptr;
(b) double (*fa)(), x, b[100], *ptr;
Ans : Yes. We may put them all on one line. "fa" is a pointer for a function returning a double. "x" is a double. "b[100]" an array of doubles. "ptr", a pointer to double.
Exercise : What is the difference between the following :
Ans : The first is to declare "fa" pointer to a function returning a double. The second is to declare a function prototype : "fa" is a function returning a pointer (for double).
Exercise : Write a program that does Simpson's Integration.

Ans :
#include <stdio.h>
#include <math.h>
/* This is the function to integrate g(x) = 6x3 + 3x -2 */
double g(double x)
{ return 6*x*x*x + 3*x - 2;
}
/* This subroutine does Simpson's Integration. We have to pass to it
the address of the function to be integrated, and lower and upper
limits of integration, and the number of divisions
*/
double simpson( double (*f)(double), double xlow, double xhigh, int ndiv)
{ int mdiv, i;
double h, h2, sum1, sum4, sum2, x;
if (ndiv < 2)
{ndiv = 2;
}
mdiv = 2 * ndiv;
h = (xhigh - xlow)/(double) mdiv;
h2 = h + h;
sum1 = f(xhigh) + f(xlow);
for (sum4=0., x=xlow+h, i=0; i<ndiv; i++, x += h2)
{sum4 += f(x);
}
for (sum2=0., x=xlow+h2, i=0; i<ndiv-1; i++, x+= h2)
{sum2 += f(x);
}
return (h/3*(sum1 + 4.*sum4 + 2.*sum2));
}
int main()
{ printf("Area is %12.4f\n", simpson(g, 0, 4, 10));
return 0;
}
Examples of cast operator to convert one data type to another :
double x;
x = (double) 2; /* This will convert an integer into double. */
h = (xhigh - xlow)/(double) mdiv ; /* This is from the above program.
"mdiv" is converted into double first.
Usually compiler will does the
conversion for us, without our
using a cast */
The syntax is
| (data type) expression |
Mostly, cast is used to convert pointers. e.g.
struct
{ char name[40];
int age;
double wages;
} rec;
char *ptr;
ptr = (char *) &rec; /* Since ptr stores only the address of character,
but &rec is address of a structure. Hence, if
we want to assign it to ptr, we have to change
its data type first using a cast. */
Exercise : The following are 2 subroutines in <stdlib.h>. The first one does binary search of a sorted list, the second does sorting.
void *bsearch(void *key, void *base, size_t n, size_t size,
int (*cmp)(void *keyval, void *datum))
void qsort(void *base, size_t n, size_t size, int (*cmp)(void *, void *))
|
Ans :
void *key is the address where "key" is stored.
void *base is the address where the sorted list is. The list must be
sorted first (in ascending order) before binary search can
be carried out.
size_t n Number of objects in the sorted list.
("Object" may be common data types, or structures, or pointers,
.... etc.)
size_t size Size in byte of one object.
int (*cmp)(void *keyval, void *datum)
Address of a function. That function has 2 arguments,
both of type "pointer". That function returns an integer.
It returns 0 if keyval = datum
<0 if keyval < datum
>0 if keyval > datum
bsearch will return NULL if key is not found, or, if key is found, the address.
void *base address where the array to be sorted is.
size_t n Number of objects in the array.
size_t size Size in byte of one object.
int (*cmp)(void *, void *)
Address of a function, which returns an integer based
on whether the two are equal, less than, or greater than.
Same as that in bsearch above.
qsort does not return any value.
It may be noticed that "void pointer" (void *) are used in the above two. In fact, "void pointer" can take the place of any pointer type, and is called a "generic pointer". Usually "void pointer" is also a character pointer.
Below is an example of how to use the above two subroutines.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{ char name[40];
int age;
double wages;
} Mrec;
int namesort(Mrec *pa, Mrec *pb)
{ int idummy;
idummy = strcmp(pa->name, pb->name); /* Use "string compare" function in
<string.h>. */
return idummy;
}
int main()
{ Mrec a[4], *ptr;
char buffer[1000];
int i;
/* We artifically put data into the 4 records */
strcpy(a[0].name, "Wu Siu Yan"); /* strcpy(..) = string copy, subroutine in
<string.h>. */
strcpy(a[1].name, "Tom");
strcpy(a[2].name, "Mary");
strcpy(a[3].name, "Jack");
a[0].age = 51;
a[1].age = 25;
a[2].age = 30;
a[3].age = 47;
a[0].wages = 1000;
a[1].wages = 1500;
a[2].wages = 2200;
a[3].wages = 1600;
qsort(a, 4, sizeof(Mrec), namesort); /* Whan array is passed as argument,
the compiler will pass the address
of its first element */
/* Print the sorted result */
for (i=0; i<4; i++)
{printf("%-40s %3d %5.0f\n",a[i].name, a[i].age, a[i].wages);
}
/* Accepts a key, and see if it is in the list, using binary search */
L20:
printf("Enter name -> ");
gets(buffer);
if (strcmp(buffer, "****") == 0)
{return 0;
}
ptr = (Mrec *) bsearch(buffer, a, 4, sizeof(Mrec), namesort);
/* Since bsearch returns a void pointer, we must cast the
pointer to that of (Mrec *), because "ptr" is a Mrec pointer.
All subroutines that returns a void pointer must be
cast into a pointer of proper type before use. */
if (ptr == NULL)
{printf(" *** No record with name %s found ***\n", buffer);
}
else
{printf(" *** Found ***\n");
printf("%-40s %3d %5.0f\n",ptr->name, ptr->age, ptr->wages);
}
goto L20;
}
Exercise : If we wish to sort the records according to age, (youngest first) what should be changed ?
Ans : The comparison subroutine as well as the call statement has to be changed,
int agesort(Mrec *pa, Mrec *pb)
{ return (pa->age - pb->age);
/* If oldest first, then "return (pb->age - pa->age); */
}
/* In the main program, the call statement is now */
qsort(a, 4, sizeof(Mrec), agesort);
Exercise : If we wish to sort the records according to wages (highest wages first), what should be changed ?
Ans : The comparison subroutine as well as the call statement has to be changed,
int wagesort(Mrec *pa, Mrec *pb)
{ return (pb->wages - pa->wages);
}
/* In the main program, the call statement is now */
qsort(a, 4, sizeof(Mrec), wagesort);
Exercise : If we wish to sort according to name first, but if the names are the same, then sort it according to age (eldest first). What should be the sort subroutine and the call statement ?
Ans :
int nameagesort(Mrec *pa, Mrec *pb)
{ int iret;
iret = strcmp(pa->name, pb->name);
if (iret == 0)
{return (pb->age - pa->age);
}
else
{return iret;
}
}
/* In the main program, the call statement is now */
qsort(a, 4, sizeof(Mrec), nameagesort);
(Note : I use Debian LINUX, the item is "Libc". The name may be "glibc" ... in LINUX from other distributors. Also, some distributors may even omit "Libc" and include "c++" library instead.)
Exercise : What are global variables and local variables. Can all subroutines access global variables ? Can an outside subroutine access a local variable ? (If you are unfamiliar with these concepts, it is advisable that you read Qbasic in this website first.) Point out which are global variables and which are local variables in the following program :
#include <c.h>
/*You may use <stdio.h>, <stdlib.h>, <string.h> instead */
double A[100];
int Iflag, Ncount;
int compare(double *a, double *b)
{ return (*a - *b);
}
int main()
{ char buffer[1000];
int i;
Ncount = 0;
L20:
printf("Enter a number (**** = end) -> ");
gets(buffer);
if (strcmp(buffer, "****") == 0)
{goto L100;
}
sscanf(buffer, "%lf", &(A[Ncount]));
Ncount++;
goto L20;
/* This sort the numbers in ascending order */
L200:
qsort(A, Ncount, sizeof(double), compare);
/* This prints the sorted list */
for (i=0; i<Ncount; i++)
{printf("%10.3f",A[i]);
}
printf("\n");
return 0;
}
Ans :
Any variable declared outside main() or other subroutines are global variables. Those declared within main() or subroutines are local variables.
Hence "double A[100]; int iflag, Ncount;" are global variables.
Whereas "char buffer[1000]; int i;" are local variables.
Global variables may be accessed by all subroutines, but not so with local variables (see "scoping" below).
Global variables are assigned static memory, whereas local variables are assigned
dynamic memory (unless declared with "static"), and they are taken from the
Global variables are initialized to 0 by the compiler, local variables are not. Hence we must assign values to local variables before using them.
Exercise : In a large program with many subroutines, very often, the subroutines are put in different files. e.g.
FILE "/home/tom/t63a.c" contains
double A[100];
int Iflag, Ncount;
int ascendcmp(double *a, double *b)
{ return (*a - *b);
}
int descendcmp(double *a, double *b)
{ return (*b - *a);
}
FILE "/home/tom/t63main.c" contains
#include <c.h>
int main()
{ char buffer[1000];
int (*pf)();
int i, ichoice;
Ncount = 0;
L20:
printf("Enter a number (**** = end) -> ");
gets(buffer);
if (strcmp(buffer, "****") == 0)
{goto L100;
}
sscanf(buffer, "%lf", &(A[Ncount]));
Ncount++;
goto L20;
/* This sort the numbers in ascending order */
L100:
printf("Do you want to sort it in ascending order (0) or descending order (1) ? \n");
gets(buffer);
sscanf(buffer,"%d",&ichoice);
if (ichoice != 0 && ichoice != 1)
{printf(" *** 0 or 1 please ***\n");
goto L100;
}
if (ichoice == 0)
{pf = ascendcmp;
}
else
{pf = descendcmp;
}
qsort(A, Ncount, sizeof(double), pf);
/* This prints the sorted list */
for (i=0; i<Ncount; i++)
{printf("%10.3f",A[i]);
}
printf("\n");
return 0;
}
Then what modifications are needed in order than main(..) may use global variables
"A[100], Ncount" as well as subroutines
Ans : We should modify "/home/tom/t63main.c" to be
#include <c.h>
extern double A[100];
extern int Iflag, Ncount;
extern int ascendcmp(double *, double *);
extern int descendcmp(double *, double *);
int main()
{ char buffer[1000];
int (*pf)();
int i, ichoice;
.....
.....
.....
}
And the compile command should be
gcc -Wall t63main.c t63a.c -I/home/tom/include/
"extern" is a C keyword. It informs the compiler that those variables as well as subroutines are defined outside this file.
Exercise : Suppose we modify file "/tom/t63a.c" to be
static double A[100];
static int Iflag, Ncount;
static int ascendcmp(double *a, double *b)
{ return (*a - *b);
}
static int descendcmp(double *a, double *b)
{ return (*b - *a);
}
i.e. with "static" added, and then compile with
gcc -Wall t63main.c t63a.c -I/home/tom/include/Do you think it will work this time?
Ans : No. "static" has another meaning here (ordinarily, it would mean that the variable should be given static memory and not dynamic memory.) It informs the compiler that those global variables or subroutines are NOT to be accessed by files outside. They are considered to be "private". Therefore the compilation will fail.
Exercise : Study the following program
#include <stdio.h>
void suba(void)
{ static int k=100;
printf("%4d\n", k);
k++;
}
int main()
{ int i;
for (i=0; i<5; i++)
{suba();
}
return 0;
}
What will it produce ? Suppose we remove "static",
#include <stdio.h>
void suba(void)
{ int k=100; /* "static" removed */
printf("%4d\n", k);
k++;
}
int main()
{ int i;
for (i=0; i<5; i++)
{suba();
}
return 0;
}
What will the program produce ?
Ans : With "static", it will produce "100, 101, 102, 103, 104".
Without "static", it will produce "100, 100, 100, 100, 100".
It is because, "static" informs the compiler to allocate static memory to "k", and also give it initial value "100". Hence on every call, "k" will NOT be given initial value, and "k++" will increment "k".
But without "static", the compiler will assign "k" memory in the "runtime stack". Also the compiler will compile the initialization "int k=100" into
int k;
k = 100;
Hence everytime the subroutine is called, "k" has value "100".
Exercise : Study the following program
#include <stdio.h>
int K=100;
void suba(void)
{ printf("suba - %d\n", K);
printf("suba - %d\n", L);
printf("suba - %d\n", M);
return;
}
int L=200;
void subb(void)
{ printf("subb - %d\n", K);
printf("subb - %d\n", L);
printf("suba - %d\n", M);
return;
}
int M=300;
void subc(void)
{ printf("subc - %d\n", K);
printf("subc - %d\n", L);
printf("subc - %d\n", M);
return;
}
int main()
{ suba();
subb();
subc();
return 0;
}
What are the global variables ? What will be the outcome of the program ?
Ans : When you compile it, there will be many compilation errors. In short, a global variable is "visible" only to the subroutines below it, and not above it. Had we put
#include <stdio.h>
int K=100;
int L=200;
int M=300;
void suba(void)
{ ....
}
void subb(void)
{ ....
}
void subc(void)
{ ....
}
int main()
{ ....
}
There will not be any problem.
#include <filename> /* File in system directory, "/usr/include/" ... */
#include "filename" /* File in current directory */
(Notice that "#include" tells the pre-processor to include content from the
files. There is no restriction on the content of those files ! Although
mostly they are header files and contain function prototypes or constant
definitions. But we may put "global variables, or Master Record definitions etc."
in them. Also those files may contain "#include .... " too !)
|
#define token1 token2 /* Pre-processor will replace very
occurrences of token1 by token2.
You may regard it as "function" definition
or "macro" expansion. */
Exercise : Will the following work as expected ?
#define prod(x,y) x*y
....
....
(in the program)
y = prod(a+b,c);
Ans : No. Pre-processor will convert it to " a+b*c ".
Correct one should be
#define prod(x,y) (x)*(y)
|
#define token numeric-value
#if (token)
.... /* If token is true (i.e. non-zero), this part
.... will be compiled. */
#else
.... /* This part will be compiled if token is false. */
....
#endif
(Alternate form)
#define token /* define */
#undef token /* undefine - cancel the previous "define" */
#ifdef token /* if defined token */
#ifndef token /* if not defined token */
....
....
#else
....
....
#endif
|
There are documentation about "pre-processor" in LINUX, and you may read them for more.
In the example programs, we used
int main()But the full form is (both may be used)
int main(int nargv, char **argv, char **env)You may view it as
int main(int nargv, char **argv)
int main(int nargv, char *argv[], char *env[])Suppose the program is in the file "/home/tom/t20.c" and you compile it with
int main(int nargv, char *argv[])
gcc -Wall -o t20 t20.c -I/home/tom/include/ -lmi.e. You require the output file be named "t20" and not the usual "a.out". Then when you run the program with
t20 tom mary jackthe operating system will put 4 in "int nargv" (number of arguments), and put "t20", "tom", "mary", "jack" in certain places and passes their addresses to "char *argv[]", i.e.
argv[0] will point to "t20"
argv[1] will point to "tom"
argv[2] will point to "mary"
argv[3] will point to "jack"
Also the operating system will put the addresses of "environment variables" in
the character pointer array "char *env[]", the last being indicated by a NULL value.
The following program will simply print out those arguments and environment variables :
#include <stdio.h>
int main(int nargv, char *argv[], char *env[])
{ int i;
char *ptr;
printf("Number of arguments is %d\n"
"And they are : -\n\n" , nargv);
for (i=0; i<nargv; i++)
{printf("%s\n", argv[i]);
}
printf("Environment variables are :-\n\n");
for (i=0; ; i++)
{ ptr = env[i];
if (ptr == NULL)
{break;
}
printf("%s\n", ptr);
}
return 0;
}
Hence we may write C programs and use them as commands.
The following is a program that will convert a MSDOS file (where a line ends with '\r' '\n' ) into a LINUX file (where a line ends with only '\n'), or vice versa.
gcc -Wall -o convert t70.c
convert infilename outfilename
#include <stdio.h>
int main(int nargv, char *argv[])
{ int ierror, ichoice, c;
FILE *fin, *fout;
if (nargv < 3)
{printf("input file as well as output file needed\n");
return 1;
}
ierror = 0;
if ( (fin=fopen(argv[1],"r")) == NULL )
{ierror = 1;
}
if ( (fout=fopen(argv[2],"w")) == NULL )
{ierror = 1;
}
if (ierror == 1)
{printf("Error in openning files. Aborted.\n\n");
}
L20:
printf(" 1 - MSDOS to LINUX\n"
" 2 - LINUX to MSDOS\n"
" - > ");
scanf("%d", &ichoice);
if (ichoice != 1 && ichoice != 2)
{printf(" *** 1 or 2, please ***\n\n");
goto L20;
}
if (ichoice != 1) {goto L100;}
L40:
c = fgetc(fin);
if (c == EOF)
{goto L200;
}
if (c != '\r')
{fputc(c, fout);
}
goto L40;
L100:
c = fgetc(fin);
if (c == EOF)
{goto L200;
}
if (c == '\n')
{fputc('\r', fout);
fputc('\n', fout);
}
else
{fputc(c, fout);
}
goto L100;
L200:
fclose(fin);
fclose(fout);
return 0;
}
Thus we can write lots and lots of commands! And this design philosophy makes C and UNIX powerful.
Normally, we would use || as a logical connectives. But you may find other uses of ||, e.g.
#include <c.h>
int die(char *s)
{ printf("%sn\n",s);
exit(1);
return 1;
}
int main(int narg, char *argv[])
{ FILE *fin;
(fin=fopen(argv[1],"r")) || die("*** Unable to open file");
.....
.....
fclose(fin);
return 0;
}
When the computer executes (A || B), it will first check if "A" is true. If "A" is true, then it will not check "B". Only when "A" is false, it will check "B". e.g. the following code is valid
if (ptr==NULL || *ptr='a') {.....}"A" fails means "ptr" is not NULL, hence we may store value at that address.
(fin=fopen(argv[1],"r")) || die("*** Unable to open file");works the same way. When "fopen(..)" fails, it will return NULL, i.e. 0 (or "false"), and "die(..)" will be executed.
I dislike such kind of codes. I prefer a more direct one,
if ( (fin=fopen(argv[1],"r")) == NULL)
{die("*** Unable to open file");
}
because it is much easier to understand. But many people program that way, (especially
in PERL), and if you are to read programs by others, you should know this strange usage
of OR (||).
In C, a data structure may contain other data structures, and they, in turn, contain other data structures. Recursion is common in data types.
Recursion may be used in program codes too. For a subroutine in C, it may call itself. The most common example is factorial function
#include <stdio.h>
int factorial(int n)
{ if (n <= 1)
{return 1;
}
else
{return (n*factorial(n-1));
}
}
int main()
{ int n;
L20:
puts("Enter number ");
scanf("%d",&n);
if (n == -1)
{return 1;
}
printf("Factorial of %d is %d\n", n, factorial(n));
goto L20;
}
Notice that it is not always expedient to use recursion, e.g. the above factorial subroutine may be written using a simple loop. Moreover, recursion is slower and uses more memory.
But there are situations where we must use recursion. Writing compiler whose grammar is specified by recursive descend is one, below is another where we must use recursion.
Suppose we have a sequence of numbers {7, 96, 31, 14, 18, 95, 63}, we may put it in a binary tree as follows.

Exercise : Draw a binary tree for the sequence {64, 50, 30, 96, 25, 27, 51}.
Ans :

Important points to remember for a binary tree : -
Below is a subroutine that sorts the numbers we key in. Because "binary tree" grows, we need additional memory for each additional node. Either we reserve a large array for this purpose, or we request memory from the operating system. "malloc(..)" is a library function that requests memory from the operating system. "malloc(..)" is a standard subroutine in <stdlib.h>.
void *malloc(size_t nsize)
Note : size_t is defined in header files as unsigned int (integer). We request
memory "nsize" bytes, and malloc(..) returns the address where
memory is allocated. It returns NULL is no memory is available.
e.g. double *ptr;
ptr = (double *) malloc(sizeof(double));
|
void free(void *ptr)
Note : When we no longer need the memory, we have to return it back.
When the program terminates, all memory will be released automatically.
|
Below is a program that sorts a array of numbers using a "binary tree".
#include <c.h>
#define DEBUG 0
typedef struct DD
{double data;
struct DD *pright; /* These address registers store the address */
struct DD *pleft; /* of the right and left portions */
} Mrec;
static Mrec *P0; /* P0 stores the top node address */
static int Msize, Ifirst=1; /* Msize = sizeof(Mrec).
Ifirst is a flag, first time
or not. */
/* This subroutine compares 2 records.
It returns -1 if the first is "less than" the second.
0 if they are the same.
1 if the first is "greatter than" the second.
Exercise : If you want to sort in descending order, what should
be the compare(..) subroutine.
*/
int compare(Mrec *pa, Mrec *pb)
{ return (pa->data - pb->data);
}
void store(double a)
{ Mrec *ptr, *ptr2, *ptr3;
int iret;
/* Request memory using library subroutine "void *malloc(size_t n)"
Since "malloc" returns a pointer to void, it must be casted before use.
*/
ptr = (Mrec *) malloc(Msize);
assert(ptr != NULL);
#if (DEBUG)
printf("%p ",ptr);
#endif
ptr->data = a; /* Store the data */
if (Ifirst == 1)
{P0 = ptr; /* Store address of top-most node */
Ifirst = 0;
goto L100;
}
ptr2 = P0;
L20:
iret = compare(ptr, ptr2);
if (iret <= 0) /* less than or equal */
{ptr3 = ptr2->pleft;
if (ptr3 != NULL) /* NULL means there is nothing on that portion */
{ptr2 = ptr3;
goto L20;
}
else
{ptr2->pleft = ptr;
goto L100;
}
}
else
{ptr3 = ptr2->pright;
if (ptr3 != NULL)
{ptr2 = ptr3;
goto L20;
}
else
{ptr2->pright = ptr;
goto L100;
}
}
L100:
ptr->pleft = NULL;
ptr->pright = NULL;
return;
}
void mysort(Mrec *p)
{ Mrec *ptr;
/* Print the left portion first */
ptr = p->pleft;
if (ptr != NULL)
{mysort(ptr); /* Notice that recursion is used here */
} /* for the left portion */
/* Print itself */
printf("%10.2f", p->data);
/* Print the right portion next */
ptr = p->pright;
if (ptr != NULL)
{mysort(ptr); /* Notice that recursion is used here */
} /* for the right portion. */
return;
}
void freememory(Mrec *p)
{ Mrec *ptr;
/* Free the left portion first */
ptr = p->pleft;
if (ptr != NULL)
{freememory(ptr); /* Notice the use of recursion */
}
/* Free itself */
free(p);
#if (DEBUG)
printf("%p ", p);
#endif
/* Free the right portion next */
ptr = p->pright;
if (ptr != NULL)
{freememory(ptr); /* Notice the use of recursion */
}
return;
}
int main()
{ char buffer[1000];
double dummy;
Msize = sizeof(Mrec);
L20:
puts("Enter number (**** = end) ");
gets(buffer);
if (strcmp(buffer,"****") == 0)
{goto L100;
}
sscanf(buffer,"%lf",&dummy);
store(dummy);
goto L20;
L100:
mysort(P0); /* Prints the sorted list */
printf("\n\n");
freememory(P0); /* This frees all memory gotten from malloc */
return 0;
}
It is important to release memory no longer needed. "Memory leaks" may cause a computer system to fail. I heard from TV that a program in a Police station worked fine day and night for 2 weeks, then suddenly it failed. Later, it was discovered that "memory leaks" is the cause.
Suppose a variable assumes only a finite number of states, e.g. The variable district may be "Hong Kong", "Kowloon", "New Territories". Either we may use coding : 0 for "Hong Kong", 1 for "Kowloon", 2 for "New Territories", or we may use enumeration.
Syntax (simplified) : "enum" is a C keyword. The syntax for "enum" is very similar to that of "struct".
enum [tag] { identifer1, identifier2, ... } variable1, variable2, ... ;
Note : an "enum" variable is in fact an integer.
{identifier1, identifier2, ... } are the symbolic names for {0, 1, 2, ... }.
e.g.
enum {banana, orange, apple, pear } fruit;
The variable "fruit" is an integer. "banana, orange, apple, pear"
are symbolic names for {0, 1, 2, 3}. Notice that it may start from any number,
e.g.
enum {banana = 5, orange, apple, pear} fruit;
Then it starts from 5. {5, 6, 7, 8}
|
Example :
#include <c.h>
typedef enum { HongKong, Kowloon, NT } District;
int main()
{ District area;
L20:
puts("Enter area code");
scanf("%d",&area); /* We key in 0, 1, 2, ... */
if (area == -1)
{return 0;
}
if (area == HongKong) /* Same as if (area == 0) ... */
{printf("Area is Hong Kong\n");
}
else if (area == Kowloon)
{printf("Area is Kowloon\n");
}
else if (area == NT)
{printf("Area is New Territories\n");
}
else
{printf(" *** ERROR , area code not recognized ***\n");
}
goto L20;
}
| [Previous] | [Home] | [Next] |