Problema em exercicio com fortran [Resolvido]

Iniciado por pedrofearless2106, 02 de Junho de 2014, 17:00

tópico anterior - próximo tópico

pedrofearless2106

Boa tarde pessoals.

Esta semana resolvi ajudar uma colega que tinha a seguinte tarefa: "Escreva um programa que solicite um número octal, que será armazenado em uma variável character. Por exemplo, o usuário entra com o número 377 e o programa converte-o em um número decimal. Estruture o programa para lidar com até 5 dígitos octais (use select case)."
Ok. Até aí tudo bem, fiz e entreguei a ela.
No outro dia ela me falou que seria testado com números binários (como sendo octais), aí começou o problema.
Ela me disse que o professor irá inserir números com zero(s) antes dos outros dígitos, testei o programa nessas condições e quando a entrada é 00101, por exemplo, esse número não é reconhecido como 101. Da forma que o programa está estruturado, nesse caso, a casa da unidade fica igual a '101' (deveria ser 1).
Há alguma forma de transformar o '00101' em '101', para o select case reconhecê-lo corretamente?

Ficarei muito agradecido pela ajuda de vcs.

Documento .f90
https://mega.co.nz/#!tY50jICY!zX0TxfezmpKcZ6aLZdSLbmuKF-XdqwxqothjWuDwQp8


program octtodec
implicit none
!VARIAVEIS
character(len=6) :: oct !Max=77777
character(len=6) :: un, dez, hund, mil, dmil!Unidades, dezenas, centenas, milhar, dezenas de milhar
integer(kind=4) :: dec, ioct !Decimal e octal(inteiro)
integer(kind=4) :: dec1, dec2, dec3, dec4!Variaveis usadas na formula de conversão.
integer(kind=4) :: iu, id, ih, im, idm!Correspondentes inteiros de "un,dez,hund,mil,dmil".


!OBSERVACOES
write(*,"(t8,'OBSERVAÇÕES')")
print*,'Este programa converte um número octal em decimal.'
print*,'Os números octais não admitem 8 ou 9 em nenhuma das suas casas (unidade,dezena,centena...).'
print*,'Este programa admite a entrada de um octal com, no máximo 5 casas.'
print*,'Portanto, o maior valor para o octal será "77777".'
print*,'Sua saída está em forma de tabela, com valores de octal e decimal em suas respectivas colunas.'
print*,''

!ENTRADA
write(*,"(t8,'ENTRADA')")
write(unit=*,fmt=*) "Digite o número octal a ser convertido."
read(unit=*,fmt=*) oct !Octal
read(oct,*) ioct !Le o valor do octal e converte-o para inteiro

!Condicao de entrada (0<=valor<=77777)
do while ((ioct.gt.77777).or.(ioct.lt.0))
print*,'Digite um valor válido (0<=valor<=77777).'
read(unit=*,fmt=*) oct
read(oct,*) ioct
end do

!CALCULOS (processamento)
!inicialização das variáveis inteiras.
iu=0!Unidades
id=0!Dezenas
ih=0!Centenas
im=0!Milhar
idm=0!Dezenas de milhar

!Condicao para separar as casas do numero octal.
select case(ioct)
case(:9)!Caso o octal seja menor ou igual a 9.
un=oct(:1) !A casa das unidades sera a primeira casa da direita.
!read(un,*) iu !Transforma a casa da unidade de character para inteiro.
case(10:99)!Caso o octal esteja no intervalo 10<=octal<=99
un=oct(2:)!A casa das unidades sera a 2º casa da direita.
dez=oct(:1)!A casa das dezenas sera a 1º casa da direita.
!read(un,*) iu
!read(dez,*) id
case(100:999)
un=oct(3:)
dez=oct(2:2)
hund=oct(:1)
!read(un,*) iu
!read(dez,*) id
!read(hund,*) ih
case(1000:9999)
un=oct(4:)
dez=oct(3:3)
hund=oct(2:2)
mil=oct(:1)
!read(un,*) iu
!read(dez,*) id
!read(hund,*) ih
!read(mil,*) im
case default
un=oct(5:)
dez=oct(4:4)
hund=oct(3:3)
mil=oct(2:2)
dmil=oct(:1)
!read(un,*) iu
!read(dez,*) id
!read(hund,*) ih
!read(mil,*) im
!read(dmil,*) idm
end select

print*,un,dez,hund,mil,dmil

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!Transformacao de char para integer
read(un,*) iu!Transforma a casa das unidades de character para inteiro.
if(ioct.gt.9)read(dez,*) id!Transforma a casa das dezenas de character para inteiro.
if(ioct.gt.99)read(hund,*) ih!Transforma a casa das centenas de character para inteiro.
if(ioct.gt.999)read(mil,*) im!Transforma a casa das unidades de milhar de character para inteiro.
if(ioct.gt.9999)read(dmil,*) idm!Transforma a casa das dezenas de milhar de character para inteiro.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
print*,''

print*,ioct
print*,iu
print*,id
print*,ih
print*,im
print*,idm

