working vlad's lab1
This commit is contained in:
@@ -1 +0,0 @@
|
||||
g++ task11.cpp -o task11
|
||||
@@ -1,13 +0,0 @@
|
||||
aabbcc
|
||||
bookkeeper
|
||||
Mississippi
|
||||
x
|
||||
aa
|
||||
aba
|
||||
aaa
|
||||
baaa
|
||||
aaab
|
||||
abba
|
||||
1222333
|
||||
(four spaces)
|
||||
--====
|
||||
1
others/vlad`s/lab1/in.txt
Normal file
1
others/vlad`s/lab1/in.txt
Normal file
@@ -0,0 +1 @@
|
||||
aaaaabababbabababaaabbbbabababbbaabbaabbabb
|
||||
@@ -1,95 +1,170 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static bool file_exists(const std::string &path) {
|
||||
struct stat st{};
|
||||
return ::stat(path.c_str(), &st) == 0;
|
||||
#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];
|
||||
if (path) {
|
||||
snprintf(msg, sizeof(msg), "%s: %s: %s\n", what, path, strerror(saved));
|
||||
} else {
|
||||
snprintf(msg, sizeof(msg), "%s: %s\n", what, strerror(saved));
|
||||
}
|
||||
(void) write(STDERR_FILENO, msg, strlen(msg));
|
||||
_exit(exit_code);
|
||||
}
|
||||
|
||||
static std::string make_out_name(const std::string &in) {
|
||||
std::size_t pos = in.find_last_of('.');
|
||||
if (pos == std::string::npos) return in + ".out";
|
||||
return in.substr(0, pos) + ".out";
|
||||
}
|
||||
|
||||
static bool parse_nonneg_ll(const char *s, long long &out) {
|
||||
if (!s || *s == '\0') return false;
|
||||
char *end = nullptr;
|
||||
static long long parse_ll(const char *s) {
|
||||
char *end = NULL;
|
||||
errno = 0;
|
||||
long long v = std::strtoll(s, &end, 10);
|
||||
if (errno != 0 || end == s || *end != '\0') return false;
|
||||
if (v < 0) return false;
|
||||
out = v;
|
||||
return true;
|
||||
long long v = strtoll(s, &end, 10);
|
||||
if (errno != 0 || end == s || *end != '\0' || v < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " input_file replace_count\n";
|
||||
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;
|
||||
}
|
||||
|
||||
std::string in_path = argv[1];
|
||||
long long target = 0;
|
||||
if (!parse_nonneg_ll(argv[2], target)) {
|
||||
std::cerr << "Usage: " << argv[0] << " input_file replace_count\n";
|
||||
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);
|
||||
}
|
||||
|
||||
if (!file_exists(in_path)) {
|
||||
std::cerr << "Error: input file does not exist.\n";
|
||||
return -1;
|
||||
int in_fd = open(in_path, O_RDONLY);
|
||||
if (in_fd < 0) {
|
||||
die_perror("open input failed", in_path, -1);
|
||||
}
|
||||
|
||||
std::ifstream in(in_path);
|
||||
if (!in) {
|
||||
std::cerr << "Error: cannot open input file.\n";
|
||||
return -1;
|
||||
mode_t filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /* rw-rw-rw- */
|
||||
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);
|
||||
}
|
||||
|
||||
std::string out_path = make_out_name(in_path);
|
||||
std::ofstream out(out_path);
|
||||
if (!out) {
|
||||
std::cerr << "Error: cannot create output file.\n";
|
||||
return -1;
|
||||
char rbuf[RBUFSZ];
|
||||
char wbuf[WBUFSZ];
|
||||
size_t wlen = 0;
|
||||
|
||||
/* state */
|
||||
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) {
|
||||
/* buffer first byte of a potential pair */
|
||||
prev = c;
|
||||
have_prev = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
long long replacements = 0;
|
||||
std::string line;
|
||||
if (c == prev) {
|
||||
/* non-overlapping pair found: output prev, then second element possibly replaced */
|
||||
unsigned char out1 = prev;
|
||||
unsigned char out2 = c;
|
||||
|
||||
while (std::getline(in, line)) {
|
||||
if (!line.empty() && replacements < target) {
|
||||
for (std::size_t i = 1; i < line.size() && replacements < target; ++i) {
|
||||
if (line[i] == line[i - 1]) {
|
||||
if (line[i] != ' ') {
|
||||
line[i] = ' ';
|
||||
++replacements;
|
||||
if (replacing_enabled && total_replacements < cap) {
|
||||
out2 = ' ';
|
||||
total_replacements++;
|
||||
if (total_replacements == cap) {
|
||||
replacing_enabled = 0;
|
||||
}
|
||||
} else {
|
||||
replacing_enabled = 0;
|
||||
}
|
||||
|
||||
/* write out1 */
|
||||
if (wlen == sizeof(wbuf)) {
|
||||
ssize_t wrote = write(out_fd, wbuf, wlen);
|
||||
if (wrote < 0 || (size_t) wrote != wlen) die_perror("write failed", out_path, -1);
|
||||
wlen = 0;
|
||||
}
|
||||
wbuf[wlen++] = (char) out1;
|
||||
|
||||
/* write out2 */
|
||||
if (wlen == sizeof(wbuf)) {
|
||||
ssize_t wrote = write(out_fd, wbuf, wlen);
|
||||
if (wrote < 0 || (size_t) wrote != wlen) die_perror("write failed", out_path, -1);
|
||||
wlen = 0;
|
||||
}
|
||||
wbuf[wlen++] = (char) out2;
|
||||
|
||||
/* consume pair: reset have_prev so next byte starts a new potential pair */
|
||||
have_prev = 0;
|
||||
} else {
|
||||
/* no pair: output prev, shift window to c */
|
||||
if (wlen == sizeof(wbuf)) {
|
||||
ssize_t wrote = write(out_fd, wbuf, wlen);
|
||||
if (wrote < 0 || (size_t) wrote != wlen) die_perror("write failed", out_path, -1);
|
||||
wlen = 0;
|
||||
}
|
||||
wbuf[wlen++] = (char) prev;
|
||||
|
||||
prev = c;
|
||||
have_prev = 1;
|
||||
}
|
||||
}
|
||||
} else if (n == 0) {
|
||||
/* flush any pending single prev */
|
||||
if (have_prev) {
|
||||
if (wlen == sizeof(wbuf)) {
|
||||
ssize_t wrote = write(out_fd, wbuf, wlen);
|
||||
if (wrote < 0 || (size_t) wrote != wlen) die_perror("write failed", out_path, -1);
|
||||
wlen = 0;
|
||||
}
|
||||
wbuf[wlen++] = (char) prev;
|
||||
have_prev = 0;
|
||||
}
|
||||
out << line;
|
||||
if (!in.eof()) out << '\n';
|
||||
if (!out) {
|
||||
std::cerr << "Error: write error.\n";
|
||||
return -1;
|
||||
if (wlen > 0) {
|
||||
ssize_t wrote = write(out_fd, wbuf, wlen);
|
||||
if (wrote < 0 || (size_t) wrote != wlen) die_perror("write failed", out_path, -1);
|
||||
wlen = 0;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
die_perror("read failed", in_path, -1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!in.eof() && in.fail()) {
|
||||
std::cerr << "Error: read error.\n";
|
||||
return -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);
|
||||
}
|
||||
|
||||
if (replacements != target) {
|
||||
std::cerr << "Error: could not perform exactly requested replacements.\n";
|
||||
return -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);
|
||||
}
|
||||
|
||||
std::cout << replacements << std::endl;
|
||||
return 0;
|
||||
int exit_code = (int) (total_replacements & 0xFF);
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user