0% found this document useful (0 votes)
244 views

Module 5

This document discusses file handling in C programming. It describes different types of files like text files, unformatted data files, and binary files. It explains various file operations like creation, opening, reading, writing and closing files. It also discusses functions used for file processing like fopen(), fclose(), fread(), fwrite(), fgets(), fputs() etc and how to open, read and write files in both text and binary modes.

Uploaded by

Soumya Vijoy
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
244 views

Module 5

This document discusses file handling in C programming. It describes different types of files like text files, unformatted data files, and binary files. It explains various file operations like creation, opening, reading, writing and closing files. It also discusses functions used for file processing like fopen(), fclose(), fread(), fwrite(), fgets(), fputs() etc and how to open, read and write files in both text and binary modes.

Uploaded by

Soumya Vijoy
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 78

File handling

File
File is a place on disk where data is stored. There are two different types of data files,

stream-oriented (or standard) data files system-oriented (or low-level)data files

Stream-oriented data files can be subdivided into two categories.

text files: Text files store character data. A text file can be thought of as a stream of characters that can be processed sequentially.

unformatted data filesorganizes data into blocks containing contiguous bytes of information. These blocks represent more complex data structures, such as arrays and structures.

System-oriented data files are more closely related to the computers operating

system than stream oriented data files.

File

Stream oriented data files

System oriented data files

Text files

Unformatte d data files

Binary files

Reason to use file-Need of permanency of storage of data

File operations
Different operations that can be performed on a file are Creation of a new file Opening an existing file Reading from a file Writing to a file Closing a file

Steps in Processing a File


Declare a file pointer variable Open a file using fopen function Process the file using suitable function Close the file using fclose() function

Declaration of file pointer


In C we use FILE * to represent a pointer to a file. Syntax of declaring file pointer is

FILE *file-pointer-name FILE is a special structure Declared in stdio.h Ex:FILE *fp;

opening a file

A data file must be opened before it can be created or processed. To open the file we have called the function fopen( ). The general format of opening a file is fp=fopen(filename,mode); filename-string of characters that makeup a valid filename for the os. mode specifies the purpose of opening the file.

example
FILE *FP; FP=FOPEN(sample.dat,w); will open a new data file called sample.dat as writing only mode

Different modes of opening a file


meaning mode Open an exising file for reading only r w Open a new file for writing only. If a file with the specified file-name currently exists, it will be destroyed and a new file created in its place.

Open an existing file for appending(or adding) data to it. a

Opens an existing file for both reading and writing


r+

Open a new file for both reading and writing.


w+ a+ Open an existing file for both reading and appending. a new file will be created if the file with specified filename doesnt exist

Closing a file
A data file must be closed as soon as all the operations on it

have been completed. A library function fclose is for this purpose Syntax is fclose(file-pointer) Ex:fclose(fp);

Reading and Writing a data file


For reading and writing to a file following standard i/o functions

are there. Function purpose name getc() Putc() getw putw fprintf fscanf fgets fputs read a character from file write a character to file read integer write integer write set of data values read set of data values Read string of characters from file Write string of characters to file

GETC and PUTC functions

getc is used to read a character from a file that has been opened

in read mode C=getc(fp) will read a character from file


Putc is used to write a character to the file

putc(c,fp); will write the character contained in character variable c to the file associated with FILE pointer fp.

Program to read character from keyboard,convert to uppercase and write to file


#include <stdio.h> #include <ctype.h> main( ) { FILE * fpt; char c; fpt = fopen("sample.dat", "w"); do { putc(toupper(c = getchar()), fpt ) ; } while (c ! = \n) ; fclose (fpt) ; }

getw and putw functions


These functions similar to getc and putc are used to read and write integer values General form of getw and putw are

putw(integer,fp); getw(fp);

Program #include <stdio.h> main() { FILE *f1, *f2, *f3; int number, i; f1 = fopen("DATA", "w"); for(i = 1; i <= 30; i++) { scanf("%d", &number); if(number == -1) break; putw(number,f1); } fclose(f1); f1 = fopen("DATA", "r"); f2 = fopen("ODD", "w"); f3 = fopen("EVEN", "w");

