Fortran調用函數變量陷阱

Fortran函數調用之“變量”陷阱


    最近筆者迫於應試壓力強行修煉了一波“Fortran”編程,在編程過程中發現了一些讓初學者猝不及防的陷阱,在此分享一下。

  I  fortran函數編程不同於C/C++、Java之處的幾個要點:    

在這裏總結幾個Fortran編程是需要注意的幾個要點:

1、當調用含參函數時,必須給參數聲明類型,這是必須的
2、當使用循環變量進行循環處理時,必須聲明循環變量爲integer類型
3、函數名代表函數的函數體內返回值,不論是在被調函數體內,還是在主調程序體內都必須聲明以
函數名命名的返回值變量的(即聲明函數的返回值類型),主調程序中用關鍵詞 external修飾被調函數
聲明的格式形如:
		real fun
		external fun

    II 當調用fortran函數時,我們必須爲函數的參數在參數體內聲明類型後才能使用,不同於C/C++、Java在參數括號中直接聲明,但有一個更顯著的問題所在,在Fortran函數中聲明並賦處置的變量在主調函數的連續調用中的值不會隨着再次調用而重新初始化,看例:

!  paractise.f90 
!
!  FUNCTIONS:
!	paractise      - Entry point of console application.
!
!	Example of displaying 'Hello World' at execution time.
!

!****************************************************************************
!
!  PROGRAM: paractise
!
!  PURPOSE:  Entry point for 'Hello World' sample console application.
!
!****************************************************************************

	program paractise

	implicit none
	
	integer days, times, i
	real, allocatable ::averTemp(:)
	real fun
	external fun

	print *, "請輸入天數:"
	read *, days
	print *, "請輸入每天的時段數:"
	read *, times

	allocate(averTemp(days))

	
	do i = 1, days
		averTemp(i) = fun(times)
	end do

	print*, "每天的各個時段的平均溫度:"
	do i = 1, days
		print *, averTemp(i)
	end do

	stop
	end program paractise

	function fun(times)
	implicit none
		integer i, times		!聲明函數參數的類型,this is necessary	
		real fun				!聲明函數的返回值類型, this is necessary too
		real, allocatable ::timesinfo(:)
		real ::sum = 0			!請關注這裏!!!!!

		print *, "輸出一下sum的值:", sum
		

		allocate(timesinfo(times))
		print *, "請輸入", times, "個時次的溫度:"
		read *, timesinfo
	
		do i = 1, times
			sum = sum + timesinfo(i)
		end do
		fun = sum / times
	!	sum = 0				!這裏需要注意的是,不同於C、Java類的語言,
	end function fun			!循環體內對此調用同樣的函數,函數體內定義
						!的變量是在多次調用過程中是共用的,因此在本體累加的時候,每次需要將sum清

    試運行截圖:


    Unbelievable,按照Java類似的語言以往的編程邏輯,不是這樣的啊!!

    於是,我嘗試着將變量sum的聲明與賦初值分開,即

  

    real sum     sum = 0

有程序修改如下:

!  paractise.f90 
!
!  FUNCTIONS:
!	paractise      - Entry point of console application.
!
!	Example of displaying 'Hello World' at execution time.
!

!****************************************************************************
!
!  PROGRAM: paractise
!
!  PURPOSE:  Entry point for 'Hello World' sample console application.
!
!****************************************************************************

	program paractise

	implicit none
	
	integer days, times, i
	real, allocatable ::averTemp(:)
	real fun
	external fun

	print *, "請輸入天數:"
	read *, days
	print *, "請輸入每天的時段數:"
	read *, times

	allocate(averTemp(days))

	
	do i = 1, days
		averTemp(i) = fun(times)
	end do

	print*, "每天的各個時段的平均溫度:"
	do i = 1, days
		print *, averTemp(i)
	end do

	stop
	end program paractise

	function fun(times)
	implicit none
		integer i, times		!聲明函數參數的類型,this is necessary	
		real fun				!聲明函數的返回值類型, this is necessary too
		real, allocatable ::timesinfo(:)
		real ::sum 		!請關注這裏!!!!!
		sum = 0			!sum 類型聲明與賦值分開
		print *, "輸出一下sum的值:", sum
		

		allocate(timesinfo(times))
		print *, "請輸入", times, "個時次的溫度:"
		read *, timesinfo
	
		do i = 1, times
			sum = sum + timesinfo(i)
		end do
		fun = sum / times
	!	sum = 0					!這裏需要注意的是,不同於C、Java類的語言,
	end function fun			!循環體內對此調用同樣的函數,函數體內定義
								!的變量是在多次調用過程中是共用的,因此在本體累加的時候,每次需要將sum清零

    試運行截圖:


    

此時sum的值終於在再次調用函數是迴歸爲0,才能正常處理邏輯。

III 顯然,雖然在多次調用函數時,但函數體內的相同變量在內存中是同一塊區域,必須在再入函數時將該變量進行初始化,方能正確處理邏輯,上面的處理方法,來講函數體內的變量聲明與賦初值分開既是實現這樣的處理!

    望每天進步一點,再見

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章