The first step involves getting the filename as a command-line argument, opening the file for writing, and allowing the user to write into it. To implement this is relatively straightforward but will require quite a few new language elements. Let’s take a look at the complete program first, as shown in the following listing.
Listing 6.7 First version of the qn app
program qn
use iso_fortran_env, only: stdin => input_unit
implicit none
integer :: fileunit ❶
character(len=9999) :: filename, text ❷
if (command_argument_count() < 1) stop 'Usage: qn <filename>' ❸
call get_command_argument(1, filename) ❹
open(newunit=fileunit, file=trim(filename)) ❺
do ❻
read(stdin, '(a)') text ❼
write(fileunit, '(a)') trim(text) ❽
flush(fileunit) ❾
end do
end program qn
❶ I/O unit number used to connect to a file
❸ Prints a short help message if no command-line arguments were provided
❹ Reads the first CLI argument and stores its value into filename
❺ Opens the file with the given filename
❼ Reads text from standard input (keyboard)
❽ Writes text to file while trimming any trailing whitespace
❾ On each write, flushes the contents to the file
The first step is to parse the command line for an argument, and its value will be the name of the file to write notes into. Here we use the built-in command_argument_count function and the get_command_argument subroutine to check for the number of arguments, and to store the value of the first argument into the character variable filename. Note that we declared filename as character(len=9999). There’s no special meaning behind this number–we’re simply declaring a character variable long enough to store strings of arbitrary length. On most Linux file systems, maximum path length is 4,096, but this should be handled elsewhere. You’ll learn in more detail how command _argument_count and get_command_argument work in chapter 10.
Fixed-length or allocatable character variables?
If you’re thinking that using fixed-length character variables is awkward, you’re absolutely right! Why would I not use allocatable character strings instead? This situation is due to Fortran’s inability to implicitly allocate a dynamic character variable on a read statement. In other words, the character variable must be allocated before using it on the right side of a read statement, which would require us to somehow know what the length of the input data would be.
The choice to use fixed-length strings that are just long enough to hold most input data is thus a pragmatic one, though not too elegant.