CAPÍTULO 7: F90/7 – UTILIZAÇÃO DE INFORMAÇÕES ALFANUMÉRICAS

Nós comentamos no subconjunto F90/2, que os computadores poderiam operar com informações alfabéticas, mas que isto seria visto num capítulo mais adiante. Agora vamos aprender a manusear este tipo de dados, pois, até então, só trabalhamos com dados do tipo real ou inteiro.

Neste capítulo veremos como:

1)      Ler dados alfanuméricos através de linha (registros) de dados;

2)      Mudá-los de um lugar para outro na memória do computador; e

3)      Como investigar uma parte desta informação.

CONJUNTO DE CARACTERES

 O termo informação alfabética, não é adequado para o que iremos aprender e utilizar neste subconjunto. Ele é verdadeiro para informações que contém apenas letras, como por exemplo, o nome de uma pessoa:

“Maria da Silva”

Mas. quando queremos manusear informações envolvendo letras, números, e caracteres especiais,  como por exemplo, o endereço de uma pessoa:

“RUA MACIEL PINHELRO, 333”

Então, ele se torna inadequado. Este tipo de informação nós chamaremos de informação alfanumérica. Isto porque o conjunto de caracteres não envolve somente o uso de letras, mas  também o uso de números, sinais de pontuação, espaços em branco e outros caracteres especiais, como no caso do texto de um livro, ou como neste exemplo:

“Será que estou sendo claro nesta explicação?”

No conjunto de caracteres acima temos: 44 caracteres, onde:

-          6 são caracteres brancos;

-          1 é o ponto de interrogação; e

-          os restantes são letras.

VARIÁVEIS DE CARACTERES

Da mesma maneira que reservamos espaço de memória no computador para variáveis inteiras ou reais, nós reservamos uma parte da memória para armazenarmos nossos dados alfanuméricos. Uma variável de caracteres chamada FRASE pode ser declarada como:

CHARACTER*50 :: FRASE

ou

CHARACTER :: FRASE*50

ou

CHARACTER (LEN = 50) :: FRASE

Nós sabemos que FRASE é uma variável de caracteres por causa da palavra chave Fortran CHARACTER, e que a quantidade memória reservada para esta variável deve conter até 50 caracteres.

Por exemplo, queremos guardar na variável FRASE seguinte conjunto de caracteres:

“Isto é muito simples de se aprender”

Então, esta frase será. colocada a partir da 1a. Posição mais à esquerda da variável. Como este conjunto de caracteres possui 35 caracteres, então, as primeiras 35 posições, serão preenchidas com eles e o restante será preenchido com caracteres branco, ou seja:

 1                 1                   2                   3                   4                   5

 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0

Isto é muito simples de se aprender

Agora se o conjunto de caracteres a ser guardado for maior que o tamanho definido para a variável, então o conjunto será truncado a partir da primeira posição excedente do tamanho da variável. Por exemplo, definimos uma variável caractere chamada NOME, com 10 caracteres:

CHARACTER (LEN = 10) ::  NOME

Nela, queremos guardar o conjunto de caracteres que possui 15 caracteres:

Aline Guimarães de Faria

Logo, será armazenado na variável apenas:

                   1

 1 2 3 4 5 6 7 8 9 0

Aline Guim

Então, os caracteres restante serão perdidos.

LEITURA E IMPRESSÃO DE VARIÁVEIS DE CARACTERES

 Nós aprendemos a mostrar um conjunto de caracteres no subconjunto F90/1 do Fortran na forma de constante literal tal como:

WRITE (*, *) “VOLUME”

Agora que sabemos como usar variáveis de caracteres, vamos aprender a ler informações alfanuméricas através da entrada padrão e mostrá-las.

Por exemplo, programa que lê e imprime nome de uma pessoa:

 

PROGRAM mostra_nome

   IMPLICIT NONE

   ! Programa que lê e imprime o nome de uma pessoa

   CHARACTER (LEN = 20) :: nome

   WRITE(*, *) “Lê e imprime o nome de uma pessoa:”

   WRITE(*, *)

   WRITE(*, *) “Digite o nome a ser mostrado:”

   WRITE (*, *)

   READ (*, *) nome

   WRITE(*, *) “Nome lido:”

   WRITE(*, *) nome

   STOP

END PROGRAM mostra_nome

Se for digitada a cadeia de caracteres: Amanda Nascimento, o resultado apresentado pelo programa será o nome:

Amanda Nascimento

 Nós podemos também atribuir diretamente valor a uma variável de caracteres como fazemos com as variáveis reais e inteiras. Por exemplo:

CHARACTER :: NOME*15

NOME = “Amanda Nascimento”

COMPARAÇÃO ENTRE CONJUNTO DE CARACTERES

