#include <string>
#include <fstream>
#include <cstdlib>

// To understand the solution, we need to understand the problem.  If the i-th
// line in the file has i characters, it is perfect.  For example, if the tenth
// line in the file contains ten characters, then it is perfect.  If the first
// character in a line is the i-th character in the file and the line contains
// i characters, then the line is semi-perfect.  For example, if the first
// character in a line is the twenty-seventh charcter in the file and the line
// contains 27 characters, then the line is semi-perfect.  We want a program
// that finds perfect and semi-perfect lines in a file.

// To find perfect lines, the program needs to know the number of the current
// line in the file and the number of characters in the current line; that is,
// it needs to keep count of the number of lines in the file, and the number of
// characters in the current line.  A line is perfect when those two values are
// equal.  In other words, a line is perfect when line_pos = line_size, where
// line_pos is the number of the current line in the file and line_size is
// the number of characers in the current line.

// To find semi-pefrect lines, the program needs to know the position within
// the file of the first character of a line and the number of characters in
// the line; that is, it needs to keep count of the number of characters in the
// file and the line size.  A line is semi-perfect when those two values are
// equal.  In other words, a line is semi-prefect when char_pos = line_size,
// where char_pos is the file position of the line's first character line_size
// is the number of characters in the line.

// Almost all the necessary information needed to solve the problem is found by
// the algorithm created in the third design test.  The one slight sticking
// point making sure that char_pos doesn't get changed while computing
// line_size; otherwise char_pos won't have the position of the first character
// in the line.  The minimum and maximum line sizes and character count aren't
// needed for this problem, and can be dropped from the code.


int main() {

  const string fname = "my.dat";
  ifstream ins(fname.c_str());
  if (!ins) {
    cerr << "Can't open " << fname << ".\n";
    return EXIT_FAILURE;
    }

  // Remember - line and character positions are numbered starting from 1.

     int char_pos = 1;
     int line_cnt = 1;

  while (true) {

    int line_size = 0;
    int c;

    // Find the number of characters in the current line.  Set line_size to -1
    // if there are no more lines in the file; otherwise set line_size to the
    // number of characters in the line.

       do {
	 c = ins.get();
	 if (c == EOF)
	   line_size = -1;
	 else
	   line_size++;
	 }
       while ((line_size > -1) && (c != '\n'));

    // If there are no more lines, there's nothing else to do.

       if (line_size < 0) break;

    // char_pos contains the file position of the first character in the
    // current line, line_cnt contains the current line's number, and line_size
    // contains the number of characters in the current line.  With these
    // values the tests for perfect and semi-prefect lines are simple.  It is
    // important that the tests for perfect and semi-perfect lines be kept
    // separate because it is possible for a line to be both perfect and
    // semi-perfect (how?).

       if (line_cnt == line_size)
	 cout << "Line " << line_cnt << " is perfect.\n";
       if (char_pos == line_size)
	 cout << "Line " << line_cnt << " is semi-perfect.\n";

    // Update the file position variables for the next line.

       char_pos += line_size;
       line_cnt++;
    }

  ins.close();
  }


syntax highlighted by Code2HTML, v. 0.9