Jornada/T | 13. Operações com Strings
13. Operações com Strings
A maior parte do trabalho com sistemas comerciais consiste basicamente em processar arquivos, registros e campos. Algumas vezes, porém, é necessário fazer algumas operações com strings, caracter a caracter. O COBOL possui alguns recursos específicos para facilitar a operação com strings.
Modificadores de referência são recursos do COBOL que permitem ao programador fazer referências a uma parte de uma variável alfanumérica. Isso também poderia ser feito através da subdivisão da variável em itens elementares, mas os modificadores de referência facilitam esse trabalho.
Veja o exemplo abaixo. A data é uma variável alfanumérica de 10 posições no formato DD/MM/AAAA. Suponha que tenhamos que mover apenas o mês e o ano para um determinado campo. Uma das soluções seria:
01 DATA-X.
03 FILLER     PIC X(003).
03 MES-ANO-X  PIC X(007).
MOVE MES-ANO-X TO WR-DET-MES-ANO
Usando modificados de referência podemos mover apenas a parte que nos interessa, sem precisar criar itens elementares só para isso:
01 DATA-X PIC X(010).
MOVE DATA-X(4:7) TO WR-DET-MES-ANO
O comando acima move apenas a substring que começa na posição 4 e tem tamanho de 7 caracteres. Você poderia usar variáveis – ou uma combinação de variáveis e literais – para indicar a posição inicial e a extensão da substring que pretende acessar. Os três exemplos abaixo são válidos:
MOVE DATA-X(POSINI:TAMSTR) TO WR-DET-MES-ANO
MOVE DATA-X(WT-INI:7) TO WR-DET-MES-ANO
MOVE DATA-X(4:WT-TAM) TO WR-DET-MES-ANO
A extensão pode ser omitida. O exemplo abaixo moveria para a variável WR-DET-MES-ANO a substring de DATA-X que começa na posição 4 e que vai até o último caracter dessa variável:
MOVE DATA-X(4:) TO WR-DET-MES-ANO
Também é possível aplicar modificadores de referência a ocorrências isoladas de uma tabela interna ou array. O próximo exemplo move apenas os três primeiros caracteres da décima segunda ocorrência da tabela interna WV-MES:
MOVE WV-MES(12) (1:3) TO WR-DET-MES
O COBOL permite a concatenação de dois ou mais campos alfanuméricos através do comando STRING. Seu formato mais simples é:
STRING campo1 campo2 ... campoN INTO campoX
Neste formato, todo o conteúdo de campo1, campo2 … campoN é copiado, caracter a caracter, para campoX.
01  CAMPO1      PIC X(010) VALUE "COMMON".
01  CAMPO2      PIC X(010) VALUE "BUSINESS".
01  CAMPO3      PIC X(010) VALUE "ORIENTED".
01  CAMPO4      PIC X(010) VALUE "LANGUAGE".
01 NOME-COMPLETO PIC X(040) VALUE SPACES.
STRING CAMPO1 CAMPO2 CAMPO3 CAMPO4 INTO NOME-COMPLETO
DISPLAY "NOME COMPLETO: " NOME-COMPLETO
O trecho acima, quando executado, mostrará:
NOME COMPLETO: COMMON    BUSINESS  ORIENTED  LANGUAGE
Os espaços entre as palavras são os espaços que existiam à direita de CAMPO1, CAMPO2, CAMPO3 e CAMPO4 (repare que essas variáveis têm dez caracteres de tamanho). O comando concatenou todos os caracteres (inclusive os espaços em branco) e os juntou na variável NOME-COMPLETO porque assumiu a opção default DELIMITED BY SIZE.
Mas o comando STRING permite que sejam estabelecidos outros delimitadores. Seguindo no mesmo exemplo, se fizéssemos…
STRING CAMPO1 CAMPO2 CAMPO3 CAMPO4
INTO NOME-COMPLETO
… teríamos a seguinte saída:
NOME COMPLETO: COMMONBUSINESSORIENTEDLANGUAGE
Observe que o caracter que indicamos na cláusula DELIMITED BY marca o fim da string a ser copiada; o delimitador em si não é copiado. Para inserir um espaço depois de cada palavra poderíamos combinar variáveis e literais, cada uma delas com um tipo de delimitador:
STRING CAMPO1 DELIMITED BY SPACE
" "    DELIMITED BY SIZE
CAMPO2 DELIMITED BY SPACE
CAMPO3 DELIMITED BY SPACE
CAMPO4 DELIMITED BY SPACE
DISPLAY "NOME COMPLETO: " NOME-COMPLETO
Nesse exemplo o programa exibiria…
NOME COMPLETO: COMMON BUSINES ORIENTED LANGUAGE
…porque as variáveis CAMPO1, CAMPO2, CAMPO3 e CAMPO4 foram concatenadas até o primeiro espaço encontrado, exclusive. Já os literais " " (espaço) foram copiados by size.
O comando STRING não apaga o valor do campo de destino antes de iniciar as cópias; ele simplesmente copia o primeiro caracter do primeiro campo para a primeira posição do campo de destino e para de copiar quando chega ao final do campo (DELIMITED BY SIZE) ou encontra o delimitador informado (DELIMITED BY literal). Os caracteres do campo de destino que não receberam conteúdo ficam com seus valores anteriores. Observe o exemplo abaixo:
MOVE ALL "*" TO NOME-COMPLETO
O campo de destino (NOME-COMPLETO) foi previamente preenchido com asteriscos. Quando o comando STRING é executado os campos e literais de origem são copiados caracter a caracter, deixando os demais com o conteúdo anterior. O resultado do DISPLAY seria:
NOME COMPLETO: COMMON BUSINESS ORIENTED LANGUAGE************************
Por default, os caracteres começam a ser copiados para a primeira posição do campo de destino, mas isso pode ser mudado com a cláusula WITH POINTER:
MOVE 6 TO PONTEIRO
WITH POINTER PONTEIRO
Nesse caso, criamos na WORKING uma variável chamada PONTEIRO e iniciamos ela com o valor 6 antes do comando STRING. Ela fará com que o conteúdo concatenado só comece na sexta posição do campo de destino. A saída desse trecho de programa seria:
NOME COMPLETO: *****COMMON BUSINESS ORIENTED LANGUAGE*****************
Separando strings
Quando precisamos separar uma string maior em strings menores, delimitadas por algum caracter ou não, usamos o comando UNSTRING, que em seu formato mais simples pode ser codificado assim:
UNSTRING campo-origem
INTO campo1 campo2 ... campoN
Vamos ver como funciona num exemplo prático:
01 ELEMENTOS.
03 ELEMENTO1 PIC X(020) VALUE SPACES.
03 ELEMENTO2 PIC X(020) VALUE SPACES.
03 ELEMENTO3 PIC X(020) VALUE SPACES.
03 ELEMENTO4 PIC X(020) VALUE SPACES.
01 NOME-COMPLETO PIC X(080) VALUE
"COMMON BUSINESS ORIENTED LANGUAGE".
UNSTRING NOME-COMPLETO
INTO ELEMENTO1 ELEMENTO2 ELEMENTO3 ELEMENTO4
DISPLAY "ELEMENTO1: " ELEMENTO1
DISPLAY "ELEMENTO2: " ELEMENTO2
DISPLAY "ELEMENTO3: " ELEMENTO3
DISPLAY "ELEMENTO4: " ELEMENTO4
Esse trecho de código exibiria as seguintes mensagens na tela do usuário:
ELEMENTO1: COMMON BUSINESS ORIE
ELEMENTO2: NTED LANGUAGE
ELEMENTO3:
Repare que o programa copiou o campo de origem (NOME-COMPLETO), caracter a caracter, para os campos de destino (ELEMENTO1, ELEMENTO2, ELEMENTO3 e ELEMENTO4). Ele preencheu os 20 bytes do primeiro campo e depois continuou no segundo. Os campos 3 e 4 ficaram com espaços porque não havia mais conteúdo no campo de origem.
Parar separar o campo de origem palavra por palavra precisamos indicar um delimitador. O trecho…
…mostraria:
ELEMENTO1: COMMON
ELEMENTO2: BUSINESS
ELEMENTO3: ORIENTED
ELEMENTO4: LANGUAGE
Assim como no comando STRING, qualquer literal pode ser usada como delimitador no comando UNSTRING:
UNSTRING LINHA-PLANILHA
DELIMITED BY ";"
INTO CIDADE ESTADO PAIS CEP
Separaria a variável LINHA-PLANILHA…
ITABIRITO;MINAS GERAIS;BRASIL;35450-000
Agora observe esse outro exemplo, onde a variável LINHA planilha possui mais de um ponto-e-vírgula separando cada campo:
ITABIRITO;;;MINAS GERAIS;;;BRASIL;;;35450-000
Nesse caso, o resultado do UNSTRING seria:
CEP: MINAS GERAIS
Isso aconteceu porque dissemos que nosso delimitador era formado por um único ponto-e-vírgula. O COBOL interpretou que entre o primeiro e o segundo ponto-e-vírgula existia um caracter nulo e por isso preencheu o segundo campo (ESTADO) com esse valor. A mesma coisa aconteceu entre o segundo o segundo e o terceiro ponto-e-vírgula, o que também deixou o campo PAIS vazio.
Para instruir o COBOL a interpretar sucessivas ocorrências de um delimitador como um só precisamos incluir a opção ALL na cláusula DELIMITED BY:
DELIMITED BY ALL ";"
Resultaria em…
Pesquisando substrings
Quando queremos verificar se uma substring aparece no conteúdo de uma variável alfanumérica usamos o comando INSPECT:
INSPECT variável TALLYING contador FOR ALL literal
Esse comando vai contar quantas vezes literal aparece no conteúdo de variável e a quantidade será armazenada na variável numérica contador. O exemplo abaixo conta quantas vezes o caracter arroba aparece no conteúdo da variável WT-NM-EMAIL. O resultado é salvo na variável WT-CT-ARROBA:
INSPECT WT-NM-EMAIL
TALLYING WT-CT-ARROBA
FOR ALL "@"
O comando INSPECT possui diversas variações. É possível, por exemplo, obter o tamanho efetivamente preenchido em uma variável alfanumérica:
03 NOME         PIC X(020) VALUE "PAULO".
03 CONTADOR     PIC 9(006) VALUE ZEROS.
INSPECT NOME
TALLYING CONTADOR
DISPLAY "NOME PREENCHIDO COM " CONTADOR " CARACTERES"
O exemplo acima mostraria…
NOME PREENCHIDO COM 5 CARACTERES
…pois instruímos o comando a contar a quantidade de caracteres existentes antes do primeiro espaço. Naturalmente, também é possível contar substrings com mais de um caracter:
03 NOME-COMPLETO       PIC X(040) VALUE "JOHN SMITH".
03 SOBRENOME          PIC X(005) VALUE "SMITH".
03 CONTADOR           PIC 9(006) VALUE ZEROS.
INSPECT NOME-COMPLETO
FOR ALL SOBRENOME
DISPLAY "O SOBRENOME APARECE " CONTADOR "VEZ(ES)"
Esse exemplo acima mostraria:
O SOBRENOME APARECE 1 VEZ(ES)
O comando INSPECT também permite contar mais de uma substring ao mesmo tempo usando mais de um contador. O exemplo abaixo conta quantas vezes cada vogal aparece numa variável alfanumérica:
INSPECT variável
TALLYING contadorA FOR ALL "A"
contadorE FOR ALL "E"
contadorI FOR ALL "I"
contadorO FOR ALL "O"
contadorU FOR ALL "U"
Podemos também contar várias substrings usando um único contador:
TALLYING contador FOR ALL "A" ALL "E" ALL "I" ALL "O" ALL "U"
Substituindo substrings
O comando INSPECT possui uma cláusula opcional chamada REPLACING que permite a substituição de strings dentro de uma variável alfanumérica. No exemplo abaixo todas as ocorrências de conteudo1 em variável será substituído por conteudo2:
REPLACING ALL conteudo1 BY conteudo2
O comando INSPECT não pode inserir ou excluir caracteres de uma variável. Por esse motivo o conteúdo anterior e o conteúdo novo devem sempre a mesma quantidade de caracteres.
A opção REPLACING também permite a substituição de todos os caracteres antes ou depois de determinado delimitador:
03 EMAIL PIC X(100) VALUE "CONTATO@ME.COM".
DISPLAY "ANTES  = " EMAIL
REPLACING CHARACTERS BY SPACES
AFTER INITIAL "@"
DISPLAY "DEPOIS = " EMAIL
ANTES  = CONTATO@ME.COM
DEPOIS = CONTATO@
E existem outras opções posicionais:
Figura 58. Exemplo de INSPECT com a cláusula REPLACING
Existe um outro formato do comando INSPECT que não é a ideal para a substituição de substrings mas pode facilitar muito a conversão de caracteres.
CONVERTING literal1 TO literal2
Esse comando é mais prático quando precisamos substituir um conjunto de caracteres por outro, pois todos eles podem ser declarados num único literal. O comando substitui o primeiro caracter de literal1 pelo primeiro caracter de literal2, o segundo caracter de literal1 pelo segundo caracter de literal2 e assim sucessivamente.
Figura 59. Exemplos de INSPECT com cláusula CONVERTING
Processamento de strings, na prática
Vamos ver um exemplo real em que o dado precisa ser processado caracter a caracter. Vamos aproveitar e rever algumas operações de entrada e saída com arquivos indexados.
Cada registro do cadastro de clientes que usamos em alguns exemplos anteriores está com o campo NR-TELEFONE-1 editado de uma maneira diferente, situação muito comum em sistemas legados. Precisamos construir um programa que altere esse campo padronizando a edição do número de telefone da seguinte maneira:
Para telefones fixos: (AA) PPPP-MMMM, onde AA é o código de área, PPPP é o prefixo de quatro dígitos dos telefones fixos e MMMM é a milhar
Para telefones móveis: (AA) PPPPP-MMMM, onde AA é o código de área, PPPPP é o prefixo de cinco dígitos dos telefones móveis e MMMM é a milhar.
O quadro abaixo mostra como estão os telefones nesse momento e como eles devem ficar após a execução do programa:
Figura 60. Número do telefone no cadastro de clientes
Repare que existem registros onde o telefone foi carregado sem edição nenhuma, outros que estão sem código de área, outros ainda editados de com pontos no lugar dos traços… e até alguns que estão com a edição correta.
Nosso próximo programa precisa ler todos os registros desse cadastro e padronizar a edição para que todos os telefones fiquem como aparece na terceira coluna.
Vamos quebrar o problema em sete passos:
Eliminar caracteres não numéricos. Vamos substituir todos os parênteses, traços e pontos por espaços. O telefone do cliente 003502, por exemplo, passaria de "31-3561-1973" para " 31 3561 1973".
Separar o número de telefone em campos menores, delimitados por espaços. O telefone do cliente 003502 seria dividido em três variáveis: a primeira ficaria com "31", a segunda com "3561" e a terceira com "1973".
Reagrupar os campos menores, aproveitando apenas os caracteres numéricos. O telefone do cliente 003502 ficaria com "3135611973"
Verificar o tamanho da string resultante. O tamanho da string é que vai nos ajudar a decidir se o telefone é fixo ou móvel. Um tamanho de 8 caracteres significa que o telefone é fixo e está sem código de área. Um tamanho 9 significa que o telefone é móvel e também está sem código de área. Tamanho 10 indica que o telefone é fixo mas está com código de área preenchido. Tamanho 11 corresponde a um telefone móvel com código de área preenchido.
Determinar código de área. Como alguns telefones estão sem código de área, precisamos definir um critério para determiná-lo durante a execução do programa. Nosso cadastro hipotético só tem clientes dos estados do Rio de Janeiro e de Minas Gerais. Logo, o código de área será 21 para RJ e 31 para MG.
Aplicar uma máscara de edição ao número de telefone. Se o telefone for fixo, a edição será (AA) PPPP-MMMM. Se o telefone for móvel a edição será (AA) PPPPP-MMMM. Os caracteres que usaremos para preencher AA, PPPP, PPPPP e MMMM vai depender da quantidade de caracteres existentes no telefone reagrupado, que calculamos no passo 4.
Regravar registro do cadastro de clientes com o número de telefone editado.
O programa acessará apenas o cadastro de clientes, arquivo CRA0201. A codificação da IDENTIFICATION, da ENVIRONMENT e da FILE SECTION não têm nenhuma particularidade, por isso veremos o passo a passo para construção do programa a partir da WORKING. Você poderá conferir o programa completo mais adiante nesse capítulo.
Começamos com o file status do cadastro de clientes…
03 WT-ST-CRA0201            PIC  X(002) VALUE SPACES.
E em seguida criamos dois itens de grupo que usaremos para edição de telefones fixos e móveis. O que muda nesses dois campos é o tamanho do item elementar chamado prefixo, que possui 4 caracteres para telefones fixos e 5 caracteres para telefones móveis:
01 WT-TELEFONE-FIXO.
03 FILLER                   PIC  X(001) VALUE "(".
03 WT-FIXO-AREA             PIC  X(002) VALUE SPACES.
03 FILLER                   PIC  X(002) VALUE ")".
03 WT-FIXO-PREFIXO          PIC  X(004) VALUE SPACES.
03 FILLER                   PIC  X(001) VALUE "-".
03 WT-FIXO-MILHAR           PIC  X(004) VALUE SPACES.
01 WT-TELEFONE-MOVEL.
03 FILLER                   PIC  X(001) VALUE "(".
03 WT-MOVEL-AREA            PIC  X(002) VALUE SPACES.
03 WT-MOVEL-PREFIXO         PIC  X(005) VALUE SPACES.
03 FILLER                   PIC  X(001) VALUE "-".
03 WT-MOVEL-MILHAR          PIC  X(004) VALUE SPACES.
Por último declaramos algumas variáveis auxiliares. Precisamos de uma variável para calcular o tamanho dos strings que estiverem em cada telefone:
03 WT-AUX-TAMANHO           PIC  9(002) VALUE ZEROS.
Em seguida, precisamos de algumas variáveis alfanuméricas que usaremos para quebrar o telefone do cliente em componentes menores. A quantidade de variáveis que precisaremos está diretamente relacionada às diferentes formas de edição dos telefones. Sabemos que o telefone será quebrado em componentes menores separados (delimitados) por espaços. Logo, "26416965" precisará apenas de uma variável; "31 3551 1283" precisaria de três… Vamos criar umas cinco. Podemos ajustar depois dos primeiros testes, se for necessário.
03 WT-AUX-PARTE-1           PIC  X(015) VALUE SPACES.
03 WT-AUX-PARTE-2           PIC  X(015) VALUE SPACES.
03 WT-AUX-PARTE-3           PIC  X(015) VALUE SPACES.
03 WT-AUX-PARTE-4           PIC  X(015) VALUE SPACES.
03 WT-AUX-PARTE-5           PIC  X(015) VALUE SPACES.
Precisamos também de uma variável para reagrupar as partes que foram quebradas no passo anterior:
03 WT-AUX-TELEFONE          PIC  X(015) VALUE SPACES.
E mais uma variável auxiliar para guardarmos o código de área que estabeleceremos a partir do Estado (RJ ou MG) de cada cliente:
03 WT-AUX-PARTE-4           PIC  X(015) VALUE SPACES.
03 WT-AUX-AREA              PIC  X(002) VALUE SPACES.
O diagrama estruturado do nosso programa é bem simples. Toda a lógica de edição dos números de telefone acontecerá no parágrafo 2-PROCESSA, que será executado para todos os registros do cadastro de clientes:
Figura 61. Diagrama estruturado do programa CRP0302
O parágrafo 1-INICIA tem apenas a abertura do arquivo e a leitura do primeiro registro. Nossa intenção é processar todos os registros do arquivo de entrada e por isso precisamos acessá-lo sequencialmente. Mas sabemos que o book de declaração desse arquivo usa ACCESS MODE IS DYNAMIC. Logo, para ler esse arquivo sequencialmente precisamos complementar o comando READ com a cláusula NEXT:
Começamos o parágrafo 2-PROCESSA codificando o primeiro dos sete passos que descrevemos anteriormente. Precisamos substituir todos os caracteres não numéricos por espaços. Para isso, usaremos o comando INSPECT REPLACING:
* ELIMINA TODOS OS CARACTERES NAO NUMERICOS, QUEBRA A VARIAVEL
* EM COMPONENTES NUMERICOS, CONCATENA ESSES COMPONENTES, APLICA
* UMAS MASCARA DE EDICAO AO NUMERO CONCATENADO E ATUALIZA O RE-
* GISTRO COM O NUMERO EDITADO
* ELIMINA CARACTERES NAO NUMERICOS
INSPECT CRA0201-NR-TELEFONE-1
REPLACING ALL "(" BY SPACE
ALL ")" BY SPACE
ALL "-" BY SPACE
ALL "." BY SPACE
Você pode ver o efeito desse comando sobre os números de telefone na figura abaixo. Repare que, agora, só existem números e espaços nesse campo:
Figura 62. Efeito do comando INSPECT REPLACING em cada número de telefone processado
Nosso segundo passo precisa quebrar o número de telefone em partes delimitadas por espaços. O comando UNSTRING processa caracter a caracter e para quando não há mais caracteres no campo de origem. Esse Por esse motivo é possível que, em alguns casos, ele não precise de todas as cinco variáveis que usaremos como campo de destino. Como o UNSTRING não faz nenhum tipo de inicialização desses campos, precisamos garantir que, antes da sua execução, todas as variáveis sejam inicializadas com espaços.
* QUEBRA NUMERO DE TELEFONE EM COMPONENTES NUMERICOS
MOVE SPACES TO WT-AUX-PARTE-1
MOVE SPACES TO WT-AUX-PARTE-2
MOVE SPACES TO WT-AUX-PARTE-3
MOVE SPACES TO WT-AUX-PARTE-4
MOVE SPACES TO WT-AUX-PARTE-5
UNSTRING CRA0201-NR-TELEFONE-1
DELIMITED BY ALL SPACES
INTO WT-AUX-PARTE-1
WT-AUX-PARTE-2
WT-AUX-PARTE-3
WT-AUX-PARTE-4
WT-AUX-PARTE-5
O efeito desse comando pode ser visto na figura abaixo.
Figura 63. Efeito do comando UNSTRING em cada telefone processado
Repare que, em alguns casos, o UNSTRING não colocou nada na variável WT-AUX-PARTE-1. Isso aconteceu quando o número de telefone transitório começava com um espaço em branco. E esses números ficaram assim depois que substituímos os caracteres não numéricos por espaços.
Agora podemos reagrupar essas partes, também delimitadas por espaços, numa única variável. Como o comando STRING também não inicializa a variável de destino, moveremos espaços para WT-AUX-TELEFONE antes do comando:
* REAGRUPA COMPONENTES DO TELEFONE
MOVE SPACES TO WT-AUX-TELEFONE
STRING WT-AUX-PARTE-1
INTO WT-AUX-TELEFONE
Observe na figura abaixo que agora temos uma variável alfanumérica com todos os caracteres numéricos alinhados à esquerda:
Figura 64. Efeito do comando STRING em cada número de telefone processado
Estamos quase prontos para mover o número de telefone para a variável editada. Antes disso, precisamos decidir se o telefone é fixo ou móvel, pois as máscaras de edição são diferentes. Para isso precisamos saber quantos caracteres estão preenchidos na variável auxiliar e faremos isso com o comando INSPECT TALLYING:
* OBTEM O TAMANHO DO TELEFONE APOS A CONCATENACAO
MOVE ZEROS TO WT-AUX-TAMANHO
INSPECT WT-AUX-TELEFONE
TALLYING WT-AUX-TAMANHO
Veja que usando a opção "FOR CHARACTERS" estamos contando quantos caracteres diferentes de espaços temos na variável WT-AUX-TELEFONE. O resultado desse comando é mostrado na figura abaixo:
Figura 65. Efeito do comando INSPECT TALLYING sobre cada número de telefone processado
Agora determinaremos o código de área em função do Estado onde cada cliente está localizado. A princípio precisamos fazer isso apenas para os telefones que estão sem código de área (aqueles que têm tamanho 8 ou 9). Para simplificar, testaremos o campo CD-ESTADO de todos os telefones e armazenaremos o código de área numa variável auxiliar:
* PREENCHE O CODIGO DE AREA EM FUNCAO DO CAMPO ESTADO
IF CRA0201-CD-ESTADO = "RJ"
MOVE "21" TO WT-AUX-AREA
MOVE "31" TO WT-AUX-AREA
E agora estamos prontos para mover os telefones para as variáveis editadas que criamos na WORKING: WT-TELEFONE-FIXO e WT-TELEFONE-MOVEL. Faremos isso testando o tamanho que calculamos anteriormente.
* PREENCHE O NUMERO DE TELEFONE EDITADO DE ACORDO COM O TAMANHO
* DO NUMERO RESULTANTE DA CONCATENACAO.
* SE TAMANHO FOR 8
* SIGNIFICA QUE E' UM TELEFONE FIXO SEM CODIGO DE AREA
* SE TAMANHO FOR 10
* SIGNIFICA QUE E' UM TELEFONE FIXO COM CODIGO DE AREA
* SE TAMANHO FOR 9
* SIGNIFICA QUE E' UM TELEFONE MOVEL SEM CODIGO DE AREA
* SE TAMANHO FOR 11
* SIGNIFICA QUE E' UM TELEFONE MOVEL COM CODIGO DE AREA
EVALUATE WT-AUX-TAMANHO
MOVE WT-AUX-AREA TO WT-FIXO-AREA
MOVE WT-AUX-TELEFONE(1:4) TO WT-FIXO-PREFIXO
MOVE WT-AUX-TELEFONE(5:4) TO WT-FIXO-MILHAR
MOVE WT-TELEFONE-FIXO TO CRA0201-NR-TELEFONE-1
MOVE WT-AUX-TELEFONE(3:4) TO WT-FIXO-PREFIXO
MOVE WT-AUX-TELEFONE(7:4) TO WT-FIXO-MILHAR
MOVE WT-AUX-AREA TO WT-MOVEL-AREA
MOVE WT-AUX-TELEFONE(1:5) TO WT-MOVEL-PREFIXO
MOVE WT-AUX-TELEFONE(6:4) TO WT-MOVEL-MILHAR
MOVE WT-TELEFONE-MOVEL TO CRA0201-NR-TELEFONE-1
MOVE WT-AUX-TELEFONE(3:5) TO WT-MOVEL-PREFIXO
MOVE WT-AUX-TELEFONE(8:4) TO WT-MOVEL-MILHAR
MOVE SPACES TO CRA0201-NR-TELEFONE-1
Observe que estamos fazendo as movimentações usando modificadores de referência, pois eles nos permitem acessar substrings de uma string maior. Isso é necessário porque os componentes que queremos estão em posições diferentes, dependendo de como o telefone foi preenchido no passado. Por exemplo, e o tamanho do telefone for 8 (telefone fixo sem código de área), o prefixo estará nas posições 1 a 4 e a milhar nas posições 5 a 8. Já se o tamanho for 10 (telefone fixo com código de área), o prefixo estará nas posições 3 a 6 e a milhar nas posições 7 a 10. As variáveis editadas, depois de preenchidas, são mostradas na figura abaixo:
Figura 66. Variáveis auxiliares editadas após execução das movimentações
As variáveis editadas foram movidas para o campo do arquivo no próprio EVALUATE. Agora podemos regravar o registro e ler o próximo a ser processado:
* MOVE NUMERO EDITADO PARA REGISTRO E ATUALIZA ARQUIVO
Obviamente, poderíamos ter codificado esse programa sem nenhum comando especial para manipulação de strings. Com um monte de itens elementares, PERFORMs VARYING e IFs teríamos obtido os mesmos resultados. Ao usar UNSTRING, STRING, INSPECT e substrings, porém, conseguimos um programa menor e mais fácil de entender.