Nós precisamos comparar conjuntos de. caracteres por 2 motivos: um deles é para efeito de reconhecimento, ou seja, para saber se 2 conjuntos de caracteres são o mesmo ou não. A comparação entre conjuntos de caracteres alfanuméricos é feita através de operação lógica, como para dados numéricos. O valor desta operação é:

-          VERDADEIRA – Se o conjunto de caracteres forem iguais.

-          FALSA – Se o conjunto de caracteres forem diferentes.

Vejamos então um exemplo de programa de reconhecimento que lê e mostra um conjunto de palavras até encontrar a palavra PARE, mostrando, no final, a quantidade de palavras lidas, exceto a palavra PARE:

 

PROGRAM le_mostra

   IMPLICIT NONE

   ! Programa que lê e imprime palavras até que seja encontrada

   ! a palavra PARE

   CHARACTER (LEN = 10) :: palavra

   INTEGER :: contador

 

   WRITE (*, *) “Programa que lê e imprime palavras até que seja&

                & encontrada a palavra PARE, mostrando no final a&

                & quantidade de palavras lidas:“

   WRITE (*, *)

   contador = 0

   WRITE (*, *) “Informe uma palavra:“

   READ (*, *) palavra

   DO WHILE (palavra /= “PARE” .AND. palavra /= “Pare” .AND.&

             palavra /= “pare”)

      WRITE (*, *) palavra

      contador = contador + 1

      WRITE (*, *) “Informe uma palavra:“

      READ (*, *) palavra

   END DO

   WRITE (*, *) “Quantidade de palavras impressas: “, contador

   STOP

END PROGRAM le_mostra

Se a seqüência de dados digitada for:

SALVADOR

ARACAJU

RECIFE

MACEIO

PARE

As palavras mostradas como saída do programa, serão:

SALVADOR

ARACAJU

RECIFE

MACEIO

Note que a última palavra, PARE, nunca será mostrada. Porém, se não existir a palavra PARE como dado, o programa ficará sempre esperando ler uma nova palavra para ser mostrada.

O outro motivo para comparação de conjunto de caracteres é quando queremos colocá-los em ordem.

O alfabeto e os dígitos seguem a seguinte ordem:

-          0 vem antes der 9;

-          A vem antes de Z;

-          o branco tem menor valor

A ordem de precedência entre os caracteres, que o Fortran manipula, é definido pela tabela ASCII.

Os operadores .GT . e .LT. são usados para comparar os conjuntos de caracteres. Se dois conjuntos de tamanhos diferentes devem ser comparados, são incluídos caracteres, brancos à direita do conjunto menor para que ambos os conjuntos tenham o mesmo comprimento durante a comparação. Por exemplo:

“JOAO” .GT . “JORGE” Þ FALSO

“JOAO .LT. “JOAQUIM” Þ VERDADEIRO

“ A” .LT. “A” Þ VERDADEIRO

“22” .GT. “156” Þ VERDADEIRO

Por exemplo, um programa que lê 10 palavras e mostra aquela que seria a última em ordem alfabética:

 

PROGRAM ordem_alfabetica

   IMPLICIT NONE

   ! Lê 10 nomes e mostra a último nome em ordem alfabética

   CHARACTER (LEN = 15) :: nome, ultimo

   INTEGER :: vezes

 

   WRITE(*, *) “Lê 10 nomes e mostra o último nome em&

               & ordem alfabética”

   WRITE(*, *)

   ultimo = “”

   WRITE(*, *) “Informe os 10 nomes: ”

   DO vezes = 1, 10, 1

      READ (*, *) nome

      IF (nome .GT. ultimo) THEN

         ultimo = nome

      END IF

   END DO

   WRITE(*, *) “A último nome em ordem alfabética é ”, ultimo

   STOP

END PROGRAM ordem_alfabetica

Se as palavras digitadas forem:

NILCE

VANIA

FATIMA

MARLUCE

LASTENIA

PAULETE

JANAINA

ANA

MONICA

AMANDA

O resultado do programa será:

A última palavra na ordem alfabética é: Vania

Note que a variável ULTIMA foi inicializada com caracteres branco porque ela precisa de um valor inicial para ser usado no comando IF, e este valor deve ser mínimo para que na primeira comparação a variável ULTIMA possa ser substituída pelo primeiro dado lido, no caso, NILCE.

Porque a condição (“NILCE” .GT. “               ”) é VERDADEIRA.

CONCATENAÇÃO DE CADEIAS DE CARACTERES

