Ajuda necessidade ALLOCATABLE matriz em Fortran
-
03-07-2019 - |
Pergunta
Eu realmente estou tendo problemas com variedade ALLOCATABLE.
Eu tenho que copiar todas as informações de um arquivo em conjunto allocatable. O arquivo é assim:
3
3 5
2 1
4 0
3 é o número de pontos outros mostra pontos de seis números no gráfico em (x, y) forma. Então, (3,5), (2, 1), (4,0) são os pontos. Mas eu tenho problema de fazer esses números como um par.
Eu tentei código, e aqui é a minha codificação:
PROGRAM practice
IMPLICIT NONE
INTEGER :: astat, ioStatus
INTEGER :: x, y
INTEGER :: num, code1, code2, code3, code4, code5, code6
! num shows number of location. in this case 3
! code 1 to 6 shows x and y variable. and code1 and 2 have to be paired.
! as well as this, code 3 and 4, code 5 and 6 have to be paired
! Declare TYPE
! set 1 to 3 show pair of (x, y)
TYPE Location
INTEGER :: set1, set2, set3
INTEGER :: num_locations
END TYPE
! Array ()
! for number of locations to visit
TYPE(Location), DIMENSION(:) :: numLocationArray(1000)
! allocatable array
! For locations
TYPE(Location), DIMENSION(:, :) :: LocationArray
ALLOCATABLE :: LocationArray
! allocate LocationArray
ALLOCATE(LocationArray(x, y), STAT = astat)
IF (astat < 0) STOP "allocate failed"
! open input file to copy info into array
OPEN (UNIT = 10, File ="input.txt", STATUS = "OLD", ACTION = "READ", &
IOSTAT = ioStatus)
IF (ioStatus < 0) STOP "open failed"
! format of the file
100 FORMAT (I1, /, 2I2, /, 2I2, / 2I2)
! Do loop to set table
DO x = 0, size(LocationArray), 1
READ (UNIT = 10, FMT = 100, IOSTAT = ioStatus) num, code1, code2, &
code3, code4, code5, code6
! check whether program read file correctly (option)
PRINT *, num, code1, code2, code3, code4, code5, code6
IF (x == code1) THEN
DO y = 0, size(LocationArray), 1
IF (y == code2) THEN
LocationArray%set1 = LocationArray(x, y)
! check whether copied correctly
PRINT *, LocationArray(x, y)
PRINT *, LocationArray%set1
END IF
END DO
END IF
END DO
! ==============
! execution part
! ==============
! instructions:
! use pointer to do excecution
! read allocatable array above
! do excecution (distance) ** do not forget to go back to the original place (0,0)
! ** do not forget to try every single possible way
! when get total distance, do distance times 2 and figure out cost
! print all info (cost, distance, and steps)
! (example of output)
! The minimum cost is 36
! The distance travelled is 18
! Step 1: Start at ( 0, 0)
! Step 2: Goes to ( 2, 1)
! Step 3: Goes to ( 3, 5)
! Step 4: Goes to ( 4, 0)
! Step 5: Ends at ( 0, 0)
END PROGRAM
Este programa não funciona ... Eu tenho um erro:
LocationArray%set1 = LocationArray(x, y)
Error: Can't convert TYPE(location) to INTEGER(4) at (1)
Eu cansei de descobrir este erro, mas eu não podia Alguém qualquer conselho ou sugestão sobre a minha codificação?
Perdoe meu Inglês, eu sou japonês.
Se alguém tem dúvidas sobre minha pergunta (eu quero dizer necessidade de mais explicação), por favor me avise.
Obrigado. Uka
Solução
Na definição do tipo Location
, você disse que set1, set2, e set3 são inteiro variáveis, então você tentar atribuir um array a ele. Eu acho que o que você quer, uma vez que estes são pares, é ter set1, set2, e SET3 ser um array de inteiros de tamanho 2.
E se você alterar o tipo Location
a ser:
TYPE Location
INTEGER, DIMENSION(2) :: set1, set2, set3
INTEGER :: num_locations
END TYPE
Além disso, o loop para ler os dados não faz sentido para mim. Eu acho que eu escrevê-lo como (note que os arrays em Fortran são 1-base por padrão, não baseado em zero como em C):
DO x = 1, size(numLocationArray), 1
READ (UNIT = 10, FMT = 100, IOSTAT = ioStatus) num, code1, code2, &
code3, code4, code5, code6
! check whether program read file correctly (option)
PRINT *, num, code1, code2, code3, code4, code5, code6
numLocationArray(x)%num_locations = num
numLocationArray(x)%set1(0) = code1
numLocationArray(x)%set1(1) = code2
numLocationArray(x)%set2(0) = code3
numLocationArray(x)%set2(1) = code4
numLocationArray(x)%set3(0) = code5
numLocationArray(x)%set3(1) = code6
END DO
Você, obviamente, precisa fazer algo para detectar e lidar com o fim da condição de arquivo também.
Se o número de locais é verdadeiramente varaible, então você precisa fazer algo como:
TYPE Coordinate
INTEGER :: x
INTEGER :: y
END TYPE
TYPE Locations
TYPE(Coordinate), DIMENSION(:), ALLOCATABLE :: location
INTEGER :: num_locations
END TYPE
TYPE(Location), DIMENSION(:) :: numLocationArray(1000)
! open input file to copy info into array
OPEN (UNIT = 10, File ="input.txt", STATUS = "OLD", ACTION = "READ", &
IOSTAT = ioStatus)
IF (ioStatus < 0) STOP "open failed"
! format of the file
100 FORMAT (I1 )
200 FORMAT (2I2)
DO n = 1, size(numLocationArray), 1
READ (UNIT = 10, FMT = 100, IOSTAT = iostatus) num
numLocationArray(n)%num_locations = num
ALLOCATE (numLocationArray(n)%locations(num), STAT = astat)
if (astat < 0) STOP 'allocate failed'
DO l = 1, num, 1
READ (UNIT = 10, FMT = 200, IOSTAT = iostatus) x, y
numLocationArray(n)%locations(l)%x = x
numLocationArray(n)%locations(l)%y = y
END DO
END DO
Outras dicas
Parece que você está tentando dar um inteiro o valor de dois inteiros. É algo como você tenta fazer = (ou var = 5,5).