You are on page 1of 32

FileHandlinginC

Wefrequentlyusefilesforstoringinformationwhichcan
beprocessedbyourprograms.Inordertostoreinformation
permanentlyandretrieveitweneedtousefiles.
Files are not only used for data. Our programs are also
storedinfiles.
Theeditorwhichyouusetoenteryourprogramandsaveit,
simplymanipulatesfilesforyou.
TheUnixcommands cat,cp,cmp areallprograms
whichprocessyourfiles.
InordertousefileswehavetolearnaboutFileI/Oi.e.how
towriteinformationtoafileandhowtoreadinformation
fromafile.
WewillseethatfileI/Oisalmostidenticaltotheterminal
I/Othatwehavebeingusingsofar.
The primary difference between manipulating files and
doingterminalI/Oisthatwemustspecifyinourprograms
whichfileswewishtouse.
Asyouknow,youcanhavemanyfilesonyourdisk.Ifyou
wishtouseafileinyourprograms,thenyoumustspecify
whichfileorfilesyouwishtouse.
1

Specifyingthefileyouwishtouseisreferredtoasopening
thefile.
Whenyouopenafileyoumustalsospecifywhatyouwish
todowithiti.e. Read fromthefile, Write tothefile,or
both.
Becauseyoumayuseanumberofdifferentfilesinyour
program,youmustspecifywhenreadingorwritingwhich
file you wish to use. This is accomplished by using a
variablecalledafilepointer.
Everyfileyouopenhasitsownfilepointervariable.When
youwishtowritetoafileyouspecifythefilebyusingits
filepointervariable.
Youdeclarethesefilepointervariablesasfollows:

FILE*fopen(),*fp1,*fp2,*fp3;
Thevariablesfp1,fp2,fp3arefilepointers.Youmay
useanynameyouwish.
Thefile<stdio.h>containsdeclarationsfortheStandard
I/O library and should always be included at the very
beginningofCprogramsusingfiles.
2

Constantssuchas FILE, EOF and NULL aredefinedin


<stdio.h>.
Youshouldnotethatafilepointerissimplyavariablelike
anintegerorcharacter.
Itdoesnotpointtoafileorthedatainafile.Itissimply
usedtoindicatewhichfileyourI/Ooperationrefersto.
A file number is used in the Basic language and a unit
numberisusedinFortranforthesamepurpose.
The function fopen is one of the Standard Library
functionsandreturnsafilepointerwhichyouusetorefer
tothefileyouhaveopenede.g.
fp=fopen(prog.c,r);

The above statement opens a file called prog.c for


readingandassociatesthefilepointerfpwiththefile.
WhenwewishtoaccessthisfileforI/O,weusethefile
pointervariablefptorefertoit.
Youcanhaveuptoabout20filesopeninyourprogram
youneedonefilepointerforeachfileyouintendtouse.
3

FileI/O
TheStandardI/OLibraryprovidessimilarroutinesforfile
I/OtothoseusedforstandardI/O.
Theroutinegetc(fp)issimilartogetchar()
andputc(c,fp)issimilartoputchar(c).
Thusthestatement
c=getc(fp);

readsthenextcharacterfromthefilereferencedby fpand
thestatement
putc(c,fp);

writesthecharactercintofilereferencedbyfp.

/* file.c: Display contents of a file on


screen*/
#include<stdio.h>
voidmain()
{
FILE*fopen(),*fp;
intc;
fp=fopen(prog.c,r);
c=getc(fp);
while(c!=EOF)
{
putchar(c);
c=getc(fp);

}
fclose(fp);
}

Inthisprogram,weopenthefileprog.cforreading.
Wethenreadacharacterfromthefile.Thisfilemustexist
forthisprogramtowork.
Ifthefileisempty,weareattheend,so getcreturnsEOFa
special value to indicate that the end of file has been
reached.(Normally1isusedforEOF)

Thewhileloopsimplykeepsreadingcharactersfromthe
fileanddisplayingthem,untiltheendofthefileisreached.
Thefunctionfclose isusedtoclosethefilei.e.indicate
thatwearefinishedprocessingthisfile.
Wecouldreusethefilepointerfpbyopeninganotherfile.
Thisprogramisineffectaspecialpurposecatcommand.
Itdisplaysfilecontentsonthescreen,but only forafile
calledprog.c.
Byallowingtheuserenter afilename,whichwouldbe
storedinastring,wecanmodifytheabovetomakeitan
interactivecatcommand:

