PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : template struct für zusammengesetzte Integer


aths
2003-04-01, 20:36:56
C++

Folgendes Problem: Ich möchte Bitfolgen auf bestimmte Eigenschaften prüfen, wobei die Bitfolge länger als ein unsigned int sein kann. Für die eigentliche Prüfung reichen die hinteren 8 Bit allerdings garantiert immer aus.

Xmas schlug vor, das mit einem Template variabel zu gestalten, um zusammengesetzte unsigned Integer mit unterschiedlichen Größen zu erlauben. Ich hab da was geschrieben (bzw. sein Template-Gerüst modifiziert) aber damit bin ich nicht so recht zufrieden.

Der Grund-Datentyp soll ein 32-bittiges Unsigned Integer sein. Die struct soll außerdem folgende Methoden beinhalten:

shr, shl (Bitschieben nach rechts und links),

Ausgabe der ganzen Zahl in Dual- und Hex-Darstellung, nach Möglichkeit auch in dezimaler Darstellung,

und die Operatoren + und -.




Bitschieben (mit () für ein Bit bzw. (x) für x Bits) habe ich schon fertig :naughty:

Meine bisherige struct kann ich leider nicht zeigen da das ganze via Telnet auf einer Linux-Kiste geproggt wurde (habe lokal kein C++ installiert.)


Das ganze soll nur von mir verwendet werden, daher sind keine private Variablen geplant. Direktes Setzen via .value[2]=555 z.B. soll möglich bleiben.


Wer könnte da mal mit einer schnuckeligen template struct aushelfen?


So weit stehts im Moment:


bint-test.cpp

#include <iostream.h>
#include "bint.h"


void main() {
bint<3> i96(12);
//i96.value[0]=7;
i96.value[1]=0;
i96.shr(1);
cout<<i96.value[0]<<endl;
cout<<i96.digits<<endl;
int64 i64(1,1);
cout<<i64.value[0]<<endl;
i64.hexout();
i96.hexout();
i96.phex(12);
}
code][code]bint.h

#include "bint.cpp"


typedef bint<2> int64;
typedef bint<3> int96;
typedef bint<4> int128;
typedef bint<5> int160;
typedef bint<6> int192;
typedef bint<7> int256;bint.cpp

template <int i> struct bint {
unsigned int value[i+4];
int digits;char hexlut[16];

void fillhexlut() {
hexlut[0]="0";
hexlut[1]="1";
//="0123456789ABDCDEF"; // Wie füllt man ein Char-Array mit einem Schlag?!
}

bint() {
digits=i;
// fillhexlut();
hexlut[0]="0";
hexlut[1]="1"; //Klappt offenbar nicht?

for (int j=0;j<i;++j) value[j]=0;
}

bint(int a) {
digits=i;
// fillhexlut();
for (int j=1;j<i;++j) value[j]=0;
;
}
bint(int a,int b) {
digits=i;
// fillhexlut();
for (int j=2;j<i;++j) value[j]=0;
value[0]=a;value[1]=b;
}
bint(int a,int b, int c) {
digits=i;
fillhexlut();
for (int j=3;j<i;++j) value[j]=0;
value[0]=a;value[1]=b;value[2]=c;
}
bint(int a, int b, int c, int d) {
digits=i;
fillhexlut();
for (int j=4;j<i;++j) value[j]=0;
value[0]=a;value[1]=b;value[2]=c;value[3]=d;
}

void phex(unsigned int a) {
char buffer[4];
unsigned l,h,r=a;
for (int j=0;j<4;++j) {
h=r/16;
l=r%16;
buffer[3-j]=hexlut[h];
}
for (int j=0;j<4;++j) cout<<","<< (buffer[j]); // buffer ist immer leer?!
}

void hexout() {cout.setf(ios::hex);
for (int j=0;j<digits;++j) phex(value[j]); // funzt nicht
}

void shr() {
for (int j=0;j<i-1;++j) {
value[j]>>=1;
value[j]+=value[j+1] << 31;
}
value[i-1]>>=1;
}

void shr(int a) {
for (int j=0;j<a;++j) shr();
}/**/**

};

zeckensack
2003-04-01, 20:58:00
typedef bint<2> int64;
typedef bint<3> int96;
typedef bint<4> int128;
typedef bint<5> int160;
typedef bint<6> int192;
typedef bint<7> int256;Ist offenbar ein Tippfehler. Korrekttypedef bint<2> int64;
typedef bint<3> int96;
typedef bint<4> int128;
typedef bint<5> int160;
typedef bint<6> int192;
typedef bint<7> int224;
typedef bint<8> int256;

void fillhexlut() {
strncpy(hexlut,"0123456789ABCDEF",16); //_so_ füllt man ein Char-Array mit einem Schlag
}

