I wonder why the following code does not work?
function out = test(str1, str2)
aux = sprintf(str1, str2);
end
Somehow MATLAB does not like how I supply the argument str1, which is entered by the user, to the function sprintf.
Read the documentation on sprintf in MATLAB. It's rather clear what's wrong: the first argument in your case. MATLAB's sprintf requires a format spec, so unless the first argument is a format specification, rather than say 'hello' matching the second string, this won't work. You'll probably want something along the lines of sprintf('%s %s', str1, str2) or sprintf([str1 ' ' str2]), i.e. explicitly concatenating the strings into one literal text string first.
Your current function will work if you call it as test('%s', 'hello') by the way, or even test('%f %f', [pi 5]). So you might want to use input verification to make sure you're only inputting strings.
Related
Is there a function in Lua that returns a string inserted into another one on given position?
For example string.insert(str1, str2, pos).
Using it: string.insert('Hello World!', 'My ', 6) becomesHello My World! and so on.
There is no such function in the standard Lua library. But it's easy to write one:
function string.insert(str1, str2, pos)
return str1:sub(1,pos)..str2..str1:sub(pos+1)
end
Note how it automatically handles negative positions (*), which count from the end of the string, as most other string functions do.
(*) it needs a small change to make pos=-1 work.
Suppose I have a string like so.
string = "This is just an {example} of a string. {Quite} boring."
At some point in the code, I want to use a function to replace the words between the curly brackets with something else. I prodded around in the manual, and came up with this solution.
function stringModify(a)
return string.gsub(a, '{(.-)}', stringDecide("%1"))
end
function stringDecide(a)
if a == "example" then
return "excellent example"
elseif a == "Quite" then
return "Not"
else
return "ERROR"
end
end
Only that it doesn't work the way I want it. The if part, for example, treats variable a as a literal "%1", instead of the contents of the capture.
How do I make it so that the contents of the capture is compared, instead the literal interpretation of the "%1" string?
You don't have to do the whole %1 thing to pass the captures over to your function. One possible mode of operation of string.gsub takes a function as an argument and passes it a string/array of strings representing the capture(s) every time it finds a match:
The last use of captured values is perhaps the most powerful. We can call string.gsub with a function as its third argument, instead of a replacement string. When invoked this way, string.gsub calls the given function every time it finds a match; the arguments to this function are the captures, while the value that the function returns is used as the replacement string.
Taking this into account, you can just remove a few characters from your existing code so you pass the function rather than calling it:
function stringModify(a)
return string.gsub(a, '{(.-)}', stringDecide)
end
and your stringDecide function will work unmodified, as you can see.
In your existing code, what you're wanting to happen is that string.gsub will call stringDecide for each match, substituting the string captured into the string parameter to stringDecide on each call, but what's in fact happening is that stringDecide is being called once with the literal parameter "%1" before string.gsub is even called, and it is returning "ERROR" as expected, basically expanding your string.gsub call in place to string.gsub(a, '{(.-)}', "ERROR").
I would like to define a function which returns the string "NaN" or sprintf("%g",val) depending on whether val is a string or a numeric value. Initially I was trying to test if val was defined (using the gnuplot "exists" function) but it seems that I cannot pass any undefined variable to a function (an error is issued before the function is evaluated). Therefore: is there a way to test inside a function whether the argument is a string or numeric?
I search for a function isstring which I can use somehow like
myfunc(val)=(isstring(val)?"NaN":sprintf("%g",val))
The goal is to output the values of variables without risking errors in case they are undefined. However I need it as a function if I want a compact code for many variables.
Gnuplot doesn't really have the introspection abilities that many other languages have. In fact, it treats strings and numbers (at least integers) very similarly:
print "1"+2 #prints 3
a=1
print "foo".a #prints foo1
I'm not exactly sure how this is implemented internally. However, what you're asking is very tricky to get to work.
Actually, I think your first attempt (checking if a variable exists) is more sensible as type-checking in gnuplot is impossible*. You can pass the variable name to the function as a string, but the problem is that you don't seem to have a handle on the value. All seems lost -- But wait, gnuplot has an eval statement which when given a string will evaluate it. This seems great! Unfortunately, it's a statement, not a function (so it can't be used in a function -- argv!). The best solution I can come up with is to write a function which returns an expression that can be evaluated using eval. Here goes:
def exists_func(result,var)=sprintf("%s=exists('%s')?sprintf('%g',var):'NaN'",result,var,var)
Now when you want to use it, you just prefix it with eval
a=3
eval exists_func("my_true_result","a")
print my_true_result #3
eval exists_func("my_false_result","b")
print my_false_result #NaN
This goes against the grain a little bit. In most programming languages, you'd probably want to do something like this:
my_true_result=exists_func(a)
But alas, I can't figure out how to make that form work.
Of course, the same thing goes here that always goes with eval. Don't use this function with untrusted strings.
*I don't actually know that it's impossible, but I've never been able to get it to work
EDIT
In response to your comment above on the question, I think a function like this would be a little more intuitive:
def fmt(x)=(x==x)?sprintf("%g",x):"NaN"
With this function, your "sentinal/default" value should be NaN instead of "undefined", but it doesn't seem like this should make too much of a difference...(Really, if you're willing to live with "nan" instead of "NaN" you don't need this function at all -- sprintf will do just fine. (Note that this works because according to IEEE, NaN doesn't equal anything (even itself)).
You helped me a lot these days with gnuplot. I want to give you something back because I have found a solution to check if a variable is numeric or not. This helps to decide which operators can be used on it (e.g. == for numbers, eq for strings).
The solution is not very simple, but it works. It redirects gnuplot's print command to a temp file, writes the variable to the file with print myvar and evaluates the file's first line with system("perl -e '<isnumeric(line#1 in temp file)?>' ") (<> is pseudo-code). Let me know if there's room for imrpovements and let me hear your suggestions!
Example: myvar is a float. Any integer (1 or "1") or string value ("*") works too!
myvar = -2.555
# create temporary file for checking if variables are numeric
Int_tmpfle = "tmp_isnumeric_check"
# redirect print output into temp file (existing file is overwritten)
set print Int_tmpfle
# save variable's value to file
print myvar
# check if file is numeric with Perl's 'looks_like_number' function
isnumeric = system("perl -e 'use Scalar::Util qw(looks_like_number); \
open(FLE,".Int_tmpfle."); $line = < FLE >; \
if (looks_like_number($line) > 0) {print qq(y)} ' ")
# reset print output to < STDOUT> (terminal)
set print "-"
# make sure to use "," when printing string and numeric values
if (isnumeric eq "y") {print myvar," is numeric."} else {print myvar," is not numeric."}
Is there any way to replace a character at position N in a string in Lua.
This is what I've come up with so far:
function replace_char(pos, str, r)
return str:sub(pos, pos - 1) .. r .. str:sub(pos + 1, str:len())
end
str = replace_char(2, "aaaaaa", "X")
print(str)
I can't use gsub either as that would replace every capture, not just the capture at position N.
Strings in Lua are immutable. That means, that any solution that replaces text in a string must end up constructing a new string with the desired content. For the specific case of replacing a single character with some other content, you will need to split the original string into a prefix part and a postfix part, and concatenate them back together around the new content.
This variation on your code:
function replace_char(pos, str, r)
return str:sub(1, pos-1) .. r .. str:sub(pos+1)
end
is the most direct translation to straightforward Lua. It is probably fast enough for most purposes. I've fixed the bug that the prefix should be the first pos-1 chars, and taken advantage of the fact that if the last argument to string.sub is missing it is assumed to be -1 which is equivalent to the end of the string.
But do note that it creates a number of temporary strings that will hang around in the string store until garbage collection eats them. The temporaries for the prefix and postfix can't be avoided in any solution. But this also has to create a temporary for the first .. operator to be consumed by the second.
It is possible that one of two alternate approaches could be faster. The first is the solution offered by PaĆlo Ebermann, but with one small tweak:
function replace_char2(pos, str, r)
return ("%s%s%s"):format(str:sub(1,pos-1), r, str:sub(pos+1))
end
This uses string.format to do the assembly of the result in the hopes that it can guess the final buffer size without needing extra temporary objects.
But do beware that string.format is likely to have issues with any \0 characters in any string that it passes through its %s format. Specifically, since it is implemented in terms of standard C's sprintf() function, it would be reasonable to expect it to terminate the substituted string at the first occurrence of \0. (Noted by user Delusional Logic in a comment.)
A third alternative that comes to mind is this:
function replace_char3(pos, str, r)
return table.concat{str:sub(1,pos-1), r, str:sub(pos+1)}
end
table.concat efficiently concatenates a list of strings into a final result. It has an optional second argument which is text to insert between the strings, which defaults to "" which suits our purpose here.
My guess is that unless your strings are huge and you do this substitution frequently, you won't see any practical performance differences between these methods. However, I've been surprised before, so profile your application to verify there is a bottleneck, and benchmark potential solutions carefully.
You should use pos inside your function instead of literal 1 and 3, but apart from this it looks good. Since Lua strings are immutable you can't really do much better than this.
Maybe
"%s%s%s":format(str:sub(1,pos-1), r, str:sub(pos+1, str:len())
is more efficient than the .. operator, but I doubt it - if it turns out to be a bottleneck, measure it (and then decide to implement this replacement function in C).
With luajit, you can use the FFI library to cast the string to a list of unsigned charts:
local ffi = require 'ffi'
txt = 'test'
ptr = ffi.cast('uint8_t*', txt)
ptr[1] = string.byte('o')
I've a question about Fortran 77 and I've not been able to find a solution.
I'm trying to store an array of strings defined as the following:
character matname(255)*255
Which is an array of 255 strings of length 255.
Later I read the list of names from a file and I set the content of the array like this:
matname(matcount) = mname
EDIT: Actually mname value is hardcoded as mname = 'AIR' of type character*255, it is a parameter of a function matadd() which executes the previous line. But this is only for testing, in the future it will be read from a file.
Later on I want to print it with:
write(*,*) matname(matidx)
But it seems to print all the 255 characters, it prints the string I assigned and a lot of garbage.
So that is my question, how can I know the length of the string stored?
Should I have another array with all the lengths?
And how can I know the length of the string read?
Thanks.
You can use this function to get the length (without blank tail)
integer function strlen(st)
integer i
character st*(*)
i = len(st)
do while (st(i:i) .eq. ' ')
i = i - 1
enddo
strlen = i
return
end
Got from here: http://www.ibiblio.org/pub/languages/fortran/ch2-13.html
PS: When you say: matname(matidx) it gets the whole string(256) chars... so that is your string plus blanks or garbage
The function Timotei posted will give you the length of the string as long as the part of the string you are interested in only contains spaces, which, if you are assigning the values in the program should be true as FORTRAN is supposed to initialize the variables to be empty and for characters that means a space.
However, if you are reading in from a file you might pick up other control characters at the end of the lines (particularly carriage return and/or line feed characters, \r and/or \n depending on your OS). You should also toss those out in the function to get the correct string length. Otherwise you could get some funny print statements as those characters are printed as well.
Here is my version of the function that checks for alternate white space characters at the end besides spaces.
function strlen(st)
integer i,strlen
character st*(*)
i = len(st)
do while ((st(i:i).eq.' ').or.(st(i:i).eq.'\r').or.
+ (st(i:i).eq.'\n').or.(st(i:i).eq.'\t'))
i = i - 1
enddo
strlen = i
return
end
If there are other characters in the "garbage" section this still won't work completely.
Assuming that it does work for your data, however, you can then change your write statement to look like this:
write(*,*) matname(matidx)(1:strlen(matname(matidx)))
and it will print out just the actual string.
As to whether or not you should use another array to hold the lengths of the string, that is up to you. the strlen() function is O(n) whereas looking up the length in a table is O(1). If you find yourself computing the lengths of these static strings often, it may improve performance to compute the length once when they are read in, store them in an array and look them up if you need them. However, if you don't notice the slowdown, I wouldn't worry about it.
Depending on the compiler that you are using, you may be able to use the trim() intrinsic function to remove any leading/trailing spaces from a string, then process it as you normally would, i.e.
character(len=25) :: my_string
my_string = 'AIR'
write (*,*) ':', trim(my_string), ':'
should print :AIR:.
Edit:
Better yet, it looks like there is a len_trim() function that returns the length of a string after it has been trimmed.
intel and Compaq Visual Fortran have the intrinsic function LEN_TRIM(STRING) which returns the length without trailing blanks or spaces.
If you want to suppress leading blanks or spaces, use "Adjust Left" i.e. ADJUSTF(STRING)
In these FORTRANs I also note a useful feature: If you pass a string in to a function or subroutine as an argument, and inside the subroutine it is declared as CHARACTER*(*), then
using the LEN(STRING) function in the subroutine retruns the actual string length passed in, and not the length of the string as declared in the calling program.
Example:
CHARACTER*1000 STRING
.
.
CALL SUBNAM(STRING(1:72)
SUBROUTINE SYBNAM(STRING)
CHARACTER*(*) STRING
LEN(STRING) will be 72, not 1000