I need a program to convert from base a to base b, where base a and b could be from 2 to 36.
My idea was to use strings as the numbers, convert to base 10 as an intermediary and then convert from base 10 to base b. As I'm new on Fortran I can't understand quite the functions and substring, right now I'm getting the error:
intToChar = cadena(int,int)
1
Error: Unclassifiable statement at (1)
On the next code:
CHARACTER FUNCTION intToChar(int)
IMPLICIT NONE
INTEGER, INTENT(IN) :: int
CHARACTER(LEN = 36) :: cadena
cadena = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
intToChar = cadena(int,int)
END FUNCTION intToChar
I'm following this tutorial
The syntax to select a substring from a character variable uses a colon :, not a comma ,. The line the compiler is complaining about should be:
intToChar = cadena(int:int)
This will select the single character as position int from cadena, which appears to be your goal with that function.
Related
This question already has an answer here:
Fortran CHARACTER (LEN = *) only apply to dummy argument or PARAMETER
(1 answer)
Closed 1 year ago.
In the mainline, how to I declare "to_upper" and "string" so as to call this function?
Pure Function to_upper (str) Result (string)
! Changes a string to upper case
Implicit None
Character(*), Intent(In) :: str
Character(LEN(str)) :: string
Integer :: ic, i
program tescc
character (*) to_upper, to_lower
character (*) tes1,tes2
tes1='LoWs' tes2=to_upper(tes1)
print*,tes1,',',tes2
end
gfortran -o tescc tescc.f tescc.f:4:24: 4 |
character (*) tes1,tes2 |
1 Error: Entity with assumed character length at (1) must be a dummy argument or a PARAMETER tescc.f:4:29:
You would need to declare three strings, one for the function, one which is the input string, and another for the output string. You would first need to end this function. You need to say the function name is a string because that is what it returns.
This function does nothing so you would need to finish writing the function algorithm. But,
Here is an example code to run this function:
program main
implicit none
character(100) :: to_upper
character(100) :: some_str, other_str
some_str = "hello world"
other_str = to_upper(some_str)
end program main
pure function to_upper (str) Result (string)
! Changes a string to upper case
implicit None
Character(*), Intent(In) :: str
Character(LEN(str)) :: string
Integer :: ic, i
end function
This question already has an answer here:
Difference between "character*10 :: a" and "character :: a(10)"
(1 answer)
Closed 3 years ago.
I am trying to find the position of a character in a string using the following code.
implicit none
character string(10);
string="abcdefghik"
print *, index(string, "c")
end program test
But the output is 10 times 0 instead of 3. The same happens with the scan function.
What am I doing wrong?
The bug:
You defined your string as an array of single characters of length 10:
character :: string(10)
A character string of length 10 is defined as
character(len=10) :: string
These two are two different concepts. See:
What is the difference between a Char Array and a String?
Difference between "character*10 :: a" and "character :: a(10)"
Why do I get 10 zeros?
The reason you obtained 10 times the value zero is because both INDEX and SCAN are elemental functions. This means that they execute for every element of the array. But this is not all, you would imagine that it would at least return ones the number 1 for the third array ellement. Unfortuntately, the assignment
character array(10)
array = "abcdefghik"
print *, array
will assign 10 times the letter a. You notice that this will return aaaaaaaaaa. This is due to array assignments.
Working code:
program test
implicit none
character(len=10) :: string;
string="abcdefghik"
print *, index(string, "c")
end program test
This question already has answers here:
Access elements of returned array in Fortran
(4 answers)
Closed 5 years ago.
I have a function str that takes an integer and converts it to a string. I also want to consider a substring of the string of that value, which would be easy if it were a character value rather than a character function.
In other words, I'd like to write something like this:
str(12345)(2:3)
instead of having to do this:
character(10) :: c
c = str(12345)
print *, c(2:3)
or rolling my own substr() function. Is there any way to do what I want without storing the character value in a temporary character variable or writing another function?
Here's a complete program:
program main
character(10) :: c
! works fine
c = str(12345)
print *, c(2:3)
! nope
print *, str(12345)(2:3)
! this would work if i wrote a substr function
print *, substr( str(12345), 2, 3 )
contains
character(len=1064) function str(k)
! convert an integer to string
integer, intent(in) :: k
write (str, *) k
str = adjustl(str)
end function str
end program main
No, you cannot substring or array-index a Fortran expression. And a function result is an expression. The closest thing to avoiding a temporary is using associate from Fortran 2003, but you won't save much code either
associate(c=>str(12345))
print *,c(2:3)
end associate
I have a third party script for a subroutine that I need to work with. This subroutine is as follows
Subroutine COpen(io, Name )
Character*(*) Name
Character*1023 NameIn, NameOut
NameIn = Trim(Name)//' '
Call Get_OrMakeFileName( NameIn, NameOut )
Open(io,file=NameOut,access="APPEND")
End
I don't understand the Character*(*) name syntax. Isn't the typical way to declare string variables simply. character :: name*4 with the *4 part designating the number of characters? Can anyone please explain the purpose of this alternate syntax? What kind of object does it generate?
In short: character*(*) declares a character variable of assumed length.
There are a number of ways of declaring the length of a character variable. One, as seen in the question's code, is
character*1023 ...
where a literal constant follows the *. Equivalent to that is
character([len=]1023) ...
(len= being optional). In this case the length needn't be a literal constant.
These two forms declare a variable of a particular length. There are two other forms of a length for a character variable:
assumed length - character([len=]*) ... ;
deferred length - character([len=]:) ....
Like with character*1023 the assumed and deferred length declarations may be written in this style:
character*(*) ... ! Assumed length
character*(:) ... ! Deferred length
character*(1023) ... ! For completeness
Well, what does "assumed length" mean?
For a dummy argument such as Name it's length is taken from the length of the actual argument of the procedure. With character :: Name*4 the argument is of length 4, regardless of the length of the argument to the subroutine (as long as it's of length at least 4). When the dummy is of assumed length it is of length 12 if the argument is of length 12, and so on.
Although not in the question, a character named constant may also assume its length from the defining expression:
character*(*), parameter :: label='This long'
Deferred length is left to other questions.
Basically, here's my problem. I'm calling someone else's FORTRAN functions from my C++ code, and it's giving me headaches. Some code:
function c_error_message()
character(len = 255) :: c_error_message
errmsg(1:9) = 'ERROR MSG'
return
end
That's the FORTRAN function. My first question is: Is there anything in there that would cause a segfault?
If not, then second: What does that return? A pointer?
I'm trying to call it with the following C statement:
char *e = c_error_message_();
That causes a segfault.
c_error_message();
That too causes a segfault.
I declared c_error_message_() earlier on with the following code:
extern"C" {
char* c_error_message_();
}
Would declaring a function with a different return type than the actual return type cause a segfault?
I'm at a loss. Thanks for any replies.
Here is a method that works. When I tried to use the ISO C Binding with a function returning a string, the compiler objected. So if instead you use a subroutine argument:
subroutine fort_err_message (c_error_message) bind (C, name="fort_err_message")
use iso_c_binding, only: C_CHAR, C_NULL_CHAR
character (len=1, kind=C_CHAR), dimension (255), intent (out) :: c_error_message
character (len=255, kind=C_CHAR) :: string
integer :: i
string = 'ERROR MSG' // C_NULL_CHAR
do i=1, 255
c_error_message (i) = string (i:i)
end do
return
end subroutine fort_err_message
The Fortran is a bit awkward because technically a C-string is an 1D array of characters.
And example C code to demo that this works:
#include <stdio.h>
void fort_err_message ( char chars [255] );
int main ( void ) {
char chars [255];
fort_err_message ( chars );
printf ( "%s\n", chars );
return 0;
}
Since the second line declares a name that is the same as the function name, it is declaring the type of the function return, namely a scaler character string of 255 characters. But in theory this doesn't tell us the internal API -- that is up the the compiler. I don't know where "errmsg" comes from -- it must be declared elsewhere -- perhaps a global variable as suggested by Michael Anderson. Or maybe this is a mistake and the line should be c_error_message = "ERROR MSG". (There is no need to designate the sub-string range -- the rest of the string will be filled with blanks.) IMO, the best approach to calling Fortran from C (or vice-a-versa) is to use the ISO C Binding, which will cause the Fortran compiler to use a C compatible Interface. I haven't done a function returning a string, but have done strings as arguments.
FORTRAN functions return the value assigned to the function name. The type returned is specified by the function definition, and in this case, it is returning an character string 255 characters long. I think the type mismatch is why you are segfaulting. So what C type should you use? I don't know.
I found this Using C with FORTRAN page, and the author strongly recommends using FORTRAN subtroutines and calling them as C functions returning type void.
Here is an F95 quick reference.