Words (1): Uma função para contar a quantidade de palavras numa string

Em outras linguagens, como Java ou Javascript, é possível fazer um split e transformar uma string num array em que cada ocorrência corresponda a uma palavra da string original.

Num primeiro momento, podemos imaginar que o COBOL faria a mesma coisa com o comando UNSTRING, mas existe uma diferença essencial: enquanto Java, Javascript e outras linguagens trabalham com arrays dinâmicos (arrays cuja quantidade de ocorrências se pode definir em tempo de execução), no COBOL temos que estabelecer uma quantidade máxima de palavras para que o UNSTRING funcione do jeito que queremos. Algo como:

UNSTRING UMA-STRING-QUALQUER
   DELIMITED BY ALL SPACES
   INTO PALAVRA(1)
        PALAVRA(2)
        PALAVRA(3)
        PALAVRA(4)

Se no comando acima, UMA-STRING-QUALQUER tivesse cinco palavras, a quinta seria perdida. Em um programa real…

identification division.
program-id. gtc034.

data division.
working-storage section.
01 uma-string-qualquer pic x(080) 
    value "perform paragrafo varying indice from 1 by 1".
01 palavra pic x(010) occurs 4.

procedure division.
    unstring uma-string-qualquer
        delimited by all spaces
        into palavra(1)
             palavra(2)
             palavra(3)
             palavra(4)

    display "palavra(1)=" palavra(1)
    display "palavra(2)=" palavra(2)
    display "palavra(3)=" palavra(3)
    display "palavra(4)=" palavra(4)

    stop run.

…o resultado da execução seria:

 > Executing task in folder coblab: gtc034 < 
 palavra(1)=perform   
 palavra(2)=paragrafo 
 palavra(3)=varying   
 palavra(4)=indice    

Felizmente usando alguns recursos do COBOL 2002 é possível criar funções que contornam essa limitação. E esses recursos estão disponíveis na maior parte dos compiladores atuais.

Este artigo faz parte de uma série de três onde pretendo mostrar como criei essas funções.

Criando a função getWordCount

A função abaixo foi codificada e testada no GnuCOBOL 3.1.0, mas com poucas alterações pode ser implementada em quase todos os compiladores que incorporaram os recursos do COBOL 2002:

identification division.
function-id.    getWordCount.

environment division.
configuration section.
repository.
    function all intrinsic.

data division.
working-storage section.
01 subscript        binary-short unsigned value zeros.
01 stringState      pic 9(001)  value zeros.
    88 wasSpace                 value 1 false 0.

linkage section.
01 fullString       pic x any length.
01 wordsCounted     binary-short unsigned.

procedure division using fullString returning wordsCounted.
0-main.

    move zeros to subscript
    move zeros to stringState
    move zeros to wordsCounted

    perform varying subscript from 1 by 1 until subscript > length(fullString)
        if fullString(subscript:1) = spaces 
            set wasSpace to true
        else    
            if subscript = 1
                add 1 to wordsCounted
            else    
                if wasSpace 
                    add 1 to wordsCounted
                    set wasSpace to false
                end-if
            end-if
        end-if
    end-perform

    goback.

end function getWordCount.

Criando a variável fullString na linkage section com pic x any length a função poderá receber strings de qualquer tamanho. Quem vai definir esse tamanho é o programa chamador.

Outro ponto importante é que essa versão mais recente do GnuCOBOL não permite ainda declarar a cláusula “is initial” no parágrafo function-id da identification division. Por isso, coloquei os três comandos “move zero” no início da procedure, garantindo que as variáveis serão sempre inicializadas se o programa chamador executar a função mais de uma vez.

Testando a função

Codificando um programa chamador…

identification division.
program-id. gtc035.

environment division.
configuration section.
repository.
    function getWordCount.

data division.
working-storage section.
01 uma-string-qualquer pic x(080) 
    value "perform paragrafo varying indice from 1 by 1".

procedure division.
inicio.

    display "O conteudo da string possui " 
             getWordCount(uma-string-qualquer) 
             " palavras"
    stop run.

…temos o seguinte resultado:

 > Executing task in folder coblab: gtc035 < 
 O conteudo da string possui 00008 palavras

No próximo artigo…

…vamos mostrar uma função que também em COBOL que usa essa getWordCount para recuperar uma palavra dentro da string.