!Condicao para quando alguma das casas tiver valor maior que 7
if((iu.gt.7).or.(id.gt.7).or.(ih.gt.7).or.(im.gt.7).or.(idm.gt.7)) then
write(*,"(t9,'SAÍDA')")
write(unit=*,fmt="(t2,'Valor inserido = ')",advance='no')
write(unit=*,fmt="(i5)") ioct
if (iu.gt.7)print*,'A casa das unidades não pode ser maior que 7.'

if (id.gt.7)print*,'A casa das dezenas não pode ser maior que 7.'

if (ih.gt.7)print*,'A casa das centenas não pode ser maior que 7.'

if (im.gt.7)print*,'A casa das unidades de milhar não pode ser maior que 7.'

if (idm.gt.7)print*,'A casa das dezenas de milhar não pode ser maior que 7.'
print*,''
print*,'OBS: Na próxima vez, digite um valor válido.'
stop!Caso as condicoes do "if" forem satisfeitas, o programa irá parar.
endif

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!Fórmulas para calcular o octal(poderia ser feito um subprograma baseado em polinomios)
dec1=iu*(8**0)+id*(8**1)
dec2=dec1+ih*(8**2)
dec3=dec2+im*(8**3)
dec4=dec3+idm*(8**4)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!Condição para o calculo do octal
select case(ioct)
case(:7)
dec=ioct
case(10:77)
dec=dec1
case(100:777)
dec=dec2
case(1000:7777)
dec=dec3
case (10000:)
dec=dec4
end select

!SAIDA na tela
write(*,"(t9,'SAÍDA')")
1 format (21('='))!Escreve 21 sinais "="
2 format ('|',t4,'Octal',t11,'|',t13,'Decimal',t21,'|')!Para escrever as palavras e strings "|" do titulo da tabela.
3 format ('|',t3,i6,t11,'|',t13,i6,t21,'|')!Para escrever os valores e os strings "|"
4 format ('|',t11,'|',t21,'|')!Para escrever os strings "|", o 1º colado no lado esquerdo do terminal, o 2º e o 3º 11 e 21 espacos depois.
write(unit=*,fmt=1)
write(unit=*,fmt=2)
write(unit=*,fmt=1)
write(unit=*,fmt=4)
write(unit=*,fmt=3) ioct, dec!Escreve os valores do octal e seu equivalente decimal de acordo com o formato 3
write(unit=*,fmt=4)
write(unit=*,fmt=1)

end program



pedrofearless2106

#1
Olá pessoals, boa noite (ou dia).
Consegui resolver esse problema, depois de pensar um pouco mais.
Adicionei as variáveis i, j e test. Adicionei também um loop para análise dos dígitos do valor inserido (1ª caixa de ! - fica bem alinhado aqui no editor).
Mudei o select case de separação dos dígitos, agora ficou em função de j. Ainda não testei todas as possibilidades, mas creio que ele está certo.
Muito obrigado a todos os que visualizaram o post.

Caso queiram testar, segue o documento f90.
https://mega.co.nz/#!EBAxFTBJ!W63_eqaankRtuT7rHpKY5GQ6TLhJl4URmEr305m6ums

OBS: Se ainda não tem familiaridade com a linguagem Fortran, no linux (pelo terminal) compila-se assim:

  • Digita-se: gfortran(ou ifort) <caminho do .f90> -o <caminho do .x>
    Ex: gfortran ./octtodec.f90 -o ./octtodec.x
  • Executa-se assim: <caminho do .x>
    Ex: ./octtodec.x (o "./" significa diretório atual)


program octtodec
implicit none
!VARIAVEIS
character(len=6) :: oct !Max=77777
character(len=1) :: un, dez, hund, mil, dmil !Unidades, dezenas, centenas, milhar, dezenas de milhar
character(len=1) :: test !Variavel para analise inicial dos dígitos
integer :: dec, ioct !Decimal e octal(inteiro)
integer :: dec1, dec2, dec3, dec4 !Variaveis usadas na formula de conversão.
integer :: i, j !Contadores usados no 'desmembramento' dos dígitos.
integer :: iu, id, ih, im, idm !Correspondentes inteiros de "un,dez,hund,mil,dmil".


!OBSERVACOES
write(*,"(t8,'OBSERVAÇÕES')")
print*,'Este programa converte um número octal em decimal.'
print*,'Os números octais não admitem 8 ou 9 em nenhuma das suas casas (unidade,dezena,centena...).'
print*,'Este programa admite a entrada de um octal com, no máximo 5 casas.'
print*,'Portanto, o maior valor para o octal será "77777".'
print*,'Sua saída está em forma de tabela, com valores de octal e decimal em suas respectivas colunas.'
print*,''

!ENTRADA
write(*,"(t8,'ENTRADA')")
write(unit=*,fmt=*) "Digite o número octal a ser convertido."
read(unit=*,fmt=*) oct !Octal
read(oct,*) ioct !Le o valor do octal e converte-o para inteiro