Nós podemos concatenar (juntar ou unir) duas cadeias de caracteres, criando uma terceira. Para isso utilizamos o operador de concatenação (//).

Por exemplo, se quisermos unir o conteúdo da variável caractere estado com a constante “ é um estado do Brasil”, armazenando a nova cadeia na variável nova_cadeia, poderemos ter:

  

   CHARACTER (LEN = 10) :: estado

   CHARACTER (LEN = 35) :: nova_cadeia

   estado = “Pernambuco”

   nova_cadeia = estado // “ é um estado do Brasil”

   WRITE(*, *) “<”, nova_cadeia, “>”

O resultado da impressão seria:

<Pernambuco é um estado do Brasil>

Numa expressão de concatenação, pode-se concatenar várias constantes e/ou variáveis do tipo caractere.

SUB-CADEIA DE UMA CADEIA DE CARACTERES

Nós podemos extrair ou incluir uma parte ou sub-cadeia numa uma cadeia de caracteres. Utilizando a seguinte estrutura sintática:

 

   <cadeia original>(<posição de início>:<posição final>)

Considerando que as posições dos caracteres de uma cadeia são numeradas a partir de 1 da esquerda para a direita, <posição de início> é a posição do caractere da cadeia original, onde começa a sub-cadeia e, <posição final> é a posição do caractere da cadeia original, onde termina a sub-cadeia. A cadeia de onde se extrairá sub-cadeia pode ser uma constante ou uma variável.

Por exemplo, se quisermos extrair e mostrar a palavra “estado” da cadeia “Pernambuco é um estado do Brasil”, podemos fazer:

 

   WRITE(*, *) “Pernambuco é um estado do Brasil”(17:22)

Ou

   CARACTERE (LEN=32) :: cadeia

   ...

   cadeia = “Pernambuco é um estado do Brasil”

   WRITE(*, *) cadeia(17:22)

Se omitirmos a <posição de início>, a posição de inicio será considerada a primeira posição da cadeia original e, se omitirmos a <posição final>, a posição final será considerada a última posição da cadeia original.

Assim, cadeia(:10) extrai “Pernambuco” e cadeia(24:) extrai “do Brasil”.

Podemos também fazer atribuições a uma sub-cadeia de uma cadeia, utilizando o recurso mostrado acima no lado esquerdo de uma atribuição, resultando assim em alteração de parte da cadeia original:

 

   cadeia(16:22) = “a parte”

   WRITE(*, *) cadeia

O resultado da impressão seria: “Pernambuco é uma parte do Brasil”

FUNÇÕES INTRÍNSECAS PARA MANIPULAR CADEIAS DE CARACTERES

Fortran fornece uma série de funções para manipulação de cadeias de caracteres, como mostra o quadro a seguir:

 

Função

Descrição

ACHAR(i)

Retorna o caractere de posição i na tabela ASCII.

ADJUSTL(cadeia)

Alinha a cadeia à esquerda, retirando os brancos do início e colocando-os no final.

ADJUSTR(cadeia)

Alinha a cadeia à direita, retirando os brancos do final e colocando-os no início.

CHAR(i, tipo)

Retorna o i-ésimo caractere no conjunto de caracteres especificado por tipo. Se omitir o tipo o conjunto será o ASCII.

IACHAR(c)

Posição do caractere c na tabela ASCII.

INDEX(cadeia, sub-cadeia, back)

Se back é falso (back=.false.) ou não está presente, retorna a posição da primeira ocorrência da sub-cadeia na cadeia. Se back é verdadeiro (back=.true.), retorna a última ocorrência da sub-cadeia na cadeia. Zero é retornado, se não houver nenhuma ocorrência.

LEN(cadeia)

Retorna o tamanho de cadeia.

LEN_TRIM(cadeia)

Retorna o tamanho de cadeia, excluídos os brancos à direita.

REPEAT(cadeia, n)

Cria uma nova cadeia com n repetições de cadeia.

SCAN(cadeia, conjunto, back)

Procura  na cadeia por qualquer um dos caracteres do conjunto.

TRIM(cadeia)

Retorna uma nova cadeia sem os brancos da direita.

VERIFY(cadeia, conjunto, back)

Verifica se um conjunto de caracteres contém todos os caracteres da cadeia.

EXEMPLOS DE PROGRAMAS QUE MANIPULAM CADEIAS DE CARACTERES

Um programa para encontrar o tamanho de uma cadeia, excluídos seus brancos à direita. Este programa implementa o mesmo que a função LEN_TRIM():

 

PROGRAM tamanho

   IMPLICIT NONE

   CHARACTER (LEN = 30) :: cadeia

   INTEGER :: fim

   WRITE (*, *) "Informe a cadeia a ser medida: "

   READ (*, *) cadeia

   fim = 30

   DO WHILE (fim > 0 .AND. cadeia(fim:fim) == " ")

      fim = fim - 1

   END DO

   WRITE (*, *) "Tamanho da cadeia = ", fim

   STOP

END PROGRAM tamanho

Se quisermos inverter os caracteres de uma mesma cadeia, poderemos usar este programa:

 

PROGRAM inverte1

   IMPLICIT NONE

   CHARACTER (LEN = 40) :: cadeia

   CHARACTER (LEN=1) :: caractere

   INTEGER :: p

   WRITE (*, *) "Informe a cadeia a ser invertida: "

   READ (*, *) cadeia

   DO p = 1, 20, 1

      caractere = cadeia(p:p)

       cadeia(p:p) = cadeia(41-p:41-p)

       cadeia(41-p:41-p) = caractere

   END DO

   WRITE (*, *) "Cadeia invertida -->", cadeia

   STOP

END PROGRAM inverte1

Uma segunda versão do programa anterior para gerar uma segunda cadeia a partir da inversão dos caracteres de uma cadeia original:

 

 

PROGRAM inverte2

   IMPLICIT NONE

   CHARACTER (LEN = 40) :: cadeia1, cadeia2

   INTEGER :: p

   WRITE (*, *) "Informe a cadeia a ser invertida: "

   READ (*, *) cadeia1

   DO p = 1, 40, 1

      cadeia2(p:p) = cadeia1(41-p:L41-p)

   END DO

   WRITE (*, *) "Cadeia invertida -->", cadeia2

   STOP

END PROGRAM inverte2

A seguir um programa completo Fortran para abreviar um nome de pessoa. Por exemplo, se o programa ler o nome “Andréa Guimarães de Faria” como entrada gera como saída: Faria, A. G.

 

PROGRAM abrevia_nome

   IMPLICIT NONE

   CHARACTER (LEN = 30) :: nome, abreviatura

   INTEGER :: isub, fsub, inome, fnome

   WRITE (*, *) "Informe o nome a abreviar: "

   READ (*, *) nome

   fsub = 30

   DO WHILE (fsub > 0 .AND. nome(fsub:fsub) == " ")

      fsub = fsub - 1

   END DO

   isub = fsub

   DO WHILE (isub > 0 .AND. nome(isub:isub) /= " ")

      isub = isub - 1

   END DO

   abreviatura = nome(isub+1:fsub)//","

   inome = 1

   DO WHILE(inome < isub)

      fnome = inome

      DO WHILE (fnome < isub .AND. nome(fnome:fnome) /= " ")

         fnome = fnome + 1

      END DO

      IF (nome(inome:fnome-1) /= "de") THEN

         abreviatura = abreviatura(:LEN_TRIM(abreviatura))//&

                       &" "//nome(inome:inome)//"."

      END IF

      inome = fnome

      DO WHILE (inome < isub .AND. nome(inome:inome) == " ")

         inome = inome + 1

      END DO

   END DO

   WRITE (*, *) "Nome abreviado--> ", abreviatura

   STOP

END PROGRAM abrevia_nome

 

EXERCÍCIOS

1)      Dizer se são verdadeiras ou falsas, as comparações dos seguintes conjuntos de caracteres:

