From 3371a1b8de9a2dfae1f1baf1ab0914e1b01207bc Mon Sep 17 00:00:00 2001 From: pajjilykk Date: Thu, 23 Oct 2025 20:13:27 +0700 Subject: [PATCH] working #3 vlad --- lab_3/vlad/Makefile | 51 +++++++++++++ lab_3/vlad/parent.c | 88 +++++++++++++++++++++++ lab_3/vlad/task11.c | 170 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 309 insertions(+) create mode 100644 lab_3/vlad/Makefile create mode 100644 lab_3/vlad/parent.c create mode 100644 lab_3/vlad/task11.c diff --git a/lab_3/vlad/Makefile b/lab_3/vlad/Makefile new file mode 100644 index 0000000..9fe5e1c --- /dev/null +++ b/lab_3/vlad/Makefile @@ -0,0 +1,51 @@ +# Компилятор и флаги +CC = gcc +CFLAGS = -Wall -Wextra -std=c99 -pedantic + +# Целевые файлы +TARGET_PARENT = parent +TARGET_TASK11 = task11 + +# Исходные файлы +SRC_PARENT = parent.c +SRC_TASK11 = task11.c + +# Объектные файлы +OBJ_PARENT = $(SRC_PARENT:.c=.o) +OBJ_TASK11 = $(SRC_TASK11:.c=.o) + +.PHONY: all clean help test + +all: $(TARGET_PARENT) $(TARGET_TASK11) + +$(TARGET_PARENT): $(OBJ_PARENT) + $(CC) $(CFLAGS) -o $@ $^ + @echo "Родительская программа собрана: $@" + +$(TARGET_TASK11): $(OBJ_TASK11) + $(CC) $(CFLAGS) -o $@ $^ + @echo "Программа лаб. работы №11 собрана: $@" + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(TARGET_PARENT) $(TARGET_TASK11) $(OBJ_PARENT) $(OBJ_TASK11) input* output* + @echo "Очистка завершена" + +help: + @echo "Доступные цели:" + @echo " all - собрать все" + @echo " clean - удалить все скомпилированные файлы" + @echo " test - запустить тестирование программы" + +test: all + @echo "Создаем тестовые файлы..." + @echo "abbaabbccdd" > input1.txt + @echo "hello world !!" > input2.txt + @echo "Запуск parent..." + ./$(TARGET_PARENT) 5 input1.txt output1.txt input2.txt output2.txt + @echo "Содержимое output1.txt:" + @cat output1.txt || echo "Файл output1.txt не найден" + @echo "Содержимое output2.txt:" + @cat output2.txt || echo "Файл output2.txt не найден" diff --git a/lab_3/vlad/parent.c b/lab_3/vlad/parent.c new file mode 100644 index 0000000..8d8b0e2 --- /dev/null +++ b/lab_3/vlad/parent.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + if (argc < 4) { + fprintf(stderr, + "Usage: parent [ ...]\n" + " max_replacements: maximum number of replacements\n" + " input/output: pairs of input and output files\n"); + return -1; + } + + if ((argc - 2) % 2 != 0) { + fprintf(stderr, "Error: number of input/output files must be even (pairs of input/output)\n"); + return -1; + } + + const char *max_replacements_arg = argv[1]; + int num_pairs = (argc - 2) / 2; + + pid_t *child_pids = malloc(num_pairs * sizeof(pid_t)); + if (!child_pids) { + perror("malloc failed"); + return -1; + } + + for (int i = 0; i < num_pairs; i++) { + const char *input_file = argv[2 + i * 2]; + const char *output_file = argv[2 + i * 2 + 1]; + + pid_t pid = fork(); + if (pid < 0) { + perror("fork failed"); + // Wait for already started children + for (int j = 0; j < i; j++) { + waitpid(child_pids[j], NULL, 0); + } + free(child_pids); + return -1; + } + + if (pid == 0) { + // Child process + printf("Child %d (PID=%d) processing %s -> %s\n", i + 1, getpid(), input_file, output_file); + execl("./task11", "task11", input_file, output_file, max_replacements_arg, (char *) NULL); + + // If exec returns, error happened + fprintf(stderr, "Child %d: execl failed for %s: %s\n", i + 1, input_file, strerror(errno)); + _exit(-1); + } + + // Parent process + child_pids[i] = pid; + } + + printf("Parent process waiting for children...\n"); + + int ret_code = 0; + for (int i = 0; i < num_pairs; i++) { + int status; + pid_t pid = waitpid(child_pids[i], &status, 0); + if (pid < 0) { + perror("waitpid failed"); + continue; + } + + if (WIFEXITED(status)) { + int code = WEXITSTATUS(status); + printf("Child %d (PID=%d) exited with code %d\n", i + 1, pid, code); + if (code != 0) { + ret_code = code; + } + } else if (WIFSIGNALED(status)) { + printf("Child %d (PID=%d) terminated by signal %d\n", i + 1, pid, WTERMSIG(status)); + } else { + printf("Child %d (PID=%d) ended abnormally\n", i + 1, pid); + } + } + + free(child_pids); + printf("All children finished\n"); + return ret_code; +} diff --git a/lab_3/vlad/task11.c b/lab_3/vlad/task11.c new file mode 100644 index 0000000..db1bfd4 --- /dev/null +++ b/lab_3/vlad/task11.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include +#include +#include +#include + +#define RBUFSZ 4096 +#define WBUFSZ 4096 + +static void die_perror(const char *what, const char *path, int exit_code) { + int saved = errno; + char msg[512]; + int n; + if (path) { + n = snprintf(msg, sizeof(msg), "%s: %s: %s\n", what, path, strerror(saved)); + } else { + n = snprintf(msg, sizeof(msg), "%s: %s\n", what, strerror(saved)); + } + if (n > 0) (void) write(STDERR_FILENO, msg, (size_t) n); + _exit(exit_code); +} + +static long long parse_ll(const char *s) { + char *end = NULL; + errno = 0; + long long v = strtoll(s, &end, 10); + if (errno != 0 || end == s || *end != '\0' || v < 0) { + errno = EINVAL; + return -1; + } + return v; +} + +static void xwrite_all(int fd, const char *buf, size_t len, const char *path) { + size_t off = 0; + while (off < len) { + ssize_t n = write(fd, buf + off, len - off); + if (n < 0) { + if (errno == EINTR) continue; + die_perror("write failed", path, -1); + } + off += (size_t) n; + } +} + +int main(int argc, char *argv[]) { + if (argc != 4) { + const char *usage = + "Usage: lab1_var11 \n" + "Variant 11: for every pair of identical consecutive characters, replace the second with a space.\n" + " Stop after replacements globally.\n"; + (void) write(STDERR_FILENO, usage, strlen(usage)); + return -1; + } + + const char *in_path = argv[1]; + const char *out_path = argv[2]; + long long cap = parse_ll(argv[3]); + if (cap < 0) { + die_perror("invalid max_replacements", argv[3], -1); + } + + int in_fd = open(in_path, O_RDONLY); + if (in_fd < 0) { + die_perror("open input failed", in_path, -1); + } + + mode_t filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + int out_fd = open(out_path, O_CREAT | O_WRONLY | O_TRUNC, filePerms); + if (out_fd < 0) { + die_perror("open output failed", out_path, -1); + } + + char rbuf[RBUFSZ]; + char wbuf[WBUFSZ]; + size_t wlen = 0; + + long long total_replacements = 0; + int replacing_enabled = 1; + + int have_prev = 0; + unsigned char prev = 0; + + for (;;) { + ssize_t n = read(in_fd, rbuf, sizeof(rbuf)); + if (n > 0) { + for (ssize_t i = 0; i < n; i++) { + unsigned char c = (unsigned char) rbuf[i]; + + if (!have_prev) { + prev = c; + have_prev = 1; + continue; + } + + if (c == prev) { + unsigned char out1 = prev; + unsigned char out2 = c; + + if (replacing_enabled && total_replacements < cap) { + out2 = ' '; + total_replacements++; + if (total_replacements == cap) { + replacing_enabled = 0; + } + } else { + replacing_enabled = 0; + } + + if (wlen == sizeof(wbuf)) { + xwrite_all(out_fd, wbuf, wlen, out_path); + wlen = 0; + } + wbuf[wlen++] = (char) out1; + + if (wlen == sizeof(wbuf)) { + xwrite_all(out_fd, wbuf, wlen, out_path); + wlen = 0; + } + wbuf[wlen++] = (char) out2; + + have_prev = 0; + } else { + if (wlen == sizeof(wbuf)) { + xwrite_all(out_fd, wbuf, wlen, out_path); + wlen = 0; + } + wbuf[wlen++] = (char) prev; + + prev = c; + have_prev = 1; + } + } + } else if (n == 0) { + if (have_prev) { + if (wlen == sizeof(wbuf)) { + xwrite_all(out_fd, wbuf, wlen, out_path); + wlen = 0; + } + wbuf[wlen++] = (char) prev; + have_prev = 0; + } + if (wlen > 0) { + xwrite_all(out_fd, wbuf, wlen, out_path); + wlen = 0; + } + break; + } else { + if (errno == EINTR) continue; + die_perror("read failed", in_path, -1); + } + } + + if (close(in_fd) < 0) { + die_perror("close input failed", in_path, -1); + } + if (close(out_fd) < 0) { + die_perror("close output failed", out_path, -1); + } + + char res[64]; + int m = snprintf(res, sizeof(res), "%lld\n", total_replacements); + if (m > 0) { + (void) write(STDOUT_FILENO, res, (size_t) m); + } + + return 0; +}