/* cat2.c: Prompt user for filename and


displayfileonscreen*/
#include<stdio.h>
voidmain()
{
FILE*fopen(),*fp;
intc;
charfilename[40];
printf(Enterfiletobedisplayed:);
gets(filename);
fp=fopen(filename,r);

c=getc(fp);

while(c!=EOF)
{
putchar(c);
c=getc(fp);
}
fclose(fp);
}

Inthisprogram,wepassthenameofthefiletobeopened
whichisstoredinthearraycalledfilename,tothefopen
function. In general, anywhere a string constant such as
7

prog,c can beusedso can acharacter arraysuchas


filename.(Notethereverseisnottrue).

Theaboveprogramssufferamajorlimitation.Theydonot
checkwhetherthefilestobeusedexistornot.

Ifyouattempttoreadfromannonexistentfile,
yourprogramwillcrash!!
The fopen function was designed to cope with this
eventuality. It checks if the file can be opened
appropriately. If the file cannot be opened, it returns a
NULL pointer.Thusbycheckingthefilepointerreturned
by fopen, you can determine if the file was opened
correctlyandtakeappropriateactione.g.
fp=fopen(filename,r);
if(fp==NULL)
{
printf(Cannotopen%sforreading\n,filename
);
exit(1);/*Terminateprogram:Commitsuicide!!
*/
}

Theabovecodefragmentshowhowaprogrammightcheck
ifafilecouldbeopenedappropriately.
Thefunctionexit()isaspecialfunctionwhichterminates
yourprogramimmediately.
8

exit(0)meanthatyouwishtoindicatethatyourprogram
terminatedsuccessfullywhereasanonzerovaluemeansthat
yourprogramisterminatingduetoanerrorcondition.
Alternatively, you could prompt the user to enter the
filenameagain,andtrytoopenitagain:
fp=fopen(fname,r);
while(fp==NULL)
{
printf(Cannotopen%sforreading\n,fname);
printf(\n\nEnterfilename:);
gets(fname);
fp=fopen(fname,r);
}

Inthiscodefragment,wekeepreadingfilenamesfromthe
useruntilavalidexistingfilenameisentered.
Exercise: Modifytheabovecodefragmenttoallowthe
user3chancestoenteravalidfilename.Ifavalidfilename
isnotenteredafter3chances,terminatetheprogram.
RULE: Always check when opening files, that fopen
succeedsinopeningthefilesappropriately.
Obeyingthissimplerulewillsaveyoumuchheartache.

Example1:Writeaprogramtocountthenumberoflines
andcharactersinafile.
Note:Eachlineofinputfromafileorkeyboardwillbe
terminated by the newline character \n. Thus by
countingnewlinesweknowhowmanylinesthereareinour
input.

10

/*count.c:Countcharactersinafile*/
#include<stdio.h>
voidmain()
/* Prompt user for file and count number of
characters
andlinesinit*/
{
FILE*fopen(),*fp;
intc,nc,nlines;
charfilename[40];
nlines=0;
nc=0;
printf(Enterfilename:);
gets(filename);
fp=fopen(filename,r);
if(fp==NULL)
{
printf(Cannotopen%sforreading\n,filename
);
exit(1);/*terminateprogram*/
}
c=getc(fp);
while(c!=EOF)
{
if(c==\n)
nlines++;
nc++;
c=getc(fp);
}
fclose(fp);
if(nc!=0)
{
11

printf(Thereare%dcharactersin%s\n,nc,
filename);
printf(Thereare%dlines\n,nlines);
}
else
printf(File:%sisempty\n,filename);
}

Example2:Writeaprogramtodisplay filecontents20
linesatatime.Theprogrampausesafterdisplaying20lines
untiltheuserpresseseitherQtoquitorReturntodisplay
the next 20 lines. (The Unix operating system has a
commandcalledmoretodothis)Asinpreviousprograms,
wereadthefilenamefromuserandopenitappropriately.
Wethenprocessthefile:
readcharacterfromfile
whilenotendoffileandnotfinisheddo
begin
displaycharacter
ifcharacterisnewlinethen
linecount=linecount+1;
iflinecount==20then
begin
linecount=1;
Promptuserandgetreply;
end
12

readnextcharacterfromfile
end

13

