Problem p00607 (C++) — buggy submission, verdict: Runtime Error

#include <cassert>
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int crow = 0, ccol = 0;
string buf = "";
vector<string> lines;

void input() {
  while (1) {
    string s;
    getline(cin, s);
    if (s == "END_OF_TEXT")
      break;
    lines.push_back(s + "\\n");
  }
}

void assign_buf(string s, bool is_cl_only = false) {
  buf = s;
  if (!is_cl_only) {
    assert(buf.back() == '\\n');
    buf.pop_back();
  }
}

bool is_col_begin() { return ccol == 0; }
bool is_col_end() { return ccol + 1 == lines[crow].size(); }
bool is_row_begin() { return crow == 0; }
bool is_row_end() { return crow + 1 == lines.size(); }

int get_col_begin() { return 0; }
int get_col_end() { return (int)lines[crow].size() - 1; }
int get_row_begin() { return 0; }
int get_row_end() { return (int)lines.size() - 1; }

void up() {
  crow = max(get_row_begin(), crow - 1);
  ccol = 0;
}
void down() {
  crow = min(get_row_end(), crow + 1);
  ccol = 0;
}
void right() {
  if (is_col_end() && is_row_end())
    return;

  if (is_col_end())
    down(), ccol = get_col_begin();
  else
    ccol++;
}
void left() {
  if (is_col_begin() && is_row_begin())
    return;

  if (is_col_begin())
    up(), ccol = get_col_end();
  else
    ccol--;
}

void delete_char() {
  if (is_col_end()) {
    if (is_row_end())
      return;
    string &target = lines[crow];
    assert(target.back() == '\\n');
    target.pop_back();
    target += lines[crow + 1];
    lines.erase(lines.begin() + crow + 1);
  } else {
    lines[crow].erase(lines[crow].begin() + ccol);
  }
}

void show_state(char op) {
  printf("operate [%c]: row = %d, col = %d\\n", op, crow, ccol);
  for (auto x : lines)
    cout << x;
}

bool operate(char op) {
  assert(crow >= 0 && ccol >= 0);
  assert(crow + 1 <= lines.size());
  assert(ccol + 1 <= lines[crow].size());

  if (op == 'a') {
    ccol = get_col_begin();
  }
  if (op == 'e') {
    ccol = get_col_end();
  }
  if (op == 'p') {
    up();
  }
  if (op == 'n') {
    down();
  }
  if (op == 'f') {
    right();
  }
  if (op == 'b') {
    left();
  }
  if (op == 'd') {
    delete_char();
  }
  if (op == 'k') {
    if (is_col_end()) {
      if (!is_row_end()) {
        // printf("kill ring\\n");
        delete_char();
        assign_buf("\\n", true);
      }
    } else {
      string &target = lines[crow];
      assign_buf(target.substr(ccol));
      target = target.substr(0, ccol) + "\\n";
    }
  }
  if (op == 'y') {
    if (buf.size()) {
      if (buf == "\\n") {
        string &target = lines[crow];
        string s1 = target.substr(0, ccol);
        string s2 = target.substr(ccol);

        if (s1.back() != '\\n')
          s1 += "\\n";
        if (s2.back() != '\\n')
          s2 += "\\n";

        target = s1;
        lines.insert(lines.begin() + crow + 1, s2);

        down();
      } else {
        string &target = lines[crow];
        target.insert(ccol, buf);
        ccol += buf.size();
      }
    }
  }

  // show_state(op);
  return op == '-';
}

int main() {
  input();

  while (1) {
    char c;
    cin >> c;
    if (operate(c))
      break;
  }
  for (auto x : lines) {
    cout << x;
  }
  return 0;
}


Error: 0

Fixed submission:

#include <cassert>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int crow = 0, ccol = 0;
string buf = "";
vector<string> lines;

void input() {
  while (1) {
    string s;
    getline(cin, s);
    if (s == "END_OF_TEXT")
      break;
    lines.push_back(s + "\\n");
  }
}

void assign_buf(string s, bool is_cl_only = false) {
  buf = s;
  if (!is_cl_only) {
    assert(buf.back() == '\\n');
    buf.pop_back();
  }
}

bool is_col_begin() { return ccol == 0; }
bool is_col_end() { return ccol + 1 == lines[crow].size(); }
bool is_row_begin() { return crow == 0; }
bool is_row_end() { return crow + 1 == lines.size(); }

int get_col_begin() { return 0; }
int get_col_end() { return (int)lines[crow].size() - 1; }
int get_row_begin() { return 0; }
int get_row_end() { return (int)lines.size() - 1; }

void up() {
  crow = max(get_row_begin(), crow - 1);
  ccol = 0;
}
void down() {
  crow = max(get_row_end(), crow + 1);
  ccol = 0;
}
void right() {
  if (is_col_end() && is_row_end())
    return;

  if (is_col_end())
    down(), ccol = get_col_begin();
  else
    ccol++;
}
void left() {
  if (is_col_begin() && is_row_begin())
    return;

  if (is_col_begin())
    up(), ccol = get_col_end();
  else
    ccol--;
}

void delete_char() {
  if (is_col_end()) {
    if (is_row_end())
      return;
    string &target = lines[crow];
    target.pop_back();
    target += lines[crow + 1];
    lines.erase(lines.begin() + crow + 1);
  } else {
    lines[crow].erase(lines[crow].begin() + ccol);
  }
}

bool operate(char op) {
  assert(crow >= 0 && ccol >= 0);
  assert(crow + 1 <= lines.size());
  assert(ccol + 1 <= lines[crow].size());

  if (op == 'a') {
    ccol = get_col_begin();
  }
  if (op == 'e') {
    ccol = get_col_end();
  }
  if (op == 'p') {
    up();
  }
  if (op == 'n') {
    down();
  }
  if (op == 'f') {
    right();
  }
  if (op == 'b') {
    left();
  }
  if (op == 'd') {
    delete_char();
  }
  if (op == 'k') {
    if (is_col_end()) {
      if (!is_row_end()) {
        delete_char();
        assign_buf("\\n", true);
      }
    }
    string &target = lines[crow];
    assign_buf(target.substr(ccol));
    target = target.substr(0, ccol) + "\\n";
  }
  if (op == 'y') {
    if (buf.size()) {
      if (buf == "\\n") {
        string &target = lines[crow];
        string s1 = target.substr(0, ccol);
        string s2 = target.substr(ccol);

        target = s1;
        lines.insert(lines.begin() + crow + 1, s2);

        down();
      } else {
        string &target = lines[crow];
        target.insert(ccol, buf);
        ccol += buf.size();
      }
    }
  }
  return op == '-';
}

int main() {
  input();

  while (1) {
    char c;
    cin >> c;
    if (operate(c))
      break;
  }
  for (auto x : lines) {
    cout << x;
  }
  return 0;
}