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


Previous
Next