Найти подстроку в строке в COBOL

Моя проблема заключается в том, что, учитывая переменную, которую я читаю из файла, посмотрите, содержит ли она другую строку или соответствует ей.

Другими словами, найти в файле все записи, переменная которых

БРЭДД ПИК Х(30)

соответствует или содержит строку, введенную с клавиатуры.

Я очень уверен, что эта проблема решена с помощью инструкции INSPECT, и я пробовал что-то вроде этого в своем коде:

           READ BRANCHFILE NEXT RECORD 
             AT END SET EndOfFile TO TRUE
           END-READ.
           PERFORM UNTIL EndOfFile
               INSPECT BBRADD 
                 TALLYING CONT for CHARACTERS
                   BEFORE INITIAL CITY
               IF CONT>1
                   DISPLAY " BRANCH CODE    :" BBRID
                   DISPLAY " BRANCH NAME    :" BBRNAME
                   DISPLAY " BRANCH ADDRESS :" BBRADD
                   DISPLAY " PHONE          :" BBRPH
                   DISPLAY " E-MAIL         :" BEMAIL
                   DISPLAY " MANAGER NAME   :" BMGRNAME
                   DISPLAY " ------------------"
                   DISPLAY " ------------------"
               END-IF
               READ BRANCHFILE NEXT RECORD 
                   AT END SET EndOfFile TO TRUE
               END-READ
               MOVE 0 TO CONT
           END-PERFORM.

Где CITY — это переменная, которую я ввожу с клавиатуры.

¿Кто-нибудь знает, как найти "подстроку" в "строке"?

Например, если я ввел слово «Сарагоса», моя программа должна вывести все записи в файле, переменная BBRADD которого содержит слово «Сарагоса».

01 BRANCHREC. 
   88 EndOfFile VALUE HIGH-VALUE. 
   02 BBRID PIC X(6). 
   02 BBRNAME PIC X(15). 
   02 BBRADD PIC X(30). 
   02 BBRPH PIC X(10). 
   02 BEMAIL PIC X(20). 
   02 BMGRNAME PIC X(25). 

person daniegarcia254    schedule 13.10.2014    source источник
comment
Я пробую предложенный вами код. Сначала мне нужно найти, как реализовать код для вычисления длины переменной CITY, так что я на ней.   -  person daniegarcia254    schedule 14.10.2014
comment
Не беспокойтесь об этом пока. Жестко закодируйте длину, чтобы увидеть, получит ли она то, что вы хотите (так и будет), а затем попробуйте найти длину. Нет особого смысла сначала делать дополнительную работу, если вы обнаружите, что она не годится для того, что вы хотите, поэтому всегда сначала тестируйте код на предмет того, что вы хотите :-)   -  person Bill Woodger    schedule 14.10.2014
comment
Приятно слышать. Если у вас есть проблемы с длиной города, можно без особых усилий использовать FUNCTION REVERSE ... и INSPECT ... TALLYING ... FOR LEADING SPACE. Есть менее нагружающие процессор способы, но это распространено. Если у вас есть проблемы, начните другой вопрос. Удачи.   -  person Bill Woodger    schedule 14.10.2014
comment
Спасибо, это уже решено =)   -  person daniegarcia254    schedule 14.10.2014


Ответы (1)


Вам нужно будет каждый раз устанавливать CONT на ноль перед INSPECT.

CONT просто обновляется со своего начального значения при запуске INSPECT. После того, как вы найдете свою первую, каждая запись будет выглядеть так, как будто в ней есть ГОРОД.

Поначалу может показаться странным, что это работает таким образом, но если бы это было не так, вы были бы ограничены в тех случаях, когда вы хотите, чтобы это работало именно так.

А, если приглядеться, вы устанавливаете CONT на начальное значение, просто делаете это в неожиданном месте. Если он должен быть равен нулю, установите его в ноль непосредственно перед тем, как он должен быть равен нулю. Гораздо легче найти, и тем, кто изменит программу в будущем, будет сложнее испортить ее.

Однако у вас есть другая проблема. Допустим, ГОРОД — это PIC X(20). Пользователь вводит SEVILLA, и ваш INSPECT теперь будет искать SEVILLA, за которой следуют 13 пробелов. В идеале вы бы хотели, чтобы SEVILLA сопровождалась одним пробелом.

Вы должны иметь возможность проверить введенное пользователем значение с завершающим пробелом, но не более того.

В настоящее время популярным способом сделать это является модификация ссылки.

Вам нужно взять пользовательский ввод, узнать, сколько пробелов в конце он содержит, вычислить длину данных, добавить один для завершающего пробела и сохранить это значение в поле (предпочтительно поле BINARY).

Тогда ваш INSPECT может выглядеть так:

           INSPECT BBRADD 
             TALLYING CONT for CHARACTERS
               BEFORE INITIAL CITY ( 1 : length-of-data-plus-one )

Однако тогда у вас возникнут проблемы, если SEVILLA фактически находится в начале поля.

Таким образом, вы делаете небольшое изменение не для подсчета символов, которые появляются перед ним, а для подсчета его появления.

           INSPECT BBRADD 
             TALLYING CONT for ALL
                           CITY ( 1 : length-of-data-plus-one )

Вместо этого многие люди будут кодировать цикл PERFORM с модификацией ссылок и выполнять тест таким образом. В окончательной версии INSPECT, приведенной выше, вам придется самостоятельно кодировать логику завершения. В целях обучения было бы хорошо сделать это в обоих направлениях.

При выполнении file-io всегда используйте и проверяйте FILE STATUS. Поместите READ в абзац и выполните его, вам не нужны два разных фрагмента кода. Если вы используете FILE STATUS, вам не нужно AT END (или END-READ), поскольку поле, которое вы используете для получения значения FILE STATUS, будет «10» для конца файла. Просто используйте 88 в этом поле со значением «10».

Редактирование вашего вопроса теперь указывает, где находится ваш существующий 88-й уровень.

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

С другой стороны, это не «портативное» решение: если вы используете другие COBOL, вы можете обнаружить, что после достижения конца файла доступ к данным в разделе FD больше недействителен. В стандарте не определено, что происходит в этой ситуации, поэтому вы получаете различия между компиляторами.

Вы можете сохранить 88 в элементе группы, если бы он был переносимым, используя READ ... INTO ... и имея макет записи в WORKING-STORAGE. Это занимает немного больше времени, так как данные должны быть переданы из одного места в другое.

Я предпочитаю 88 в поле СОСТОЯНИЕ ФАЙЛА и упрощаю ЧТЕНИЕ, имея возможность удалить AT END и END-READ. Я уже не могу получить доступ к области записи под FD, поэтому я не могу случайно получить неправильные значения, которые выглядят хорошо.

person Bill Woodger    schedule 13.10.2014
comment
Хорошо, я уже попробовал это, и это работает отлично. Код распознает подстроку, содержащуюся в строке. Спасибо друг! - person daniegarcia254; 14.10.2014