Škôlka jazyka C http://skolka-jazyka-c.freespace.sk/ |
|
10. lekcia C (Bitové operácie a bitové pole) základná škola http://skolka-jazyka-c.freespace.sk/viewtopic.php?f=32&t=561 |
Stránka 1 z 1 |
Autor: | libcosenior [ 27 Jan 2013, 11:09 ] |
Predmet príspevku: | 10. lekcia C (Bitové operácie a bitové pole) základná škola |
1. Napíš funkciu int dlzka_int(void), ktorá vráti dĺžku premennej typu int v bitoch. Zabezpeč, aby funkcia pracovala správne na ľubovoľnom type počítača. Vyskúšaj v programe. Spoiler: Kód: /********************************** * 1.c v.1.0 * * Zistenie dlzky typu int v bitoch * ================================ * **********************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #define VELKOST_INT (sizeof(int) * 8) // pocet bitov v int, v mojom pripade 32 /* uplne funkcne prototypy funkcii */ char* des_dvoj_kr(unsigned int desiatkove); int dlzka_int(void); /* funkcia main() */ int main(void) { printf("\nDlzka cisla typu int je %d bitov.\n", dlzka_int()); return 0; } /* zjisti dlzku int v bitoch */ int dlzka_int(void) { unsigned int x, i = 0; /* mozne definicie maximalneho cisla unsigned int, vsetky si ich mozte vyskusat */ //x = ~0; //x &= ~0; //x &= ~0xF; //x = 0xFFFFFFFF; //x = 0xffffffff; //x = 42949672945; //x = UINT_MAX; x = -1; printf("maximalne unsigned cislo je %u\n\n", x); /* Vypocet poctu bytov za pomoci bitoveho posunu doprava z maximalneho cisla unsignad int sa budeme postupne posuvat do prava po jednom bite az po nulu, teda bity sa posuvaju a zlava stracaju, menia sa na nuly a vlastne dekadicke cisla sa postupne znizuju delenim dvomi */ printf("%2d. bit ->\tdec: %10u\t bin: %32s\n", i, x, des_dvoj_kr(x)); while ((x >>= 1) != 0) { // bitovy posun do prava i++; printf("%2d. bit ->\tdec: %10u\t bin: %32s\n", i, x, des_dvoj_kr(x)); } i += 1; printf("%2d. bit ->\tdec: %10u\t bin: %32s\n", i, x, des_dvoj_kr(x)); return (i); } /* pomocna fánkcia na vypis binarneho cisla prevod z desiatkoveho na dvojkove, vystup dvojkove (retazec) */ char* des_dvoj_kr(unsigned int desiatkove) { int i = 0, j, k = -1; char *p_pom, *p_pom1, *p_dvojkove; /* dynamicka alokacia s kontrolou volnej pamati */ if ((p_pom = (char *) malloc(35)) == NULL) { printf("Malo pamati!"); return; } if ((p_pom1 = (char *) malloc(35)) == NULL) { printf("Malo pamati!"); return; } if ((p_dvojkove = (char *) malloc(35)) == NULL) { printf("Malo pamati!"); return; } /* vypocet dvojkoveho cisla, prevod na retazec, jeho otocenie od zadu, doplnenie nul do celej dlzky dvojkoveho cisla */ while (desiatkove != 0) { // cyklus kym nebude 0 p_pom[i] = (desiatkove % 2) + 48; //zvysok po deleni 2 zmeneny na znak desiatkove /= 2; i++; // pom[i] sa zvacsuje s kazdym cyklom } p_pom[i] = '\0'; // ukoncenie retazca for (j = i; j >= 0; j--) p_pom1[j] = p_pom[k++]; // prepis od zadu p_pom1[i + 1] = '\0'; // ukoncenie retazca for (j = 0; j < VELKOST_INT - strlen(p_pom1); j++) // doplnenie nul do velkosti p_dvojkove[j] = '0'; // int minus velkost p_pom1 strcat(p_dvojkove, p_pom1); //spojenie retacov do jedneho bin cisla return (p_dvojkove); } 2. Napíš funkciu unsigned rotuj_doprava(unsignet x, int n), ktorá spôsobí rotáciu (nie posun) čísla o n bitov doprava. Vyskúšaj v programe. Spoiler: Kód: /*************************** * 2.c v.1.0 * * Rotacia bitov doprava * ========================= * * bity sa posuvaju do prava * a nulty bit sa presuva * na najvyssi bit * ***************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #define VELKOST_INT (sizeof(int) * 8) // pocet bitov v int, v mojom pripade 32 /* uplne funkcne prototypy funkcii */ unsigned rotuj_doprava(unsigned int x, int n); char* des_dvoj_kr(unsigned int desiatkove); /* funkcia main */ int main(void) { unsigned cislo, i = 0; cislo = 2147483648; /******************************************************************** * vyskusaj si aj zadavanie cisiel, odkomentuj nasledujuce dva riadky * a zakomentuj riadok: cislo = 2147483648; ********************************************************************/ //printf("Zadaj kladne cislo. ktore chces rotovat do prava: "); //scanf("%u", &cislo); printf("%u(d) %0*x(h) %32s(b)\n\n", cislo, sizeof(int) * 2, rotuj_doprava(cislo, i), des_dvoj_kr(rotuj_doprava(cislo, i))); /* vypise o kolko bitov je rotacia, dec cislo, hex cislo a bin cislo */ for (i = 0; i <= sizeof(int) * 8; i++) { printf("rotacia %2d bit: %10u(d) %0*x(h) %32s(b)\n", i, rotuj_doprava(cislo, i), sizeof(int) * 2, rotuj_doprava(cislo, i), des_dvoj_kr(rotuj_doprava(cislo, i))); } return 0; } /* rotuje bity doprava */ unsigned rotuj_doprava(unsigned int x, int n) { unsigned int i, k; /* priprava jednotky v najvyssom bite */ /* do unsigned k vlozime same jednotky (negacia nuly) */ k = ~0; /* 4294967295(d) ffffffff(h) 11111111111111111111111111111111(b) */ /* na najvyssí bit dame nulu (posun doprava o jeden bit) */ k >>= 1; /* 2147483647(d) 7fffffff(h) 01111111111111111111111111111111(b) */ /* spravime negaciu, teda na najvyssom bite bude jednotka a dalej nuly */ k = ~k; /* 2147483648(d) 80000000(h) 10000000000000000000000000000000(b) */ while (n-- != 0) { i = x & 1; x >>= 1; x |= (i == 1) ? k : 0; } return x; } /* pomocna fánkcia na vypis binarneho cisla prevod z desiatkoveho na dvojkove, vystup dvojkove (retazec) */ char* des_dvoj_kr(unsigned int desiatkove) { int i = 0, j, k = -1; char *p_pom, *p_pom1, *p_dvojkove; /* dynamicka alokacia s kontrolou volnej pamati */ if ((p_pom = (char *) malloc(35)) == NULL) { printf("Malo pamati!"); return; } if ((p_pom1 = (char *) malloc(35)) == NULL) { printf("Malo pamati!"); return; } if ((p_dvojkove = (char *) malloc(35)) == NULL) { printf("Malo pamati!"); return; } /* vypocet dvojkoveho cisla, prevod na retazec, jeho otocenie od zadu, doplnenie nul do celej dlzky dvojkoveho cisla */ while (desiatkove != 0) { // cyklus kym nebude 0 p_pom[i] = (desiatkove % 2) + 48; //zvysok po deleni 2 zmeneny na znak desiatkove /= 2; i++; // pom[i] sa zvacsuje s kazdym cyklom } p_pom[i] = '\0'; // ukoncenie retazca for (j = i; j >= 0; j--) p_pom1[j] = p_pom[k++]; // prepis od zadu p_pom1[i + 1] = '\0'; // ukoncenie retazca for (j = 0; j < VELKOST_INT - strlen(p_pom1); j++) // doplnenie nul do velkosti p_dvojkove[j] = '0'; // int minus velkost p_pom1 strcat(p_dvojkove, p_pom1); //spojenie retacov do jedneho bin cisla return (p_dvojkove); } 3. Napíš funkciu unsigned invert(unsigned x, int p, int n), ktorá invertuje (zmení 1 za 0 a naopak) n bitov premennej x počnúc od pozície p vrátane. Ostatné bity ostanú nezmenené. Vyskúšaj v programe. Spoiler: Kód: /************************ * 3.c v.1.0 * * Inverzia skupiny bitov * ====================== * ************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #define VELKOST_INT (sizeof(int) * 8) // pocet bitov v int, v mojom pripade 32 /* uplne funkcne prototypy funkcii */ unsigned invert(unsigned int x, int p, int n); char* des_dvoj_kr(unsigned int desiatkove); /* funkcia main */ int main(void) { unsigned int cislo, i, j; /* zadanie vstupnych dat */ printf("Zadaj unsigned int cislo: "); scanf("%u", &cislo); printf("Zadaj od ktorej pozicie sa maju bity invertovat: "); scanf("%u", &i); printf("Zadaj kolko bitov sa ma invertovat: "); scanf("%u", &j); /* vypis vystupov */ printf("\n%s\n", des_dvoj_kr(cislo)); // zadane cislo binarne printf("%s\n", des_dvoj_kr(invert(cislo, i, j))); // invert coslo binarne return 0; } /* invertuje skupinu zadanu bitov p = pozicia od, n = pocet invertovanych bitov */ unsigned invert(unsigned int x, int p, int n) { unsigned int i, k = x, j = p, l, m; m = VELKOST_INT; if (n <= m) { // aby pocet invertovanych bitov nebol vacsi ako velkost int if (n <= j) { // ak pocet bitov neprekroci pravy posledny bit i = j - n; // posledny bit na inverziu vpravo od pozicie while (j > i) { // od pozicie po posldeny bit na inverziu vravo k ^= (1 << j - 1); // negacia vyclenenych bitov j--; // krok } } else { while (j > 0) { // od pozicie po posldny bit vpravo (0) k ^= (1 << j - 1); // negacia vyclenenych bitov j--; // krok } l = m - (n - p); /* poradove cislo bitu potrebne pri prekroceni prveho praveho bitu a presunu na prvy lavy bit aby sme vedeli az pokial sa budu bity invertovat*/ while (m > l) { // od 1. bitu vlavo po l k ^= (1 << m - 1); // negacia vyclenenych bitov m--; // krok } } } else printf("Pocet invertovanych bitov mimo rozsah! Neinvertujem!\n"); return k; } /* pomocna fánkcia na vypis binarneho cisla prevod z desiatkoveho na dvojkove, vystup dvojkove (retazec) */ char* des_dvoj_kr(unsigned int desiatkove) { int i = 0, j, k = -1; char *p_pom, *p_pom1, *p_dvojkove; /* dynamicka alokacia s kontrolou volnej pamati */ if ((p_pom = (char *) malloc(35)) == NULL) { printf("Malo pamati!"); return; } if ((p_pom1 = (char *) malloc(35)) == NULL) { printf("Malo pamati!"); return; } if ((p_dvojkove = (char *) malloc(35)) == NULL) { printf("Malo pamati!"); return; } /* vypocet dvojkoveho cisla, prevod na retazec, jeho otocenie od zadu, doplnenie nul do celej dlzky dvojkoveho cisla */ while (desiatkove != 0) { // cyklus kym nebude 0 p_pom[i] = (desiatkove % 2) + 48; //zvysok po deleni 2 zmeneny na znak desiatkove /= 2; i++; // pom[i] sa zvacsuje s kazdym cyklom } p_pom[i] = '\0'; // ukoncenie retazca for (j = i; j >= 0; j--) p_pom1[j] = p_pom[k++]; // prepis od zadu p_pom1[i + 1] = '\0'; // ukoncenie retazca for (j = 0; j < VELKOST_INT - strlen(p_pom1); j++) // doplnenie nul do velkosti p_dvojkove[j] = '0'; // int minus velkost p_pom1 strcat(p_dvojkove, p_pom1); //spojenie retacov do jedneho bin cisla return (p_dvojkove); } 4. Napíš program, ktorý bude využívať bitové pole na úschovu dátumu. Položky poľa budú: bity 15 - 9 : rok, ku ktorému sa pripočíta konštanta 1980 teda 22 znamená v skutočnosti rok 2002 bity 8 - 5 : mesiac bity 4 - 0 : deň Program vyskúšaj tak, že načítaš z klávesnice dátum, uložíš ho do bitového poľa, to vytlačíš ako typ unsigned a potom dátum vytlačí ako naozajstný dátum. Na vytlačenie premennej ako unsigned použi union. Spoiler: Kód: /****************************************************** * 4.c v.1.0 * * Bitove pole - pouzitie pro ulozenie zhusteneho cisla * ==================================================== * ******************************************************/ #include <stdio.h> typedef struct { unsigned den : 5; // bity 0 - 4 unsigned mesiac : 4; // bity 5 - 8 unsigned rok : 7; // bity 9 - 15 } DATUM; typedef union { DATUM datum; // deklarovana premenna typu DATUM unsigned int cislo; // deklarovana premenna typu unsigned int } BITY; // deklarovany union typ int main(void) { BITY dnes; // deklarovana premenna typu BITY unsigned int den, mesiac, rok; printf("Zadaj dnesni datum [dd.mm.rrrr]: "); scanf("%d.%d.%d", &den, &mesiac, &rok); dnes.datum.den = den; dnes.datum.mesiac = mesiac; dnes.datum.rok = rok - 2000; // rok dnesneho datumu je nad 2000 //printf("Premenna ako unsigned int je %u\t%s\n", dnes, des_dvoj_kr((unsigned int) dnes)); printf("Premenna ako unsigned int je %u\n\n", dnes); printf("Dnesny datum je %2u.%2u.%4u\n\n", dnes.datum.den, dnes.datum.mesiac, dnes.datum.rok + 2000); printf("Vysvetlenie na datume 23.1.2013:\n" "Premenna 3077839415(d) je 111111111111101 0001101 0001 10111(b)\n" "pricom bity:\n" "0 - 4 (10111) obsahuju cislo 23\n" "5 - 8 (0001) obsahuju cislo 1\n" "9 - 15 (0001101) obsahuju cislo 13, teda 2013 - 2000.\n\n"); return 0; } |
Stránka 1 z 1 | Všetky časy sú v GMT + 1 hodina |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |