Готовые отчеты (2020) / Java. Лабораторная работа 4
.pdfФедеральное агентство связи ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ
ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ «САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ТЕЛЕКОММУНИКАЦИЙ ИМ. ПРОФ. М. А. БОНЧ-БРУЕВИЧА» (СПбГУТ)
Факультет инфокоммуникационных сетей и систем Кафедра программной инженерии и вычислительной техники
ЛАБОРАТОРНАЯ РАБОТА №4
по дисциплине «Разработка Java-приложений управления телекоммуникациями»
Выполнил: студент 3-го курса дневного отделения группы ИКПИ-85
Коваленко Леонид Александрович Преподаватель:
доцент кафедры ПИиВТ Белая Татьяна Иоанновна
Санкт-Петербург
2020
Цель работы Ознакомиться с механизмом систем ввода и вывода данных.
Ход работы
Задание №1.
Создадим циклический двусвязный список CircularLinkedList с выделенной головой (т. е. голова не хранит значение, а «пустой» список состоит из одной головы, замкнутой на себя), в котором будут реализованы следующие методы:
—конструктор с параметром n — числом элементов;
—метод добавления элемента;
—метод удаления элемента;
—методы получения и изменения значения элемента списка по
индексу.
Также реализуем оптимизацию скорости доступа: внутри экземпляра списка будет храниться ссылка-узел и его номер, к которому производилось предыдущее обращение, а методы доступа (методы получения и изменения значения) к узлу по его номеру (а также методы добавления и удаления) должны двигаться к заданному узлу от ближайшего элемента: от предыдущего узла, от головы вперед, от головы назад (от хвоста).
Кроме того, создадим файл CircularLinkedListTest.java для проверки работы класса CircularLinkedList. Коды этих двух файлов приведены в табл. 1, 2.
Таблица 1 — Код vectors/CircularLinkedList.java package vectors;
public class CircularLinkedList implements IVector { // Конструктор
public CircularLinkedList(int n) {
current = head = new Node(0, null, null); head.prev = head.next = head; current_index = -1;
if (n > 0) {
Node temp = head;
for (int i = 0; i < n; ++i) {
temp = (temp.next = new Node(0, temp, null));
}
temp.next = head; head.prev = temp; size = n;
} else {
2
size = 0;
}
}
// Получение элемента по индексу
public double get(int i) throws VectorIndexOutOfBoundsException { if (i >= 0 && i < size) {
if (Math.abs(i - current_index) > Math.min(i + 1, size - i)) { current = head;
current_index = (i + i < size) ? -1 : size;
}
for (; current_index < i; ++current_index) { current = current.next;
}
for (; current_index > i; --current_index) { current = current.prev;
}
return current.value;
}
throw new VectorIndexOutOfBoundsException("VectorIndexOutOfBoundsException", i);
}
// Изменение значения элемента по индексу public void set(int i, double value) throws
VectorIndexOutOfBoundsException { if (i >= 0 && i < size) {
if (Math.abs(i - current_index) > Math.min(i + 1, size - i)) { current = head;
current_index = (i + i < size) ? -1 : size;
}
for (; current_index < i; ++current_index) { current = current.next;
}
for (; current_index > i; --current_index) { current = current.prev;
}
current.value = value; return;
}
throw new VectorIndexOutOfBoundsException("VectorIndexOutOfBoundsException", i);
}
//Получение длины списка public int size() {
return size;
}
//Добавление элемента в список
public void add(int i, double elem) throws VectorIndexOutOfBoundsException {
if (i >= 0 && i <= size) {
if (Math.abs(i - current_index) > Math.min(i + 1, size - i)) { current = head;
current_index = (i + i < size) ? -1 : size;
}
for (; current_index < i; ++current_index) { current = current.next;
}
for (; current_index > i; --current_index) { current = current.prev;
}
current = current.prev;
current.next = new Node(elem, current, current.next);
3
current.next.next.prev = current.next; current = current.next;
++size; return;
}
throw new VectorIndexOutOfBoundsException("VectorIndexOutOfBoundsException", i);
}
// Удаление элемента из списка
public void remove(int i) throws VectorIndexOutOfBoundsException { if (i >= 0 && i < size) {
if (Math.abs(i - current_index) > Math.min(i + 1, size - i)) { current = head;
current_index = (i + i < size) ? -1 : size;
}
for (; current_index < i; ++current_index) { current = current.next;
}
for (; current_index > i; --current_index) { current = current.prev;
}
current = current.prev; current.next = current.next.next; current.next.prev = current; current = current.next;
--size; return;
}
throw new VectorIndexOutOfBoundsException("VectorIndexOutOfBoundsException", i);
}
//Нахождение нормы Евклида public double normEuclidean() {
double r = 0;
for (Node temp = head.next; temp != head; temp = temp.next) { r += temp.value * temp.value;
}
return Math.sqrt(r);
}
//Вывод всех элементов списка
public void print() { Node temp = head.next; if (temp != head) {
System.out.print(temp.value); temp = temp.next;
}
for (; temp != head; temp = temp.next) { System.out.print(" " + temp.value);
}
System.out.println();
}
// Вывод всех элементов списка в обратном порядке public void rprint() {
Node temp = head.prev; if (temp != head) {
System.out.print(temp.value); temp = temp.prev;
}
for (; temp != head; temp = temp.prev) { System.out.print(" " + temp.value);
}
4
System.out.println();
}
// Класс "Узел"
public static class Node {
public Node(double value, Node prev, Node next) { this.value = value;
this.prev = prev; this.next = next;
}
public double value; public Node prev, next;
}
private Node head, current; private int size, current_index;
}
Таблица 2 — Код CircularLinkedListTest.java
import vectors.CircularLinkedList;
import vectors.VectorIndexOutOfBoundsException;
public class CircularLinkedListTest {
public static void main(String[] args) throws VectorIndexOutOfBoundsException {
CircularLinkedList list = new CircularLinkedList(10); System.out.print("Source list (10 elements): "); list.print();
System.out.println("\nMethod \'set\'. list.set(0, 1) and list.set(list.size() - 1, 10)");
list.set(0, 1); list.set(list.size() - 1, 10); System.out.print("New list: "); list.print();
System.out.print("Reversed new list: "); list.rprint(); System.out.println("\nMethod \'get\'.");
System.out.println("list.get(0): " + list.get(0)); System.out.println("list.get(list.size() - 1): " +
list.get(list.size() - 1));
System.out.print("\nMethod \'set\'. Ordered list: "); for (int i = 0, len = list.size(); i < len; ++i) {
list.set(i, i);
}
list.print();
System.out.print("Reverse ordered list: "); list.rprint();
System.out.print("Test of method \'get\': "); boolean flag = true;
for (int i = 0, len = list.size(); i < 10000000; ++i) { int k = (int) Math.random() * len;
if (list.get(k) != k) { flag = false; break;
}
}
System.out.println(flag ? "it works" : "this does not work"); System.out.println("\nMethod \'add\'."); System.out.println("list.add(0, -1) and list.add(list.size(), 10)"); list.add(0, -1);
list.add(list.size(), 10); System.out.print("List: "); list.print();
5
System.out.print("Reversed list: "); list.rprint();
System.out.println("list.normEuclidean(): " + list.normEuclidean()); CircularLinkedList newList = new CircularLinkedList(0); newList.add(0, 1);
newList.add(1, 2); newList.add(2, 3); newList.add(3, 4);
System.out.print("\nList[1, 2, 3, 4]: "); newList.print();
newList.remove(3);
newList.remove(2);
newList.remove(1);
newList.remove(0);
System.out.print("After removing all items:"); newList.print();
newList = new CircularLinkedList(0); newList.add(0, 1);
newList.add(0, 2); newList.add(0, 3); newList.add(0, 4);
System.out.print("List[4, 3, 2, 1]: "); newList.print();
newList.remove(0);
newList.remove(0);
newList.remove(0);
newList.remove(0);
System.out.print("After removing all items:"); newList.print();
}
}
Результат компиляции и запуска приведен на рис. 1.
Рисунок 1 — Компиляция и запуск CircularLinkedListTest.java
Задание №2.
Модифицируем класс Vectors из предыдущей работы, добавив в него следующие методы (табл. 3):
6
— метод записи вектора в байтовый поток: public static void
outputVector(Vector v, OutputStream out);
— метод чтения вектора из байтового потока: public static Vector
inputVector(InputStream in);
— метод записи вектора в символьный поток: public static void
writeVector(Vector v, Writer out);
— метод чтения вектора из символьного потока: public static Vector
readVector(Reader in).
Вобоих случаях записанный вектор будет представлять собой последовательность чисел, первым из которых является размерность вектора (тип int), а остальные являются значениями координат (тип double).
Вслучае символьного потока будем считать, что вектор записывается в одну строку, в которой числа разделены пробелами. Для чтения вектора из символьного потока будем использовать класс StreamTokenizer.
Также опишем класс VectorStreamTest (табл. 4), находящийся вне пакета vectors, содержащий точку входа программы — метод main(), в котором
проверим возможности методов записи и методов чтения. Таблица 3 — Измененный код vectors/Vectors.java
package vectors;
import java.io.IOException; import java.io.Writer; import java.io.Reader; import java.io.InputStream; import java.io.OutputStream;
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.PrintWriter; import java.io.StreamTokenizer;
public class Vectors {
// Умножение вектора на число
public static IVector mul(IVector array, double number) { int size = array.size();
IVector r = new Array(size); try {
for (int i = 0; i < size; ++i) { r.set(i, array.get(i) * number);
}
}
catch(Exception e) { System.out.println(e.getMessage());
}
return r;
}
7
// Сложение двух векторов
public static IVector sum(IVector array, IVector arg) throws IncompatibleVectorSizesException {
int size = array.size(); if (size != arg.size()) {
throw new IncompatibleVectorSizesException("IncompatibleVectorSizesException", array.size(), arg.size());
}
IVector r = new Array(size); try{
for (int i = 0; i < size; ++i) { r.set(i, array.get(i) + arg.get(i));
}
}
catch(Exception e) { System.out.println(e.getMessage());
}
return r;
}
// Скалярное произведение двух векторов
public static double mul(IVector array, IVector arg) throws IncompatibleVectorSizesException {
int size = array.size(); if (size != arg.size()) {
throw new IncompatibleVectorSizesException("IncompatibleVectorSizesException", array.size(), arg.size());
}
double r = 0; try {
for (int i = 0; i < size; ++i) {
r += array.get(i) * arg.get(i);
}
}
catch(Exception e) { System.out.println(e.getMessage());
}
return r;
}
// Метод записи вектора в байтовый поток
public static void outputVector(IVector v, OutputStream out) throws IOException {
DataOutputStream dos = new DataOutputStream(out); int len = v.size();
dos.writeInt(len); try{
for (int i = 0; i < len; ++i) { dos.writeDouble(v.get(i));
}
}
catch(Exception e) { System.out.println(e.getMessage());
}
dos.flush();
}
// Метод чтения вектора из байтового потока
public static IVector inputVector(InputStream in) throws IOException { DataInputStream dis = new DataInputStream(in);
int len = dis.readInt(); IVector result = new Array(len);
8
try {
for (int i = 0; i < len; ++i) { result.set(i, dis.readDouble());
}
}
catch(Exception e) { System.out.println(e.getMessage());
}
return result;
}
// Метод записи вектора в символьный поток
public static void writeVector(IVector v, Writer out) throws IOException
{
PrintWriter pw = new PrintWriter(out); int len = v.size();
pw.print(len); try{
for (int i = 0; i < len; ++i) { pw.print(' '); pw.print(v.get(i));
}
}
catch(Exception e) { System.out.println(e.getMessage());
}
pw.flush();
}
// Метод чтения вектора из символьного потока
public static IVector readVector(Reader in) throws IOException { StreamTokenizer token = new StreamTokenizer(in);
int t = token.nextToken();
IVector v = new Array((t != StreamTokenizer.TT_EOF) ? (int) token.nval : 0);
t = token.nextToken(); try {
for (int i = 0; t != StreamTokenizer.TT_EOF; ++i, t = token.nextToken()) {
if (t == StreamTokenizer.TT_NUMBER) { v.set(i, token.nval);
}
}
}
catch(Exception e) { System.out.println(e.getMessage());
}
return v;
}
}
Таблица 4 — Код VectorStreamTest.java
import vectors.Array; import vectors.Vectors;
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.CharArrayReader; import java.io.CharArrayWriter;
public class VectorStreamTest {
public static void main(String[] args) throws Exception { Array arr = new Array(8);
for (int i = 0, len = arr.size(); i < len; ++i) { arr.set(i, i);
9
}
System.out.println("Work with byte streams"); System.out.print("Source array: "); arr.print();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Vectors.outputVector(arr, byteArrayOutputStream); byteArrayOutputStream.flush(); System.out.print("Internal data (in bytes): "); System.out.println(byteArrayOutputStream.toString()); ByteArrayInputStream byteArrayInputStream = new
ByteArrayInputStream(byteArrayOutputStream.toByteArray()); System.out.print("Received array: "); Vectors.inputVector(byteArrayInputStream).print();
System.out.println("\nWork with character streams"); System.out.print("Source array: ");
arr.print();
CharArrayWriter charArrayWriter = new CharArrayWriter(); Vectors.writeVector(arr, charArrayWriter); charArrayWriter.flush();
System.out.print("Internal data (in chars): "); System.out.println(charArrayWriter.toString()); CharArrayReader charArrayReader = new
CharArrayReader(charArrayWriter.toCharArray());
System.out.print("Received array: "); Vectors.readVector(charArrayReader).print();
}
}
Результат компиляции и запуска приведен на рис. 2.
Рисунок 2 — Компиляция и запуск VectorStreamTest.java Задание №3.
Модифицируем классы Array и CircularLinkedList таким образом, чтобы они были сериализуемыми (табл. 5, 6).
Таблица 5 — Измененный код vectors/Array.java
package vectors;
import java.io.Serializable;
public class Array implements IVector, Serializable {
//Конструктор public Array(int n) {
data = new double[n];
}
//Получение элемента по индексу
10