Манипулировать структурой данных COBOL - PullRequest
4 голосов
/ 08 марта 2010

Я хотел бы, чтобы информация управляла таблицами.
Я сталкиваюсь с несколькими проблемами с куском кода cobol, как показано ниже:

01 TABLE-1.  
    05 STRUCT-1 OCCURS 25 TIMES.
        10 VALUE-1 PIC AAA.  
        10 VALUE-2 PIC 9(5)V999.  
    05 NUMBER-OF-OCCURS PIC 99.

Как вы обновляете значения? (обновить VALUE-2, когда вы знаете VALUE-1)
Как найти значение и добавить новое?
Большое спасибо!

Ответы [ 3 ]

8 голосов
/ 08 марта 2010

Как найти значение / Как обновить значение

Сначала вы должны найти запись (строку), которую хотите обновить. Обычно это делается путем поиска в таблице данное ключ значение. 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 записи.

1 голос
/ 08 июня 2010

Ух ты ... это был длинный ответ. Предположим, что числовое имя II:

Выполнять варьирование II от 1 до 1

до II> ЧИСЛО ПРОИСХОЖДЕНИЯ

Если значение-1 (II) = известное-значение-1

 Move New-Value-2 to Value-2 (II)

End-If

End-Perform

1 голос
/ 08 марта 2010

Для заполнения и изменения данных в таблицах в разделе «рабочее хранилище» необходимо использовать индекс / индекс, который вы можете определить в рабочем хранилище, а затем записать обработку код в разделе процедуры. В этом случае вы можете использовать execute..until.

...