Как найти значение / Как обновить значение
Сначала вы должны найти запись (строку), которую хотите обновить. Обычно это делается путем поиска в таблице
данное ключ значение. COBOL предоставляет несколько способов сделать это. Я рекомендую вам начать с
просмотр КОБОЛ ПОИСК
заявление. Если STRUCT-1
записей отсортированы, вы можете использовать SEARCH ALL
, в противном случае вы должны использовать SEARCH
или просто код
свой собственный цикл поиска. Чтобы использовать любой из этих методов, вам нужно будет где-то объявить другую переменную
в вашей программе для использования в качестве индекса (смещения) в таблице STRUCT-1
. COBOL предоставляет фразу INDEXED BY
на
OCCURS
предложение для объявления индекса, определенного для данной таблицы
(см. OCCURS )
Как только вы установите индекс в STRUCT-1
, чтобы указать на строку, которая будет обновлена, вы просто MOVE
значение для соответствующих переменных в этой строке, например
ПЕРЕМЕСТИТЬ 123.456 В ЗНАЧЕНИЕ-2 (IDX-1)
где IDX-1 - индекс, указанный выше. Обратите внимание, что вы можете использовать целое число или
индексная переменная
чтобы указать номер строки для обновления, вы не ограничены использованием переменной типа INDEX. Тем не мение,
как правило, более эффективно использовать переменные INDEX над другими типами переменных, особенно
при работе с многомерными таблицами, где программа делает множество ссылок на таблицу.
Как добавить новую строку
Сначала узнайте, что STRUCT-1
содержит ровно 25 строк. КОБОЛ не имеет механизма динамического
увеличить или уменьшить это число (я слышал, что это будет возможно в следующем стандарте ISO COBOL - но не
задержите дыхание в ожидании этого). Технически все 25
строки доступны в любое время. Однако общее соглашение состоит в том, чтобы «вырастить» таблицу из пустой
до полного последовательно, по одной строке за раз. Чтобы использовать это соглашение, вам нужно присвоить переменную
отслеживать последний использованный номер строки (не забудьте инициализировать эту переменную на ноль при запуске программы).
В вашем примере это выглядит как переменная NUMBER-OF-OCCURS
делает эту работу
(Я не упоминал об этом, но вам нужна эта переменная, чтобы ограничить ПОИСК, рассмотренный выше).
Чтобы «добавить» строку, просто увеличьте NUMBER-OF-OCCURS
на 1. Будьте осторожны, чтобы не превысить размер таблицы. пример
код может быть:
IF NUMBER-OF-OCCURS < (LENGTH OF TABLE-1 / LENGTH OF STRUCT-1 (1))
ADD +1 TO NUMBER-OF-OCCURS
ELSE
table is full, preform some error/recovery routine
END-IF
Приведенный выше код позволяет избежать явного использования числа, встречающегося в TABLE-1
, что, в свою очередь, может сохранить
ряд проблем с обслуживанием, когда / если количество OCCURS когда-либо изменяется.
См. ПРИМЕЧАНИЕ внизу: здесь действительно большие Woops - вы его поймали!
Теперь вернемся к проблеме поиска. В следующем примере кода показано, как вы можете
продолжить:
РАБОЧАЯ ХРАНИЛИЩА Декларация:
01 FOUND-IND PIC X(1).
88 FOUND-YES VALUE 'Y'.
88 FOUND-NO VALUE 'N'.
77 MAX-IDX USAGE IS INDEX.
01 TABLE-1.
05 STRUCT-1 OCCURS 25 TIMES INDEXED BY IDX-1.
10 VALUE-1 PIC AAA.
10 VALUE-2 PIC 9(5)V999.
05 NUMBER-OF-OCCURS PIC 99.
Что было добавлено:
FOUND-IND
используется, чтобы указать, была ли найдена искомая строка. 88 уровней дают конкретные значения для установки / тестирования
MAX-IDX
используется для установки верхнего предела поиска. Вы могли бы использовать NUMBER-OF-OCCURS
в тесте верхних границ, но это заставило бы использовать тип данных в каждом тесте, который не очень эффективен
IDX-1
используется как индекс (смещение) в таблице STRUCT-1
.
Лично я бы объявил NUMBER-OF-OCCURS
как PIC S9(4) BINARY
, но то, что у вас есть, будет работать.
Предполагается, что STRUCT-1
не отсортировано и NUMBER-OF-OCCURS
представляет текущий
количество активных строк в STRUCT-1
это
пример того, как вы можете кодировать SEARCH
при поиске значения 'ABC':
SET FOUND-NO TO TRUE
IF NUMBER-OF-OCCURS > ZERO
SET IDX-1 TO 1
SET MAX-IDX TO NUMBER-OF-OCCURS
SEARCH STRUCT-1
WHEN IDX-1 > MAX-IDX
CONTINUE
WHEN VALUE-1 (IDX-1) = 'ABC'
SET FOUND-YES TO TRUE
END-SEARCH
END-IF
IF FOUND-YES
row found, use IDX-1 to reference the row containing 'ABC'
ELSE
row not found, IDX-1 does not contain a valid index
END-IF
Как это работает:
- Начните с предположения, что строки нет в таблице, установив для
FOUND-NO
значение true.
- Первая
IF
гарантирует, что в STRUCT-1
есть по крайней мере 1 активная строка перед началом поиска (ошибкой является установка INDEX на ноль - так что вам нужно быть осторожным). -
SEARCH
завершается, когда удовлетворяется первое предложение SEARCH WHEN
. Вот почему глагол «ничего не делать» CONTINUE
можно использовать, когда у нас заканчиваются строки для поиска. Другое условие завершения (поиск искомого значения) - это единственное место, где можно установить FOUND-YES
.
- Когда
SEARCH
завершится, проверьте успешность или неудачу, а затем действуйте соответствующим образом.
Некоторые упражнения для исследования:
- Почему мне не пришлось кодировать предложение
AT END
в операторе SEARCH
?
- Почему мне не пришлось кодировать предложение
VARYING
в операторе SEARCH
?
- Почему я кодировал предложения
WHERE
в том порядке, в котором я это сделал?
Надеюсь, это поможет вам начать правильный путь.
Редактировать
В ответ на ваш вопрос в комментариях: Можем ли мы использовать NUMBER-OF-OCCURS в качестве индекса для поиска .
ответ - да, но вам нужно реализовать некоторые другие правила. При использовании NUMBER-OF-OCCURS
в качестве индекса вы больше не можете использовать его, чтобы отслеживать, сколько строк в настоящее время содержат
действительные данные. Это означает, что вам нужен другой механизм для определения неиспользуемых строк в STRUCT-1
.
Это может быть достигнуто путем инициализации неиспользуемых строк с помощью значения (например, LOW-VALUE
), которое вы
никогда не захочет положить в таблицу. SEARCH
становится:
SET FOUND-NO TO TRUE
MOVE 1 TO NUMBER-OF-OCCURS
SEARCH STRUCT-1 VARYING NUMBER-OF-OCCURS
WHEN VALUE-1 (NUMBER-OF-OCCURS) = 'ABC'
SET FOUND-YES TO TRUE
END-SEARCH
Выше будет искать каждую строку в STRUCT-1
в случае, если значение, которое вы ищете
(т. е. ABC
) нет в таблице. В качестве оптимизации вы можете добавить второе предложение WHEN
, чтобы завершить
поиск при нахождении дозорного значения:
WHEN VALUE-1 (NUMBER-OF-OCCURS) = LOW-VALUE
CONTINUE
Вышеприведенное предполагает, что LOW-VALUE
использовался для идентификации неиспользуемых строк. Вы также можете сбросить IDX-1
и MAX-IDX
из вашего рабочего хранилища, так как это решение не нуждается в них.
Использование NUMBER-OF-OCCURS
в качестве индекса также означает, что вы должны изменить способ поиска пустой строки
вставить новое значение. Самый простой способ сделать это, чтобы найти в таблице, используя выше
код для LOW-VALUE
вместо 'ABC'
. Если FOUND-YES
был установлен в конце поиска, то
NUMBER-OF-OCCURS
- индекс первой неиспользованной строки. Если FOUND-NO
было установлено, то таблица
уже полный.
Приведенный выше код намного проще, чем я изначально предлагал. Так почему я дал вам больше
сложное решение? Более сложное сложное решение более эффективно, потому что оно делает много
меньше внутренних вычислений смещения и преобразований типов данных при работе через таблицу.
Это также избегает делать дополнительные
SEARCH
чтобы найти следующую неиспользованную строку. Эти эффективности
может не иметь значения в вашем приложении, но если таблицы большие и часто используются, вы
следует учитывать аспект производительности при поиске таблиц и принудительных преобразованиях типов данных (для
пример стоимости преобразования поля PIC 99
в индексную ссылку).
Примечание:
Мой оригинальный пример для расчета, была ли таблица заполнена, используя специальный регистр LENGTH OF
будет работать в этом примере, но имеет действительно плохо встроенное предположение! LENGTH OF TABLE-1
включает
не только таблица STRUCT-1
, но и NUMBER-OF-OCCURS
. Длина NUMBER-OF-OCCURS
меньше одного
occurance STRUCT-1
, так что все работает нормально из-за усечения результата в целочисленное значение.
Это очень хороший пример работы кода по неправильной причине! Чтобы сделать правильный расчет
вам придется настроить рабочее хранилище на что-то вроде:
01 TABLE-1.
05 STRUCT-TABLE.
10 STRUCT-1 OCCURS 25 TIMES.
20 VALUE-1 PIC AAA.
20 VALUE-2 PIC 9(5)V999.
05 NUMBER-OF-OCCURS PIC 99.
и расчет границ станет:
IF NUMBER-OF-OCCURS < (LENGTH OF STRUCT-TABLE / LENGTH OF STRUCT-1 (1))
ADD +1 TO NUMBER-OF-OCCURS
ELSE
table is full, preform some error/recovery routine
END-IF
Или вы можете просто удалить NUMBER-OF-OCCURS
из определения TABLE-1
записи.