Files
CS-LABS/mine/lab_1/vlad`s/task11.c
2025-12-10 16:50:28 +07:00

171 lines
4.9 KiB
C

#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#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 <input.txt> <output.txt> <max_replacements>\n"
"Variant 11: for every pair of identical consecutive characters, replace the second with a space.\n"
" Stop after <max_replacements> 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;
}