H
Hallo,
wenn man wollte könnte man sich natürlich einen Wrapper basteln, der automatisch eine Konvertierung ins binär-System durchführt. Ein eigener streambuf wäre natürlich sehr bequem, mir fällt spontan aber nicht ein, wie man die Aufgabe mit einem solchen lösen könnte. Auf streambuf-Ebene gibt es nur noch Zeichen, es wird also schwer dort Zahlen zu erkennen.
Bleibt erstmal nur ein StreamWrapper.
Hier mal ein fürchterlich naiver und ungetesteter Ansatz:
string decimalToBinary(unsigned long value,
unsigned binDigits = numeric_limits<unsigned long>::digits,
bool trimLeft = true)
{
bool leadingZero = true;
unsigned digit = 1 << (binDigits-1);
string ret;
ret.reserve(binDigits);
do
{
if (value & digit)
{
ret += '1';
leadingZero = false;
}
else if (!trimLeft || !leadingZero)
{
ret += '0';
}
digit /= 2;
} while (digit != 0);
return ret;
}
class BinWrapper
{
public:
explicit BinWrapper(ostream& os, bool trimLeft = false)
: realStream_(os)
, trimLeft_(trimLeft)
{}
ostream& getStream() const
{
return realStream_;
}
friend BinWrapper& operator << (BinWrapper& os, const std::string& s);
BinWrapper& operator<<(ios& (*pf)(ios&))
{
realStream_ << pf;
return *this;
}
BinWrapper& operator<<(ostream& (*pf)(ostream&))
{
realStream_ << pf;
return *this;
}
BinWrapper& operator<<(ios_base& (*pf)(ios_base&))
{
realStream_ << pf;
return *this;
}
BinWrapper& operator<<(streambuf *sb)
{
realStream_ << sb;
return *this;
}
BinWrapper& operator<<(const char* s)
{
return *this << std::string(s);
}
BinWrapper& operator<<(unsigned long n)
{
return writeNumber(n, numeric_limits<unsigned long>::digits);
}
BinWrapper& operator<<(char c)
{
return writeNumber(c, numeric_limits<char>::digits);
}
BinWrapper& operator<<(bool n)
{
return writeNumber(n, numeric_limits<bool>::digits);
}
BinWrapper& operator<<(short n)
{
return writeNumber(n, numeric_limits<short>::digits);
}
BinWrapper& operator<<(unsigned short n)
{
return writeNumber(n, numeric_limits<unsigned short>::digits);
}
BinWrapper& operator<<(int n)
{
return writeNumber(n, numeric_limits<int>::digits);
}
BinWrapper& operator<<(unsigned int n)
{
return writeNumber(n, numeric_limits<unsigned int>::digits);
}
BinWrapper& operator<<(long n)
{
return writeNumber(n, numeric_limits<long>::digits);
}
BinWrapper& operator<<(float n)
{
return writeFloatNumber(n, numeric_limits<float>::digits);
}
BinWrapper& operator<<(double n)
{
return writeFloatNumber(n, numeric_limits<double>::digits);
}
BinWrapper& operator<<(long double n)
{
return writeFloatNumber(n, numeric_limits<long double>::digits);
}
BinWrapper& operator<<(void * n)
{
writeNumber((unsigned long) n, numeric_limits<unsigned long>::digits);
}
template <class T>
BinWrapper& operator<<(const T& t)
{
realStream_ << t;
return *this;
}
private:
BinWrapper& writeNumber(unsigned long n, unsigned binDigits)
{
std::string binStr = decimalToBinary(n, binDigits, trimLeft_);
realStream_ << binStr;
return *this;
}
BinWrapper& writeFloatNumber(unsigned long n, unsigned binDigits)
{
throw "not implemented";
return *this;
}
ostream& realStream_;
bool trimLeft_;
};
BinWrapper& operator << (BinWrapper& os, const std::string& s)
{
for (unsigned i = 0 ; i < s.length() ; ++i)
{
std::string binStr = decimalToBinary(s[i], numeric_limits<char>::digits,
os.trimLeft_);
os.realStream_ << binStr;
}
return os;
}
int main()
{
BinWrapper binOut(cout);
binOut << "Hallo Welt" << 123 << endl;
}
Für Floating-Point-Zahlen muss man sich mal das entsprechende IEEE-Format anschauen. Ich kannte auch mal den Algo zur Umwandlung. Habe ich im Moment aber vergessen und keine Lust nachzusehen
Ansonsten müsste man das natürlich etwas ordentlicher machen. So mit beliebiger Feldbreite usw.