Fortran77 parameter when executing program - fortran

I am currently doing a Fortran77 assignment, so please don't tell me the exact coding, but please give me a hint of what I want to do:
Using UNIX terminal, I would like to get the parameter passed on by executing
./program.exe parameter

In standard Fortran77 you can't. End of story. Accessing command line arguments with fortran programs wasn't standardized until Fortran 2003.
If you're using the GNU fortran compiler, you can use the iargc() and getarg(i, arg) functions, which return the number of arguments and the value of a specific argument, resepectively.

It is possible to access command line arguments in FORTRAN77.
Given below is the code fragment I use :
CHARACTER ARGV*10
N=IARGC()
CALL GETARG(1,ARGV)
Just do ./a.out 1 2 3
ARGV will store the value of the first argument, i.e, 1
To convert this argument to float, use
READ (ARGV,*) RARG
RARG will convert ARGV into a floating-point integer.

Related

Provide variables as input arguments to MATLAB system command for a C++ executable

I have an algorithm implemented in MATLAB. I want to replace different built-in operations with my own C++ implementations. I do not want to use MEX for its extra overhead. Is there any way to provide variables as input arguments to my C++ executable function using the "system" command. For example, for a multiplier implemented in C++, the following works.
result = system('multiplier.exe 10 50')
The result is 500. But the following does not work:
a = 10;
b = 50;
result = system('multiplier.exe a b');
The result is always 0 in this case.
I have tried to use setenv and getenv functions. But the result is still 0.
Any help??
As hinted by user4581301 in a comment, your code is taking a and b as the strings a and b literally, and not translating them as 10 and 50 as expected by you. You need to put the values of a and b after converting them to strings instead. i.e.
result = system(['multiplier.exe ', num2str(a), ' ', num2str(b)]);
Matlab is passing them as string.
Trying to write your values to a file and reading from those file inside the said program might be a work around. But if your inputs/outputs are long and you want them to have appropriate data type, than you might want to filter the input and output streams (stdin stdout) from matlab and cpp to get the appropriate behavior.

C++ passing variable number of locations from a given array to a function

The following piece of code works in C++ when running on Windows:
void* paramsList[MAX_PARAMS_NUM] = { 0 };
...some code to populate paramsList (p.s MAX_PARAMS_NUM is a constant)
vsnprintf((char*)pStr, MAXLEN, (char*)pTempFormat, (va_list)paramsList);
This code works fine on Windows, but i am trying to make it run on Linux and the program crushes because this conversion of paramsList to va_list doesn't work there.
Now the setting of this scenario is that i get a format string from a server that i don't control. The format string ('pTempFormat') is like the one used in printf of unknown number of % in it (maximum is MAX_PARAMS_NUM) and i populate the paramsList accordingly and then i use vsnprintf to create a string from the format string i got and the values populated in paramsList.(those values can be anything from integers, to hex to char * (aka strings) and any combination of them, according to the format string received from the server).
i don't know how many locations paramsList to pass to vsnprintf until i finish populating it according to the format string received from the server. So i need to somehow either pass a variable number of locations from paramsListto vsnprintf or to convert those locations into va_list (which i couldn't figure out how to do from what i read online).
I also considered using a combination of variadic templates and va_list - to somehow pass a variable number of locations from paramsListto a variadic function and to pass them on to vsnprintf. But i couldn't figure out how to pass certain locations from a given array to a variadic function either.
Update:
I use Visual Studio 2015 to compile on Windows, and GCC 4.9 on Ubuntu.
The error i am getting when trying to compile this code on Linux is: error: ISO C++ forbids casting to an array type 'va_list {aka __va_list_tag [1]}'
va_list is an unspecified type. That means it may be a void* [] or something else entirely.
That it worked by chance in some cases is just that va_list is compatible with void* [] on one particular platform for one compiler, it is by no means indication that this is legal.
The correct way to deal with this is, unfortunately, to stop using the printf family and parse the format string yourself, there is no standard functionality to reach in and fetch the parsed format string to use for yourself.

Fortran and gnuplot: parameter passing and returning a value

