#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; }