Anm: char x="X"; kann nicht gehen, da "" immer einen terminierten String liefert. Richtig ist:
char x='X';
Man beachte die einfachen Anführungszeichen.

Zur hexlut an sich ist zu sagen, daß diese immer gleich ist, also sinnigerweise
static const char* hexlut="0123456789ABCDEF";
Auf die Weise spart man die Kopieraktion bei jedem Anlegen der Instanz ('Optimierung').

aths
2003-04-01, 21:04:01
Originally posted by zeckensack
typedef bint<2> int64;
typedef bint<3> int96;
typedef bint<4> int128;
typedef bint<5> int160;
typedef bint<6> int192;
typedef bint<7> int256;Ist offenbar ein Tippfehler. Korrekttypedef bint<2> int64;
typedef bint<3> int96;
typedef bint<4> int128;
typedef bint<5> int160;
typedef bint<6> int192;
typedef bint<7> int224;
typedef bint<8> int256;

void fillhexlut() {
strncpy(hexlut,"0123456789ABCDEF",16); //_so_ füllt man ein Char-Array mit einem Schlag
}

Anm: char x="X"; kann nicht gehen, da "" immer einen terminierten String liefert. Richtig ist:
char x='X';
Man beachte die einfachen Anführungszeichen.

Zur hexlut an sich ist zu sagen, daß diese immer gleich ist, also sinnigerweise
static const char* hexlut="0123456789ABCDEF";
Auf die Weise spart man die Kopieraktion bei jedem Anlegen der Instanz ('Optimierung'). Das verbessere ich dann erst mal :)

aths
2003-04-01, 21:12:19
static const char* hexlut="0123456789ABCDEF";


- dort wo die Member-Variablen angelegt werden? g++ heult dann jedenfalls rum, das ginge lt. ANSI-C++ nicht.

zeckensack
2003-04-01, 21:21:44
Originally posted by aths
static const char* hexlut="0123456789ABCDEF";


- dort wo die Member-Variablen angelegt werden? g++ heult dann jedenfalls rum, das ginge lt. ANSI-C++ nicht. Statische Konstanten sind immer etwas 'tricky'. Die Deklaration erfolgt in der Klasse, die Definition außerhalb. Ehrlich gesagt habe ich das bei Templates noch nie gemacht, aber bei 'normalen' Klassen geht's so//Header
class
Whatever
{
static const char* hexlut;
};
//.cpp
#include "Header.h"

const char* Whatever::hexlut="0123456789ABCDEF";

Demirug
2003-04-01, 21:29:01
Originally posted by zeckensack
Statische Konstanten sind immer etwas 'tricky'. Die Deklaration erfolgt in der Klasse, die Definition außerhalb. Ehrlich gesagt habe ich das bei Templates noch nie gemacht, aber bei 'normalen' Klassen geht's so//Header
class
Whatever
{
static const char* hexlut;
};
//.cpp
#include "Header.h"

const char* Whatever::hexlut="0123456789ABCDEF";

Ja bei Templates geht das im Prinzip genauso. Das Problem ist dabei nur das man bei Templates ja normalerweise kein cpp File hat.

Wenn man die statische Variable nur in einer Funktion braucht kann man sie auch dort deklarieren und auch gleich definieren. Ansonsten muss man noch mehr trickens. Statische Memberfunktion die den Wert zurückgibt welcher dann dort auf die eben gesagte Art definiert wird.

also so in etwa

static const char* GetHexlut ()
{
static const char* hexlut ="0123456789ABCDEF";

return hexlut;
}

aths
2003-04-01, 21:31:33
Ähm... ich habe in der Header-Datei selbst nur die typedefs, in oben in der Header-Datei inkludiere ich die cpp-Datei, welche den Code der Structure enthält.

Wenn ich in der struct die Variable anlege und in Header, nach dem include, den Wert zuweisen will, bekomme ich 'nen Syntax Error.

Ähm²... ich lese jetzt erst Demis Antwort.

Ähm³... die Sache mit hexlut klappt soweit. (Der Source oben enthält eine falsche Berechnung, das hab ich bei mir schon korrigiert.) Da mach ich morgen mal weiter, so einige Fragen hätte ich da nämlich noch :)

KiBa
2003-04-02, 15:35:16
was spricht eigentlich gegen den einsatz von std::bitset<N>?

ist so ähnlich wie ein vector<bool> bloß mit zur kompilierzeit festgelegter größe. die ganzen geforderten funktionen wie boolsche operatoren, vergleich, shift, eingabe und ausgabe (normal über streams und damit in beliebiger darstellung) und viele andere sind da schon eingebaut.