/*display.c:Filedisplayprogram*/
/* Prompt user for file and display it 20 lines at a
time*/
#include<stdio.h>
voidmain()
{
FILE*fopen(),*fp;
intc,linecount;
charfilename[40],reply[40];
printf(Enterfilename:);
gets(filename);
fp = fopen( filename, r ); /* open for
reading*/
if(fp==NULL)/*checkdoesfileexistetc
*/
{
printf(Cannotopen%sforreading\n,filename
);
exit();/*terminateprogram*/
}
linecount=1;
reply[0]=\0;
c=getc(fp); /*Read1stcharacterifany
*/
while(c!=EOF&&reply[0]!=Q&&reply[0]!=
q)
{
putchar(c);
/*Displaycharacter*/
if(c==\n)
linecount=linecount+1;
if(linecount==20)
{
linecount=1;
14

printf([Press Return to continue, Q to


quit]);
gets(reply);
}
c=getc(fp);
}
fclose(fp);
}

Thestringreplywillcontaintheusersresponse.Thefirst
characterofthiswillbereply[0].Wecheckifthisisq
orQ.Thebrackets[]in printf areusedtodistinguish
theprogramsmessagefromthefilecontents.
Example3:Writeaprogramtocomparetwofilesspecified
bytheuser,displayingamessageindicatingwhetherthe
files are identical or different. This is the basis of a
compare command provided by most operating systems.
Hereourfileprocessingloopisasfollows:
readcharactercafromfileA;
readcharactercbfromfileB;
whileca==cbandnotEOFfileAandnotEOFfile
B
begin
readcharactercafromfileA;
readcharactercbfromfileB;
end
ifca==cbthen
printout(Filesidentical);
else
printout(Filesdiffer);
15

ThisprogramillustratestheuseofI/Owithtwofiles.In
general you can manipulate up to 20 files, but for most
purposesnotmorethan4fileswouldbeused.Allofthese
examples illustrate the usefulness of processing files
character by character. As you can see a number of
OperatingSystemprogramssuchascompare,type,more,
copy can be easily written using character I/O. These
programs are normally called system programs as they
come with the operating system. The important point to
noteisthattheseprogramsareinnowayspecial.Theyare
nodifferentinnaturethananyoftheprogramswehave
constructedsofar.

16

/*compare.c:comparetwofiles*/
#include<stdio.h>
voidmain()
{
FILE*fp1,*fp2,*fopen();
intca,cb;
charfname1[40],fname2[40];
printf(Enterfirstfilename:);
gets(fname1);
printf(Entersecondfilename:);
gets(fname2);
fp1 = fopen( fname1, r ); /* open for
reading*/
fp2 = fopen( fname2, r ) ; /* open for
writing*/
if(fp1==NULL)/*checkdoesfileexistetc
*/
{
printf(Cannot open %s for reading \n,
fname1);
exit(1);/*terminateprogram*/
}
elseif(fp2==NULL)
{
printf(Cannot open %s for reading \n,
fname2);
exit(1);/*terminateprogram*/
}
else
/*bothfilesopenedsuccessfully*/
{
ca=getc(fp1);
cb=getc(fp2);
while(ca!=EOF&&cb!=EOF&&ca==
cb)
{
ca=getc(fp1);
cb=getc(fp2);
}
if(ca==cb)
17

printf(Filesareidentical\n);
elseif(ca!=cb)
printf(Filesdiffer\n);
fclose(fp1);
fclose(fp2);
}
}

18

WritingtoFiles
Thepreviousprogramshaveopenedfilesforreadingand
readcharactersfromthem.
Towritetoafile,thefilemustbeopenedforwritinge.g.
fp=fopen(fname,w);

Ifthefiledoesnotexistalready,itwillbecreated. Ifthe
filedoesexist,itwillbeoverwritten!So,becarefulwhen
opening files for writing, in case you destroy a file
unintentionally.Openingfilesforwritingcanalsofail.If
youtrytocreateafileinanotherusersdirectorywhereyou
donothaveaccessyouwillnotbeallowedandfopenwill
fail.
CharacterOutputtoFiles
Thefunctionputc(c,fp)writesacharactertothefile
associatedwiththefilepointerfp.
Example:
Writeafilecopyprogramwhichcopiesthefile
prog.ctoprog.old
Outlinesolution:
Openfilesappropriately
Checkopensucceeded
Readcharactersfromprog.cand
Write characters to prog.old until all characters
copied
19

Closefiles

Thestep:Readcharacters....andwrite..mayberefined
to:
readcharacterfromprog.c
whilenotendoffiledo
begin
writecharactertoprog.old
readnextcharacterfromprog.c
end

