Unformatted Character Input
This program is a close approximation of my offering
for my City & Guilds examination.
The exam question asked for a program which produced a
set of multiplication tables for a float.
The approach I chose parses input for tokens then prints
the times table. The program handles garbage input and
overflow.
If a float or garbage is entered instead of an int when
required, entry is truncated. The program makes great use
of globals and is not object oriented :)
These were not specified in the exam question.
| Header |
| Flags,
globals and function prototypes. |
|
// flags
enum Ttoken {FLOAT, ENTER, IGNORE};
enum Tfloat {WHOLEPOS, FRACTION, NEGATIVE, NEG_FRACTION};
// global constants
const unsigned BUF_SZ =10; // extra buffer to
facilitate '-' & '.'
const int MAX_INTEGER =15;
const char WELCOME[]="Welcome to the Table
Program.";
const char ENTER_FLOAT[]="\nEnter table no.
Any number less than 9 digits.\n";
const char ENTER_INT[]="\nEnter multiplier
no. Any positive whole number less than 15.\n";
const char AGAIN[]="\nPress y to repeat. Any
other key to end.";
// global variables
Ttoken currToken;
Tfloat floatType;
unsigned currInput;
char buf[BUF_SZ];
int currInputNo;
float fVar;
int iVar;
//function headers
Ttoken GetFloat();
void GetInt();
|
| Note: |
|
|
| GetFloat |
| Header
|
|
Ttoken
GetFloat()
{
char ch;
cin.get(ch);
switch(ch) // test input character
{
case '0' :
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
case '8' :
case '9' :
// handle buf overflow
if(floatType==NEG_FRACTION && buf[BUF_SZ-1])
currToken =IGNORE; // token is ignored
if((floatType==FRACTION || floatType==NEGATIVE)
&& buf[BUF_SZ-2])
currToken =IGNORE; // token is ignored
if(floatType==WHOLEPOS && buf[BUF_SZ-3])
currToken =IGNORE; // token is ignored
else
{
currToken =FLOAT; // float
break;
}
case '-':
if(buf[0]) // '-' accepted only once
{
currToken= IGNORE;
break;
}
else
{
floatType=NEGATIVE;
currToken= FLOAT;
break;
}
case '.':
if(floatType==FRACTION)
{
currToken= IGNORE;
break;
}
else
{
if(floatType==NEGATIVE)
floatType=NEG_FRACTION;
else
floatType=FRACTION;
currToken= FLOAT;
break;
}
case '\n':
currToken =ENTER;
break;
default :
return currToken =IGNORE;
}//switch(ch)
switch(currToken) // test parser flag
{ // and process input
case FLOAT: // parses number
{
buf[currInput]=ch;
currInput++;
return currToken =FLOAT;
}
case ENTER: // sets float variable
fVar =atof(buf);
return currToken =ENTER;
}//switch
};// GetFloat()
|
| Note: |
|
|
| GetInt |
| Header
|
|
void
GetInt()
{
char ch;
cin.get(ch);
switch(ch) // test input character
{
case '0' :
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
case '8' :
case '9' :
cin.putback(ch);
do
{
cin>>iVar;
}while(iVar<1 || iVar>MAX_INTEGER);
default:
;
}//switch
}//GetToken()
|
| Note: |
|
|
| main |
| Header
|
|
void
main()
{
int loop=0;
clrscr();
cout<<WELCOME;
do // main loop
{
// initialise variables
currInput = 0;
for(int i=0;i<BUF_SZ; i++)
buf[i] =0;
fVar =0;
iVar =0;
if(loop)
{
cin.ignore(); // take '\n' from istream
clrscr();
}
cout<<ENTER_FLOAT;
do // parse input for float
{
GetFloat();
}while(currToken!=ENTER);
do
{
clrscr();
cout<<ENTER_INT;
GetInt();
}while(!iVar);
cin.ignore(); // for '\n'
cout.setf(ios::fixed);
cout<<"\nThe "<<fVar<<"
times table to "<<iVar<<"
is:-\n";
for(int ii=1; ii<=iVar; ii++)
cout<<ii*fVar<<endl;
cout<<AGAIN<<endl; // loop?
loop=1;
}while(cin.get()=='y');
};
|
| Note: |
|
|
|
|