Tải bản đầy đủ - 0 (trang)
3 Stream I/O of LINT Objects

3 Stream I/O of LINT Objects

Tải bản đầy đủ - 0trang

14.3StreamI/OofLINTObjects

TheclassescontainedintheC++standardlibrarysuchasistreamand

ostreamareabstractionsofinputandoutputdevicesderivedfromthe

baseclassios.Theclassiostreamisinturnderivedfromistream

andostream,anditenablesbothwritingandreadingofitsobjects.[1]

Inputandoutputtakeplacewiththehelpoftheinsertandextract

operators"<<"and">>"(cf.[Teal],Chapter8).Thesearisethrough

overloadingtheshiftoperators,forexampleintheform

ostream&ostream::operator<<(inti);

istream&istream::operator>>(int&i);

inwhichtheyenableoutput,respectivelyinput,ofintegervaluesthrough

expressionsoftheform

cout<
cin>>i;

Asspecialobjectsoftheclassesostreamandistream,coutandcin

representthesameabstractfilesastheobjectsstdoutandstdinof

thestandardClibrary.

Theuseofthestreamoperators"<<"and">>"forinputandoutput

makesitunnecessarytoconsiderparticularpropertiesofthehardwarein

use.Inandofitselfthisisnothingnew,fortheCfunctionprintf()

behavesthesameway:Aprintf()instructionshouldalways,

regardlessofplatform,leadtothesameresult.However,aboveand

beyondthealteredsyntax,whichisorientedtothemetaphoricalimageof

theinsertionofobjectsintoastream,theadvantagesoftheC++

implementationofstreamslieinthestricttypechecking,whichinthe

caseofprintf()ispossibleonlytoalimiteddegree,andinits

extensibility.Inparticular,wemakeuseofthelatterpropertyby

overloadingtheinsertandextractoperatorssothattheysupportinput

andoutputofLINTobjects.TothisendtheclassLINTdefinesthe

followingstreamoperators:

friendostream&operator<<(ostream&s,constLINT&ln);



friendfstream&operator<<(fstream&s,constLINT&ln);

friendofstream&operator<<(ofstream&s,constLINT&ln);

friendfstream&operator>>(fstream&s,LINT&ln);

friendifstream&operator>>(ifstream&s,LINT&ln);

Asimpleformulationoftheoverloadedinsertoperatorsfortheoutputof

LINTobjectsmightlooksomethinglikethefollowing:

#include



ostream&operator<<(ostream&s,constLINT&ln)

