1003 lines
12 KiB
C++
1003 lines
12 KiB
C++
#include "iostream.h"
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
|
|
namespace opp {
|
|
|
|
ios::ios(void)
|
|
: mFlags(0), mState(0), mWidth(0), mPrecision(6), mFill(' ')
|
|
{}
|
|
|
|
inline ios::~ios(void)
|
|
{
|
|
|
|
}
|
|
|
|
char ios::fill(void) const
|
|
{
|
|
return mFill;
|
|
}
|
|
|
|
char ios::fill(char fillch)
|
|
{
|
|
char c = mFill;
|
|
mFill = fillch;
|
|
return c;
|
|
}
|
|
|
|
char ios::width() const
|
|
{
|
|
return mWidth;
|
|
}
|
|
|
|
char ios::width(char wide)
|
|
{
|
|
char w = mWidth;
|
|
mWidth = wide;
|
|
return w;
|
|
}
|
|
|
|
char ios::precision() const
|
|
{
|
|
return mPrecision;
|
|
}
|
|
|
|
char ios::precision(char wide)
|
|
{
|
|
char w = mPrecision;
|
|
mPrecision = wide;
|
|
return w;
|
|
}
|
|
|
|
ios::fmtflags ios::flags(void) const
|
|
{
|
|
return mFlags;
|
|
}
|
|
|
|
ios::fmtflags ios::flags(ios::fmtflags f)
|
|
{
|
|
fmtflags pf = mFlags;
|
|
mFlags = f;
|
|
return pf;
|
|
}
|
|
|
|
ios::fmtflags ios::setf(ios::fmtflags f)
|
|
{
|
|
fmtflags pf = mFlags;
|
|
mFlags |= f;
|
|
return pf;
|
|
}
|
|
|
|
ios::fmtflags ios::setf(ios::fmtflags f, ios::fmtflags m)
|
|
{
|
|
fmtflags pf = mFlags;
|
|
mFlags = (mFlags & ~m) | f;
|
|
return pf;
|
|
}
|
|
|
|
ios::fmtflags ios::unsetf(ios::fmtflags f)
|
|
{
|
|
fmtflags pf = mFlags;
|
|
mFlags &= ~f;
|
|
return pf;
|
|
}
|
|
|
|
bool ios::good(void) const
|
|
{
|
|
return mState == goodbit;
|
|
}
|
|
|
|
bool ios::eof(void) const
|
|
{
|
|
return (mState & eofbit) != 0;
|
|
}
|
|
|
|
bool ios::fail(void) const
|
|
{
|
|
return (mState & (badbit | failbit)) != 0;
|
|
}
|
|
|
|
bool ios::bad(void) const
|
|
{
|
|
return (mState & badbit) != 0;
|
|
}
|
|
|
|
bool ios::operator!(void) const
|
|
{
|
|
return fail();
|
|
}
|
|
|
|
ios::operator bool(void)
|
|
{
|
|
return !fail();
|
|
}
|
|
|
|
|
|
ios::statebits ios::rdstate(void) const
|
|
{
|
|
return mState;
|
|
}
|
|
|
|
void ios::clear(void)
|
|
{
|
|
mState = goodbit;
|
|
}
|
|
|
|
|
|
|
|
|
|
ostream & endl(ostream & os)
|
|
{
|
|
os.put('\n');
|
|
return os;
|
|
}
|
|
|
|
|
|
iosetf setf(ios::fmtflags flags)
|
|
{
|
|
return iosetf(flags);
|
|
}
|
|
|
|
ostream & operator<<(ostream & os, const iosetf & s)
|
|
{
|
|
os.setf(s.flags);
|
|
return os;
|
|
}
|
|
|
|
iosetw setw(char width)
|
|
{
|
|
return iosetw(width);
|
|
}
|
|
|
|
ostream & operator<<(ostream & os, const iosetw & s)
|
|
{
|
|
os.width(s.width);
|
|
return os;
|
|
}
|
|
|
|
|
|
iosetprecision setprecision(char precision)
|
|
{
|
|
return iosetprecision(precision);
|
|
}
|
|
|
|
ostream & operator<<(ostream & os, const iosetprecision & s)
|
|
{
|
|
os.precision(s.precision);
|
|
return os;
|
|
}
|
|
|
|
|
|
iosetfill setfill(char fill)
|
|
{
|
|
return iosetfill(fill);
|
|
}
|
|
|
|
ostream & operator<<(ostream & os, const iosetfill & s)
|
|
{
|
|
os.fill(s.fill);
|
|
return os;
|
|
}
|
|
|
|
inline ostream::ostream(void)
|
|
{}
|
|
|
|
|
|
void ostream::bput(char ch)
|
|
{
|
|
}
|
|
|
|
ostream & ostream::put(char c)
|
|
{
|
|
bput(c);
|
|
return * this;
|
|
}
|
|
|
|
ostream & ostream::write(const char * s, int n)
|
|
{
|
|
for(int i=0; i<n; i++)
|
|
bput(s[i]);
|
|
|
|
return *this;
|
|
}
|
|
|
|
void ostream::putnum(const char * buffer, char prefix, char size)
|
|
{
|
|
char r = 0;
|
|
if (size < mWidth)
|
|
r = mWidth - size;
|
|
|
|
fmtflags adj = mFlags & adjustfield;
|
|
|
|
if (adj == internal)
|
|
{
|
|
while (size > prefix)
|
|
bput(buffer[--size]);
|
|
}
|
|
|
|
if (adj != left)
|
|
{
|
|
while (r > 0)
|
|
{
|
|
bput(mFill);
|
|
r--;
|
|
}
|
|
}
|
|
|
|
while (size > 0)
|
|
bput(buffer[--size]);
|
|
|
|
while (r > 0)
|
|
{
|
|
bput(mFill);
|
|
r--;
|
|
}
|
|
|
|
mFlags = 0;
|
|
mWidth = 0;
|
|
mFill = ' ';
|
|
}
|
|
|
|
void ostream::numput(unsigned n, char sign)
|
|
{
|
|
char buffer[10];
|
|
|
|
char base = 10;
|
|
if (mFlags & hex)
|
|
base = 16;
|
|
else if (mFlags & oct)
|
|
base = 8;
|
|
|
|
char i = 0;
|
|
char o = 'a' - 10;
|
|
if (mFlags & uppercase)
|
|
o = 'A' - 10;
|
|
|
|
unsigned nt = n;
|
|
while (nt)
|
|
{
|
|
char d = nt % base;
|
|
nt /= base;
|
|
|
|
if (d < 10)
|
|
d += '0';
|
|
else
|
|
d += o;
|
|
buffer[i++] = d;
|
|
}
|
|
|
|
if (!i)
|
|
buffer[i++] = '0';
|
|
char prefix = i;
|
|
if (sign)
|
|
buffer[i++] = sign;
|
|
|
|
putnum(buffer, prefix, i);
|
|
}
|
|
|
|
void ostream::numput(unsigned long n, char sign)
|
|
{
|
|
char buffer[20];
|
|
|
|
char base = 10;
|
|
if (mFlags & hex)
|
|
base = 16;
|
|
else if (mFlags & oct)
|
|
base = 8;
|
|
|
|
char i = 0;
|
|
char o = 'a' - 10;
|
|
if (mFlags & uppercase)
|
|
o = 'A' - 10;
|
|
|
|
unsigned long nt = n;
|
|
while (nt)
|
|
{
|
|
char d = nt % base;
|
|
nt /= base;
|
|
|
|
if (d < 10)
|
|
d += '0';
|
|
else
|
|
d += o;
|
|
buffer[i++] = d;
|
|
}
|
|
|
|
if (!i)
|
|
buffer[i++] = '0';
|
|
char prefix = i;
|
|
if (sign)
|
|
buffer[i++] = sign;
|
|
|
|
putnum(buffer, prefix, i);
|
|
}
|
|
|
|
|
|
ostream & ostream::operator<<(bool val)
|
|
{
|
|
if (val)
|
|
bput('1');
|
|
else
|
|
bput('0');
|
|
return *this;
|
|
}
|
|
|
|
ostream & ostream::operator<<(char val)
|
|
{
|
|
bput(val);
|
|
return *this;
|
|
}
|
|
|
|
ostream & ostream::operator<<(int val)
|
|
{
|
|
if (val < 0)
|
|
numput((unsigned)-val, '-');
|
|
else if (mFlags & showpos)
|
|
numput((unsigned)val, '+');
|
|
else
|
|
numput((unsigned)val, 0);
|
|
return *this;
|
|
}
|
|
|
|
ostream & ostream::operator<<(unsigned val)
|
|
{
|
|
numput(val, 0);
|
|
return *this;
|
|
}
|
|
|
|
ostream & ostream::operator<<(long val)
|
|
{
|
|
if (val < 0)
|
|
numput(-val, '-');
|
|
else if (mFlags & showpos)
|
|
numput(val, '+');
|
|
else
|
|
numput(val, 0);
|
|
return *this;
|
|
}
|
|
|
|
ostream & ostream::operator<<(unsigned long val)
|
|
{
|
|
numput(val, 0);
|
|
return *this;
|
|
}
|
|
|
|
static float fround5[] = {
|
|
0.5e-0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6
|
|
};
|
|
|
|
ostream & ostream::operator<<(float val)
|
|
{
|
|
char buffer[20];
|
|
|
|
char d = 0;
|
|
|
|
float f = val;
|
|
|
|
if (f < 0.0)
|
|
{
|
|
f = -f;
|
|
buffer[d++] = '-';
|
|
}
|
|
else if (mFlags & showpos)
|
|
buffer[d++] = '+';
|
|
|
|
char prefix = d;
|
|
|
|
if (isinf(f))
|
|
{
|
|
buffer[d++] = 'I';
|
|
buffer[d++] = 'N';
|
|
buffer[d++] = 'F';
|
|
}
|
|
else
|
|
{
|
|
int exp = 0;
|
|
|
|
char fdigits = mPrecision;
|
|
|
|
if (f != 0.0)
|
|
{
|
|
while (f >= 1000.0)
|
|
{
|
|
f /= 1000;
|
|
exp += 3;
|
|
}
|
|
|
|
while (f < 1.0)
|
|
{
|
|
f *= 1000;
|
|
exp -= 3;
|
|
}
|
|
|
|
while (f >= 10.0)
|
|
{
|
|
f /= 10;
|
|
exp ++;
|
|
}
|
|
|
|
}
|
|
|
|
char digits = fdigits + 1;
|
|
bool fexp = mFlags & scientific;
|
|
|
|
if (!(mFlags & fixed))
|
|
{
|
|
if (exp > 3 || exp < 0)
|
|
fexp = true;
|
|
}
|
|
|
|
if (!fexp)
|
|
{
|
|
while (exp < 0)
|
|
{
|
|
f /= 10.0;
|
|
exp++;
|
|
}
|
|
|
|
digits = fdigits + exp + 1;
|
|
|
|
if (digits < 7)
|
|
f += fround5[digits - 1];
|
|
else
|
|
f += fround5[6];
|
|
|
|
if (f >= 10.0)
|
|
{
|
|
f /= 10.0;
|
|
fdigits--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (digits < 7)
|
|
f += fround5[digits - 1];
|
|
else
|
|
f += fround5[6];
|
|
|
|
if (f >= 10.0)
|
|
{
|
|
f /= 10.0;
|
|
exp ++;
|
|
}
|
|
}
|
|
|
|
|
|
char pdigits = digits - fdigits;
|
|
|
|
if (digits > 20)
|
|
digits = 20;
|
|
|
|
if (pdigits == 0)
|
|
buffer[d++] = '0';
|
|
|
|
for(char i=0; i<digits; i++)
|
|
{
|
|
if (i == pdigits)
|
|
buffer[d++] = '.';
|
|
if (i > 6)
|
|
buffer[d++] = '0';
|
|
else
|
|
{
|
|
int c = (int)f;
|
|
f -= (float)c;
|
|
f *= 10.0;
|
|
buffer[d++] = c + '0';
|
|
}
|
|
}
|
|
|
|
if (fexp)
|
|
{
|
|
buffer[d++] = 'E';
|
|
if (exp < 0)
|
|
{
|
|
buffer[d++] = '-';
|
|
exp = -exp;
|
|
}
|
|
else
|
|
buffer[d++] = '+';
|
|
|
|
buffer[d++] = exp / 10 + '0';
|
|
buffer[d++] = exp % 10 + '0';
|
|
}
|
|
}
|
|
|
|
char r = 0;
|
|
if (d < mWidth)
|
|
r = mWidth - d;
|
|
|
|
fmtflags adj = mFlags & adjustfield;
|
|
|
|
char i = 0;
|
|
if (adj == internal)
|
|
{
|
|
while (i < prefix)
|
|
bput(buffer[i++]);
|
|
}
|
|
|
|
if (adj != left)
|
|
{
|
|
while (r > 0)
|
|
{
|
|
bput(mFill);
|
|
r--;
|
|
}
|
|
}
|
|
|
|
while (i < d)
|
|
bput(buffer[i++]);
|
|
|
|
while (r > 0)
|
|
{
|
|
bput(mFill);
|
|
r--;
|
|
}
|
|
|
|
mFlags = 0;
|
|
mWidth = 0;
|
|
mFill = ' ';
|
|
|
|
return *this;
|
|
}
|
|
|
|
ostream & ostream::operator<<(const char * p)
|
|
{
|
|
char i = 0;
|
|
while (p[i])
|
|
bput(p[i++]);
|
|
return *this;
|
|
}
|
|
|
|
ostream & ostream::operator<<(const string & s)
|
|
{
|
|
for(char i=0; i<s.size(); i++)
|
|
bput(s[i]);
|
|
return *this;
|
|
}
|
|
|
|
inline ostream & ostream::operator<<(manip m)
|
|
{
|
|
return m(*this);
|
|
}
|
|
|
|
|
|
costream::costream(void)
|
|
{}
|
|
|
|
void costream::bput(char ch)
|
|
{
|
|
putchar(ch);
|
|
}
|
|
|
|
istream::istream(void)
|
|
: mBufferPos(0), mBufferFill(0)
|
|
{}
|
|
|
|
void istream::refill(void)
|
|
{
|
|
|
|
}
|
|
|
|
istream & istream::putback(char c)
|
|
{
|
|
mBuffer[--mBufferPos] = c;
|
|
return *this;
|
|
}
|
|
|
|
istream & istream::unget(void)
|
|
{
|
|
if (!(mState & eofbit))
|
|
mBufferPos--;
|
|
return *this;
|
|
}
|
|
|
|
char istream::get(void)
|
|
{
|
|
if (mState != goodbit)
|
|
{
|
|
mState |= failbit;
|
|
return 0;
|
|
}
|
|
else if (mBufferPos == mBufferFill)
|
|
refill();
|
|
if (mBufferPos < mBufferFill)
|
|
return mBuffer[mBufferPos++];
|
|
else
|
|
{
|
|
mState |= eofbit;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
void istream::doskipws(void)
|
|
{
|
|
while (char c = get())
|
|
{
|
|
if (c > ' ')
|
|
{
|
|
unget();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
istream & istream::get(char & c)
|
|
{
|
|
c = get();
|
|
return *this;
|
|
}
|
|
|
|
istream & istream::get(char * s, char size)
|
|
{
|
|
return get(s, size, '\n');
|
|
}
|
|
|
|
istream & istream::get(char * s, char size, char delim)
|
|
{
|
|
char i = 0;
|
|
while (i + 1 < size)
|
|
{
|
|
char c = get();
|
|
if (c == delim)
|
|
{
|
|
unget();
|
|
break;
|
|
}
|
|
s[i++] = c;
|
|
}
|
|
if (size)
|
|
s[i++] = 0;
|
|
return *this;
|
|
}
|
|
|
|
istream & istream::getline(char * s, char size)
|
|
{
|
|
return getline(s, size, '\n');
|
|
}
|
|
|
|
istream & istream::getline(char * s, char size, char delim)
|
|
{
|
|
char i = 0;
|
|
while (i + 1 < size)
|
|
{
|
|
char c = get();
|
|
if (c == delim)
|
|
break;
|
|
s[i++] = c;
|
|
}
|
|
if (size)
|
|
s[i++] = 0;
|
|
return *this;
|
|
}
|
|
|
|
istream & istream::ignore(char size)
|
|
{
|
|
ignore(size, '\n');
|
|
return *this;
|
|
}
|
|
|
|
istream & istream::ignore(char size, char delim)
|
|
{
|
|
while (size)
|
|
{
|
|
char c = get();
|
|
if (c == delim)
|
|
break;
|
|
size--;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
istream & istream::operator>>(bool & val)
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
unsigned istream::getnum(void)
|
|
{
|
|
doskipws();
|
|
|
|
fmtflags bflags = mFlags & basefield;
|
|
|
|
char base = 10;
|
|
if (bflags == hex)
|
|
base = 16;
|
|
else if (bflags == oct)
|
|
base = 8;
|
|
|
|
unsigned n = 0;
|
|
bool sign = false;
|
|
|
|
char ch = get();
|
|
if (ch == '-')
|
|
{
|
|
sign = true;
|
|
ch = get();
|
|
}
|
|
else if (ch == '+')
|
|
ch = get();
|
|
|
|
bool digits = false;
|
|
|
|
if (ch == '0')
|
|
{
|
|
if (bflags == 0)
|
|
{
|
|
base = 8;
|
|
ch = get();
|
|
if (ch == 'x' || ch == 'X')
|
|
{
|
|
base = 16;
|
|
ch = get();
|
|
}
|
|
else
|
|
digits = true;
|
|
}
|
|
else
|
|
digits = true;
|
|
}
|
|
|
|
for(;;)
|
|
{
|
|
if (ch >= '0' && ch <= '9')
|
|
n = n * base + (ch - '0');
|
|
else if (base > 10 && ch >= 'A' && ch <= 'F')
|
|
n = n * base + (ch - 'A' + 10);
|
|
else if (base > 10 && ch >= 'a' && ch <= 'f')
|
|
n = n * base + (ch - 'a' + 10);
|
|
else
|
|
break;
|
|
ch = get();
|
|
digits = true;
|
|
}
|
|
unget();
|
|
|
|
if (!digits)
|
|
mState |= failbit;
|
|
|
|
if (sign)
|
|
return -n;
|
|
else
|
|
return n;
|
|
}
|
|
|
|
unsigned long istream::getnuml(void)
|
|
{
|
|
doskipws();
|
|
|
|
fmtflags bflags = mFlags & basefield;
|
|
|
|
char base = 10;
|
|
if (bflags == hex)
|
|
base = 16;
|
|
else if (bflags == oct)
|
|
base = 8;
|
|
|
|
unsigned long n = 0;
|
|
bool sign = false;
|
|
|
|
char ch = get();
|
|
if (ch == '-')
|
|
{
|
|
sign = true;
|
|
ch = get();
|
|
}
|
|
else if (ch == '+')
|
|
ch = get();
|
|
|
|
if (ch == '0')
|
|
{
|
|
if (bflags == 0)
|
|
{
|
|
base = 8;
|
|
ch = get();
|
|
if (ch == 'x' || ch == 'X')
|
|
{
|
|
base = 16;
|
|
ch = get();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool digits = false;
|
|
for(;;)
|
|
{
|
|
if (ch >= '0' && ch <= '9')
|
|
n = n * base + (ch - '0');
|
|
else if (base > 10 && ch >= 'A' && ch <= 'F')
|
|
n = n * base + (ch - 'A' + 10);
|
|
else if (base > 10 && ch >= 'a' && ch <= 'f')
|
|
n = n * base + (ch - 'a' + 10);
|
|
else
|
|
break;
|
|
ch = get();
|
|
digits = true;
|
|
}
|
|
unget();
|
|
|
|
if (!digits)
|
|
mState |= failbit;
|
|
|
|
if (sign)
|
|
return -n;
|
|
else
|
|
return n;
|
|
}
|
|
|
|
float istream::getnumf(void)
|
|
{
|
|
doskipws();
|
|
|
|
char cs = get();
|
|
|
|
bool sign = false;
|
|
if (cs == '-')
|
|
{
|
|
sign = true;
|
|
cs = get();
|
|
}
|
|
else if (cs == '+')
|
|
cs = get();
|
|
|
|
if (cs >= '0' && cs <= '9' || cs == '.')
|
|
{
|
|
float vf = 0;
|
|
while (cs >= '0' && cs <= '9')
|
|
{
|
|
vf = vf * 10 + (int)(cs - '0');
|
|
cs = get();
|
|
}
|
|
|
|
if (cs == '.')
|
|
{
|
|
float digits = 1.0;
|
|
cs = get();
|
|
while (cs >= '0' && cs <= '9')
|
|
{
|
|
vf = vf * 10 + (int)(cs - '0');
|
|
digits *= 10;
|
|
cs = get();
|
|
}
|
|
vf /= digits;
|
|
}
|
|
|
|
char e = 0;
|
|
bool eneg = false;
|
|
|
|
if (cs == 'e' || cs == 'E')
|
|
{
|
|
cs = get();
|
|
if (cs == '-')
|
|
{
|
|
eneg = true;
|
|
cs = get();
|
|
}
|
|
else if (cs == '+')
|
|
{
|
|
cs = get();
|
|
}
|
|
|
|
while (cs >= '0' && cs <= '9')
|
|
{
|
|
e = e * 10 + cs - '0';
|
|
cs = get();
|
|
}
|
|
|
|
}
|
|
|
|
if (e)
|
|
{
|
|
if (eneg)
|
|
{
|
|
while (e > 6)
|
|
{
|
|
vf /= 1000000.0;
|
|
e -= 6;
|
|
}
|
|
vf /= tpow10[e];
|
|
}
|
|
else
|
|
{
|
|
while (e > 6)
|
|
{
|
|
vf *= 1000000.0;
|
|
e -= 6;
|
|
}
|
|
vf *= tpow10[e];
|
|
}
|
|
}
|
|
|
|
if (sign)
|
|
return -vf;
|
|
else
|
|
return vf;
|
|
}
|
|
else
|
|
mState |= failbit;
|
|
|
|
return 0;
|
|
}
|
|
|
|
istream & istream::operator>>(int & val)
|
|
{
|
|
val = getnum();
|
|
return *this;
|
|
}
|
|
|
|
istream & istream::operator>>(unsigned & val)
|
|
{
|
|
val = getnum();
|
|
return *this;
|
|
}
|
|
|
|
istream & istream::operator>>(long & val)
|
|
{
|
|
val = getnuml();
|
|
return *this;
|
|
}
|
|
|
|
istream & istream::operator>>(unsigned long & val)
|
|
{
|
|
val = getnuml();
|
|
return *this;
|
|
}
|
|
|
|
istream & istream::operator>>(float & val)
|
|
{
|
|
val = getnumf();
|
|
return *this;
|
|
}
|
|
|
|
istream & istream::operator>>(char * p)
|
|
{
|
|
doskipws();
|
|
char i = 0;
|
|
char c = get();
|
|
while (c > ' ')
|
|
{
|
|
p[i++] = c;
|
|
c = get();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
istream & istream::operator>>(string & s)
|
|
{
|
|
doskipws();
|
|
s.clear();
|
|
char c = get();
|
|
while (c > ' ')
|
|
{
|
|
s += c;
|
|
c = get();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
cistream::cistream(void)
|
|
{}
|
|
|
|
void cistream::refill(void)
|
|
{
|
|
mBufferPos = 0;
|
|
|
|
char fill = 0;
|
|
while (fill < 32)
|
|
{
|
|
char ch = getchar();
|
|
mBuffer[fill++] = ch;
|
|
if (ch == '\n')
|
|
break;
|
|
}
|
|
|
|
mBufferFill = fill;
|
|
}
|
|
|
|
cistream cin;
|
|
costream cout;
|
|
|
|
} |