20

/*filecopy.c:Copyprog.ctoprog.old*/
#include<stdio.h>
voidmain()
{
FILE*fp1,*fp2,*fopen();
intc;
fp1=fopen(prog.c, r); /*open
forreading*/
fp2=fopen(prog.old,w);../*openfor
writing*/
if(fp1==NULL) /*checkdoesfile
existetc*/
{
printf(Cannotopenprog.cforreading\n
);
exit(1);/*terminateprogram*/
}
elseif(fp2==NULL)
{
printf(Cannot open prog.old for
writing\n);
exit(1);/*terminateprogram*/
}
else
/*bothfilesO.K.*/
{
c=getc(fp1);

while(c!=EOF)
{
putc(c,fp2);/*copytoprog.old
*/
c=getc(fp1);
}
fclose(fp1);

/*Nowclosefiles*/
21

fclose(fp2);
printf(Filessuccessfullycopied\n);
}
}

22

Theaboveprogramonlycopiesthespecificfileprog.cto
the file prog.old. We can make it a general purpose
programbypromptingtheuserforthefilestobecopied
andopeningthemappropriately.
/*copy.c:Copyanyuserfile*/
#include<stdio.h>
voidmain()
{
FILE*fp1,*fp2,*fopen();
intc;
charfname1[40],fname2[40];
printf(Entersourcefile:);
gets(fname1);
printf(Enterdestinationfile:);
gets(fname2);
fp1 = fopen( fname1, r ); /* open for
reading*/
fp2=fopen(fname2,w);../*openforwriting*/
if(fp1==NULL)/*checkdoesfileexistetc
*/
{
printf(Cannot open %s for reading \n,
fname1);
exit(1);/*terminateprogram*/
}
elseif(fp2==NULL)
{
printf(Cannot open %s for writing \n,
fname2);
exit(1);/*terminateprogram*/
}
else
/*bothfilesO.K.*/
{
c=getc(fp1);
/*readfromsource*/
23

while(c!=EOF)
{
putc(c,fp2);/*copytodestination*/
c=getc(fp1);
}
fclose(fp1);
/*Nowclosefiles*/
fclose(fp2);
printf(Filessuccessfullycopied\n);
}
}

24

CommandLineParameters:Argumentsto
main()
Accessingthecommandlineargumentsisaveryusefulfacility.It
enablesyoutoprovidecommandswithargumentsthatthe
commandcanusee.g.thecommand
%catprog.c
takestheargument"prog.c"andopensafilewiththatname,
whichitthendisplays.Thecommandlineargumenstincludethe
commandnameitselfsothatintheaboveexample,"cat"and
"prog.c"arethecommandlinearguments.Thefirstargumenti.e.
"cat"isargumentnumberzero,thenextargument,"prog.c",is
argumentnumberoneandsoon.
ToaccesstheseargumentsfromwithinaCprogram,youpass
parameterstothefunctionmain().Theuseofargumentsto
mainisakeyfeatureofmanyCprograms.
Thedeclarationofmainlookslikethis:
intmain(intargc,char*argv[])
Thisdeclarationstatesthat
1.
2.
3.

mainreturnsanintegervalue(usedtodetermineifthe
programterminatessuccessfully)
argcisthenumberofcommandlineargumentsincluding
thecommanditselfi.eargcmustbeatleast1
argvisanarrayofthecommandlinearguments
25

Thedeclarationofargvmeansthatitisanarrayofpointersto
strings(thecommandlinearguments).Bythenormalrulesabout
argumentswhosetypeisarray,whatactuallygetspassedtomain
istheaddressofthefirstelementofthearray.Asaresult,an
equivalent(andwidelyused)declarationis:
intmain(intargc,char**argv)
Whentheprogramstarts,thefollowingconditionsholdtrue:
oargcisgreaterthan0.
oargv[argc]isanullpointer.
oargv[0],argv[1],...,argv[argc1]arepointersto
strings
withimplementationdefinedmeanings.
oargv[0]isastringwhichcontainstheprogramsname,oris
an
emptystringifthenameisntavailable.Remainingmembers
of
argvaretheprogramsarguments.

26

Example:print_argsechoesitsargumentstothestandardoutput
isaformoftheUnixechocommand.