{

if(!ln.init)

LINT::panic(E_LINT_VAL,"ostreamoperator<<",0,__LINE

s<
s<
returns;

}

Theoperator<
hexadecimalvaluesandaddsthebinarylengthofthenumberina

separateline.Inthenextsectionweshallconsiderthepossibilitiesof

improvingtheappearanceoftheoutputofLINTobjectswiththeaidof

formattingfunctions,andweshallalsousemanipulatorstomakethe

outputcustomizable.



14.3.1FormattedOutputofLINTObjects

InthissectionweshallmakeuseofthebaseclassiosoftheC++

standardlibraryandofitsmemberfunctionstodefineourownLINTspecificformattingfunctionsforthepurposeofcontrollingtheoutput

formatofLINTobjects.Furthermore,weshallcreatemanipulatorsthat

willmakethecustomizationoftheoutputformatforLINTobjectsas

simpleasitisforthestandardtypesdefinedinC++.

ThecrucialpointinthecreationofformattedoutputofLINTobjectsisthe

possibilityofsettingformattingspecificationsthatwillbehandledbythe



insertoperator.Tothisendweshallconsiderthemechanismprovidedfor

theclassios(fordetailssee[Teal],Chapter6,and[Pla2],Chapter6),

whosememberfunctionxalloc()intheobjectsoftheclassesderived

fromiosallocatesastatusvariableoftypelongandreturnsanindexto

thisstatusvariablealsooftypelong.Westorethisindexinthelong

variableflagsindex.Bymeansofthisindexthememberfunction

ios::iword()canbeusedtoaccessreadingandwritingtothe

allocatedstatusvariable(cf.[Pla2],page125).

ToensurethatthistakesplacebeforeaLINTobjectisoutput,wedefine,

inthefileflintpp.h,theclassLintInitasfollows:

classLintInit

{

public:

LintInit(void);

};

LintInit::LintInit(void)

{

//getindextolongstatusvariableinclassios

LINT::flagsindex=ios::xalloc();

//setthedefaultstatusincoutandincerr

cout.iword(LINT::flagsindex)=

cerr.iword(LINT::flagsindex)=

LINT::lintshowlength|LINT::linthex|LINT::lintshowbase;

}

TheclassLintInithasasitsonlyelementtheconstructor

LintInit::LintInit().Furthermore,intheclassLINTwedefinea

memberdatumsetupoftypeLintInit,whichisinitializedviathe

constructorLintInit::LintInit().Thecalltoxalloc()takes

placewithinthisinitialization,andthestatusvariabletherebyallocatedis

giventheestablishedstandardoutputformatforLINTobjects.Inthe

followingweshallshowasectionoftheLINTclassdeclaration,which

containsthedeclarationofLintInit()asafriendofLINT,the

declarationofthevariablesflagsindexandsetup,andvariousstatus



valuesasenumtypes:

classLINT

{

public:

//...

enum{

lintdec=0x10,

lintoct=0x20,

linthex=0x40,

lintshowbase=0x80,

lintuppercase=0x100,

lintbin=0x200,

lintshowlength=0x400

};

//...

friendLintInit::LintInit(void);

//...

private:

//...

staticlongflagsindex;

staticLintInitsetup;

//...

};

Settingthevariablesetupasstatichastheeffectthatthisvariable

existsonlyonceforallLINTobjectsandthustheassociatedconstructor

LintInit()iscalledonlyonce.

Wewouldlikenowtopauseforamomentandconsiderwhatallthis

effortnetsus.Settingtheoutputformatcouldjustaswellbemanagedvia

astatusvariable,whichasamemberofLINTwouldbemuchsimplerto

dealwith.Thedecisiveadvantageofthemethodthatwehavechosenis

thattheoutputformatcanbesetforeachoutputstreamseparatelyand

independentlyoftheothers(cf.[Pla2],page125),whichcouldnotbe

accomplishedwithaninternalLINTstatusvariable.Thisisdonethrough



thepoweroftheclassios,whosemechanismsweemployforsuch

purposes.

Nowthatthenecessarypreliminarieshavebeentakencareof,wecan

definethestatusfunctionsasmemberfunctionsofLINT.Theseare

displayedinTable14.1.

Weshallconsiderasanexampleoftheimplementationofthestatus

functionsthefunctionLINT::setf(),whichreturnsthecurrentvalueof

thestatusvariableasalongwithreferencetoanoutputstream:

Table14.1:LINTstatusfunctionsandtheireffects

Statusfunction



Explanation



staticlong

LINT::flags

(void);



readthestatusvariablewithreferenceto

cout



staticlong

LINT::flags

(ostream&);



readthestatusvariablewithreferencetoan

arbitraryoutputstream



staticlong

LINT::setf

(long);



setindividualbitsofthestatusvariablewith

referencetocoutandreturntheprevious

value



staticlong

setindividualbitsofthestatusvariablewith

LINT::setf

referencetoanarbitraryoutputstreamand

(ostream&,long);

returnthepreviousvalue

staticlong

LINT::unsetf

(long);

staticlong



restoreindividualbitsofthestatusvariable

withreferencewithreferencetocoutand

returnthepreviousvalue



LINT::unsetf

restoreindividualbitsofthestatusvariable

(ostream&,long); withreferencetoanarbitraryoutputstream

andreturnthepreviousvalue

staticlong

LINT::restoref

(long);



setthestatusvariablewithreferencetocout

withavalueandreturnthepreviousvalue



staticlong

setthestatusvariablewithreferencetoan

LINT::restoref

arbitraryoutputstreamwithavalueand

(ostream&,long);

returnthepreviousvalue



longLINT::setf(ostream&s,longflag)

{

longt=s.iword(flagsindex);

//theflagsforthebasisofthenumericalrepresentation

//aremutuallyexclusive

if(flag&LINT::lintdec)

{

s.iword(flagsindex)=(t&~LINT::linthex&~LINT::lintoct

&~LINT::lintbin)|LINT::lintdec;

flag^=LINT::lintdec;

}



if(flag&LINT::linthex)

{

s.iword(flagsindex)=(t&~LINT::lintdec&~LINT::lintoct

&~LINT::lintbin)|LINT::linthex;

flag^=LINT::linthex;

}



if(flag&LINT::lintoct)

{

s.iword(flagsindex)=(t&~LINT::lintdec&~LINT::linthex

&~LINT::lintbin)|LINT::lintoct;

flag^=LINT::lintoct;



}



if(flag&LINT::lintbin)

{

s.iword(flagsindex)=(t&~LINT::lintdec&~LINT::lintoct

&~LINT::linthex)|LINT::lintbin;

flag^=LINT::lintbin;

}

//allremainingflagsaremutuallycompatible

s.iword(flagsindex)|=flag;

returnt;

}

WiththehelpoftheseandtheremainingfunctionsofTable14.1wecan

determinetheoutputformatsinthefollowing.First,thestandardoutput

formatrepresentsthevalueofaLINTobjectasahexadecimalnumberin

acharacterstring,wheretheoutputfillsasmanylinesonthescreenas

requiredbythenumberofdigitsoftheLINTobject.Inanadditionalline

thenumberofdigitsoftheLINTobjectisdisplayedflushleft.The

followingadditionalmodesforoutputofaLINTobjecthavebeen

implemented:

1. Basefortherepresentationofdigits

ThestandardbasefortherepresentationofdigitsofLINT

objectsis16,andfortherepresentationofthelengthitis10.

ThisdefaultforLINTobjectscanbesetforthestandardoutput

streamcouttoaspecifiedbasebyacallto

LINT::setf(LINT::base);

andto

LINT::setf(ostream,LINT::base);

foranarbitraryoutputstream.Herebasecanassumeanyone

ofthevalues



linthex,lintdec,lintoct,lintbin,

whichdenotethecorrespondingoutputformat.Acallto

LINT::setf(lintdec),forexamplesetstheoutputformatto

decimaldigits.Thebasefortherepresentationofthelengthcan

besetwiththefunction

ios::setf(ios::iosbase);

withiosbase=hex,dec,oct.

2. Displayoftheprefixforthenumericalrepresentation

ThedefaultisforaLINTobjecttobedisplayedwithaprefix

indicatinghowitisrepresented.Acallto

LINT::unsetf(LINT::lintshowbase);

LINT::unsetf(ostream,LINT::lintshowbase);

changesthissetting.

3. Displayofhexadecimaldigitsinuppercaseletters

Thedefaultisthedisplayofhexadecimaldigitsandthedisplay

oftheprefix0xforahexadecimalrepresentationinlowercase

lettersabcdef.However,acallto

LINT::setf(LINT::lintuppercase);

LINT::setf(ostream,LINT::lintuppercase);

changesthis,sothattheprefix0Xanduppercaseletters

ABCDEFaredisplayed.

4. DisplayofthelengthofaLINTobject

ThedefaultisthedisplayofthebinarylengthofaLINTobjects.

Thiscanbechangedbyacallto

LINT::unsetf(LINT::lintshowlength);

LINT::unsetf(ostream,LINT::lintshowlength);

sothatthelengthisnotdisplayed.



5. Restoringthestatusvariableforthenumerical

representation

ThestatusvariablefortheformattingofaLINTobjectcanbe

restoredtoapreviousvalueoldflagsbyacalltothetwo

functions

LINT::unsetf(ostream,LINT::flags(ostream));

LINT::setf(ostream,oldflags);

Callstothesetwofunctionsarecollectedintheoverloaded

functionrestoref():

LINT::restoref(flag);

LINT::restoref(ostream,flag);

Flagscanbecombined,asinthecall

LINT::setf(LINT::bin|LINT::showbase);

This,however,ispermittedonlyforflagsthatarenotmutuallyexclusive.

Theoutputfunctionthatfinallygeneratestherequestedrepresentational

formatforLINTobjectsisanextensionoftheoperatorostream&

operator<<(ostream&s,LINTln)alreadysketchedabove,

whichevaluatesthestatusvariablesoftheoutputstreamandgenerates

theappropriateoutput.Forthistheoperatorusestheauxiliaryfunction

lint2str()containedinflintpp.cpp,whichinturncallsthefunction

xclint2str_l()torepresentthenumericalvalueofaLINTobjectina

characterstring:

ostream&operator<<(ostream&s,constLINT&ln)

{

USHORTbase=16;

longflags=LINT::flags(s);

char*formatted_lint;



if(!ln.init)LINT::panic(E_LINT_VAL,"ostreamoperator<<"

if(flags&LINT::linthex)



{

base=16;

}

else

{

if(flags&LINT::lintdec)

{

base=10;

}

else

{

if(flags&LINT::lintoct)

{

base=8;

}

else

{

if(flags&LINT::lintbin)

{

base=2;

}

}

}

}

if(flags&LINT::lintshowbase)

{

formatted_lint=lint2str(ln,base,1);

}

else

{

formatted_lint=lint2str(ln,base,0);

}

if(flags&LINT::lintuppercase)

{

strupr_l(formatted_lint);



}

s<
if(flags&LINT::lintshowlength)

{

long_flags=s.flags();//getcurrentstatus

s.setf(ios::dec);//setflagfordecimaldisplay

s<
s.setf(_flags);//restorepreviousstatus

}

returns;

}



14.3.2Manipulators

Buildingonthepreviousmechanisms,wewouldlikeinthissectionto

obtainmoreconvenientpossibilitiesforcontrollingtheoutputformatfor

LINTobjects.Tothisendweusemanipulators,whichareplaceddirectly

intotheoutputstreamandthusdisplaythesameeffectsasoccurin

callingtheabovestatusfunctions.Manipulatorsareaddressesof

functionsforwhichthereexistspecialinsertoperatorsthatontheirpart

acceptapointertoafunctionasargument.Asanexampleweconsider

thefollowingfunction:

ostream&LintHex(ostream&s)

{

LINT::setf(s,LINT::linthex);

returns;

}

Thisfunctioncallsthestatusfunctionsetf(s,LINT::linthex)in

thecontextofthespecifiedoutputstreamostream&sandthereby

effectstheoutputofLINTobjectsashexadecimalnumbers.Thename

LintHexofthefunctionwithoutparenthesesisviewedasapointerto

thefunction(cf.[Lipp],page202)andcanbesetinanoutputstreamasa

manipulatorwiththehelpoftheinsertoperator



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

3 Stream I/O of LINT Objects

Tải bản đầy đủ ngay(0 tr)

×