/* Read from DATA file */ while((number = getw(f1)) != EOF) { if(number %2 == 0) putw(number, f3); /* Write to EVEN file */ else putw(number, f2); /* Write to ODD file */ } fclose(f1); fclose(f2); fclose(f3); }

fprintf and fscanf functions


identical to printf and scanf functions except that they work on files. The first argument of theses functions is a file pointer which

specifies the file to be used.

The general form of fprintf is


fprintf(fp,control string, list);

fp is a file pointer associated with a file that has been opened for

writing.
control string is file output specifications list may include variable, constant and string.

ex:fprintf(f1,%s %d,name,age);

Here name is an array variable of type char and age is an int variable

The general format of fscanf is fscanf(fp,control string,list); Example: fscanf(f2,%s %d,item,&quantity);

/* Writes records to a file using structurewhile ( another == 'Y' ) */ #include "stdio.h" { main( ) printf ( "\nEnter name, age and basic salary: " ) { ; FILE *fp ; scanf ( "%s %d %f", e.name, &e.age, &e.bs ) ; char another = 'Y' ; fprintf ( fp, "%s %d %f\n", e.name, e.age, e.bs struct emp ); { printf ( "Add another record (Y/N) " ) ; char name[40] ; fflush ( stdin ) ; int age ; another = getche( ) ; float bs ; } }; fclose ( fp ) ; struct emp e ; fp = fopen ( "EMPLOYEE.DAT", "w" ) ; fp = fopen ( "EMPLOYEE.DAT", "r" ) ; if ( fp == NULL ) if ( fp == NULL ) { { puts ( "Cannot open file" ) ; puts ( "Cannot open file" ) ; exit( ) ; exit( ) ; } } while ( fscanf ( fp, "%s %d %f", e.name, &e.age, &e.bs ) != EOF ) printf ( "\n%s %d %f", e.name, e.age, e.bs ) ; fclose ( fp ) ;

fgets() and fputs() functions


fputs () function writes the contents of the array to the file.

fputs() does not automatically add a new line character the end of the string, it must be explicitly done.

syntax

fputs ( str, fp); Str is a pointer to null terminated string to be written


fputs function return a non-negative value on success.On error, the function

returns EOF.

Example for fputs


printf(\n enter a few lines of text :\n); while( strlen(gets(str))>0) { fputs(str, fp); fputs(\n); }

Fgets function
Fgets() which reads in an entire line from file fgets ( string ,maxlen, fp );

fgets takes three arguments.


String the maximum length of the string. File pointer

Fgets function returns the same string parameter on success.If the End-of-File is encountered and no characters have been read, a null pointer is returned.

