Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

jab4-answer / Job4_FilterComments / src / job4 / Job4_FilterComments

.java
Скачиваний:
11
Добавлен:
18.03.2015
Размер:
13.02 Кб
Скачать
/**
* Реализация
* Вынести в отдельный пакет tools и реализовать в класс MatrixUtils следующие
* методы, использованные в ЛР №2:
• static int[] readVector(InputStream stm, int size, CheckComment isComment)
для чтения вектора чисел из потока
здесь stm входной поток с данными (может иметь более подходящий тип, например, BufferedReader ),
size кол-во элементов в векторе,
isComment это интерфейс проверки является ли строка комментарием. Интерфейс имеет вид:
interface CheckComment {
boolean isComment(String data);
}

• static int[][] readMatrix(InputStreamstm, introws, intcols, CheckComment isComment)
для чтения матрицы из потока
здесь stm входной поток с данными,
rows, cols кол-во срок и столбцов матрицы,

• static StringBuilder getPrintViewVector(int[] vector)
для формирования текстового дампа для вектора – числа в одну строку

• static StringBuilder getPrintViewMatrix(int[][] matrix)
дляформированиядампа матрицы по строкам.

Выполнить лабораторную работу №2 с использованием функций нового пакета.
Все методы главного класса, кроме main, сделать НЕ статическими.
Интерфейс CheckComment реализовать внутренним классом.

(*) Дополнительное задание: реализовать с минимальными изменениями:
1) Комментарии в конце строки: если в строке встречается пара символов "//", то
начало строки до этих символов - данные, после них - комментарий.
(!) Это здесь сделано заменой метода интерфейса CheckComment.isComment на
новый CheckComment.removeComment, который способен изменять строку данных,
удаляя комментарии и незначащие пробелы.

2) Частичные комментарии внтутри строк, когда данные и комментарий могут
перемежаться, вида:
{ коментарий внутри фигурных скобок }
(*коментарий внутри круглых скобок *)
/ * коментарий внутри косых скобок * /

3) Комментарии из п 2 могут быть многострочные, т.е. начинаться на одной строке,
а заканчиваться в другой (в любом её месте).
(!) Учесть, что в любой строке могу встречаться совместно разные виды
комментариев, причём неоднократно.
Например:
25 { комментарий 1 } -3 4 (* комментарий 2*) 32 // комментарий до конца строки.
*/

package job4;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import my.utils.MatrixUtils;
import my.utils.MatrixUtils.CheckComment;