I would like to call a gnuplot script from a program in Fortran. The program is supposed to perform a linear fit, to obtain the linear parameters and to send them back to the main program. I know that gnuplot can be called from Fortran using the command
call system ('gnuplot script.gnu')
what I don't know is how to send parameters to gnuplot in this call (let's say a real variable called t) and to return back to the main program the values of the fitted parameters (two real values a and b).
Note: I would like to avoid the use of files to communicate between the programs: I don't want gnuplot to write a file that it is then read by the Fortran program.
My script for the linear fitting:
f(x)=a*x+b
fit [t:*] f(x) "data.txt" u 1:2 via a,b;
You can use the -e command line argument of gnuplot
call system (`gnuplot -e "t=1" script.gnu')
to pass a parameter to gnuplot. I am not aware of any way to return a value though.
(To make it really useful you will have to get the numbers into the string, see
Convert integers to strings to create output filenames at run time and many related question in the "Linked" tab about how you can do that.)
It should be very easy to do your linear fit in Fortran, the formula is very simple and there are also libraries available, and avoid all these complications.

FORTRAN WRITE in one line only (prevent newline or carriage returns) [duplicate]

I have noticed the results of list-directed output write(*,*) in Fortran is compiler dependent.
Indeed, with the code:
program one
real(8), dimension(5):: r1
do i=1,5
r1(i)=sqrt(i*10.0)
end do
write(*,*) (r1(i), i =1,5)
end program one
intel compiler ifort gives standard output broken by a newline:
3.16227769851685 4.47213602066040 5.47722530364990
6.32455539703369 7.07106781005859
while gfortran gives the equivalent one line result:
3.1622776601683795 4.4721359549995796 5.4772255750516612 6.3245553203367590 7.0710678118654755
I think that ifort is writing maximum 3 items per line (when floating real numbers).
Is there any way to make the ifort output be like gfrotran, i.e. avoid the newline?
Ideally, I would like to keep list-directed output (*,*) instructions, so I am looking for something like a compiler option or so, if any.
Since verson 14, intel fortran compiler has the wrap-margin function. By default, the record is wrapped after 80 characters. For disabling this restriction, you should specify:
on Linux: -no-wrap-margin
on WIndows: /wrap-margin-
See more on Intel Fortran's reference guide
No. List-directed (free-format) output provides convenience, but you give up control. Various aspects of the output are unspecified and allowed to be chosen to the compiler. If you want full control, you have to use formatted output.
Look into edit descriptors in your favorite Fortran book or online documentation. You can use fmt specifier in the write statement to specify edit descriptors. For example:
write(*,fmt='(5(F6.4,3X))') (r1(i), i =1,5)
should output something similar to:
3.1623 4.4721 5.4772 6.3246 7.0711
See https://software.intel.com/en-us/forums/topic/401555
Specify FORT_FMT_RECL or use
write (,"(G0,1X))"

GetCommandLine linux *true* equivalent

Similar question to Linux equivalent of GetCommandLine and CommandLineToArgv
Is it possible to get the raw command line in linux? The file /proc/self/cmdline is destroyd.
./a.out files="file 1","file 2" param="2"
prints
./a.outfiles=file 1,file 2param=2
which is junk
Escaping command line does work for all arguments but the first.
./a.out files=\"fil 1\",\"fil 2\"\ param=\"2\"
prints
./a.outfiles="fil1","fil2" param="2"
You can't do that. The command line arguments are actually passed to the new process as individual strings. See the linux kernel source:
kernel_execve
Note that kernel_execve(...) takes a const char *argv[] - so there is no such thing as a long string commandline in Linux - it's the layer above that needs to split the arguments into separate components.
Edit: actually, the system call is here:
excve system call
But the statement above still applies. The parameter for argv is already split by the time the kernel gets it from the C-library call to exec.
It is the responsibility of the "starter of the program" (typically a shell, but doesn't have to be) to produce the argv[] array. It will do the "globbing" (expansion of wildcard filenames to the actual files that it matches) and stripping of quotations, variable replacement and so on.
I would also point out that although there are several variants of "exec" in the C library, there is only one way into the kernel. All variants end up in the execve system call that I linked to above. The other variants are simply because the caller may not fancy splitting arguments into invdividual elements, so the C library "helps out" by doing that for the programmer. Similarly for passing an environment array to the new program - if the programmer don't need specific environment, he/she can just call the variant that automatically take the parent process env.