Fortran - błąd przy czytaniu pliku

Fortran - błąd przy czytaniu pliku
0

Kłaniam się, znów mam problem przy języku f90, który jest dla mnie zagadką.
Otóż:
Mam plik z kolumną liczb, przyjmijmy, że jest ich 100. W założeniu podczas wczytania pliku program ma sam policzyć, ile jest liczb, co zostało zaprogramowane.
Deklaruję więc tabelę jednowymiarową T i później określam jej skończoność liczbą i - która jest wynikiem liczenia pozycji.
Później wykonuję prosty zabieg w linii:

Kopiuj
read(1,*) T

Zauważyłam, że program czyta tylko 99 wyrazów, co spowodowane jest tym, że tabela T zostaje zakodowana na 99 pozycji. Przed określeniem wymiaru więc podniosłam liczbę i o jeden (tak, by tabela T miała wymiar stu pozycji). W tym momencie niestety program dostaje samowyrzutki z komunikatem "end of file".
**Problem właściwy: ** Program nie czyta ostatniej liczby w pliku, przy wymiarze tabeli 99 nie ma miejsca na setny wyraz (to rozumiem), a przy wymiarze tabeli 100 program się zatrzymuje z błędem "koniec pliku" (nie rozumiem, czemu).
**Pytanie: ** Jak wprowadzić do programu ostatni wyraz w pliku? (pomijając umieszczenie konkretnej liczby w kodzie)

R3
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 10 godzin
  • Postów:419
0

U mnie działa, tablice a2 i a wypełniają się dziesięcioma liczbami. Dodanie atrybutu iostat do instrukcji read pozwala na zignorowanie błędu eof

Kopiuj
program numbers
implicit none
integer, dimension(:), allocatable :: a
integer, dimension(25):: a2
integer :: fh = 666
integer :: c
allocate(a(25))
a = -1
a2 = -2
open(fh, file="numbers.in", status="old", action="read")
read(fh, *, iostat=c) a
close(fh)
open(fh, file="numbers.in", status="old", action="read")
read(fh, *, iostat=c) a2
close(fh)
print *, a
print *, a2
print *, c
deallocate(a)
end program

zawartość pliku numbers.in

Kopiuj
1
3
6
8
11
32
56
67
435
999
Kopiuj
gfortran numbers.f90 && a.exe
           1           3           6           8          11          32          56          67         435         999          -1          -1          -1          -1          -1          -1          -1          -1          -1          -1          -1          -1          -1          -1          -1
           1           3           6           8          11          32          56          67         435         999          -2          -2          -2          -2          -2          -2          -2          -2          -2          -2          -2          -2          -2          -2          -2
        5008
Kopiuj
gfortran --version
GNU Fortran (rev5, Built by MinGW-W64 project) 4.8.1
0

Błąd faktycznie zniknął, program to "akceptuje", natomiast wciąż nie czyta ostatniej liczby. Po prostu za ostatni wyraz tabeli podstawia zero (choć powinien czytać liczbę "-7").

0

Przepraszam za double, doklejam fragment kodu. Moja tabela ma 145 pozycji.

Kopiuj
real, dimension(:), allocatable ::  T
integer :: n, i, k, stalapotrzebna
character :: znak

open(1, file= "Dane.txt", status="old")
i=1
      do
      call fgetc(1, znak, k)
      if(znak .eq. achar(10) )then
      i=i+1
      else 
      if(k.ne.0) then
           exit
           end if
      end if
      end do
close(1)

allocate( T(i) )

      read(1,*, iostat=stalapotrzebna) T
      close(1)


      write(*,*) "Liczba punktow obserwacyjnych: "
      write(*,*) jjjj
      write(*,*) i, T(144), T(145)

(liczba jjjj jest liczona poprawnie, kod na jej temat pominęłam)
W odpowiedzi na ekranie mam to:
http://screenshot.sh/ou0kyjm5qi9cy

R3
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 10 godzin
  • Postów:419
0

Czytasz po raz drugi z zamkniętego pliku. Sposoby naprawy to ponowne otwarcie pliku lub niezamykanie pliku i przesunięcie aktualnego wskaźnika do pozycji początkowej 0 (fseek)

Kopiuj
!wersja 1
close(1)
allocate( T(i) )
open(1, file= "Dane.txt", status="old")
read(1,*, iostat=stalapotrzebna) T
!wersja 2
!close(1)
allocate( T(i) )
call fseek(1, 0, 0)
read(1,*, iostat=stalapotrzebna) T
0

W morzu linijek przez przypadek nie skopiowałam też tej otwierającej plik po raz drugi (czyli - miałam ustawioną wersję nr 1 od początku). Skasowałam to i wstawiłam linijkę dotyczącą przesunięcia kursora (wersja 2), ale to wciąż nie pomogło. Wyraz ostatni jest zerowy.

Kopiuj
      i=1
      do
      call fgetc(1, znak, k)
      if(znak .eq. achar(10) )then
      i=i+1
      else 
      if(k.ne.0) then
           exit
           end if
      end if
      end do
      allocate( T(i) )     
      call fseek(1, 0, 0)
      k=1
      read(1,*, iostat=stalapotrzebna) T
      close(1)

http://screenshot.sh/m3AcrkAd1ujtA

0

(tak nad i=1 wciąż jest otwieranie pliku przez open)

R3
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 10 godzin
  • Postów:419
0

nie wiem, co się dzieje u ciebie, tutaj program bezproblemowo odczytuje 6 liczb z wejścia https://ideone.com/Qu9PEZ

bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
0

Nie znam fortrana, ale czy wasze pliki mają identyczną budowę? Tzn. czy po ostatniej liczbie jest w pliku znak nowej linii?


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
0

Faktycznie, u mnie w pliku wejściowym po ostatniej liczbie nie było znaku nowej linii (tylko znak końca pliku). Po dostawieniu jednej pustej linii na końcu pliku program już czyta poprawnie cały plik.
Tylko pytanie, czy jet sposób, by to obejść? Nie wiem, w jakiej formie będą później ludzie wstawiać pliki wejściowe, a nie chcę na nich wywierać przymusu, żeby każdy plik danych kończył się pustą linią.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.