/*print_args.c:Echocommandlinearguments*/
#include<stdio.h>
#include<stdlib.h>
intmain(intargc,char*argv[])
{
inti=0;
intnum_args;
num_args=argc;
while(num_args>0)
{
printf(%s\n,argv[i]);
i++;
num_args;
}
}

Ifthenameofthisprogramisprint_args,anexampleofits
executionisasfollows:
%print_argshellogoodbyesolong
print_args
hello
goodbye
solong
%

27

Exercise: Rewrite print_argsso that it operates like the Unix


echo command. Hint: You only need to change the printf
statement.

28

ThefollowingisaversionoftheUnixcatcommand:
/*cat1.c:Displayfilesspecifiedascommandlineparameters*/
#include<stdio.h>
#include<stdlib.h>
intmain(intargc,char*argv[])
{
inti=1;
intc;
intnum_args=0;
FILE*fp;
if(argc==1)
{
fprintf(stderr,"Noinputfiles\nUsage:%catfile\n");
exit(1);
}
if(argc>1)
printf("%dfilestobedisplayed\n",argc1);
num_args=argc1;
while(num_args>0)
{
printf("[Displayingfile%s]\n",argv[i]);
num_args;
fp=fopen(argv[i],"r");
if(fp==NULL)
{
fprintf(stderr,"Cannotdisplay%s\n",argv[i]);
continue;/*Gotonextfileinlist*/
}
c=getc(fp);
while(c!=EOF)
{
putchar(c);
c=getc(fp);
}
fclose(fp);
printf("\n[Endof%s]\n\n\n",argv[i]);
i++;
}
}
29

Note:Thecontinuestatementcausesthecurrentiterationoftheloopto
stopandcontroltoreturntothelooptest.

ThefollowingisaversionoftheUnixwccommandcalled
countwhichoperatesasfollows
%countprog.c
prog.c:300characters20lines
%countlprog.c
prog.c:20lines
%countwprog.c
prog.c:300characters

/*count.c:Countlinesandcharactersinafile*/
#include<stdio.h>
#include<stdlib.h>
intmain(intargc,char*argv[])
{
intc,nc,nlines;
charfilename[120];
FILE*fp,*fopen();
if(argc==1)
{
fprintf(stderr,"Noinputfiles\n");
fprintf(stderr,"Usage:\%count[l][w]file\n");
exit(1);
}
nlines=0;
nc=0;
if((strcmp("l",argv[1])==0)||
(strcmp("w",argv[1])==0))
strcpy(filename,argv[2]);
else
strcpy(filename,argv[1]);
30

fp=fopen(filename,"r");
if(fp==NULL)
{
fprintf(stderr,"Cannotopen%s\n",filename);
exit(1);
}
c=getc(fp);
while(c!=EOF)
{
if(c=='\n')
nlines++;
nc++;
c=getc(fp);
}
fclose(fp);
if(strcmp(argv[1],"w")==0)
printf("%s:%dcharacters\n",filename,nc);
elseif(strcmp(argv[1],"l")==0)
printf("%s:%dlines\n",filename,nlines);
else
printf("%s:%dcharacters%dlines\n",filename,nc,
nlines);

LogicalORisrepresentedby||inthecodeabove.LogicalANDisrepresentedby
&&inC.
Thefunctionstrcpy()isoneofmanylibrarystringhandlingfunctions.Ittakes
twostringsasargumentsandcopiesthesecondargumenttothefirsti.e.itoperatesas
aformofstringassignment.InCyouCANNOTassignstringsas:
filename="prog.c"/*WRONG*/

strcpy(filename,"prog.c");/*CORRECT*/

Thefunctionstrcmp()isanotherstringhandlingfunction.Ittakestwo
stringsasargumentsandreturns0ifthetwostringsarethesame.Asfor
assignment,youcannotteststringequalitywith==i.e.
if(filename=="prog.c")/*WRONG*/

31

if(strcmp(filename,"prog.c")==0)/*CORRECT*/

Note:Theaboveprogramcrashesifyourunitas:
%countw
or
%countl

Thisisbecauseinthesecaseswefailedtotestiftherewasa3 rd
argumentcontainingthefilenametobeprocessed.Wesimplytry
to access this nonexistent argument and so cause a memory
violation. This gives rise to a socalled "bus error" in a Unix
environment.
Asanexercise,insertcodetocorrectthisfailure.

Exercise:WriteacopycommandtooperateliketheUnix
cpcommandthattakesitfilesfromthecommandline:
%copyfilenewfile

32

You might also like