Now I have something like this
program prova
CHARACTER (LEN=4) :: mvalue
common mvalue
mvalue='01.0'
call funzione(var1, var2,...)
end
subroutine funzione()
common mvalue
*(stuff with var1, var2, ...)*
open(10,file="./prova_"//mvalue//"_.res")
end
and the compiler returns
open(10,file="./prova_"//mvalue//"_.res")
1
Error: Operands of string concatenation operator at (1) are CHARACTER(1)/INTEGER(4)
I don't know if I can use the "implicit none" instruction in the real code, because maybe it would mess up something else...I'm sorry if I can't be more precise, but as I told you I'm new to FORTRAN, and the code is kinda extended (and written EXTREMELY poorly).
I'd prefer to pass the mvalue variable to the routine, but if I try to do
program prova
CHARACTER (LEN=4) :: mvalue
mvalue="01.0"
call func(mvalue)
end
subroutine func(mvalue)
open(10,file="./prova_"//mvalue//"_.res")
end
it returns
open(10,file="./prova_"//mvalue//"_.res")
1
Error: Operands of string concatenation operator at (1) are CHARACTER(1)/INTEGER(4)
prova.f:4.16:
call func(mvalue)
Warning: Type mismatch in argument 'mvalue' at (1); passed CHARACTER(1) to INTEGER(4)
Your subroutine:
subroutine funzione()
common mvalue
*(stuff with var1, var2, ...)*
open(10,file="./prova_"//mvalue//"_.res")
end
is missing implicit none ! Always use it in every scoping unit without any exception!
The type of mvalue is not declared and it is therefore integer implicitly.
You must declare the type in every scoping unit. Sharing it using the common is not enough!
In Fortran 90 the proper thing is to use modules and not common blocks. In any programming language in general the proper way is not to share global variables (no matter if using common, using modules or any other way), but to pass the string as an argument to the subroutine.
To your new edit the same advice is still valid: Your subroutine is missing implicit none ! Always use it in every scoping unit without any exception!
If you can't use implicit none then you MUST!!!!! be prepared to diagnose errors coming from undeclared variables. It is absolutely necessary!
A character dummy argument is declared as character*(*) mvalue
As the commenters have already pointed out, you are using two different quotation markers in such a way that it passes the compile time, but fails at runtime.
The file= dummy argument expects a string, and it gets a very long one: The entirety of ./results/file_01.0_R00.res',status='unknown. But when it tries to open that file, it fails: This is simply no valid file name.
Simply replacing the ' with " in both instances (after .res and before unknown) should make the error go away.
Related
I'm working on a simple localization function for my scripts and, although it's starting to work quite well so far, I don't know how to avoid scape/special characters to be shown in UI as part of the text after feeding the widgets with the strings returned by f:read().
For example, if in a certain Strings.ES.txt's line I have: Ignorar \"Etiquetas de capa\", I'd expect backslashes didn't end showing up just like when I feed the widget with a normal string between doble quotes like: "Ignorar \"Etiquetas de capa\"", or at least have a way to avoid it. I've been trial-and-erroring with tostring() and load() functions and different (surely nonsense 🙄) concatenations like: load(tostring("[[" .. f:read()" .. ]]")) and such without any success, so here I'm again...
Do someone know if there is a way to get scape characters in a string returned by f:read() still behave as special as when they are found in a regular one?
I don't know how to avoid [e]scape/special characters to be shown in UI as part of the text
What you want is to "unescape" or "unquote" a string to interpret escape sequences as if it were parsed as a quoted string by Lua.
[...] with the strings returned by f:read() [...]
The fact that this string was obtained using f:read() can be ignored; all that matters is that it is a string literal without quotes using quoted string escapes.
I've been trial-and-erroring with tostring() and load() functions and different [...] concatenations like: load(tostring("[[" .. f:read()" .. ]]")) and such without any success [...]
This is almost how to do it, except you chose the wrong string literal type: "Long" strings using pairs square brackets ([ and ]) do not interpret escape sequences at all; they are intended for including long, raw, possibly multiline strings in Lua programs and often come in handy when you need to represent literal strings with backslashes (e.g. regular expressions - not to be confused with Lua patterns, which use % for escapes, and lack the basic alternation operator of regular expressions).
If you instead use single or double quotes to wrap the string, it will work fine:
local function unescape_string(escaped)
return assert(load(('return "%s"'):format(escaped)))()
end
this will produce a tiny Lua program (a "chunk") for each string, which just consists of return "<contents>". Recall that Lua chunks are just functions. Thus you can simply call the function to obtain the value of the string it returns. That way, Lua will interpret the escape sequences for us. The same approach is often used to use Lua for reading data serialized as Lua code.
Note also the use of assert for error handling: load returns nil, err if there is a syntax error. To deal with this gracefully, we can wrap the call to load in assert: assert returns its first argument (the chunk returned by load) if it is truthy; otherwise, if it is falsy (e.g. nil in this case), assert errors, using its second argument as an error message. If you omit the assert and your input causes a syntax error, you will instead get a cryptic "attempt to call a nil value" error.
You probably want to do additional validation, especially if these escaped strings are user-provided - otherwise a malicious string like str"; os.execute("...") can trivially invoke a remote code execution (RCE) vulnerability, allowing it to both execute Lua e.g. to block (while 1 do end), slow down or hijack your application, as well as shell commands using os.execute. To guard against this, searching for an unescaped closing quote should be sufficient (syntax errors e.g. through invalid escapes will still be possible, but RCE should not be possible excepting Lua interpreter bugs):
local function unescape_string(escaped)
-- match start & end of sequences of zero or more backslashes followed by a double quote
for from, to in escaped:gmatch'()\\*()"' do
-- number of preceding backslashes must be odd for the double quote to be escaped
assert((to - from) % 2 ~= 0, "unescaped double quote")
end
return assert(load(('return "%s"'):format(escaped)))()
end
Alternatively, a more robust (but also more complex) and presumably more efficient way of unescaping this would be to manually implement escape sequences through string.gsub; that way you get full control, which is more suitable for user-provided input:
-- Single-character backslash escapes of Lua 5.1 according to the reference manual: https://www.lua.org/manual/5.1/manual.html#2.1
local escapes = {a = '\a', b = '\b', f = '\b', n = '\n', r = '\r', t = '\t', v = '\v', ['\\'] = '\\', ["'"] = "'", ['"'] = '"'}
local function unescape_string(escaped)
return escaped:gsub("\\(.)", escapes)
end
you may implement escapes here as you see fit; for example, this misses decimal escapes, which could easily be implemented as escaped:gsub("\\(%d%d?%d?)", string.char) (this uses coercion of strings to numbers in string.char and a replacement function as second argument to string.gsub).
This function can finally be used straightforwardly as unescape_string(f:read()).
I have functions process and matrix. The following code works
process(matrix({{2,4,6},{8,10,12},{14,16,20}}))
However the following doesn't work.
n='matrix({{2,4,6},{8,10,12},{14,16,20}})'
process(n)
It throws some error. The reason is obvious that process takes n as string rather than the output of the function matrix. So the basic difficulty involved here is about evaluating string from variable n and then give it as argument to the function process. Here loadstring function is of no use as matrix is local function and can't be referred from loadstring.
Is there any work around for this? I hope that I have clearly stated the problem here. It is about evaluating (or unloading) string and then passing it as argument to another function. Any help will be appreciated. Thanks.
as matrix is local function
Lua takes local declarations seriously. If a variable is declared local, it can only be accessed by code which is statically within the local scope of that variable. Strings which you later turn into code are not statically in the local scope and therefore cannot access local variables.
Now, with Lua 5.2+, you can provide load with a second parameter, a table which represents the global environment against which that Lua chunk will be built. If that table contains a matrix value, then the loaded string can access it. For Lua 5.1, you'd have to use setfenv on the function returned to load to accomplish a similar effect. The Lua 5.2+ method would look like this:
local env = {matrix = matrix}
local func = load("return matrix({{2,4,6},{8,10,12},{14,16,20}})", nil, "t", env)
process(func())
Note the following:
You must create an explicit table which is the global environment. There's nothing you can pass that says "make my locals available"; you have to put every local you'd like to access there. Which is, generally speaking, why you pass these things as parameters or just make them globals.
You explicitly need the "return " there if you want to get the results of the call to matrix.
You have to call the function. Functions are values in Lua, so you can freely pass them around. But if you want to pass the results of a function to another function, you have to actually call it.
Trying to understand how "%s%s" %(a,a) is working in below code I have only seen it inside print function thus far.Could anyone please explain how it is working inside int()?
a=input()
b=int("%s%s" %(a,a))
this "%s" format has been borrowed from C printf format, but is much more interesting because it doesn't belong to print statement. Note that it involves just one argument passed to print (or to any function BTW):
print("%s%s" % (a,a))
and not (like C) a variable number of arguments passed to some functions that accept & understand them:
printf("%s%s,a,a);
It's a standalone way of creating a string from a string template & its arguments (which for instance solves the tedious issue of: "I want a logger with formatting capabilities" which can be achieved with great effort in C or C++, using variable arguments + vsprintf or C++11 variadic recursive templates).
Note that this format style is now considered legacy. Now you'd better use format, where the placeholders are wrapped in {}.
One of the direct advantages here is that since the argument is repeated you just have to do:
int("{0}{0}".format(a))
(it references twice the sole argument in position 0)
Both legacy and format syntaxes are detailed with examples on https://pyformat.info/
or since python 3.6 you can use fstrings:
>>> a = 12
>>> int(f"{a}{a}")
1212
% is in a way just syntactic sugar for a function that accepts a string and a *args (a format and the parameters for formatting) and returns a string which is the format string with the embedded parameters. So, you can use it any place that a string is acceptable.
BTW, % is a bit obsolete, and "{}{}".format(a,a) is the more 'modern' approach here, and is more obviously a string method that returns another string.
I am trying to understand a small read function in my program I am trying to decipher.The code is below
READ (LREST, END=350, ERR=350) ICHR
IF (ICHR .EQ. ICKLNK) THEN
DO L = 1, 4
READ (LREST, END=350, ERR=350)
ENDDO
So basically LREST is some kind of an argument provided for this subroutine this function is in. However, I found that LREST is not defined anywhere(used grep to see where LREST is defined in my *.f files. So my questions is what is that LREST doing there in READ function. I thought the location LREST is at is where the unit is defined.
Second questions is that ICHR is a 16 character string variable define for this subroutine. However, the contents of ICHR have not been assigned. I have no idea what this READ function is trying to read from.
Going over to IF statement, ICKLNK is another 16 character string variable with a defined strings. Because ICHR is not defined, does that mean this if statement never gets entered in?
Finally, the do loop( or for loop) has variable L in it but it is not even being used for read function inside of the loop.
Im a beginning in fortran so I may just be lacking a very basic knowledge but if you know an answer to my question please let me know. Thanks!
Han
You are correct that LREST is specifying the unit number (or internal file if it is character). You seem to suggest that LREST is an argument in this subroutine or function, which means its value is passed in by whoever calls the function. Showing us only a small piece of the code makes it hard to provide further details.
Again, you say ICHR is an argument to the procedure, so it takes on the value of whatever was passed in by the call. ICLNK is probably similar, but you didn't show all the code.
The DO (not for) loop is using L just as a counter; it doesn't need to be referenced inside the loop.
Which of the following statements is FALSE?
(A) In statically typed languages, each variable in a program has a fixed type
(B) In un-typed languages, values do not have any types
(C) In dynamically typed languages, variables have no types
(D) In all statically typed languages, each variable in a program is associated with values of only a single type during the execution of the program
Can you please explain the theory as well?
C) (In dynamically typed languages, variables have no types) Is false.
The variable has a type, however it is simply not stated or decided until run time. This implies there is no type checking prior to running the program.
a useful link describing Types and what it means:
http://en.wikipedia.org/wiki/Type_system
If you have ever done much with PHP you will notice that when you declare a varialbe, you do not have to say whether it is an INT or a STRING. However, sometimes you know that you will be receiving a string, but need an int, so you can still type cast variables at runtime, even though when you declared the variable you did not explicitly state the variable would hold an int.
<?php
#some more code here.....
# over here $myValue could be of some different type, but it can dynamically change to another type
$myValue = '5'; #storing a string...so $myValue is currently of type String
$myNewValue = (int)$myValue + 5 #type casted to integer, so in this case $myValue is currently of type integer
?>
If that doesn't help, maybe take a look at this.
myPythonVariable = "I am currently a string" #the variable is of type string
myPythonVariable = 5 #the variable is now of type integer
In the above code sample, myPythonVariable always has a type, whether or not that type changes doesn't matter.