From e001baa96f331b5cf0a3c4558a3a684fecbabed0 Mon Sep 17 00:00:00 2001 From: Tibor Bizjak Date: Thu, 22 Jun 2023 13:56:04 +0200 Subject: [PATCH] k&r : solutions to bitwise excersises --- k&r/02-types-operators-and-exp/02-06.c | 36 +++++++-- k&r/02-types-operators-and-exp/02-07.c | 32 ++++++++ k&r/02-types-operators-and-exp/02-08.c | 36 +++++++++ k&r/02-types-operators-and-exp/02-bitwise.c | 89 +++++++++++++++++++++ k&r/02-types-operators-and-exp/02-bitwise.h | 7 ++ k&r/02-types-operators-and-exp/bitwise.h | 22 ----- 6 files changed, 194 insertions(+), 28 deletions(-) create mode 100644 k&r/02-types-operators-and-exp/02-07.c create mode 100644 k&r/02-types-operators-and-exp/02-08.c create mode 100644 k&r/02-types-operators-and-exp/02-bitwise.c create mode 100644 k&r/02-types-operators-and-exp/02-bitwise.h delete mode 100644 k&r/02-types-operators-and-exp/bitwise.h diff --git a/k&r/02-types-operators-and-exp/02-06.c b/k&r/02-types-operators-and-exp/02-06.c index af49667..f5e1f9a 100644 --- a/k&r/02-types-operators-and-exp/02-06.c +++ b/k&r/02-types-operators-and-exp/02-06.c @@ -1,11 +1,35 @@ -#include "bitwise.h" +#include +#include +#include "02-bitwise.h" -#define F(n) getbits(n, 4, 3) +unsigned setbits(unsigned x, int p, int n, unsigned y); -int getbits(unsigned x, int p, int n) +/* parse command line args for setbits, print result */ +int main(int argc, char *argv[]) { - printf("%d\n", x); - return (x >> (p+1-n)) & ~(~0 << n); + if (argc < 5) { + printf("error : expected 4 arguments x p n y\n"); + return 1; + } + unsigned x, y; + int bx = int_of_string(&x, argv[1]); + int p = atoi(argv[2]); + int n = atoi(argv[3]); + int by = int_of_string(&y, argv[4]); + + if (!bx || !by) { + return 2; + } + + printd_base(bx, setbits(x, p, n, y)); + putchar('\n'); + return 0; } -MAIN +/* setbits: replace n bits in position p (right adjusted) in + * x with the rightmost n bits of y, return the result */ +unsigned setbits(unsigned x, int p, int n, unsigned y) +{ + unsigned mask = ~(~0 << n); + return ((y & mask) << (p+1-n)) | (x & ~(mask << (p+1-n))); +} diff --git a/k&r/02-types-operators-and-exp/02-07.c b/k&r/02-types-operators-and-exp/02-07.c new file mode 100644 index 0000000..a4368bf --- /dev/null +++ b/k&r/02-types-operators-and-exp/02-07.c @@ -0,0 +1,32 @@ +#include +#include +#include "02-bitwise.h" + +unsigned invert(unsigned x, int p, int n); + +/* parse command line args for invert, print result */ +int main(int argc, char *argv[]) +{ + if (argc < 4) { + printf("error : expected 3 arguments x p n\n"); + return 1; + } + unsigned x; + int bx = int_of_string(&x, argv[1]); + int p = atoi(argv[2]); + int n = atoi(argv[3]); + + if (!bx) { + return 2; + } + + printd_base(bx, invert(x, p, n)); + putchar('\n'); + return 0; +} + +/* invert: invert n bits of x at positon p (right adjusted) */ +unsigned invert(unsigned x, int p, int n) +{ + return x ^ (~(~0 << n) << (p-n+1)); +} diff --git a/k&r/02-types-operators-and-exp/02-08.c b/k&r/02-types-operators-and-exp/02-08.c new file mode 100644 index 0000000..6818fa3 --- /dev/null +++ b/k&r/02-types-operators-and-exp/02-08.c @@ -0,0 +1,36 @@ +#include +#include +#include "02-bitwise.h" + +unsigned rightrot(unsigned x, int n); + +/* parse command line args for rightrot, print result */ +int main(int argc, char *argv[]) +{ + if (argc < 3) { + printf("error : expected 2 arguments x n\n"); + return 1; + } + unsigned x; + int bx = int_of_string(&x, argv[1]); + int n = atoi(argv[2]); + + if (!bx) { + return 2; + } + + printd_base(bx, rightrot(x, n)); + putchar('\n'); + return 0; +} + +/* rightrot: right rotate x by n bit positions */ +unsigned rightrot(unsigned x, int n) +{ + int p = 0; + while (x >> p) { + p++; + } + n %= p; + return (x >> n) | ((~(~0 << n) & x) << (p - n)); +} diff --git a/k&r/02-types-operators-and-exp/02-bitwise.c b/k&r/02-types-operators-and-exp/02-bitwise.c new file mode 100644 index 0000000..e07de25 --- /dev/null +++ b/k&r/02-types-operators-and-exp/02-bitwise.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include "02-bitwise.h" + +#define BASES X("0b", 2) X("0", 8) X("", 10) X("0x", 16) + +#define X(p, b) int int_of_base_##b(unsigned *x, char *s); + BASES +#undef X + +/* printd_base: prints x in base b */ +void printd_base(int b, unsigned x) +{ + if (!x) { + putchar('0'); + return; + } + + switch (b) { + #define X(p, b) case b : printf("%s", p); break; + BASES + #undef X + } + + unsigned m; + for (m = 1; m * b <= x && m * b > 0; m *= b) + ; + char d; + while (m > 0) { + if ((d = x / m) > 9) + putchar(d - 10 + 'a'); + else + putchar(d + '0'); + x %= m; + m /= b; + } +} + +/* int_of_string: converts string s to int, writes result to *x and returns base + * of the ints string representation or 0 if s is invalid */ +int int_of_string(unsigned *x, char *s) +{ + switch (*s) { + case '0' : + switch (*(s+1)) { + case 'b' : + return int_of_base_2(x, s+2); + case 'x' : + return int_of_base_16(x, s+2); + default : + return int_of_base_8(x, s+1); + } + default : + return int_of_base_10(x, s); + } + return 0; +} + +/* int_of_base_b: for base b, convert number string in base b to int and + * write it to *x. return b or 0 if invalid */ +#define MAKE_INT_OF_BASE(b) \ +int int_of_base_##b(unsigned *x, char *s) \ +{ \ + char d; \ + unsigned px = 0; \ + *x = 0; \ + for (; *s; s++) { \ + d = *s - '0'; \ + if (b > 10 && d > 9) \ + d = tolower(*s) - 'a' + 10; \ + if (d < 0 || d >= b) { \ + printf("error: invalid character in number literal in base " #b "\n"); \ + return 0; \ + } \ + px = *x; \ + *x *= b; \ + *x += d; \ + if (*x < px) { \ + printf("error : number to large\n"); \ + return 0; \ + } \ + } \ + return b; \ +} + +#define X(p, b) MAKE_INT_OF_BASE(b) + BASES +#undef X diff --git a/k&r/02-types-operators-and-exp/02-bitwise.h b/k&r/02-types-operators-and-exp/02-bitwise.h new file mode 100644 index 0000000..f6dde91 --- /dev/null +++ b/k&r/02-types-operators-and-exp/02-bitwise.h @@ -0,0 +1,7 @@ +#ifndef BITWISE_H +#define BITWISE_H + +int int_of_string(unsigned *x, char *s); +void printd_base(int base, unsigned x); + +#endif // BITWISE_H diff --git a/k&r/02-types-operators-and-exp/bitwise.h b/k&r/02-types-operators-and-exp/bitwise.h deleted file mode 100644 index 2fbdf91..0000000 --- a/k&r/02-types-operators-and-exp/bitwise.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef BITWISE_H -#define BITWISE_H - -#include - -unsigned int int_of_bin(char bs[]); -void print_bin(unsigned int n); - -/* standard main, applies function F to binary - * input and prints result (in binary) */ -#define MAIN \ -int main(int argc, char *argv[]) \ -{ \ - if (argc < 0) { \ - printf("error : expected binary string argument\n"); \ - return 1; \ - } \ - print_bin(F(int_of_bin(argv[1]))); \ - putchar('\n'); \ -} \ - -#endif // BITWISE_H