aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--6_1.c209
-rw-r--r--6_2.c68
-rw-r--r--7_2/Makefile16
-rw-r--r--7_2/data4
-rw-r--r--7_2/include/common.h32
-rw-r--r--7_2/include/drawable.h42
-rw-r--r--7_2/include/figure.h56
-rw-r--r--7_2/include/input.h24
-rw-r--r--7_2/main.c44
-rw-r--r--7_2/src/drawable.c120
-rw-r--r--7_2/src/figure.c139
-rw-r--r--7_2/src/input.c116
-rw-r--r--Makefile25
-rw-r--r--README.md50
-rw-r--r--gen.c54
16 files changed, 639 insertions, 365 deletions
diff --git a/.gitignore b/.gitignore
index ae535a6..28dd682 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
compile_flags.txt
-build/
+.clangd
+*/.clangd
+*build/
*.o
+.unused.c
diff --git a/6_1.c b/6_1.c
deleted file mode 100644
index 25c61b5..0000000
--- a/6_1.c
+++ /dev/null
@@ -1,209 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#define SIZEOFBUF 1024
-#define reset(bufsz) bufsz = SIZEOFBUF
-
-// копирует n линий из файла in в файл out
-void copy_n_lines(char **buf, size_t *bufsz, FILE *in, FILE *out, int n) {
- for (int i = 0; i < n; ++i) {
- getline(buf, bufsz, in);
- fputs(*buf, out);
- }
-}
-
-// комирует первые n столбцов из фала in в out
-void copy_n_words(char **buf, size_t *bufsz, FILE *in, FILE *out, int n, char delim) {
- ssize_t cursz;
- for (int i = 0; i < n; ++i) {
- if ((cursz = getdelim(buf, bufsz, delim, in)) < 0) return;
- fputs(*buf, out);
- }
-}
-
-// пропускает первые n слов в файле in
-void skip_n_words(char **buf, size_t *bufsz, FILE *in, int n, char delim) {
- for (int i = 0; i < n; ++i)
- getdelim(buf, bufsz, delim, in);
-}
-
-// вариант 1
-void change_surnames(FILE *in, FILE *out) {
- char *buf = malloc(SIZEOFBUF);
- size_t bufsz = SIZEOFBUF;
- ssize_t cursz;
- // первые 2 строки такие же
- copy_n_lines(&buf, &bufsz, in, out, 2);
- while (!feof(in)) {
- // получаем первое слово
- if ((cursz = getdelim(&buf, &bufsz, '\t', in)) < 0) break;
- buf[cursz-1] = '\0'; // убираем '\t' в конце
- fprintf(out, "%s%c\t", buf, rand() % ('z'-'a'+1)+'a');
- // копируем оставшуюся линию
- if (getline(&buf, &bufsz, in) < 0) break;
- fputs(buf, out);
- }
- free(buf);
-}
-
-// вариант 2
-void change_birth_dates(FILE *in, FILE *out) {
- char *buf = malloc(SIZEOFBUF);
- size_t bufsz = SIZEOFBUF;
- // первые 2 строки должны быть такими же
- copy_n_lines(&buf, &bufsz, in, out, 2);
- while (!feof(in)) {
- // и первые 3 слова тоже
- copy_n_words(&buf, &bufsz, in, out, 3, '\t');
- // меняем дату :devil:
- if (getdelim(&buf, &bufsz, '\t', in) < 0) break;
- int bd = atoi(buf);
- if (!bd) break;
- fprintf(out, "%i\t", bd + rand()%11-5);
- // выписываем оставшуюся строку
- if (getline(&buf, &bufsz, in) < 0) break;
- fputs(buf, out);
- }
- free(buf);
-}
-
-// вариант 3
-void avg_score(FILE *in, FILE *out) {
- char *buf = malloc(SIZEOFBUF);
- size_t bufsz = SIZEOFBUF;
- size_t counter = 0;
- long marks[3] = {0};
- // первые 4 столбца
- skip_n_words(&buf, &bufsz, in, 4, '\t');
- // комируем оставшуюся линию
- copy_n_lines(&buf, &bufsz, in, out, 1);
- while (!feof(in)) {
- // первые 4 столбца не интересуют
- skip_n_words(&buf, &bufsz, in, 4, '\t');
- if (getline(&buf, &bufsz, in) < 0) break;
- // здесь и в цикле выделяем 3 числа и прибавляем их к
- // оценкам по правильному индексу
- // strotok, а не getdelim, потому что доходим до конца строки
- strtok(buf, "\t\n");
- int index = 0;
- do {
- int tmp = atoi(buf);
- if (!tmp) break;
- marks[index] += tmp;
- ++index;
- } while ((buf = strtok(NULL, "\t\n")));
- ++counter;
- }
- // выводим результат
- fprintf(out, "%lf\t%lf\t%lf\n",
- (double)marks[0] / counter,
- (double)marks[1] / counter,
- (double)marks[2] / counter);
- free(buf);
-}
-
-// вариант 4
-void switch_marks(FILE *in, FILE *out) {
- char *buf = malloc(SIZEOFBUF);
- size_t bufsz = SIZEOFBUF;
- // первые 2 линие такие же
- copy_n_lines(&buf, &bufsz, in, out, 2);
- while (!feof(in)) {
- copy_n_words(&buf, &bufsz, in, out, 4, '\t');
- if (getline(&buf, &bufsz, in) < 0) break;
- // здесь и в цикле выделяем 3 числа и изменяем их по заданию
- // strotok, а не getdelim, потому что доходим до конца строки
- strtok(buf, "\t\n");
- do {
- int tmp = atoi(buf);
- if (!tmp) break;
- fprintf(out, "%i\t", 5-tmp+2); // о неет, кто поменял все оценки...
- } while ((buf = strtok(NULL, "\t\n")));
- fputc('\n', out); // не забываем newline
- }
- free(buf);
-}
-
-// вариант 5
-void excellents(FILE *in, FILE *out) {
- char *buf = malloc(SIZEOFBUF);
- size_t bufsz = SIZEOFBUF;
- ssize_t cursz;
- // возьмём столбцы из оригинального файла и скопируем нужные
- copy_n_lines(&buf, &bufsz, in, out, 1);
- copy_n_words(&buf, &bufsz, in, out, 1, '\t');
- skip_n_words(&buf, &bufsz, in, 3, '\t');
- copy_n_lines(&buf, &bufsz, in, out, 1);
- while (!feof(in)) {
- if ((cursz = getdelim(&buf, &bufsz, '\t', in)) < 0) break;
- // сохраняем фамилию на потом;
- char *lname = malloc(sizeof (char) * cursz);
- char *marks = NULL; // понадобится позже
- strncpy(lname, buf, cursz);
- // пропускаем 3 колонки (имя, отчество, дата рождения)
- skip_n_words(&buf, &bufsz, in, 3, '\t');
- // сохраняем строку оценок
- if ((cursz = getline(&buf, &bufsz, in)) < 0) goto free; // чтобы не было утечек памяти
- marks = malloc(sizeof (char) * cursz);
- strncpy(marks, buf, cursz);
- // цикл, в котором считаем кол-во пятёрок
- int fives_count = 0;
- strtok(buf, "\t\n");
- do {
- int tmp = atoi(buf);
- if (!tmp) break;
- if (tmp == 5) ++fives_count;
- } while ((buf = strtok(NULL, "\t\n")));
- if (fives_count >= 2)
- fprintf(out, "%s%s", lname, marks);
-free:
- free(lname);
- free(marks);
- }
-}
-
-// массив функций для более простого выбора варианта
-void (*variants[5])(FILE *, FILE *) = {
- change_surnames,
- change_birth_dates,
- avg_score,
- switch_marks,
- excellents
-};
-
-int main(int argc, char *argv[]) {
- srand(0xB19B00B5);
-
- // стандартный цикл обработки аргументов argv
- if (argc != 6) {
- fprintf(stderr, "usage: \n" "%s -i INPUT -o OUTPUT variant\n", *argv);
- return 1;
- }
- const char *in, *out;
- int var = 0;
- for (int i = 0; i < argc; ++i) {
- if (!strcmp(argv[i], "-i"))
- in = argv[++i];
- else if (!strcmp(argv[i], "-o"))
- out = argv[++i];
- else
- var = atoi(argv[i]);
- }
- if (var < 1 || var > 5) {
- fprintf(stderr, "Неправильный вариант: %i\n", var);
- return 1;
- }
- // открытие файлов
- FILE *f_in = fopen(in, "r");
- FILE *f_out = fopen(out, "w+");
- if (!f_in || !f_out) {
- fprintf(stderr, "Не удалось открыть файл: %s\n", strerror(errno));
- return 1;
- }
- // сам вызов функции
- variants[--var](f_in, f_out);
- return 0;
-}
-
diff --git a/6_2.c b/6_2.c
deleted file mode 100644
index 77b0a9d..0000000
--- a/6_2.c
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <stdio.h>
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define SIZEOFBUF 1024
-
-// какую функцию будем дифференцировать
-double (*const func)(double) = sin;
-
-// пункт 1
-void generate_file1(FILE *f, double min, double max, double dx) {
- for (double i = min; i < max; i += dx) {
- fprintf(f, "x = %lf\tf(x) = %lf\t f'(x) = %lf\n",
- i, func(i), (func(i+dx) - func(i)) / dx
- );
- }
-}
-
-void generate_file2(FILE *in, FILE *out) {
- char *buf = malloc(SIZEOFBUF);
- size_t bufsize = SIZEOFBUF;
- const char *delim = "xf()'= \t\n";
- while (!feof(in)) {
- getline(&buf, &bufsize, in);
- char * p = strtok(buf, delim);
- do fprintf(out, "%s\t", p);
- while ((p = strtok(NULL, delim)) != NULL);
- fputc('\n', out);
- }
-}
-
-int main(int argc, char *argv[]) {
- // стандартный цикл обработки аргументов argv
- if (argc != 5*2 + 1) {
- fprintf(stderr,
- "usage: \n" "%s -1 FILE1 -2 FILE2 -a MIN -b MAX -x DX\n"
- "\t FILE1: пункт 1, FILE2: пункт2\n"
- "\tMIN: нижняя граница дифференцирования, MAX: верхняя\n"
- "\tDX: шаг дифференцирования\n",
- *argv);
- return 1;
- }
- const char *f1, *f2;
- double min, max, dx;
- for (int i = 0; i < argc; ++i) {
- if (!strcmp(argv[i], "-1"))
- f1 = argv[++i];
- if (!strcmp(argv[i], "-2"))
- f2 = argv[++i];
- if (!strcmp(argv[i], "-a"))
- min = atof(argv[++i]);
- if (!strcmp(argv[i], "-b"))
- max = atof(argv[++i]);
- if (!strcmp(argv[i], "-x"))
- dx = atof(argv[++i]);
- }
-
- FILE *f1f = fopen(f1, "w+");
- if (!f1f) return 1;
- generate_file1(f1f, min, max, dx);
- fclose(f1f);
- f1f = fopen(f1, "r");
- FILE *f2f = fopen(f2, "w+");
- if (!f2f) return 1;
- generate_file2(f1f, f2f);
- return 0;
-}
diff --git a/7_2/Makefile b/7_2/Makefile
new file mode 100644
index 0000000..7c29431
--- /dev/null
+++ b/7_2/Makefile
@@ -0,0 +1,16 @@
+
+all: main
+
+build:
+ mkdir -p build
+
+build/%.o: src/%.c include/%.h build
+ $(CC) -c -g -ggdb -o $@ $< -Iinclude
+
+main: main.c build/drawable.o build/figure.o build/input.o
+ $(CC) -o $@ $^ -lm -lX11 -Iinclude
+
+.PHONY: clean
+
+clean:
+ $(RM) *.o main build/*
diff --git a/7_2/data b/7_2/data
new file mode 100644
index 0000000..9d831b7
--- /dev/null
+++ b/7_2/data
@@ -0,0 +1,4 @@
+l {0, 1} {1, 2};
+r {2, 2} {40, 18};
+
+c {20, 20} 10;
diff --git a/7_2/include/common.h b/7_2/include/common.h
new file mode 100644
index 0000000..660532f
--- /dev/null
+++ b/7_2/include/common.h
@@ -0,0 +1,32 @@
+#ifndef JAC_COMMON_H
+#define JAC_COMMON_H
+
+/* Для чтающих:
+ * чтобы писать
+ * `vector2 point = { 10, 20 };`
+ * вместо
+ * `struct vector2 point = { 10, 20 };`
+ * (то есть чтобы писать struct перед vector2 было необязательно)
+ * надо объявлять структуру так:
+ * ```
+ * typedef struct {
+ * long x, y;
+ * } vector2;
+ * ```
+ * Таким образом мы объявляем структуру без официального названия,
+ * но присваиваем ей синоним. Чтобы пользоваться и тем, и тем вариантами,
+ * можно сделать так:
+ * ```
+ * typedef struct vector2 {
+ * long x, y;
+ * } vector2;
+ * ```
+ * Так мы и даём ей название, и даём ей синоним.
+ */
+
+// координаты точки в 2-мерном пространстве
+typedef struct vector2 {
+ long x, y;
+} vector2;
+
+#endif // JAC_COMMON_H
diff --git a/7_2/include/drawable.h b/7_2/include/drawable.h
new file mode 100644
index 0000000..3d0caeb
--- /dev/null
+++ b/7_2/include/drawable.h
@@ -0,0 +1,42 @@
+#ifndef JCG_DRAWABLE_H
+#define JCG_DRAWABLE_H
+
+#define FILL_CHR '#'
+#define SPACE_CHR ' '
+
+// что угодно, на чём можно ''нарисовать''
+// должно иметь размер, размер пикселей, данные
+// функция put записывает пиксель по координатам x, y на поле
+// функция show выводит данные на экран/куда угодно ещё
+struct drawable {
+ long x, y, pix_s;
+ void *data;
+ void (*put)(struct drawable *self, long x, long y);
+ void(*show)(const struct drawable *self);
+};
+
+
+// конструктор
+void drawable_init(struct drawable* self,
+ void(*put_f)(struct drawable *, long, long),
+ void(*show_f)(const struct drawable *),
+ long width,
+ long height,
+ long pix_s);
+// деструктор
+void drawable_destroy(struct drawable *self);
+// конструктор для консольного поля
+struct drawable drawable_plaintxt(long width, long height);
+// конструктор для графического поля
+struct drawable drawable_X11(long width, long height);
+
+// put для консольного drawable
+void put_plaintxt(struct drawable *self, long x, long y);
+// show для консольного drawable
+void show_plaintxt(const struct drawable *self);
+// put для графического drawable
+void put_X11(struct drawable *self, long x, long y);
+// show для графического drawable
+void show_X11(const struct drawable *self);
+
+#endif // JCG_DRAWABLE_H
diff --git a/7_2/include/figure.h b/7_2/include/figure.h
new file mode 100644
index 0000000..393ca00
--- /dev/null
+++ b/7_2/include/figure.h
@@ -0,0 +1,56 @@
+#ifndef JCG_FIGURE_H
+#define JCG_FIGURE_H
+
+#include "drawable.h"
+#include "common.h"
+
+// любая фигура
+// создаётся функциями figure_point, figure_line и т.д.
+// у каждой фигуры должен быть способ "нарисоваться" на
+// любое "рисовальное" поле, используя функцию drawable.put
+struct figure {
+ enum {
+ F_NONE, F_POINT, F_RECT, F_LINE, F_CIRCLE
+ } type;
+ union {
+ struct {
+ vector2 coords;
+ } point;
+ struct {
+ vector2 upleft, downright;
+ } rect;
+ struct {
+ vector2 start, end;
+ } line;
+ struct {
+ vector2 center;
+ long rad;
+ } circle;
+ };
+ void (*draw)(const struct figure *self, struct drawable *d);
+};
+
+// массив функций по типам (lookup table)
+extern void (*const draw_lookup[])(const struct figure *, struct drawable *);
+
+// конструктор 1
+struct figure figure_point(vector2 p);
+// конструктор 2
+struct figure figure_rect(vector2 upleft, vector2 downright);
+// конструктор 3
+struct figure figure_line(vector2 start, vector2 end);
+// конструктор 4
+struct figure figure_circle(vector2 center, long radius);
+
+// draw для F_POINT
+void draw_point(const struct figure *self, struct drawable *d);
+// draw для F_RECT
+void draw_rect(const struct figure *self, struct drawable *d);
+// draw для F_LINE
+void draw_line(const struct figure *self, struct drawable *d);
+// draw для F_CIRCLE
+void draw_circle(const struct figure *self, struct drawable *f);
+
+void print_figure(const struct figure *self);
+
+#endif // JCG_FIGURE_H
diff --git a/7_2/include/input.h b/7_2/include/input.h
new file mode 100644
index 0000000..24285b8
--- /dev/null
+++ b/7_2/include/input.h
@@ -0,0 +1,24 @@
+#ifndef JAC_INPUT_H
+#define JAC_INPUT_H
+
+#include "common.h"
+#include "figure.h"
+
+extern void(*settings_handler)(const char *sett_string);
+
+// пропустить пробелы
+void skipw(char const **s);
+// проспустит цифры
+void skipd(char const **s);
+// проерить наличие символа
+char chktok(char const **str, char tok);
+// прочитать число
+char parsel(char const **str, long *l);
+// прочитать вектор из 2 чисел
+char parsev(char const **str, vector2 *v);
+// прочитать одну фигуру
+struct figure read_figure(const char *str);
+// прочитать целый файл
+struct figure *read_file(const char *path);
+
+#endif // JAC_INPUT_H
diff --git a/7_2/main.c b/7_2/main.c
new file mode 100644
index 0000000..5411ecf
--- /dev/null
+++ b/7_2/main.c
@@ -0,0 +1,44 @@
+#include <X11/X.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "input.h"
+#include "drawable.h"
+#include "figure.h"
+
+long fatness = 1; // пока никак не используется
+
+int sx = 100, sy = 100;
+
+int main(int argc, char *argv[]) {
+ char file[256] = {};
+ if (argc >= 2) {
+ size_t len = strlen(argv[1]);
+ memcpy(file, argv[1], len > 255 ? 255 : len);
+ } else {
+ printf("введите файл: ");
+ scanf("%255s", file);
+ }
+ char x11 = 0;
+ for (int i = 0; i < argc; ++i) {
+ if (!strcmp("-X", argv[i])) x11 = 1;
+ }
+ struct figure *fs = read_file(file);
+ struct drawable d = x11 ? drawable_X11(sx, sy) : drawable_plaintxt(sx, sy);
+ if (!fs) {
+ fprintf(stderr, "ERROR: errno %i: %s\n", errno, strerror(errno));
+ return 1;
+ }
+ for (struct figure *i = fs; i->type != F_NONE; ++i)
+ i->draw(i, &d);
+
+ d.show(&d);
+ free(fs);
+ drawable_destroy(&d);
+ return 0;
+}
+
diff --git a/7_2/src/drawable.c b/7_2/src/drawable.c
new file mode 100644
index 0000000..33e7290
--- /dev/null
+++ b/7_2/src/drawable.c
@@ -0,0 +1,120 @@
+#include "drawable.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+static struct {
+ enum {CTX_NO, CTX_INIT, CTX_FAIL} init;
+ Display *d;
+ Window r, w;
+ int s;
+ GC gctx;
+ XVisualInfo v;
+ XImage *i;
+ int* data;
+} X11 = { .init=CTX_NO };
+
+struct drawable drawable_plaintxt(long width, long height) {
+ struct drawable ret;
+ // with, height +1 because inclusive
+ drawable_init(&ret, put_plaintxt, show_plaintxt, width + 1, height + 1, sizeof (char));
+ memset(ret.data, 0, height*width*1);
+ return ret;
+}
+struct drawable drawable_X11(long width, long height) {
+ struct drawable ret;
+ drawable_init(&ret, put_X11, show_X11, width, height, sizeof (int));
+ int* data = ret.data;
+ for (size_t i = 0; i < width*height; ++i)
+ data[i] = 0x00FFFFFF;
+ return ret;
+}
+
+void drawable_init(struct drawable* self,
+ void(*put_f)(struct drawable *, long, long),
+ void(*show_f)(const struct drawable *),
+ long width,
+ long height,
+ long pix_s)
+{
+ self->x = width;
+ self->y = height;
+ self->pix_s = pix_s;
+ self->data = malloc(height*width*pix_s);
+ self->put = put_f;
+ self->show = show_f;
+}
+
+void drawable_destroy(struct drawable *self) {
+ free(self->data);
+}
+
+/// plaintxt methods ///
+
+void put_plaintxt(struct drawable *self, long x, long y) {
+ if (x >= self->x || y >= self->y || x < 0 || y < 0) return;
+ char *data = self->data;
+ data[self->x * y + x] = 1;
+}
+
+void show_plaintxt(const struct drawable *self) {
+ char map[2] = {SPACE_CHR, FILL_CHR};
+ for (int i = 0; i < self->y; ++i) {
+ for (int j = 0; j < self->x; ++j) {
+ char *d = self->data;
+ putchar(map[d[i*self->x + j]]);
+ }
+ putchar('\n');
+ }
+}
+
+
+/// X11 from now on ///
+
+static void init_X11(const struct drawable *self) {
+ X11.d = XOpenDisplay(NULL);
+ if (X11.d == NULL) {
+ X11.init = CTX_FAIL;
+ return;
+ }
+ X11.s = DefaultScreen(X11.d);
+ X11.r = RootWindow(X11.d, X11.s);
+ X11.gctx = DefaultGC(X11.d, X11.s);
+ Window w = XCreateSimpleWindow(X11.d, X11.r, 0, 0, self->x, self->y, 0, 0, 0x00FFFFFF);
+ if (!XMatchVisualInfo(X11.d, X11.s, 24, TrueColor, &X11.v)) {
+ XDestroyWindow(X11.d, X11.w);
+ XCloseDisplay(X11.d);
+ X11.init = CTX_FAIL;
+ return;
+ };
+ XMapWindow(X11.d, X11.w);
+ XSelectInput(X11.d, X11.w, ExposureMask);
+ X11.data = malloc(self->x * self->y * sizeof (int));
+ X11.i = XCreateImage(X11.d, X11.v.visual, X11.v.depth, ZPixmap, 0, (void*)X11.data, self->x, self->y, 8*sizeof (int), 0);
+}
+
+void put_X11(struct drawable *self, long x, long y) {
+ if (x >= self->x || y >= self->y || x < 0 || y < 0) return;
+ int *data = self->data;
+ data[self->x * y + x] = 0x00000000;
+}
+
+void show_X11(const struct drawable *self) {
+start:
+ switch (X11.init) {
+ case CTX_NO: init_X11(self); goto start;
+ case CTX_INIT: break;
+ case CTX_FAIL:
+ fprintf(stderr, "Error: Could not initialize Xlib\n");
+ return;
+ }
+ XEvent e = {};
+ XNextEvent(X11.d, &e);
+ XPutImage(X11.d, X11.w, X11.gctx, X11.i, 0, 0, 0, 0, self->x, self->y);
+}
+
diff --git a/7_2/src/figure.c b/7_2/src/figure.c
new file mode 100644
index 0000000..290d4af
--- /dev/null
+++ b/7_2/src/figure.c
@@ -0,0 +1,139 @@
+
+#include "figure.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+void (*const draw_lookup[])(const struct figure *, struct drawable *) = {
+ [F_NONE] = NULL,
+ [F_POINT] = draw_point,
+ [F_RECT] = draw_rect,
+ [F_LINE] = draw_line,
+ [F_CIRCLE] = draw_circle
+};
+
+void swapl(long *x, long *y) {
+ long tmp = *x;
+ *x = *y;
+ *y = tmp;
+}
+
+struct figure figure_point(vector2 p) {
+ return (struct figure) {
+ .type = F_POINT,
+ .point.coords = p,
+ .draw = draw_point
+ };
+}
+
+struct figure figure_rect(vector2 upleft, vector2 downright) {
+ return (struct figure) {
+ .type = F_RECT,
+ .rect = {upleft, downright},
+ .draw = draw_rect
+ };
+}
+
+struct figure figure_line(vector2 start, vector2 end) {
+ return (struct figure) {
+ .type = F_LINE,
+ .line = {start, end},
+ .draw = draw_line
+ };
+}
+
+struct figure figure_circle(vector2 center, long radius) {
+ return (struct figure) {
+ .type = F_CIRCLE,
+ .circle = {center, radius},
+ .draw = draw_circle
+ };
+}
+
+
+void draw_point(const struct figure *self, struct drawable *d) {
+ d->put(d, self->point.coords.x, self->point.coords.y);
+}
+
+void draw_rect(const struct figure *self, struct drawable *d) {
+ vector2 upleft = self->rect.upleft;
+ vector2 downright = self->rect.downright;
+ for (long i = upleft.x; i < downright.x + 1; ++i) {
+ d->put(d, i, upleft.y);
+ d->put(d, i, downright.y);
+ }
+ for (long j = upleft.y + 1; j < downright.y; ++j) {
+ d->put(d, upleft.x, j);
+ d->put(d, downright.x, j);
+ }
+}
+
+void draw_line(const struct figure *self, struct drawable *d) {
+ vector2 start = self->line.start;
+ vector2 end = self->line.end;
+ char gt45 = labs(end.y - start.y) > labs(end.x - start.x);
+ long x0 = start.x, y0 = start.y,
+ x1 = end.x, y1 = end.y;
+ if (gt45) {
+ swapl(&x0, &y0);
+ swapl(&x1, &y1);
+ }
+ if (x0 > x1) {
+ swapl(&x0, &x1);
+ swapl(&y0, &y1);
+ }
+ long dy = labs(y1-y0),
+ dx = x1 - x0,
+ err = dx >> 1, // *2
+ yinc = (y1 > y0 ? 1 : -1);
+
+ for (long x = x0, y = y0; x <= x1; ++x) {
+ if (gt45) d->put(d, y, x);
+ else d->put(d, x, y);
+ err -= dy;
+ if (err < 0) {
+ y += yinc;
+ err += dx;
+ }
+ }
+}
+
+void draw_circle(const struct figure *self, struct drawable *f) {
+ const vector2 p = self->circle.center;
+ const long rad = self->circle.rad - 1;
+ const long pi4 = ceil(M_SQRT1_2 * rad);
+ long x0 = 0, y0 = rad;
+ do {
+ // выглядит коряво, зато в 8 раз меньше повторений цикла
+ f->put(f, p.x-x0, p.y-y0); // 3 четверть
+ f->put(f, p.x-x0, p.y+y0); // 2 чет.
+ f->put(f, p.x+x0, p.y-y0); // 4 ч.
+ f->put(f, p.x+x0, p.y+y0); // 1 ч
+ f->put(f, p.x-y0, p.y-x0);
+ f->put(f, p.x-y0, p.y+x0);
+ f->put(f, p.x+y0, p.y-x0);
+ f->put(f, p.x+y0, p.y+x0);
+ ++x0;
+ // вычисляем x^2 + (y+1/2)^2 - r^2
+ // раскрыли скобки и умножили на 4, чтобы не иметь дело
+ // с дробными числами (они медленные)
+ long func = 4*x0*x0 + 4*y0*y0 - 4*y0 + 1 - 4*rad*rad;
+ y0 = (func >= 0 ? y0 - 1 : y0);
+ } while (x0 < pi4);
+}
+
+void print_figure(const struct figure *self) {
+ printf("figure {\n\t.type = %i\n\t{%li, %li},\n\t", self->type, self->line.start.x, self->line.start.y);
+ switch (self->type) {
+ case F_LINE:
+ case F_RECT:
+ printf("{%li, %li}\n\t", self->line.end.x, self->line.end.y);
+ break;
+ case F_CIRCLE:
+ printf("%li\n\t", self->circle.rad);
+ // fallthrough
+ case F_NONE:
+ case F_POINT:;
+ }
+ printf(".draw = %p\n}\n", self->draw);
+}
diff --git a/7_2/src/input.c b/7_2/src/input.c
new file mode 100644
index 0000000..d2dca7c
--- /dev/null
+++ b/7_2/src/input.c
@@ -0,0 +1,116 @@
+#include "input.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+const char *const unexpchtok = "Unexpected token: %c\n";
+const char *const invalidint = "Invalid integer: %s\n";
+
+#define error(fmt, ...) do { \
+ fprintf(stderr, fmt, __VA_ARGS__); \
+ return 0; \
+} while(0)
+
+#define maybe_realloc(size, cap, pointer, type) do { \
+ if (size >= cap) { \
+ cap <<= 1; \
+ pointer = realloc(pointer, cap * sizeof (type));\
+ } \
+} while(0)
+
+void(*settings_handler)(const char*) = NULL;
+
+void skipw(char const **s) { while(isspace(**s)) ++*s; }
+void skipd(char const **s) { while(isdigit(**s)) ++*s; }
+
+char chktok(char const **str, char tok) {
+ skipw(str);
+ long tmp = atol(*str);
+ if (**str != tok) error(unexpchtok, **str);
+ ++*str;
+ return 1;
+}
+
+char parsel(char const **str, long *l) {
+ skipw(str);
+ long tmp = atoi(*str);
+ if (tmp == 0 && **str != '0') error(invalidint, *str);
+ *l = tmp;
+ skipd(str);
+ return 1;
+}
+
+char parsev(char const **str, vector2 *v) {
+ long x, y;
+ // я ща кончу на этот код
+ char suc = chktok(str, '{')
+ && parsel(str, &x)
+ && chktok(str, ',')
+ && parsel(str, &y)
+ && chktok(str, '}');
+ if (suc) {
+ v->x = x;
+ v->y = y;
+ return 1;
+ } else return 0;
+}
+
+struct figure read_figure(const char *str) {
+ struct figure ret = {.type = F_NONE};
+ const char *strp = str;
+ skipw(&strp);
+ ++strp;
+ switch(strp[-1]) {
+ case '.': {
+ if (settings_handler != NULL) settings_handler(strp);
+ } break;
+ case 'p': {
+ if (parsev(&strp, &ret.point.coords)
+ && chktok(&strp, ';')) ret.type = F_POINT;
+ } break;
+ case 'r': {
+ if (parsev(&strp, &ret.rect.upleft)
+ && parsev(&strp, &ret.rect.downright)
+ && chktok(&strp, ';')) ret.type = F_RECT;
+ } break;
+ case 'l': {
+ if (parsev(&strp, &ret.line.start)
+ && parsev(&strp, &ret.line.end)
+ && chktok(&strp, ';')) ret.type = F_LINE;
+ } break;
+ case 'c': {
+ if (parsev(&strp, &ret.circle.center)
+ && parsel(&strp, &ret.circle.rad)
+ && chktok(&strp, ';')) ret.type = F_CIRCLE;
+ } break;
+ default:;
+ }
+ ret.draw = draw_lookup[ret.type];
+ return ret;
+}
+
+struct figure *read_file(const char *path) {
+ FILE *f = fopen(path, "r");
+ if (!f) return NULL;
+ size_t bs = 1024;
+ size_t fs = -1, fcap = 16;
+ char *buf = malloc(fcap * sizeof(struct figure));
+ struct figure *figures = malloc(fcap * sizeof (struct figure));
+ while (!feof(f)) {
+ if (getdelim(&buf, &bs, ';', f) < 0) break;
+ struct figure f = read_figure(buf);
+ if (f.type == F_NONE) continue;
+ ++fs;
+ maybe_realloc(fs, fcap, figures, struct figure);
+ memcpy(figures + fs, &f, sizeof (struct figure));
+ }
+ ++fs;
+ maybe_realloc(fs, fcap, figures, struct figure);
+ struct figure END = {.type = F_NONE, 0};
+ memcpy(figures + fs, &END, sizeof (struct figure));
+ free(buf);
+ return figures;
+}
+
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 710a9d8..0000000
--- a/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-
-VAR ?= 1
-
-all: 6_1 6_2
-
-gen: gen.c
- $(CC) -o $@ $<
-
-6_1: 6_1.c gen
- $(CC) -o $@ $<
-
-6_2: 6_2.c
- $(CC) -o $@ $< -lm
-
-.PHONY: clean run1 run2
-
-run1: gen 6_1
- ./gen 100 in.1
- ./6_1 -i in.1 -o out.1 $(VAR)
-
-run2: 6_2
- ./6_2 -1 t2.1 -2 t2.2 -a 0 -b 3.141592657 -x 0.1
-
-clean:
- rm -f gen 6_1 6_2 in.1 out.1 t2.1 t2.2
diff --git a/README.md b/README.md
index cd489ed..4f29fd3 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,42 @@
-# задания 6.1 и 6.2
-# Я заебался
-если есть вопросы - лс
-## 6.1
-Сделано для всех вариантов. Для каждого варианта своя функция с комментами
-## 6.2
-Просто сделано 2 пункта в 1 файле. Я не вижу смысл создавать 2 программы, когда можно
-создать одну, выполняюшую оба из них
+# Задания 7.1 и 7.2
+
+## 7.1:
+пока не сделал
+
+## 7.2:
+### Запуск
+кросс-платформенный, система сборки GNU make
+### идея
+
+### формат входного файлыа:
+Каждая строка соответствует шаблону:
+```
+ФИГУРА <параметры...>;
+```
+Параметры разделяются пробелом. Возможные параметры: число и точка. Формат точки: `{A, B}`, где A, B - неотрицательные числа.
+Файл не чувствителен к пробелам, переносам на другую строку и т.п.
+Вместо фигуры могут указываться дополнительные параметры, например `.fld_size` (TODO: ЗАКОНЧИТЬ И ЗАДОКУМЕНТИРОВАТЬ)
+#### Фигуры:
+* p - точка
+* l - линия
+* r - прямоугольник
+* c - круг
+#### Дополнительные параметры:
+* Пока ничего...
+#### Пример файла:
+```
+p {
+ 0, 1
+};
+l {0, 1} {1, 2};
+r {2, 2} {40, 18};
+c
+ {20, 20}
+ 1000;
+```
+### файлы исходников
+В файле [main.c](7_2/main.c) почти ничего нет. Как всегда, файлы .h и .c разбиты по папками [include](7_2/include) и [src](7_2/src) соответстенно.
+* `common.h`: только определение структуры точки. Там есть один довольно важный комментарий!
+* `drawable`: определяет функции поля (показать, нарисовать точку).
+* `figure`: определяет структуру figure и алгоритмы, которые позволяют рисовать их на любом поле типа drawable.
+* `input`: определяет функции для чтения входного файла в формате, описанном выше
diff --git a/gen.c b/gen.c
deleted file mode 100644
index 44c3d9b..0000000
--- a/gen.c
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-
-#define vowsz (sizeof vows)
-#define consz (sizeof cons)
-
-char vows[] = {'a', 'e', 'i', 'o', 'u'};
-char cons[] = {
- 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
- 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'
-};
-
-int main(int argc, char *argv[]) {
- srand(69420);
- if (argc != 3) {
- fputs("Error: usage: provide number of arguments and output filename\n"
- "./a.out 69 amogus\n", stderr);
- return 1;
- }
- int amount = atoi(argv[1]);
- FILE *f = fopen(argv[2], "w+");
- fprintf(f, "Группа N%u\n", rand());
- fputs("Ф\tИ\tО\tг.р.\tФизика\tМатан\tИнф-ка\n", f);
- for (int i = 0; i < amount; ++i) {
- char lname[8] = {0},
- name[8] = {0},
- mname[8] = {0};
- int byear = rand()%125+1900,
- scphy = rand() % 4 + 2,
- scmat = rand() % 4 + 2,
- scinf = rand() % 4 + 2;
- lname[0] = rand() % ('Z'-'A'+1)+'A';
- name[0] = rand() % ('Z'-'A'+1)+'A';
- mname[0] = rand() % ('Z'-'A'+1)+'A';
- char llastvow = 0;
- char lastvow = 0;
- char mlastvow = 0;
- for (int j = 1; j < 6; ++j) {
- if(llastvow) lname[j] = cons[rand() % consz];
- else lname[j] = vows[rand() % vowsz];
- if(lastvow) name[j] = cons[rand() % consz];
- else name[j] = vows[rand() % vowsz];
- if(mlastvow) mname[j] = cons[rand() % consz];
- else mname[j] = vows[rand() % vowsz];
- llastvow = !llastvow;
- lastvow = !lastvow;
- mlastvow = !mlastvow;
- }
- fprintf(f, "%s\t%s\t%s\t%i\t%i\t%i\t%i\n",
- lname, name, mname,
- byear, scphy, scmat, scinf);
- }
- fclose(f);
-}