Project 3
Using the cpi.csv data, write a program that will read from the command line the name of a file. Read this file into your program. Request from the command line a year. Optionally request on the command line an amount. Check that you have enough command line input. Stop with a message if you don’t have enough command line values.
Do not assume you know in advance how many lines the file contains. Use the inquire statement to check that the file exists before you attempt to open it. You can add a message to stop, e.g. stop “Invalid file”. Test that the file can be opened as part of your open statement.
Once the data have been read, check that the requested year is in range.
The ratio of any two years is an estimate of the change in the cost of living. Compute the change in the cost of living from the year you specify to the last number in the data (2020 in the sample file). Print it out neatly with some informative text. Print the result to 2 decimal places.
In 1954 a color television cost $1295. From your result how much would that be in 2020 dollars?
A rough estimate of the year-over-year inflation rate can be obtained from
inflation(i)=(cpi(i+1)-cpi(i))/12.
Compute the inflation rate for the data and print with the corresponding year to a comma-separated file. Use any plotting package with which you are familiar (Excel, Matlab, Python, R, etc.) to plot the data.
Sample solution
program inflation
! This program reads Consumer Price Index data and computes an approximation
! to the inflation rate
! Author : K. Holcomb
! Changelog:: Initial code 20130210
implicit none
character(len=80) :: infile,outfile
character(len=4) :: year_char
character(len=12) :: amount_char
real, dimension(:), allocatable :: cpi
real, dimension(:), allocatable :: inflat
real :: ratio, tv_price
real :: my_amount=0.0
integer, dimension(:), allocatable :: years
integer :: my_year
integer :: nlines,nyears
integer :: ios, inunit, outunit
integer :: nargs
integer :: cpi_index
integer :: n
logical :: file_exists
interface
function unit_number()
integer :: unit_number
end function unit_number
end interface
nargs=command_argument_count()
if (nargs .lt. 2) then
stop "Usage: datafile year <amount>"
else if (nargs .eq. 2) then
call get_command_argument(1,infile)
call get_command_argument(2,year_char)
read(year_char,'(i4)') my_year
else
call get_command_argument(1,infile)
call get_command_argument(2,year_char)
call get_command_argument(3,amount_char)
read(year_char,'(i4)') my_year
read(amount_char,*) my_amount
endif
inquire(file=infile,exist=file_exists)
if (file_exists) then
inunit=unit_number()
open(inunit,file=infile,iostat=ios)
if ( ios .ne. 0 ) then
stop "Unable to open data file"
endif
else
stop "Data file not found"
endif
nlines=0
do
read(inunit,*,end=10)
nlines=nlines+1
enddo
10 continue
rewind(inunit)
!Read and discard header
read(inunit,*)
! Subtract header line
nyears=nlines-1
allocate(years(nyears),cpi(nyears))
allocate(inflat(nyears-1))
!Read data
do n=1,nyears
read(inunit,*,iostat=ios) years(n),cpi(n)
if ( ios .ne. 0 ) stop "Error reading file"
enddo
if (my_year > years(nyears) .or. my_year < years(1)) then
stop "Requested year outside of data range."
endif
cpi_index=my_year-years(1)+1
ratio=cpi(nyears)/cpi(cpi_index)
if (my_amount==0) then
write(*,'(a,i4,a,f0.2)') "The inflation factor since ",my_year, &
" is about ",ratio
else
write(*,'(f0.2,a,i4,a,f0.2,a,i4)') my_amount," in ",my_year, &
" is about ",ratio*my_amount," in ",years(nyears)
endif
inflat=0.0
do n=1,nyears-1
inflat(n)=(cpi(n+1)-cpi(n))/12.
enddo
outfile="inflation.csv"
outunit=unit_number()
open(outunit,file=outfile,iostat=ios)
if ( ios .ne. 0 ) stop "Unable to open output file"
! Write out values for plotting
do n=1,nyears
write(outunit,'(i4,a)',advance='no') years(n)
write(outunit,*) inflat(n)
enddo
end program inflation
function unit_number()
integer :: unit_number
integer :: base_unit=10
logical :: first=.true.
if ( first ) then
unit_number=base_unit
first=.false.
else
unit_number=unit_number+1
endif
end function unit_number