!Condicao de entrada (0<=valor<=77777)
do while ((ioct.gt.77777).or.(ioct.lt.0))
print*,'Digite um valor válido (0<=valor<=77777).'
read(unit=*,fmt=*) oct
read(oct,*) ioct
end do

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!Analise dos dígitos  !
j=0  !
do i=1,5  !
test=oct(i:i)!Analisa e conta os dígitos.  !
select case(test)!Select case por character.  !
case('0','1','2','3','4','5','6','7','8','9')!Estão incluidos 8 e 9, para o "if" posterior ser executado. !
j=j+1!Conta o número de dígitos que o número possui.  !
end select  !
end do  !
print*,''  !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!CALCULOS (processamento)
!inicialização das variáveis inteiras.
iu=0!Unidades
id=0!Dezenas
ih=0!Centenas
im=0!Milhar
idm=0!Dezenas de milhar

!Condicao para separar as casas do numero octal. Ordem de oct(n:n) da esquerda para a direita.
!Ainda são do tipo character.
select case(j)
case(1)!Se j=1.
un=oct(1:1)
case(2)
un=oct(2:2)
dez=oct(1:1)
case(3)
un=oct(3:3)
dez=oct(2:2)
hund=oct(1:1)
case(4)
un=oct(4:4)
dez=oct(3:3)
hund=oct(2:2)
mil=oct(1:1)
case(5)!Se j=5.
un=oct(5:5)
dez=oct(4:4)
hund=oct(3:3)
mil=oct(2:2)
dmil=oct(1:1)
end select

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!Transformacao de character para integer
read(un,*) iu!Transforma a casa das unidades de character para inteiro.
if(j.ge.2)read(dez,*) id!Transforma a casa das dezenas de character para inteiro.
if(j.ge.3)read(hund,*) ih!Transforma a casa das centenas de character para inteiro.
if(j.ge.4)read(mil,*) im!Transforma a casa das unidades de milhar de character para inteiro.
if(j.ge.5)read(dmil,*) idm!Transforma a casa das dezenas de milhar de character para inteiro.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
print*,''

!Cálculo do valor octal a partir das variaveis "desmembradas". Para eliminar os zeros e/ou espaços da esquerda.
ioct=(idm*(10**4))+(im*(10**3))+(ih*(10**2))+(id*(10**1))+(iu*(10**0))

!Condicao para quando alguma das casas tiver valor maior que 7
if((iu.gt.7).or.(id.gt.7).or.(ih.gt.7).or.(im.gt.7).or.(idm.gt.7)) then
write(*,"(t9,'SAÍDA')")
write(unit=*,fmt="(t2,'Valor inserido = ')",advance='no')
write(unit=*,fmt="(i5)") ioct
if (iu.gt.7)print*,'A casa das unidades não pode ser maior que 7.'

if (id.gt.7)print*,'A casa das dezenas não pode ser maior que 7.'

if (ih.gt.7)print*,'A casa das centenas não pode ser maior que 7.'

if (im.gt.7)print*,'A casa das unidades de milhar não pode ser maior que 7.'

if (idm.gt.7)print*,'A casa das dezenas de milhar não pode ser maior que 7.'
print*,''
print*,'OBS: Na próxima vez, digite um valor válido.'
print*,''
stop!Caso as condicoes do "if" forem satisfeitas, o programa irá parar.
endif

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!Fórmulas para calcular o octal(poderia ser feito um subprograma baseado em polinomios)
dec1=iu*(8**0)+id*(8**1)
dec2=dec1+ih*(8**2)
dec3=dec2+im*(8**3)
dec4=dec3+idm*(8**4)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
dec=0!Inicialização do decimal. Creio que não seja necessário.
!Condição para o calculo do octal
select case(ioct)
case(:7)!Se o valor inserido "ioct" for menor ou igual a 7.
dec=ioct
case(10:77)
dec=dec1
case(100:777)
dec=dec2
case(1000:7777)!Se 1000<=ioct<=7777
dec=dec3
case (10000:)!Se ioct>=10000
dec=dec4
end select

!SAIDA na tela
write(*,"(t9,'SAÍDA')")
1 format (21('='))!Escreve 21 sinais "="
2 format ('|',t4,'Octal',t11,'|',t13,'Decimal',t21,'|')!Para escrever as palavras e strings "|" do titulo da tabela.
3 format ('|',t3,i6,t11,'|',t13,i6,t21,'|')!Para escrever os valores e os strings "|"
4 format ('|',t11,'|',t21,'|')!Para escrever os strings "|", o 1º colado no lado esquerdo do terminal, o 2º e o 3º 11 e 21 espacos depois.
write(unit=*,fmt=1)
write(unit=*,fmt=2)
write(unit=*,fmt=1)
write(unit=*,fmt=4)
write(unit=*,fmt=3) ioct, dec!Escreve os valores do octal e seu equivalente decimal de acordo com o formato 3
write(unit=*,fmt=4)
write(unit=*,fmt=1)

end program