0

UPDATE: Please see below the EDITS made to this post! The post itself will remain the original one for the sake of keeping with the logic of the discussion!


I'm trying to write a test program that opens a user-specified filename - containing two data columns and a line describing how many lines (after that line) contain data, so it may generate two arrays with that specific size to read and write it. The specified file structure is depicted below in this answer. I've been using the ideas laid out here to create variable size arrays:

    program char
    implicit none
    character(len = 200)  :: filename;
    integer :: line_number;


    print*,'What is the file name?'
    read(*,*) filename
    print*, 'the file is: ',filename
    open(1,file=filename, status = 'old')
    read(1,*)line_number
    call read_data(line_number)
    end program char

     subroutine read_data(N)
     implicit none
     integer, intent (in) :: N;
     integer :: imax, i;
     real,dimension(N) :: a,b;

     imax=N+1
     do i=2,imax
      read(1,*)a(i),b(i)
      write(1,*)a(i),b(i)
     end do

     end subroutine read_data

My test file is called 'matrix.dat' (which I do not wish to hardcode in the file!) and has the following structure, as mentioned previously: first line describes the number of lines of the matrix, the remaining lines are data columns separated solely by a space.

9
1.0 1.1
2.0 2.2
3.0 3.3
4.0 4.4
5.0 5.5
6.0 6.6
7.0 7.7
8.0 8.8
9.0 9.9

During compilation, the compiler churns out some rather unusual errors, which I do not understand.

 Strelok@Yggdrasil:~$ gcc char.f95 -o char.exe