Example for fgets FILE *fptr; char line [1000]; /* Open file and check it is open */ while (fgets(line,1000,fptr) != NULL) { printf ("Read line %s\n",line);

Feof()
It is defined in <stdio.h> Prototype:int feof( FILE * ); Used to determine if the end of the file (stream) specified, has been

reached. Return Nonzero (true) if the end of file has been reached, zero (false) otherwise. Example: #include <stdio.h> int main(void) { char buffer[256]; FILE * myfile; myfile = fopen("some.txt","r"); while (!feof(myfile)) { fgets(buffer,256,myfile); printf("%s",buffer); } fclose(myfile); } This example opens a file called some.txt for reading, then in a loop, reads lines from the file and outputs them to the screen. The loop continues until the end of the file has come.

Unformatted data files


Some applications involve the use of data files to store blocks of

data.Each block will generally represent a complex data structure, such as a structure or an array. The library functions fread and fwrite are intended to be used in situations of this type. The function fwrite sends a block of data to the specified file. The function fread reads a block of data from file

Fwrite and fread function have 4 arguments The first argument is the address of the structure to be write to the disk/read from file. The second argument is the size of the structure in bytes.sizeof() operator gives the size of the variable in bytes. The third argument is the number of such structures that we want to read/write at one time. The last argument is the pointer to the file ,we want to read/write.

Example

fwrite(&customer, sizeof(record), 1, fpt ) ;


where customer is a structure variable of type record, and

fpt is the stream pointer associated with a data file that has been opened for output. fread(&customer,sizeof(record),1,fpt);

//for writing records to file

main( )
{ FILE *fp ; char another = 'Y' ; struct emp

{
char name[40] ; int age ; float bs ; }; struct emp e ; fp = fopen ( "EMP.DAT", "wb" ) ; if ( fp == NULL ) {

puts ( "Cannot open file" ) ;


exit( ) ; }

while ( another == 'Y' ) { printf ( "\nEnter name, age and basic salary: " ) ; scanf ( "%s %d %f", e.name, &e.age, &e.bs ) ; fwrite ( &e, sizeof ( e ), 1, fp ) ; printf ( "Add another record(Y/N)); another = getche( ) ; } fclose ( fp ) ; //reads records from file fp = fopen ( "EMP.DAT", "rb" ) ; if ( fp == NULL ) { puts ( "Cannot open file" ) ; exit( ) ; } while ( fread ( &e, sizeof ( e ), 1, fp ) == 1 ) printf ( "\n%s %d %f", e.name, e.age, e.bs ) ; fclose ( fp ) ; }

Concepts of binary file


All machine language files are actually binary files a binary file is a collection of bytes.

For opening a binary file,file mode has to be mentioned as rb or

wb in fopen command Binary files can be processed sequentially or, depending on the needs of the application, they can (and usually are) processed using random access techniques Binary files differ from text files in two ways mainly: Handling of newlines: representation of end of file: storage of numbers:

Random access to files


In random access data can be accessed and processed directly 1. 2.

3.

. If we want to access a particular record random access takes less time than the sequential access. Functions for Random access are rewind() return the file pointer to the beginning fseek() position the file pointer; ftell() return the current offset of the file pointer.

fseek
This function is used for setting the file position pointer at the

specified bytes
Three arguments are used by the fseek function:

Prototype: int fseek (file *fp, long offset, int origin);


1. a pointer to a file which has been opened correctly. 2. offset-the number of bytes to move from origin this is obtained

from the formula: the desired record number * the size of one record
3. origin-Position from where offset is added. It is specified by one

of the following constants defined in <stdio.h>:

constant SEEK_SET SEEK_CUR SEEK_END

value 0

description

Move the offset bytes from Beginning of file Move the offset bytes from Current position of the file pointer Move the offset bytes from End of file

/* fseek example */ #include <stdio.h> Void main () { FILE * pFile; pFile = fopen ( "example.txt" , "w" ); fputs ( "This is an apple." , pFile ); fseek ( pFile , 9 , SEEK_SET ); fputs ( " sam" , pFile ); fclose ( pFile ); } After this code is successfully executed, the file example.txt contains: This is a sample.

statement
fseek(fp,0L,0); fseek(fp,0L,2); fseek(fp,-m, 1); fseek(fp,m,0); fseek(fp,m,1); fseek(fp,-m,1); fseek(fp,-m,2)

meaning
Go to the begining Go to end of file move back by m bytes from current position move to (m+1)th byte in file Go forward by m bytes Go backward by m bytes from current position Go backward by m bytes from end

ftell
Prototype: long int ftell ( FILE * fp ); returns current byte position in file On success, the current value of the position indicator is returned.If an error occurs, -1L is returned,
/* ftell example : getting size of a file */ #include <stdio.h> int main () { FILE * pFile; long size; pFile = fopen ("myfile.txt","rb"); if (pFile==NULL) perror ("Error opening file"); else { fseek (pFile, 0, SEEK_END); size=ftell (pFile); This program prints out the size fclose (pFile); of myfile.txt in bytes. printf ("Size of myfile.txt: %ld bytes.\n",size); } }

rewind
Prototype:void rewind ( FILE * fp); Set position indicator to the beginning On streams open for update (read+write), a call to rewind allows

to switch between reading and writing.

BITWISE OPERATIONS
Some applications require the manipulation of individual bits

within a word of memory C contains several special operators that allow such bitwise operations to be carried out easily and efficiently. These bitwise operators can be divided into three general categories: ones complement operator logical bitwise operators shift operators

Ones Complement Operator


The ones complement operator (~) is a unary operator that causes

the bits of its operand to be inverted EXAMPLE PROGRAM main ( ) { unsigned i = Ox5b3c; printf("hexadecima1values: i = %x ~i = %x\n", i, ~i); } OUTPUT hexadecimal values: i = 5b3c -i = a4c3 i = 0101 1011 0011 1100 -i = 1010 0100 1100 0011 (a4c3)

Logical Bitwise Operators


There are three logical bitwise operators: bitwise and (&), bitwise or (|) bitwise exclusive or ( ^ ) Each of these operators requires two integertype operands. The operations are carried out independently on each pair of corresponding bits within the operands.

A bitwise and expression will return a 1 if both bits have a value of 1 (i.e., if both bits are true).Otherwise, it will return a value of 0. A bitwise exclusive or expression will return a 1 if one of the bits has a value of 1 and the other has a value of 0 (one bit is true, the other false). Otherwise, it will return a value of 0. A bitwise or expression will return a 1 if one or more of the bits have a value of 1 (one or both bits are true). Otherwise, it will return a value of 0.

Logical Bitwise Operations

Example
a=Ox6db7 b= Oxa726 a b = = 0110 1101 1011 0111 1010 0111 0010 0110 = 0x2526

a & b = 0010 0101 0010 0110 a b = 0110 1101 1011 0111 = 1010 0111 0010 0110

a ^b = 1100 1010 1001 0001 a b a|b = 0110 1101 1011 0111 = 1010 0111 0010 0110 = 1110 1111 1011 0111

= Oxca91

= Oxefb7

Masking
Masking is a process in which a given bit pattern

is transformed into another bit pattern by means of a logical bitwise operation. The original bit pattern is one of the operands in the bitwise operation. The second operand, called the mask, is a specially selected bit pattern that brings about the desired transformation.

a is an unsigned integer variable whose value is Ox6db7. b = a & Ox3f; The second operand (the hexadecimal constant Ox3f) will serve as a mask. Thus, the resulting value of b will be 0x37. a = 0110 1101 1011 0111 mask = 0000 0000 0011 1111 b = 0000 0000 0011 0111 = 0x37.

Shift Operators
The two bitwise shift operators are
shift left (<<) shift right (>>) Each operator requires two operands. The first is an integer-type operand that represents the bit pattern to be

shifted. The second is an unsigned integer that indicates the number of


displacements

shift left (<<)


The left shift operator causes all of the bits in the first operand

to be shifted to the left by the number of positions indicated by


the second operand.
The leftmost bits (i.e., the overflow bits) in the original bit

pattern will be lost.


The rightmost bit positions that become vacant will be filled with

0s.

a=Ox6db7 b = a << 6;

Shift right
The right shift operator causes all of the bits in the first operand

to be shifted to the right by the number of positions indicated by the second operand.
The rightmost bits (i.e., the underflow bits) in the original bit

pattern will be lost.


the leftmost bit positions that become vacant will be filled with 0

a=Ox6db7 b = a >> 6;

Bitwise Assignment Operators


C also contains the following bitwise assignment

operators. &= ^= |= <<= >>= The left operand must be an assignable integertype identifier and the right operand must be a bitwise expression. For example a &= Ox7f is equivalent to a = a & Ox7f.

Bitfields
C allows integer members to be stored into memory spaces smaller than the compiler would ordinarily allow. These spacesaving structure members are called bit fields, and their width in bits can be explicitly declared. General format is: Struct bitfield_tag struct sample { { unsigned a : 1; unsigned b : 3; Unsigned int member1:bit_width1; unsigned c : 2; Unsigned int member2:bit_width2; unsigned d : 1; }; .. struct sample v; Unsigned int memberN:bit_widthn; }

Bitfields Enable better memory utilization Members Must be declared as int or unsigned

Enumeration
An enumeration is a user defined data type, similar to a structure or a

union.
General format to declare enumeration type is

enum tag {member I , member 2, . . . , member n }var1,var2,varn;


enum is a required keyword; tag specifies userdefined type

member I, member 2, . . . , member m are integer constants


Tag or variable name may be omiited . At least one should be exist in

declaration

Enumeration constants (members)are automatically assigned equivalent integer values, beginning with 0 for the first member , with each successive members has value increased by 1. Ex: enum days{mon,tue,wed,thur,fri,sat,sun}; Enum days start,end; Here mon to sun will assigned the values 0 to 6 Enumeration constants can be assigned explicit integer values which differ from the default values.

Those constants that are not assigned explicit values will automatically be assigned
values which increase successively by 1 from the last explicit assignment. For ex:enum colors {black = -1, blue, cyan, green, magenta, red = 2, white, yellow); Values will be

black =-1 blue =0 cyan= 1 green = 2 magenta = 3 red = 2 white = 3 yellow 4

Advantage of enumeration
The first advantage is that enumerated constants are generated

automatically by the compiler. Conversely, symbolic constants must be manually assigned values by the programmer. Another advantage of using the enumeration constant method is that your programs are more readable

Command line arguments


it is possible to pass arguments to C programs when they are

executed. This is called command line arguments


General form of main when passing argument is

int main ( int argc, char *argv[] )


Main returns an integer value.it can be used to determine program

termination successful or not When main is called, it is called with two arguments. The first argc, for argument count is the number of command-line

arguments the program.


the second argument is argv, for argument vector is a pointer to an array of character strings that contain the arguments, one per string.

argv[0] program name


argv[1] to argv[argc -1] give the other arguments as strings

#include <stdio.h> main ( int argc, char *argv[ ] ) { FILE *fs, *ft ; char ch ; if ( argc != 3 ) { puts ( "Improper number of arguments" ) ; exit( ) ; } fs = fopen ( argv[1], "r" ) ; if ( fs == NULL ) { puts ( "Cannot open source file" ) ; exit( ) ; }

ft = fopen ( argv[2], "w" ) ; if ( ft == NULL ) { puts ( "Cannot open target file" ) ; fclose ( fs ) ; exit( ) ; } while ( 1 ) { ch = fgetc ( fs ) ; if ( ch == EOF ) break ; else fputc ( ch, ft ) ; }fclose ( fs ) ;
fclose ( ft ) ; }

MACROS
A macro is a fragment of code which has been given a name. Whenever

the name is used, it is replaced by the contents of the macro.


#define statement can be used to define a macro General Form of #define is

#define macro_name replacement-text


Ex:#define PI 3.14159

Example program for macro #include <stdio.h> #define area length * width main( ) { int length,width; printf("length =) ; scanf('%d", &length); printf ("width = " ) ; scanf ("%d, &width); printf( " \n area = %d", area); }

A macro with arguments has its arguments substituted for

replacement text, when the macro is expanded General form is #define identifier(f1,f2,fn) string Identifier F1,f2,.fn are formal macro arguments.when macro called preprocessor substitutes the string

Ex: #define AREACIRCLE ( x ) ( PI * ( x ) * ( x ) ) When the statement area = AREACIRCLE( 4 ); executed then macro expand to 3.14*4*4.

Nesting of macro is possible #define square(x) ((x)*(x)) #define cube(x) (square(x)*(x))

Macros versus Functions


1.

2.

3.

4.
5.

macros make the program run faster but increase the program size, whereas functions make the program smaller and compact. When passing arguments to a macro, the number of arguments will be checked, but their data types will not. Thus, there is less error checking than with a function call. A macro identifier is not associated with an address,a macro identifier cannot be passed to a function as an argument, in the same sense that a function can be passed to another function as an argument . macro cannot call itself recursively .function can call recursively Macro cannt return value.function can return value

C preprocessor
The C preprocessor is a program that processes

our source program before it is passed to the compiler.


Preprocessor directives

unconditional

conditional

pragma define undef include line error if else elif ifdef ifndef endif

Directive #define #undef #include #ifdef

Explanation Defines a macro Undefines a macro Textually includes content of file Makes compilation of code conditional on macro being defined

#ifndef

Makes compilation of code conditional on macro not being defined


Makes end of a conditional compilation block Makes compilation of code on an expression being nonzero

#endif #if

#else
#elif #line #error #pragma

Specifies an else part of a #ifdef,#ifndef or #if directive


Combination of #else and #if Change current line number and filename Outputs an error message Is implementation specific

#undef
The #undef directive undefines a symbolic constant or a macro

identifier; i.e., it negates the effect of a #define directive that may have appeared earlier in the program. If a symbolic constant or macro has been undefined it can later be redefined General form is #undef macroname #define FOREGROUND 7 main ( ) { ..... #undef FOREGROUND ..... }

#include
The #include has 2 general forms #include <filename> and #include "filename"
Inserts the entire contents of filename in place of the #include line. First form is used for standard library header file. Angle brackets<>

indicates search for header file in standard location of library definitions. Second form Searches for a file in current directory.it is used for programmer-defined header files

Conditional Compilation
Enable the programmer to control the execution of preprocessor

directives, and the compilation of program code.


Each of the conditional preprocessor directives evaluates a constant

integer expression.
Cast expressions, sizeof()expressions, and enumeration constants cannot

be evaluated in preprocessor directives.


The conditional preprocessor construct is much like the if selection

structure.
These directives are very helpful in testing and debugging some part of C

program

#ifdef
#ifdef allows a section of a program to be compiled only if the

macro that is specified as the parameter has been defined, no matter which its value is.
General form is

For example #ifdef TABLE_SIZE int table[TABLE_SIZE];

#ifdef macroname <statement sequence> #endif

#endif

In this case, the line of code int table[TABLE_SIZE]; is only

compiled if TABLE_SIZE was previously defined with #define,

independently of its value. If it was not defined, that line will not be
included in the program compilation.

#ifndef
#ifndef serves for the exact opposite: the code

between #ifndef and #endif directives is only compiled if the specified

identifier has not been previously defined.


General form is

#ifndef macroname <statement sequence> #endif


For example:

#ifndef TABLE_SIZE

#define TABLE_SIZE 100


#endif int table[TABLE_SIZE];

#if, #else, #elif, #endif


The #if, #else and #elif (i.e., "else if") directives serve to specify some

condition to be met in order for the portion of code they surround to be compiled.
The condition that follows #if or #elif can only evaluate constant

expressions, including macro expressions.


General form of #if

Or #if<constant expression> <statement sequence1>

#if<constant expression> <statement sequence>

#endif

#else
<statement sequence2> #endif

Ex: #if TABLE_SIZE>200 #undef TABLE_SIZE #define TABLE_SIZE 200 endif The #elif command is similar to #if, except that it is used to extract one from a series of blocks of code.

General form of elif is


#if<constant expression1> <statement sequence1> #elif<constant expression2> <statement sequence2> #elif<constant expression N> <statement sequence N> #endif

if TABLE_SIZE>200 #undef TABLE_SIZE #define TABLE_SIZE 200 #elif TABLE_SIZE<50 #undef TABLE_SIZE #define TABLE_SIZE 50 #else #undef TABLE_SIZE #define TABLE_SIZE 100 #endif
#

int table[TABLE_SIZE];

The #endif command ends a block started by #if, #ifdef,

or #ifndef.

#error
The directive #error causes the preprocessor to report a fatal

error.
General form is

#error error-message
It will Stops preprocessing and prevents program compilation

#pragma
This directive is another special-purpose directive that you can

use to turn on or off certain features.


Pragmas vary from one compiler to another. So Actions will

depend on compiler
May use compiler-specific options Unrecognized #pragmas are ignored

#line
#line directive is used to change value of the LINE- and FILE-

variables
Filename is optional General form is

#line line-number <file name>


#line 100 "file1.cpp" Changes current line number to 100 and current file to

file1.Cpp

Advantages of Preprocessor in C
It improves the readability of C program.

It makes the C program easy to maintain.


It makes the C program more portable.

19.9 Predefined Symbolic Constants


Four predefined symbolic constants
Cannot be used in #define or #undef
Symbolic constant
__LINE__ __FILE__ __DATE__ __TIME__

Description
The line number of the current source code line (an integer constant). The presumed name of the source file (a string). The date the source file is compiled (a string of the form "Mmm dd yyyy" such as "Jan 19 2001"). The time the source file is compiled (a string literal of the form "hh:mm:ss").

The # and ## Operators


#operator is known as the stringize operator The # operator converts a macro argument into a string literal: Ex:

#define PRINT_INT(x) printf(#x " = %d\n", x) PRINT_INT(i/j); The preprocessor will replace the call of PRINT_INT by the following code: printf("i/j" " = %d\n", i/j); which is equivalent to printf("i/j = %d\n", i/j);

## operator ## by itself is known as the token-pasting operator Concatenates two tokens Ex: #define TOKENCONCAT( x, y ) x ## y TOKENCONCAT( O, K ) becomes OK

During program development, programmers often find it helpful to comment out large portions of code to prevent it from being compiled

For giving comments we can use #if 0 code prevented from compiling... #endif

To enable the code to be compiled, the 0 in the preceding construct is replaced by 1.

You might also like