diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | 6_1.c | 209 | ||||
-rw-r--r-- | 6_2.c | 68 | ||||
-rw-r--r-- | 7_2/Makefile | 16 | ||||
-rw-r--r-- | 7_2/data | 4 | ||||
-rw-r--r-- | 7_2/include/common.h | 32 | ||||
-rw-r--r-- | 7_2/include/drawable.h | 42 | ||||
-rw-r--r-- | 7_2/include/figure.h | 56 | ||||
-rw-r--r-- | 7_2/include/input.h | 24 | ||||
-rw-r--r-- | 7_2/main.c | 44 | ||||
-rw-r--r-- | 7_2/src/drawable.c | 120 | ||||
-rw-r--r-- | 7_2/src/figure.c | 139 | ||||
-rw-r--r-- | 7_2/src/input.c | 116 | ||||
-rw-r--r-- | Makefile | 25 | ||||
-rw-r--r-- | README.md | 50 | ||||
-rw-r--r-- | gen.c | 54 |
16 files changed, 639 insertions, 365 deletions
@@ -1,3 +1,6 @@ compile_flags.txt -build/ +.clangd +*/.clangd +*build/ *.o +.unused.c @@ -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; -} - @@ -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 @@ -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`: определяет функции для чтения входного файла в формате, описанном выше @@ -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); -} |