/usr/bin/ld: /tmp/cciriF9x.o: in function `read_data_':
char.f95:(.text+0x105): undefined reference to `_gfortran_st_read'
/usr/bin/ld: char.f95:(.text+0x135): undefined reference to `_gfortran_transfer_real'
/usr/bin/ld: char.f95:(.text+0x165): undefined reference to `_gfortran_transfer_real'
/usr/bin/ld: char.f95:(.text+0x174): undefined reference to `_gfortran_st_read_done'
/usr/bin/ld: char.f95:(.text+0x1af): undefined reference to `_gfortran_st_write'
/usr/bin/ld: char.f95:(.text+0x1df): undefined reference to `_gfortran_transfer_real_write'
/usr/bin/ld: char.f95:(.text+0x20f): undefined reference to `_gfortran_transfer_real_write'
/usr/bin/ld: char.f95:(.text+0x21e): undefined reference to `_gfortran_st_write_done'
/usr/bin/ld: /tmp/cciriF9x.o: in function `MAIN__':
char.f95:(.text+0x295): undefined reference to `_gfortran_st_write'
/usr/bin/ld: char.f95:(.text+0x2b0): undefined reference to `_gfortran_transfer_character_write'
/usr/bin/ld: char.f95:(.text+0x2bf): undefined reference to `_gfortran_st_write_done'
/usr/bin/ld: char.f95:(.text+0x2fa): undefined reference to `_gfortran_st_read'
/usr/bin/ld: char.f95:(.text+0x318): undefined reference to `_gfortran_transfer_character'
/usr/bin/ld: char.f95:(.text+0x327): undefined reference to `_gfortran_st_read_done'
/usr/bin/ld: char.f95:(.text+0x362): undefined reference to `_gfortran_st_write'
/usr/bin/ld: char.f95:(.text+0x37d): undefined reference to `_gfortran_transfer_character_write'
/usr/bin/ld: char.f95:(.text+0x39b): undefined reference to `_gfortran_transfer_character_write'
/usr/bin/ld: char.f95:(.text+0x3aa): undefined reference to `_gfortran_st_write_done'
/usr/bin/ld: char.f95:(.text+0x421): undefined reference to `_gfortran_st_open'
/usr/bin/ld: char.f95:(.text+0x45c): undefined reference to `_gfortran_st_read'
/usr/bin/ld: char.f95:(.text+0x47a): undefined reference to `_gfortran_transfer_integer'
/usr/bin/ld: char.f95:(.text+0x489): undefined reference to `_gfortran_st_read_done'
/usr/bin/ld: /tmp/cciriF9x.o: in function `main':
char.f95:(.text+0x4bb): undefined reference to `_gfortran_set_args'
/usr/bin/ld: char.f95:(.text+0x4cc): undefined reference to `_gfortran_set_options'
collect2: error: ld returned 1 exit status

Any help would be greatly appreciated. Also, if anyone can provide me with a way of having the program evaluate the columns sizes automatically instead of having me declare it a priori, I would be most grateful!


EDIT #1: Following @Swift - Friday Pie suggestion, I recompiled using gfortran, and it compiled fine. HOWEVER, upon execution of the file, I got the following error message:


strelok@Yggdrasil:~$ gfortran char.f95 -o char.exe
strelok@Yggdrasil:~$ ./char.exe
What is the file name?
matrix.dat
the file is: matrix.dat                                                                                                                                                                                          
At line 23 of file char.f95 (unit = 1, file = 'matrix.dat')
Fortran runtime error: End of file

Error termination. Backtrace:
#0  0x7faccc5c0d0a
#1  0x7faccc5c1819
#2  0x7faccc5c24ef
#3  0x7faccc802b3b
#4  0x7faccc7fbcf6
#5  0x7faccc7fcc99
#6  0x55f77a465341
#7  0x55f77a4656a4
#8  0x55f77a4656dd
#9  0x7faccc3d60b2
#10  0x55f77a46514d
#11  0xffffffffffffffff

EDIT #2: Source code has been modified, as suggested by @albert and @Ian Bush. It should now read as depicted below.

program char
implicit none
character(len = 200)  :: filename;
integer :: line_number;


print*,'What is the file name?'
read(*,*) filename
print*, 'the file is: ',filename
open(10,file=filename, status = 'old')
read(10,*)line_number
call read_data(line_number)
end program char

 subroutine read_data(N)
 implicit none
 integer, intent (in) :: N;
 integer :: imax, i;
 real,dimension(N) :: a,b;
 read(10,*)
 do i=1,N
  read(10,*) a(i),b(i)
  write(*,*) a(i),b(i)
 end do

 end subroutine read_data

Compilation errors are gone, but during execution of the program, there's an error:

strelok@Yggdrasil:~$ ./char.exe
 What is the file name?
matrix.dat
 the file is: matrix.dat                                                                                                                                                                                          
   1.00000000       1.10000002
At line 22 of file char_original.f95 (unit = 10, file = 'matrix.dat')
Fortran runtime error: End of file

Error termination. Backtrace:
#0  0x7f714b51dd0a
#1  0x7f714b51e819
#2  0x7f714b51f4ef
#3  0x7f714b75fb3b
#4  0x7f714b758cf6
#5  0x7f714b759c99
#6  0x55bb2ff56382
#7  0x55bb2ff566e5
#8  0x55bb2ff5671e
#9  0x7f714b3330b2
#10  0x55bb2ff5614d
#11  0xffffffffffffffff
Strelok
  • 189
  • 9
  • 2
    Hardly qualifies as a disaster. Nobody was killed. Not even kittens :-) – Stephen C Aug 22 '20 at 08:04
  • What I do not understand is why is my question - which is valid - immediately downvoted! – Strelok Aug 22 '20 at 08:07
  • Pass ... wasn't me. (Though it smells like it be a problem with the way you are compiling / linking the code, rather than the code itself.) – Stephen C Aug 22 '20 at 08:11
  • 3
    use `gfortran` to compile\link, otherwise you're missing a lot of arcane settings required to link with the proper run-time – Swift - Friday Pie Aug 22 '20 at 08:26
  • Thanks, I'll edit and repost any results! – Strelok Aug 22 '20 at 08:46
  • 1
    smells a bit like not enough data in the file, Why reading and writing to the same file (unit 1), file will be truncated.. when reading you are storing in the elements 2...10 whilst the arrays `a` and `b` have only the elements 1 .. 9. Furthermore don't use the low unit numbers (rule of thumb start with 10) as lower units might be in use for other things like (in C terms) 'stdout', 'stdin'. – albert Aug 22 '20 at 09:00
  • Ok, so, apparently the problem is really in how it reads - and writes - the corresponding values from the file itself. – Strelok Aug 22 '20 at 09:13
  • 1
    Why are you writing the output on the same unit number as that from which you read the input? Also as written the code will make out of bounds array accesses when i=imax=N+1 – Ian Bush Aug 22 '20 at 09:50
  • Was trying to skip the first line! – Strelok Aug 22 '20 at 09:58

1 Answers1

0

After several trial and error, and thanks to the precious comments made here, I was able to make the program work correctly! This trial and error was hampered by my carelessness - I didn't check matrix.dat , despite being told it may be overwritten - and it has! The posterior problems were created due to bad formatting of the file, and not the program itself. Here's the cleaned code! Thank you all!

  program char
  implicit none
  character(len = 200)  :: filename
  integer :: line_number

   print*,'What is the file name?'
   read(*,*) filename
   print*, 'the file is: ',filename
   open(10,file=filename, status = 'old')
   read(10,*)line_number
   call read_data(line_number)
  end program char

  subroutine read_data(N)
  implicit none
  integer, intent (in) :: N
  integer :: i, ios
  real,dimension(N) :: a,b

   do i=1,N
    read(10,'(2f3.2)',iostat=ios) a(i),b(i)
    if (ios /=0) print*,'Reading ERROR!'
    write(*,*) a(i),b(i)
   end do
  end subroutine read_data
Strelok
  • 189
  • 9
  • 1
    On a side note, my advice is to not be stingy with the indentations in your code. The exact size of indentation is highly opinionated but 4 seems be universal and ideal for many. and there is no worry about the maximum line length. Compilers already support virtually-infinite line length, and the next Fortran standard will make infinite line length officially part of the language. – Scientist Aug 22 '20 at 17:15
  • 1
    I'd also use Allocatable arrays for dynamically size objects, and it is good practice to make sure you have an interface in scope when you call a subprogram - which to first order means stick all subprograms in a module – Ian Bush Aug 22 '20 at 20:00