2016-06-12 5 views
0

나는 성격과 실수가 모두 포함 된 매트릭스를하고 난이 행렬을 읽고 (자체 크기를 찾습니다) 프로그램을 원한다. 내 행렬의 크기에 대한 내가 가진이 코드 (3,2)와매트릭스의 치수를 찾는 방법은 무엇입니까?

a b 13 15.5 13.2 
c d 16 16.75 19 
e f 19.2 12.2 18.2 

:

! A fortran95 program for G95 
Program Project2nd 
implicit none 
character(len=40), allocatable :: a(:,:) 
integer i,j,k,n,m,l,st 
character(len=40) d 
n=0; m=1; j=1; 

open(10,file=& 
'/Users/dariakowsari/Documents/Physics/Programming/Fortran95-Projects/Project2nd/input.txt', & 
    IOstat=st) 

do while (st == 0) 
    read(10,*,IOstat=st) d 
    n=n+1 
end do 

st=0 
do j=1,m 
    do while (st == 0) 
    allocate(a(1,m)) 
     read(10,*,IOstat=st) (a(1,j),j=1,m) 
      m=m+1 
     deallocate(a) 
end do 

print*, n,m 


end 

여기 내 매트릭스입니다 : 여기 내 코드입니다.

+1

당신의 코드는 실제로 세 줄을 계산합니다. m은 1로 초기화되고 iostat 오류 (단순히 파일의 끝임)와 관계없이 두 번째 루프에서 증가하기 때문에 m에 대해 2를 얻습니다. 조금은 제쳐두고,하지만 열려있는 성명서에 iostat을 지정하고 값을 확인하는 일은하지 않는 것이 좋지 않습니다. – agentp

+0

파일을 열기 전에 파일 내용에 대해 무엇을 알고 있습니까? 항상 2 (분리 된) 단일 문자 요소 뒤에 3 (숫자, 실제) 요소가 오는'n' (알려지지 않은) 행으로 구성되어 있습니까? –

+0

@High Performance Mark 우리는 행렬에 문자와 정수가 모두 들어 있다는 것을 알고 있습니다. 문자 및 m 열 정수를 포함하는 n 개의 열을 가질 수 있습니다. –

답변

1

은 나를 위해 컴파일되지 않지만 몇 가지 변경 후 내가 당신에게 유사한 결과를 얻을 수 있었다 의미 귀하의 예제 코드에서 몇 가지 오류가 있습니다. * 업데이트 내 다른 (지금 삭제) 대답 코멘트에 @francescalus에서 언급 한 바와 같이, 그 접근 방식은 정의되지 않은 동작을 포함하고 같은 적절한 해결책이 아니다. 이것은 파일보다 더 많은 엘리먼트를 읽는 것으로부터 발생했다.)

다음은이 정의되지 않은 동작을하지 말아주세요 다른 방법,하지만 아마도 매우 비효율적이다. 당신이 줄 수를 카운트했다으로

Program Project2nd 
    implicit none 
    character(len=40), allocatable :: a(:) 
    integer, allocatable :: ind(:) 
    integer, parameter :: maxElements = 100 
    integer i,j,n,m,st 
    character(len=40) d 
    n=0; 

    open(10,file='mat.txt',IOstat=st) 
    !Find number of lines 
    do while (st == 0) 
    read(10,*,IOstat=st) d 
    if(st ==0) n=n+1 
    end do 
    !Move back to the start of the file 
    rewind(10) 

    !Read all of the data 
    do m=n,maxElements,n 
    allocate(a(m)) 
    read(10,*,IOstat=st) a 
    deallocate(a) 
    rewind(10) 
    if(st.ne.0) exit 
    enddo 
    m = m -n !Need to roll back m by one iteration to get the last which worked. 
    if(mod(m,n).ne.0) then 
    print*,"Error: Number of elements not divisible by number of rows." 
    stop 
    endif 
    !Number of columns = n_elements/nrow 
    m=m/n 
    print*, n,m 
end Program Project2nd 

는 기본적으로이 그러나 읽기 (즉, 일 == 0) 성공시에만 N을 증가 할주의, 동일한 코드를 사용합니다. st가 0이 아니 자마자 블록을 종료하지 않는다는 것을 유의하십시오. 일단 블록이 끝나면 끝이납니다. 그 다음에는 파일을 되 감아 파일 시작 부분에서 다음 읽기가 시작되도록해야합니다. 당신은 당신이 정말로 다음

여기
st = 0 ; m = n 
    do while (st==0) 
    allocate(a(m)) 
    read(10,*,IOstat=st) a 
    deallocate(a) 
    rewind(10) 
    if(st.ne.0) then 
     m = m - n !Go back to value of m that worked    
     exit 
    endif 
    m=m+n 
    enddo 
+1

은 답변이 서로 다른 두 가지 답변입니까?단순히 답을 수정/개선하는 경우 새로운 답을 게시하는 대신 편집해야합니다. 여기 두 개는 거의 동일하게 보이므로 오래된 것을 지워야합니다. – agentp

+0

@agentp 감사합니다. 나는 무엇이 적절했는지 확신 할 수 없었습니다. 중요한 의미의 정의를 위해 대답을 수정하는 것에 대한 논쟁을 들었습니다. –

+0

@roygivb 감사합니다. 방금 편집을하는 동안 발견했습니다! 원본 답안을 잘못 삭제해야한다고 생각합니다. 이 버전은 (잘하면) 정확해야하며 원래 게시물의 주요 내용을 포함하도록 편집했습니다. –

1

승 수행하는 방법처럼 뭔가 두 번째 do 루프를 교체이를 방지하려는 경우 오히려 maxElement을 지정할 필요가 없습니다 거라고 언급 이전 코멘트에서

/o 되감기.

implicit none 
    character(len=100) wholeline 
    character(len=20), allocatable :: c(:) 
    integer iline,io,ni,nums 
    open(20,file='testin.dat') 
    iline=0 
    do while(.true.) 
    read(20,'(a)',iostat=io)wholeline 
    if(io.ne.0)exit 
    iline=iline+1 
    ni=lineitems(wholeline) 
    allocate(c(ni)) 
    read(wholeline,*)c 
    nums=ctnums(c) 
    write(*,*)'line',iline,' contains ',ni,'items',nums, 
$  'are numbers' 
    deallocate(c) 
    enddo 
    write(*,*)'total lines is ',iline 
    contains 

    integer function ctnums(c) 
    ! count the number of items in a character array that are numbers 
    ! this is a template, 
    ! obviously you could assign the numbers to a real array here 
    character(len=*), allocatable :: c(:)  
    real f 
    integer i,io 
    ctnums=0 
    do i = 1,size(c) 
    read(c(i),*,iostat=io)f 
    if(io.eq.0)ctnums=ctnums+1 
    enddo 
    end function 

    integer function lineitems(line) 
    ! count the number of items in a space delimited string 
    integer,parameter ::maxitems=100 
    character(len=*) line 
    character(len=80) :: c(maxitems) 
    integer iline,io 
    lineitems=0 
    do iline=1,maxitems 
    read(line,*,iostat=io)c(:iline) 
    if(io.ne.0)return 
    lineitems=iline 
    enddo 
    if(lineitems.eq.maxitems)write(*,*)'warning maxitems reached' 
    end function 
    end 

출력

line 1 contains 5 items 3 are numbers 
line 2 contains 5 items 3 are numbers 
total lines is 2