public class Job4_FilterComments {

/** файл для демонстрации чтения с пропуском комментариев */
final static String FILE_NAME = "data.txt";

public static void main(String[] args) {
try {
/**
* (!) у MatrixUtils конструктор приватный и создание здесь невозможно
* (и не нужно, т.к. все его методы статические)
*/
// MatrixUtils utils = new MatrixUtils();

// буфер под формирование выходных результатов
final StringBuilder result = new StringBuilder();

try {
/**
* Инициализируем объект, который будем использовать для проверки комментариев
*/
final CheckComment checkSingleLine = new CheckSingleLineCommentImpl();
final CheckComment checkPartOfLine = new CheckPartialLineCommentImpl();

/* Выполняем чтение из файла с разными стратегиями провеки комментариев ... */

// здесь "спотыкаемся" на входной строке
// ";// and this one too"
// т.к. в правиле по-умолчанию начало ";" не является комментарием
testReadTextFile( "\n\tпо правилам комментариев по-умолчанию...", FILE_NAME, null, result);

// здесь читаем больше - вектор, а вот на строке с частичным заполнением падаем:
// "3 5 2 1 // комментарий внутри строки"
testReadTextFile( "\n\tпо однострочным правилам комментариев ...", FILE_NAME, checkSingleLine, result);

// здест всё в порядке - прочитается и вектор и матрица ...
testReadTextFile( "\n\tпо частиным правилам комментариев ...", FILE_NAME, checkPartOfLine, result);

} finally {
// отображаем на консоли результат
System.out.println(result.toString());
}
} catch (IOException ex) {
Logger.getLogger(Job4_FilterComments.class.getName()).log(Level.SEVERE, null, ex);
}
}

/**
* Тестовая функция проверки чтения текстового файла с помощью заданного
* правила пропуска комментариев.
* @param title заголовок, для пояснения
* @param fileName имя читаемого файла
* @param checker объект, реализующий праила чтения комментариев
* @param result выходной буфер для получения читаемых данных
* @throws IOException
*/
private static void testReadTextFile( final String title,
final String fileName,
final CheckComment checker,
final StringBuilder result)
throws IOException
{
final File loadingFile = new File(fileName);

result.append(String.format("\nЧитаем файл '%s' %s\n", loadingFile.getAbsoluteFile(), title));

final BufferedReader buf = new BufferedReader(new FileReader(loadingFile.getAbsoluteFile()));
try {
/**
* вызываем чтение вектора из файла: передаём для функции чтения
* checkObj для проверки комментариев
*/
// checker.clear();
final int[] v = MatrixUtils.readVector(buf, 3, checker);
// выводим в буфер прочитанный вектор
MatrixUtils.printVector(result, "Прочитан вектор:\n", v);
result.append("\n");

final int rows = v[0], cols = v[1];
final int[][] matrix = MatrixUtils.readMatrix(buf, rows, cols, checker);
// выводим в буфер прочитанный вектор
MatrixUtils.printMatrix(result, "Прочитана матрица:\n", matrix);

result.append( String.format( "\n(*) %s: Ошибок нет\n", title));

} catch (Throwable ex) {
// здесь перехватываем все возможные имелючения в отладочных целях ...
// Logger.getLogger(Job4_FilterComments.class.getName()).log(Level.SEVERE, null, ex);
// ex.printStackTrace(System.err);
result.append(String.format("Произошла ошибка (%s):\n%s\n", ex.getClass(), ex.getMessage()));
} finally {
buf.close();
}
}

/**
* Пример класса, который реализует интерфейс CheckComment для случая ОДНОСТРОЧНЫХ комментариев.
* Комментариями считаются пустые строки, строки начинающиеся с "#", ";" или "//".
*/
public static class CheckSingleLineCommentImpl
extends Object // для явной демострации возможности указания родительского класса, при наследовании от Object это излише
implements CheckComment
{
boolean inComment = false;

@Override
public String removeComment(String data) {
if (data == null)
return null;

data = data.trim();
return "".equals(data)
|| data.startsWith("#")
|| data.startsWith("//")
|| data.startsWith(";")
? null : data;
}
}

class GenAbc<T extends CheckComment> {
T fld;
void test() {
fld.removeComment(FILE_NAME);
}
}

class Proxy implements CheckComment {
final CheckComment fld;

public Proxy(CheckComment fld) {
this.fld = fld;
}

@Override
public String removeComment(String data) {
if ("особое значение".equalsIgnoreCase(data))
return null;
String result = fld.removeComment(data);
// if (result != null && ) // изменить како-то result
return result;
}
}


/** const-массив с вариантами начала комментарием внутри строк */
final private static String[] НачалаКомменатрияВСтроке = { "#", ";", "//"};

/**
* Пример класса, который реализует интерфейс CheckComment для случая ЧАСТИНЫХ
* комментариев в строке, в том числе однострочных.
* Комментариями считается часть строки до конца этой строки после символов "#", ";" или "//".
* 1 45 -9 // комментарий в конце
* 20 30 ; // # смешанная строка
* 20 30 // ; # смешанная строка
*/
public static class CheckPartialLineCommentImpl
implements CheckComment
{
@Override
public String removeComment(String data) {
if (data == null) // пустая строка - комментарий
return null;

final int mostLeft = найтиСамыйПервый(data, НачалаКомменатрияВСтроке);

// убираем из строки часть до символов "#", ";", "//" : если они есть ...
// оставим текст перед ним ...
// (!) используется особенность работы substring в java: вторым
// параметром надо указать индекс, ПЕРЕД которым надо остановиться,
// так что не требуется обычное (iPos-1).
if (mostLeft != -1)
data = data.substring(0, mostLeft);

data = data.trim(); // убираем незначащие пробелы в начале и в конце ...
return (data.length() == 0) ? null : data;// если в строке есть что-либо, то это НЕ Комментарий
}

/**
* Найти начало комментария в строке, а когда их несколько, то найти
* начало самого первого (слева) комментария.
* @param data
* @param ВозможныеНачалаКомменатрия
* @return (-1) если нет ни одного комментария и начало самого первого если есть.
*/
private int найтиСамыйПервый(final String data, final String[] ВозможныеНачалаКомменатрия) {
int result = -1;
if (data == null)
return result;

// находим самое первое начало какого-либо комментария в строке ...
for (String start : ВозможныеНачалаКомменатрия) {
final int iPos = data.indexOf(start);
if (iPos >= 0) { // есть такой комментарий ...
if ( (result == -1) || (iPos < result)) // если это первый или он левее -> запомним
result = iPos;
// другие НАДО проверять, т.к. возможно они будут левее ...
}
}
return result;
}
}
}
Соседние файлы в папке job4