Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C: Base64-kooderintekoon apua

Sivun loppuun

Junior [22.11.2005 09:47:04]

#

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:-)

Blaze [22.11.2005 12:20:26]

#

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.

Junior [24.11.2005 19:42:09]

#

En osaa edelleenkään tehdä tarvittavia bittioperaatioita enkoodaukseen. Olisiko jollakulla joku vinkki siihen?

Metabolix [24.11.2005 19:50:59]

#

Tiettyjä bittejä talteen otettaessa & eikä |. Tutustu nyt ensin ihan paperilla siihen, mitä nuo operaatiot tekevät.

Junior [24.11.2005 19:56:31]

#

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

FooBat [24.11.2005 21:02:37]

#

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.

Metabolix [24.11.2005 22:05:33]

#

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.

FooBat [26.11.2005 00:03:49]

#

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 ];

Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta