Code:
program evenodd
implicit none
character(32767) :: inp
integer(4) :: tmp,oddCnt = 0,evenCnt = 0
integer(4), allocatable :: allVals(:)
integer(2) :: st,numVals = 0
logical :: keepReading
open(unit=9,file='./myInput.txt')
keepReading = .true.
do while(keepReading)
read(9,'(a)',iostat=st) inp
if(st < 0) then
keepReading = .false.
else
call countLine()
endif
enddo
oddCnt = count(btest(allVals(1:numVals),0))
evenCnt = numVals - oddCnt
write(6,'("Num even: ",i5," Num odd: ",i5)') evenCnt,oddCnt
contains
subroutine countLine()
implicit none
integer(2) :: stpos = 1,endpos
inp=trim(adjustl(inp))
if(len_trim(inp) == 0) return
do while(.true.)
if(index(inp(1:len_trim(inp)),' ') > 0) then
endpos=index(inp,' ')
else
endpos=len_trim(inp)
endif
read(inp(stpos:endpos),'(i13)',iostat=st) tmp
if(st == 0) call addVal(tmp)
if(endpos == len_trim(inp)) exit
inp=trim(adjustl(inp(endpos+1:)))
enddo
end subroutine countLine
subroutine addVal(x)
implicit none
integer(4), intent(in) :: x
integer(4), allocatable :: tmpStore(:)
if(.not. allocated(allVals)) allocate(allVals(8))
if(size(allVals) < numVals + 1) then
if(allocated(tmpStore)) deallocate(tmpStore)
allocate(tmpStore(size(allVals)))
tmpStore=allVals
deallocate(allVals)
allocate(allVals(size(tmpStore)*4))
allVals=tmpStore
deallocate(tmpStore)
endif
numVals = numVals + 1
allVals(numVals) = x
end subroutine addVal
end program evenodd
This isn't the cleanest... but it's not for work, etc. so i'm not that concerned.
I did it with an allocatable array, even though for this purpose there is no reason to keep all values in memory, you can do the test an item at a time. I did it this way because you asked me not to, and this sounds like an assignment. Now if you try to turn this in unaltered, you won't be able to explain the (presumably uncovered) use of allocatables, etc. I have a very similar version that just does the count an item at a time, but don't want to post it in a manner that you could just turn it in.
This isn't rigorously tested. I used the following file and it seemed to work, skipping invalid values silently:
Code:
1 2 34 998 3 1 4
2 4
3
6
77789 908 8 9 7 5
asdf tr 4 9 2
3 4 3 9 1 3 4 2 1 34 90 ad 4
5 9 1
If you have more questions, please ask, but if this is homework please say so to begin with.
-Lee
EDIT: Please excuse the do while(.true.). I hate code like that, but using cycle/exit is easier, if a little dirtier. Sorry.
EDIT 2: I thought i'd mention a design compromise i made. To simplify the logic in determining where the next value to read is, i made a sacrifice of execution time. This:
Code:
inp=trim(adjustl(inp(endpos+1:)))
Is going to take some time to do, memory manipulation, etc. There's not a need to do this, but tracking both start and end position, and doing all of the slicing to achieve this, etc. was going to require too much brain power. If execution time is of critical importance, you could change the algorithm to do this with the line "fixed" with no modifications.
EDIT 3: Bah, forget some things i wanted to mention. Company has been in town, i've been working on this on and off for the last two days, etc. What i wanted to add was that splitting up a string like this is best to have in a library that you can always use. At work we have something that will return the pointer to an array that's allocated to the appropriate size, with each item as an element. With something like that, it would be easy to just take each line, split it with that, and act on each element. Same goes for the code to add an element to an allocatable array. It's best to have one for each type, preferably with an interface so you can call the same name for all of your types, that just takes the current item count, the allocatable, and the value to add. I only implemented these things here since you wouldn't have them in a library.