a) “LUIS HENRIQUE” .EQ . “LUIZ HENRIQUE 

b) “CASA 23” .GT. “CASA 222”

c) “ICC” .LT. “I C C”

d) “RUA DA AURORA 1070” .LT. “RUA DA AURORA 1070”

e)  “SIMONE” .GE. “MIRIAN”

2)      Escrever um programa que leia uma lista de 10 nomes tal como a segue, e mostre uma lista com todas as pessoas chamada Faria.

Faria, R. M.

Nicolletti, P. S.

Barbosa, A.

Faria, A. G.

Medeiros, O.

Faria. E. F.

Faria, Z. M. M.

Falcão, N. S.

Faria, F. A. M.

Farias, J.

3)      Fazer um programa que leia 10 títulos de filmes com censura e imprima aqueles com censura livre.

Exemplo:

“A BELA ADORMECIDA” “'LIVRE”

“CASANOVA” “18”

“E O VENTO LEVOU” “LIVRE”

etc.

4)      Refazer o programa da lista anterior das notas dos alunos, para listar os nomes da forma inversa. P.ex. HIDAIANE FAYGA MATIAS CALDAS fica sendo CALDAS, HIDAIANE FAYGA MATIAS. Para tal, crie uma subrotina chamada INVERTE_NOME(nom_orig, nom_inv) que recebe o nome original e cria a versão invertida.

Sugestão: Para a subrotina, siga o seguinte algoritmo:

1.      Encontre o tamanho m do nome sem os brancos a direita com LEN_TRIM(nom_orig)

2.      Faça um DO WHILE com incremento -1 a partir de m até a primeira posição “ “ antes da última letra na posição m. Chame esta posição de n.

3.      Monte o nome inverso nom_inv=nom_orig(n+1:m) // “, “ // nom_orig(1:n)