Hei,
olen vasta aloittelemassa koodaamista, ja miettimistä riittää. Kooderini, jonka pitäisi pystyä sekä enkoodaamaan ja dekoodaamaan, ei perustu mihinkään luotuun taulukkoon vaan pyrkii hyödyntämään pelkästään bittioperaatioita, joiden avulla enkoodaus voidaan suorittaa. Olen saanut seuraavanlaisen pätkän aikaseksi:
signed int enkoodaa() { signed int merkki = getc(stdin); /*otetaan talteen merkit kerrallaan*/ while(merkki!=EOF) { /*kun merkit loppuvat*/ if (merkki<6) { /*tarkista, onko merkkien määrä alle 6, jos on lisää tarvittavat nollat, jos ei, niin enkoodaa blokki suoraan*/ .... Mitä tähän pitäisi tulla? } signed int puskuri=0; int tulos1; int tulos2; int ylimmat_bitit; tulos1=puskuri|0x03; /*otetaan talteen kaksi alinta bittiä*/ tulos<<8; /*siirretään 8 bittiä vasemmalle*/ tulos2=puskuri|0x0F; /*otetaan talteen neljä alinta bittiä*/ tulos2<<8; /*siirretään 8 bittiä vasemmalle*/ ylimmat_bitit=tulos2|0x63; /*otetaan talteen kuusi ylintä bittiä ison luvun välttämiseksi*/
Ensinnäkään en ole varma rakenteesta, toimiiko se näin? Eli ensin tarkistetaan, onko ylipäätään merkkien määrä (joita on syötetty stdinistä)tasan kuudella jaollinen, jos ei ole, niin lisätään heti suoraan tarvittavat täydennykset (=). Miten tämä tarkistus pitäisi tehdä oikein, olen jotakin hapuillut, mutta se ei varmaankaan mene ihan noin.
Jos merkkien määrä on tasan kuudella jaollinen, niin voidaan alkaa enkoodata heti - siten, että otetaan ensimmäisen tavun (8 bittiä pitkä)alimmat kaksi bittiä talteen, siirretään tulosta kahdeksan vasemmalle, sitten otetaan neljä talteen ja taas 8 bittiä vasemmalle. Nyt onkin jo kaksi kuuden bitin pätkää, alimmalle kuudelle ei tarvitse tehdä mitään, mutta pitääkö nääkin ottaa kuitenkin talteen? Ylimmät bitit olen maskannut ja pätkässäni tallentanut erilliseen muuttujaan, jotta luvusta ei tulis hirmuisoa.
Onko ylläoleva edes sinne päinkään ja jos ei, niin voisitteko auttaa kertomalla, miten sitä pitäis lähteä miettimään? Tuohan oli vasta enkoodausosio, dekoodauskin pitäis vielä miettiä, miten se vois toimia.
Kiitos:-)
Junior kirjoitti:
tarkistetaan, onko ylipäätään merkkien määrä (joita on syötetty stdinistä)tasan kuudella jaollinen,
Tuon saa kätevimmin jakojäännöksellä: lisätään niin monta nollaa, kuin pituus % 6 on.
En osaa edelleenkään tehdä tarvittavia bittioperaatioita enkoodaukseen. Olisiko jollakulla joku vinkki siihen?
Tiettyjä bittejä talteen otettaessa & eikä |. Tutustu nyt ensin ihan paperilla siihen, mitä nuo operaatiot tekevät.
Vastauksesi oli jo iso apu. Ongelma on vaan, että olen yrittäny viikon verran nimenomaan paperilla pyöritellä noita bittejä ja periaatteessa ymmärrän operaation. Kun sitten yritän miettiä, mitä se kooditasolla tarkoittaisi, bittiavaruus vilistää silmien ohi, enkä ymmärrä....tarvitsisin sellaisen rautalankamallin, joka avaisi mulle, mitä siirroissa tapahtuu
base64:ssahan muunnetaan aina 3 tavua neljäksi 6 bitin merkiksi, joten asioiden helpottamiseksi suosittelen jonkinlaista 3 tavun puskuria lukemiseen.
Sitten vaan
char codes[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; merkki1 = codes[ (tavu1 & 0xfc) >> 2 ]; merkki2 = codes[ ((tavu1 & 0x3)<<4) | ((tavu2 & 0xf0) >>4) ]; merkki3 = codes[ ((tavu2 & 0xf)<<2) | ((tavu3 & 0xc0)>>6) ]; merkki4 = codes[ tavu3 & 0x3f ];
Toivottavasti meni oikein. Lisäksi tarvitset tiedenkin erityiskäsittelyn lopun '='-merkeille.
Joo, eli tee vaikka definet helpotukseksi:
#define BITTI_1 0x01 #define BITTI_4 0x08 #define BITTI_5 0x10 #define BITTI_8 0x80
ja ne loputkin tietysti. Sitten voit noista kasata tarvittavat maskit:
#define KUUSI_ALINTA (BITTI_1 | BITTI_2 | BITTI_3 | BITTI_4 | BITTI_5 | BITTI_6)
Näistä on vielä sekin ilo, että jälkeen päin näkee, mitä on ajatellut ja tehnyt ilman, että tarvitsisi miettiä, mikä ihmeen 0xfc.
Toinen yksinkertaisemman näköinen muunnostapa on käyttää integer pukuria, jonka kuudesta alabitistä muodostetaan aina seuraava merkki (käänteisessä järjestyksessä).
int puskuri = (tavu1 << 16) | (tavu2 << 8) | tavu3; merkki4 = codes[ puskuri & 0x3f ]; puskuri >>= 6; merkki3 = codes[ puskuri & 0x3f ]; puskuri >>= 6; merkki2 = codes[ puskuri & 0x3f ]; puskuri >>= 6; merkki1 = codes[ puskuri ];
Aihe on jo aika vanha, joten et voi enää vastata siihen.