Biblioteka za logičke vektore
Napraviti malu biblioteku za rad sa logičkim vektorima predstavljenim nizom bitova (0/1). Vektor se cuva kao dinamicki niz bitova sa najmanje značajnim bitom na indeksu 0. Biblioteka treba da omogući elementarne logičke operacije, poređenje i čitanje/pisanje u fajl.
Zadatak se reševa u fajlovima logic.h, logic.c i main.c.
Biblioteka obezbeđuje:
LogicVec logic_from_string(const char *s)iLogicVec logic_from_file(FILE *f)– konstruktori iz tekstualne reprezentacije (prazna ili neispravna ulazna niska daje vektor0);LogicVec logic_not,logic_and,logic_or,logic_xor– bitovne operacije (nad vektorima različite dužine tretiraju nepostojeće bitove kao0);int logic_equal– poređenje vektora nakon normalizacije vodećih nula;int logic_fprint(FILE *f, const LogicVec *v)ivoid logic_print(const LogicVec *v)– ispis; ivoid logic_free(LogicVec *v)– oslobađanje memorije.
Ulaz
Sa standardnog ulaza se učitavaju komande do kraja ulaza. Dostupne su:
and <A> <B>,or <A> <B>,xor <A> <B>- ispisuje rezultat bitovne operacije nad vektorima zadatim kao stringovi0/1;not <A>- ispisuje negaciju;eq <A> <B>- ispisuje1ako su vektori jednaki (nakon uklanjanja vodećih nula), inače0;- fajl varijante
andf,orf,xorf,eqf,notfrade isto ali vektore čitaju iz fajlova (po jedan vektor po fajlu); read <putanja>- ispisuje vektor iz fajla; iwrite <bits> <putanja>- upisuje vektor u fajl (prepisuje ga) i ispisuje isti vektor na stdout.
Izlaz
Za svaku komandu ispisati trazeni rezultat u posebnoj liniji (0/1 string za vektore ili 0/1 za eq).
U slučaju nepoznate komande, nekompletnog ulaza ili neuspešnog otvaranja/upisa u fajl, program prijavljuje grešku na standardni izlaz za greške i završava se neuspešno.
Primer
stdin
and 1010 1100
or 1010 1100
xor 1010 1100
not 0011
eq 0101 101
stdout
1000
1110
110
1100
1
Primer
a.txt
101010
b.txt
001100
stdin
andf a.txt b.txt
xorf a.txt b.txt
eqf a.txt a.txt
notf b.txt
write 101 out.txt
stdout
1000
100110
1
110011
101
out.txt
101
Rešenje
logic.h
#ifndef LOGIC_H
#define LOGIC_H
#include <stddef.h>
#include <stdio.h>
typedef struct {
size_t len; /* number of bits */
int *bits; /* least significant bit first */
} LogicVec;
LogicVec logic_from_string(const char *s);
LogicVec logic_from_file(FILE *f);
void logic_free(LogicVec *v);
LogicVec logic_not(const LogicVec *a);
LogicVec logic_and(const LogicVec *a, const LogicVec *b);
LogicVec logic_or(const LogicVec *a, const LogicVec *b);
LogicVec logic_xor(const LogicVec *a, const LogicVec *b);
int logic_equal(const LogicVec *a, const LogicVec *b);
int logic_fprint(FILE *f, const LogicVec *v);
void logic_print(const LogicVec *v);
#endifmain.c
#include "logic.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int read_two_inline(LogicVec *a, LogicVec *b)
{
char buf_a[4096], buf_b[4096];
if (scanf("%4095s %4095s", buf_a, buf_b) != 2) {
return 0;
}
*a = logic_from_string(buf_a);
*b = logic_from_string(buf_b);
return 1;
}
static int read_one_inline(LogicVec *a)
{
char buf[4096];
if (scanf("%4095s", buf) != 1) {
return 0;
}
*a = logic_from_string(buf);
return 1;
}
static int read_two_files(const char *pa, const char *pb, LogicVec *a, LogicVec *b)
{
FILE *fa = fopen(pa, "r");
if (!fa) {
fprintf(stderr, "Error: Could not open file %s\n", pa);
return 0;
}
FILE *fb = fopen(pb, "r");
if (!fb) {
fprintf(stderr, "Error: Could not open file %s\n", pb);
fclose(fa);
return 0;
}
*a = logic_from_file(fa);
*b = logic_from_file(fb);
fclose(fa);
fclose(fb);
return 1;
}
static int read_one_file(const char *path, LogicVec *a)
{
FILE *f = fopen(path, "r");
if (!f) {
fprintf(stderr, "Error: Could not open file %s\n", path);
return 0;
}
*a = logic_from_file(f);
fclose(f);
return 1;
}
static void handle_binary(LogicVec (*op)(const LogicVec *, const LogicVec *), int is_eq)
{
LogicVec a, b;
if (!read_two_inline(&a, &b)) {
fprintf(stderr, "Error: Invalid input format.\n");
exit(EXIT_FAILURE);
}
if (is_eq) {
printf("%d\n", logic_equal(&a, &b));
} else {
LogicVec r = op(&a, &b);
logic_print(&r);
logic_free(&r);
}
logic_free(&a);
logic_free(&b);
}
static void handle_binary_file(LogicVec (*op)(const LogicVec *, const LogicVec *), int is_eq)
{
char pa[512], pb[512];
if (scanf("%511s %511s", pa, pb) != 2) {
fprintf(stderr, "Error: Invalid input format.\n");
exit(EXIT_FAILURE);
}
LogicVec a, b;
if (!read_two_files(pa, pb, &a, &b)) {
exit(EXIT_FAILURE);
}
if (is_eq) {
printf("%d\n", logic_equal(&a, &b));
} else {
LogicVec r = op(&a, &b);
logic_print(&r);
logic_free(&r);
}
logic_free(&a);
logic_free(&b);
}
static void handle_unary(LogicVec (*op)(const LogicVec *))
{
LogicVec v;
if (!read_one_inline(&v)) {
fprintf(stderr, "Error: Invalid input format.\n");
exit(EXIT_FAILURE);
}
LogicVec r = op(&v);
logic_print(&r);
logic_free(&v);
logic_free(&r);
}
static void handle_unary_file(LogicVec (*op)(const LogicVec *))
{
char path[512];
if (scanf("%511s", path) != 1) {
fprintf(stderr, "Error: Invalid input format.\n");
exit(EXIT_FAILURE);
}
LogicVec v;
if (!read_one_file(path, &v)) {
exit(EXIT_FAILURE);
}
LogicVec r = op(&v);
logic_print(&r);
logic_free(&v);
logic_free(&r);
}
static void handle_read()
{
char path[512];
if (scanf("%511s", path) != 1) {
fprintf(stderr, "Error: Invalid input format.\n");
exit(EXIT_FAILURE);
}
LogicVec v;
if (!read_one_file(path, &v)) {
exit(EXIT_FAILURE);
}
logic_print(&v);
logic_free(&v);
}
static void handle_write()
{
char bits[4096];
char path[512];
if (scanf("%4095s %511s", bits, path) != 2) {
fprintf(stderr, "Error: Invalid input format.\n");
exit(EXIT_FAILURE);
}
LogicVec v = logic_from_string(bits);
FILE *out = fopen(path, "w");
if (!out) {
fprintf(stderr, "Error: Could not open file %s\n", path);
logic_free(&v);
exit(EXIT_FAILURE);
}
if (!logic_fprint(out, &v)) {
fprintf(stderr, "Error: Could not write file %s\n", path);
fclose(out);
logic_free(&v);
exit(EXIT_FAILURE);
}
logic_print(&v);
fclose(out);
logic_free(&v);
}
int main(void)
{
char op[16];
while (scanf("%15s", op) == 1) {
if (strcmp(op, "and") == 0) {
handle_binary(logic_and, 0);
} else if (strcmp(op, "or") == 0) {
handle_binary(logic_or, 0);
} else if (strcmp(op, "xor") == 0) {
handle_binary(logic_xor, 0);
} else if (strcmp(op, "eq") == 0) {
handle_binary(logic_and, 1);
} else if (strcmp(op, "not") == 0) {
handle_unary(logic_not);
} else if (strcmp(op, "andf") == 0) {
handle_binary_file(logic_and, 0);
} else if (strcmp(op, "orf") == 0) {
handle_binary_file(logic_or, 0);
} else if (strcmp(op, "xorf") == 0) {
handle_binary_file(logic_xor, 0);
} else if (strcmp(op, "eqf") == 0) {
handle_binary_file(logic_and, 1);
} else if (strcmp(op, "notf") == 0) {
handle_unary_file(logic_not);
} else if (strcmp(op, "read") == 0) {
handle_read();
} else if (strcmp(op, "write") == 0) {
handle_write();
} else {
fprintf(stderr, "Error: Unknown operation %s\n", op);
exit(EXIT_FAILURE);
}
}
exit(EXIT_SUCCESS);
}logic.c
#include "logic.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static LogicVec logic_zero(void)
{
LogicVec v;
v.len = 1;
v.bits = calloc(1, sizeof (int));
if (v.bits) {
v.bits[0] = 0;
} else {
v.len = 0;
}
return v;
}
static void logic_strip(LogicVec *v)
{
while (v->len > 1 && v->bits[v->len - 1] == 0) {
v->len--;
}
}
LogicVec logic_from_string(const char *s)
{
if (s == NULL) {
return logic_zero();
}
size_t raw_len = strlen(s);
if (raw_len == 0) {
return logic_zero();
}
LogicVec v;
v.len = raw_len;
v.bits = calloc(raw_len, sizeof (int));
if (v.bits == NULL) {
return logic_zero();
}
for (size_t i = 0; i < raw_len; i++) {
char c = s[raw_len - 1 - i];
if (c != '0' && c != '1') {
logic_free(&v);
return logic_zero();
}
v.bits[i] = c - '0';
}
return v;
}
LogicVec logic_from_file(FILE *f)
{
if (f == NULL) {
return logic_zero();
}
size_t cap = 128;
size_t len = 0;
char *buf = malloc(cap);
if (buf == NULL) {
return logic_zero();
}
int c;
/* skip whitespace */
do {
c = fgetc(f);
if (c == EOF) {
free(buf);
return logic_zero();
}
} while (isspace(c));
while (c != EOF && !isspace(c)) {
if (len + 1 >= cap) {
cap *= 2;
char *tmp = realloc(buf, cap);
if (!tmp) {
free(buf);
return logic_zero();
}
buf = tmp;
}
buf[len++] = (char)c;
c = fgetc(f);
}
buf[len] = '\0';
LogicVec v = logic_from_string(buf);
free(buf);
return v;
}
void logic_free(LogicVec *v)
{
if (v && v->bits) {
free(v->bits);
v->bits = NULL;
v->len = 0;
}
}
LogicVec logic_not(const LogicVec *a)
{
LogicVec res;
res.len = a->len;
res.bits = calloc(res.len, sizeof (int));
if (res.bits == NULL) {
return logic_zero();
}
for (size_t i = 0; i < res.len; i++) {
res.bits[i] = a->bits[i] ? 0 : 1;
}
logic_strip(&res);
return res;
}
static LogicVec logic_binary_op(const LogicVec *a, const LogicVec *b, int (*comb)(int, int))
{
size_t max_len = (a->len > b->len) ? a->len : b->len;
LogicVec res;
res.len = max_len;
res.bits = calloc(max_len, sizeof (int));
if (res.bits == NULL) {
return logic_zero();
}
for (size_t i = 0; i < max_len; i++) {
int va = (i < a->len) ? a->bits[i] : 0;
int vb = (i < b->len) ? b->bits[i] : 0;
res.bits[i] = comb(va, vb);
}
logic_strip(&res);
return res;
}
static int comb_and(int a, int b) { return a && b; }
static int comb_or(int a, int b) { return a || b; }
static int comb_xor(int a, int b) { return a ^ b; }
LogicVec logic_and(const LogicVec *a, const LogicVec *b)
{
return logic_binary_op(a, b, comb_and);
}
LogicVec logic_or(const LogicVec *a, const LogicVec *b)
{
return logic_binary_op(a, b, comb_or);
}
LogicVec logic_xor(const LogicVec *a, const LogicVec *b)
{
return logic_binary_op(a, b, comb_xor);
}
int logic_equal(const LogicVec *a, const LogicVec *b)
{
size_t len_a = a->len;
size_t len_b = b->len;
while (len_a > 1 && a->bits[len_a - 1] == 0) {
len_a--;
}
while (len_b > 1 && b->bits[len_b - 1] == 0){
len_b--;
}
if (len_a != len_b) {
return 0;
}
for (size_t i = 0; i < a->len; i++) {
if (a->bits[i] != b->bits[i]) {
return 0;
}
}
return 1;
}
int logic_fprint(FILE *f, const LogicVec *v)
{
if (f == NULL || v == NULL || v->bits == NULL) {
return 0;
}
for (size_t i = 0; i < v->len; i++) {
fputc(v->bits[v->len - 1 - i] ? '1' : '0', f);
}
fputc('\n', f);
return 1;
}
void logic_print(const LogicVec *v)
{
logic_fprint(stdout, v);
}