Enumeration || Preprocessor || Library Functions in C

Now before we conclude this C Programming Tutorial, we will discuss the last but few of the important most additional concepts used in C.

This will include Enumeration, the Preprocessor, and Standard library functions in C.

Now let’s move on further and discuss the Enumeration concept used in C.

Enumeration in C

An enumeration may be a set of named integer constants. Enumerations are common in lifestyle.
For example, an enumeration of the coins utilized is penny, nickel, dime, quarter, half-dollar, dollar.

Enumerations are defined as very similar to structures; the keyword enum signals the beginning of an enumeration type.

The general form for enumerations is:

enum tag { enumeration list } variable_list;

  • Here, both the tag and therefore the variable list are optional.
  • But a minimum of one must be present.

Example:

enum coin {penny, nickel, dime, quarter, half_dollar, dollar};

  • Here, the above code fragment defines an enumeration called coin.

enum coin money;

  • Here, money may be a variable of type coin.
  • The enumeration tag name is often wont to declare variables of its type.

Example:

money = dime;
if(money==quarter) printf(''Money may be a quarter.\n");
printf("%d %d", penny, dime);

The output of the above code fragment is going to be 0 2.

We can specify the worth of 1 or more of the symbols by using an initializer by following the symbol with an equal sign and an integer value. Symbols that appear after an initializer are assigned values greater than the preceding value.

Example:

enum coin {penny, nickel, dime, quarter=100, half_dollar, dollar};

The values evaluated by the above fragment of the code will be: penny = 0, nickel = 1, dime = 2, quarter = 100, half_dollar = 101, and dollar = 102 respectively.

Below is an example to demonstrate the use of enumeration in a program.

Example: Program to print integer constant value using the enumeration concept.

Code:

#include <stdio.h>
int main()
{
    enum TEAM { CSK = 11, MI = 25, RCB = 15, KKR = 22, RR = 30, SH = 32 };
 
    printf("   \tIPL POINTS TABLE \n");
    printf("   TEAM \t\t   POINTS \n");
    printf("Chennai Super Kings:         %2d\n", CSK);
    printf("Kolkata Knight Riders:       %2d\n", KKR);
    printf("Mumbai Indians:              %2d\n", MI);
    printf("Royal Challengers Bangalore: %2d\n", RCB);
    printf("Rajasthan Royals:            %2d\n", RR);
    printf("Sunrisers Hyderabad:         %2d\n", SH);
    return 0;
}

Output:

        IPL POINTS TABLE 
   TEAM                    POINTS 
Chennai Super Kings:         11
Kolkata Knight Riders:       22
Mumbai Indians:              25
Royal Challengers Bangalore: 15
Rajasthan Royals:            30
Sunrisers Hyderabad:         32

Important note:

  • The key point to know about an enumeration is that each of the symbols stands for an integer value.
  • As such, they will be used anywhere that an integer is often used.
  • Each symbol is given a worth one greater than the symbol that precedes it.
  • The worth of the primary enumeration symbol is 0.

Preprocessor in C

The preprocessor provides access to many features that are not available in other high-level languages, which makes C a unique and flexible language. Using this tool, a developer can write programs that are easy to read, easy to modify, portable, and more efficient.

What is Preprocessor?

The preprocessor is a program that processes the source code before it is passed through the compiler. It operates through the control of the preprocessor command line or directives.

The preprocessor directive is placed in a source program before the mainline. The source code is examined by the preprocessor before it is passed through the compiler. If there are any actions to be taken (as per the directives), then the source code is handed over to the compiler.

Preprocessor directives have special syntax rules that are distinct from other syntaxes that we have seen in C till now.

  • They begin from symbol #
  • They don’t require a semicolon at the end.
  •  E.g.- #define and #include

Preprocessor directives can be divided into three categories:

  1. Macro Substitution Directives
  2. File Inclusion Directives
  3. Compiler Directives
Directive
Function

#define

Defined a macro substitution
#undef

Undefines a macro

#include

Specifies the files to be included
#ifdef

Test for a micro definition

#endif

Specifies the end of #if
#ifndef

Tests whether a macro is not defined

#if

Test a compile-time condition
#else

Specifies alternatives when #if fails

What are Macro Substitution Directives?

Macro Substitution is a process where an identifier in a program is replaced by a predefined string composed of one or more tokens. The preprocessor does this task under the direction #define statement. This statement is known as a macro definition.

The general form of this statement is: #define identifier string

When this statement is included at the beginning, then the preprocessor replaces every occurrence of the identifier in the source code by the string. The keyword #define is written in the same way followed by the identifier and a string with at least one blank space between them.

Simple Macro Substitution Directives

It is the most used macro to define constants.

Example:

#define

COUNT

100

#define

FALSE 0
#define SUBJECTS

6

#define

PI 3.141592
#define CAPITAL

“MUMBAI”

  • It is a convention to write all macros in capitals to identify them as symbolic constants.
  • However, a macro inside a string does not get replaced.
  • A macro definition can include more than a simple constant value.

Valid definition: #define AREA 5 * 12.46

In the usage of expression for replacement, we should prevent an unexpected order of evaluation.

Example:

ratio = D/A;

#define D 45 – 22

#define A 78 + 32

The result of the preprocessor’s substitution for D and A is:

ratio = 45-22/78+32;

Macros with arguments Substitution Directives

We can define a more complex and more useful form of replacements.

It’s form is: #define identifier(f1, f2, . . .fn) string

  • Here, there is no space between the macro identifier and the left parentheses.
  • The identifier f1, f2, . . .fn are the normal macro arguments that are analogous to the formal arguments in a function definition.
  • The subsequent occurrence of a macro with an argument is known as a macro call (similar to a function call).
  • When a macro is called, the preprocessor substitutes the string, replacing the formal parameters with the actual parameter.

Example:

#define CUBE(x) (x*x*x)

What are File Inclusion Directives?

An external file containing functions or macro definitions can be included as a part of a program so that we don’t have to write those functions or macro definitions.

It can be performed using the preprocessor directive: #include “filename”

  • Here, the filename is the name of the file containing the required definitions or functions.
  • The preprocessor inserts the entire content of the filename into the source code of the program.
  • When the filename is included within the double quotation marks, the search for the file is made first in the current directory and then in the standard directories.

What are Compiler Directives?

There could be a situation where we have to develop a different program to suit the needs of the different situations. We can also develop a comprehensive program that includes all optional codes and then directs the compiler to skip over certain parts of the source code when they are not required. In C preprocessor, a feature called conditional compilation, which can be used to ‘switch’ on or off a particular line or group of lines of the program.

Type 1

This type handles the condition definition of a macro. We must ensure that the macro TEST is always defined, irrespective of whether it has been defined or not.

Example:

#include “DEFINE.H”

#ifndef TEST

#define TEST1

#endif

. . . 
. . .

Type 2

This type makes the program portable.

We can perform this operation by following the given pattern:

. . .
. . .
main()
{
   . . .
   . . .
#ifdef IBM_PC
{
   . . .
   . . .
   . . .
}
#else
{
   . . .
   . . .
   . . .
}
#endif
   . . .
   . . .
}

If we have to run the program on  IBM PC, we must include the directive: #define IBM_PC

Type 3

This type is the same as type 2 and hence the control directives have the following form:

#ifdef ABC
      group-A lines
#else
      group-B lines
#endif
  • Here, group-A lines are included if the customer ABC is defined.
  • Otherwise, group-B lines are included.
Type 4

This type is used to handle the debugging and testing to detect the errors in the program. We can use debugging statements to isolate or correct errors, which can later be deleted or we could make them inactive.

. . .
. . .
#ifdef TEST
{
   printf("Array elements\n");
   for(i = 0; i < m; i++)
      printf("x[%d] = %d\n", i, x[i]);
}
#endif
. . .
. . .
#ifdef TEST
      printf(...);
#endif
. . .
  • Here, the statements between directives #ifdef and #endif are only included if the macro TEST is defined.
  • After, it is okay, delete or undefine the TEST. This makes all the #ifdef TEST conditions false and hence all the debugging statements are left out.

Library Functions in C

In C programming language, each of the content and form of the C standard library is defined. That is, the C library specifies a group of functions that every standard compiler should support.

However, a compiler is absolved to offer further functions not such by the standard. (And, indeed, most compilers do.) as an example, it’s common for a compiler to possess graphics functions, mouse-handler routines, and also the like, despite the fact that none of those is outlined by standard C. As long as you’ll not be porting your programs to a brand new atmosphere, you’ll use these nonstandard functions with none negative consequences.

However, if your code should be moveable, the operation of those functions should be restricted. From a sensible purpose of reading, just about all nontrivial C programs can create use of nonstandard functions, therefore you must not essentially retreat from their use simply because they’re not a part of the standard function library.

The use of header files which contains the commonly used functions in C is highlighted in the points given below:

  • Each function included within the C standard library features a header related to it.
  • The headers that are related to the functions that we use in your programs are included by using #include.
  • The headers perform 2 necessary jobs. First, several functions within the standard library work with their own specific data types, to that a program should have access.
  • These data types are included within the header associated with every function. One of the foremost common examples is the file system header <stdio.h>, that provides the type FILE that’s necessary for file operations.
  • The second reason to incorporate headers is to get the prototypes for the standard library functions. Function prototypes permit stronger type checking to be performed by the compiler.

Below is a list of header files used in C.

HEADER
FUNCTIONS INCLUDED

<ctype.h>

Character testing and conversion functions
<math.h>

Mathematical functions

<stdio.h>

I/O library functions
<stdlib.h>

Utility functions

<string.h>

String handling functions
<time.h>

Time handling functions

Below is the list of Functions included in different Header Files with their purpose.

<ctype.h>

<ctype.h>
Usage
isalnum(c)

Determine if argument is alphanumeric

isalpha(c)

Determine if argument is alphabetic
isascii(c)

Determine if argument is an ASCII character

iscntrl(c)

Determine if argument is an ASCII control character

isdigit(c)

Determine if argument is a decimal digit

isgraph(c)

Determine if argument is a graphic printing ASCII character

islower(c)

Determine if argument is lowercase
isodigit(c)

Determine if argument is an octal digit

isprint(c)

Determine if argument is a printing ASCII character
ispuncy(c)

Determine if argument is a punctuation character

<math.h>

<math.h>
Usage

acos(d)

Return the arc cosine of d
asin(d)

Return the arc sine of d

atan(d)

Return the arc tangent of d
atan2(d1,d2)

Return the arc tangent of d1/d2

ceil(d)

Return a value rounded up to the next higher integer
cos(d)

Return the cosine of d

cosh(d)

Return the hyperbolic cosine of d
exp(d)

Raise e to the power d

fabs(d)

Return the absolute value of d
floor(d)

Return a value rounded down to the next lower integer

<stdio.h>

<stdio.h>
Usage

fclose(f)

Closes file f
feof(f)

Determine if an end-of-line condition has been reached

fgetc(f)

Enter a single character form file f
fgets(s,i,f)

Enter string s, containing i characters, from file f

fprintf(f,…)

Send data items to file f
fputc(c,f)

Send a single character to file f

fputs(s,f)

Send string s to file f
fread(s,i1,i2,f)

Enter i2 data items, each of size i1 bytes, from file f to string s

fscanf(f,…)

Enter data items from file f
fseek(f,1,i)

Move the pointer to file f, a distance 1 byte from location i

<stdlib.h>

<stdlib.h>
Usage

abs(i)

Returns the absolute value of i
atof(s)

Converts string s to a double-precision quantity

atoi(s)

Converts string s to an integer
atol(s)

Converts string s to a long integer

calloc(u1,u2)

Allocates memory for an array having u1 elements, each of length u2 bytes
exit(u)

Closes all files and buffers, and terminates the program

free(p)

Free a block of allocated memory whose beginning is indicated by p
malloc(u)

Allocate u bytes of memory

rand(void)

Returns a random positive integer
realloc(p,u)

Allocate u bytes of new memory to the pointer p

<string.h>

<string.h>
Usage
strcmp(s1,s2)

Compare two strings lexicographically

strcmpi(s1,s2)

Compare two strings lexicographically, without regard to case
strcpy(s1,s2)

Copy string s2 to string s1

strlen(s)

Return the number of characters in string s
strset(s,c)

Set all characters within s to c (except null character \0)

<time.h>

<time.h>
Usage

difftime(11,12)

Return the time difference 11~12
time(p)

Return the number of seconds elapsed beyond a designated base time