Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29274 Discussions

How to convert an integer into a Character

patuco
Beginner
5,630 Views
HI everyone,
I am stuck in a pair of problems i do not have any clue how to solve. If anyone could help me it would be great
Here they are:
1.- i have a function which have to receive as second parameter an string. I am becoming from a native an integer but i do not know how to convert it to an string, and i can not change the other function to makethe second parameter able to be an integer, it has to be a character which maximum lengthshould be 60.
Here is what i am working with:
SUBROUTINE SETCOL(NEWCOL)
!MS$ATTRIBUTES DLLEXPORT,STDCALL,ALIAS:'_Setcol@4'::SETCOL
INTEGER NEWCOL
CHARACTER(2) ARRAKY
write(*,*)' val '
write(*,*) NEWCOLLISION
write(*,*)' val '
ARRAKY= NEWCOLLISION
ARRAKY= TRIM(ARRAKY)//CHAR(0)
write(*,*)'aux '
write(*,*) ARRAKY
write(*,*)'aux '
CALL LVG('SCOL',ARRAKY)
END SUBROUTINE

val

3

val

aux

(two squares)

aux

2.- I am trying to store in a char what i am becoming from a native but i am getting the same behaviour.

SUBROUTINE SETMOL(NEWMOL)
!MS$ATTRIBUTES DLLEXPORT,STDCALL,ALIAS:'_Setmol@4'::SETMOL
CHARACTER(20) NEWMOL
CALL LVG('MEX',NEWMOL)
END SUBROUTINE

I do not know why in this case i am becoming the chian correctly but when i call the function only squares are sent

Many Thanks.

0 Kudos
16 Replies
Les_Neilson
Valued Contributor II
5,630 Views

You need to look at "internal I/O"

eg :

character*60 :: a_string

integer :: a_number

write(a_string,*) a_number

In your case : WRITE(ARRAKY,*) NEWCOLLISION

Note : you may wish to use a specific format in place of the * whichputs a leading space at the beginning of the string

Les
0 Kudos
Les_Neilson
Valued Contributor II
5,630 Views
I just noticed you have ARRAKY as character*2 It needs to be as big as the string representation of the number you are writing PLUS one character for the char(0) you concatenate on to it.
For exampleif your number is in the hundreds (say 345) then ARRAKY needs to be character*4 (3+1 for the char(0)) and so on.
Les
0 Kudos
patuco
Beginner
5,630 Views
Thanks a lot,
i am trying your idea and it is partially working.Partially becausethe squares are still coming out, i do not understand why, besides the fact i am not familiar with the fortran writting formats.
0 Kudos
patuco
Beginner
5,630 Views
upss sorry you are right, the maximum value of the integer will be 20,
After performing some tests i got the minimum size of the array for the program to work is 16

Message Edited by patuco on 03-13-2006 10:11 AM

0 Kudos
patuco
Beginner
5,630 Views

A little bit more explanation because i did not find the solution of both problems. Anyone can help me?:

1.-

SUBROUTINE SETCOL(NEWCOL)
!MS$ATTRIBUTES DLLEXPORT,STDCALL,ALIAS:'_Setcol@4'::SETCOL
INTEGER NEWCOL, aux
CHARACTER*16 :: ARRAKY
ARRAKY = ' '
WRITE(ARRAKY,*) NEWCOL
ARRAKY= TRIM(ARRAKY)//CHAR(0)
CALL COMLVG('SCOL',ARRAKY)

The fact is that the integer the subroutine receives is ok, the porblem is in the conversion, because some characters are being added, and i do not know how to avoid it.

2 in the second one I am trying to store in a char * in fortran what i am sending from a native written in C++ but the message sent is not what i supposed.
Here is what I am facing with:



int size = 20;
char * buf ;
printf("Calling the c function ");
buf = (char *)calloc(size,sizeof (char));
buf = (char *)env->GetStringUTFChars(prompt,NULL);
printf("String c1: %s ", buf);
printf(" Calling fortran ");
Setname(buf);

here the variable buf stores sorrectly what i am interested in
but in fortran i become something totally different ans strange.
the call to the native is as follows:

extern "C" void __stdcall Setname(const char *);

And the native:


SUBROUTINE SETNAME(NEWMOL)
!MS$ATTRIBUTES DLLEXPORT,STDCALL,ALIAS:'_Setname@4'::SETNAME

CHARACTER(20) NEWMOL
WRITE(*,*) "fortran "
WRITE(*,*) NEWMOL
WRITE(*,*) "end fortran "
CALL COMLVG('SET',NEWMOL)
END SUBROUTINE

I though it is something with c an the communication but i do not know where is the mistake. It can not be in fortran because it is not becoming correctly the string. If anyone could help me it would be great.

Many Thanks.

Message Edited by patuco on 03-14-2006 04:33 AM

0 Kudos
Les_Neilson
Valued Contributor II
5,630 Views

OK First problem - though it may just be a typing mistake.

You have subroutine setcol with a dummy argument of NEWCOL, but later you are using NEWCOLLISON to write to arraky. What is NEWCOLLISION?

Les

0 Kudos
patuco
Beginner
5,630 Views
The typing mistakewas because i tryed to make easier the code i am usingbesides the facti had some coments in spanish so i deleted some parts of the code which are unneccesaryandwould made bigger the post. That means i replaces NEWCOLLISION for NEWCOL just because is shorter and the purpose is the same.
SUBROUTINE SETCOL(NEWCOL)
!MS$ATTRIBUTES DLLEXPORT,STDCALL,ALIAS:'_Setcol@4'::SETCOL
INTEGER NEWCOL
CHARACTER(2) ARRAKY
write(*,*)' val '
write(*,*) NEWCOL
write(*,*)' val '
ARRAKY= NEWCOL
ARRAKY= TRIM(ARRAKY)//CHAR(0)
write(*,*)'aux '
write(*,*) ARRAKY
write(*,*)'aux '
CALL LVG('SCOL',ARRAKY)
END SUBROUTINE
0 Kudos
anthonyrichards
New Contributor III
5,630 Views

As far as I can see, Les Neilson has already pointed you to the correct form that you want.

When you program ARRAKY (a 2-character variable) = NEWCOL (an integer= 20, say for arguments sake) you will get the bit pattern representing the integer copied into ARRAKY, which willNOT be identical to the bit pattern that the character string '20' requires. You must use the internal write

WRITE(ARRAKY,'(i2')) NEWCOL

if you want the character string 'nn' to be stored in ARRAKY from integer 'nn' stored in NEWCOL.

0 Kudos
patuco
Beginner
5,630 Views

Thanks for the replies Les and Anthony.

The fact is that the subroutine is becoming the value but at the same time adding to it some trush. I do not know how to avoid or even eliminate it. I do not know how to trim in Fortran or if i have to force the chain with length.

0 Kudos
anthonyrichards
New Contributor III
5,630 Views
If I try to compileCode:
	INTEGER NEWCOL
	CHARACTER*2 ARRAKY
	
	NEWCOL=2
	ARRAKY=NEWCOL

	WRITE(*,*) "NEWCOL= ", NEWCOL
	WRITE(*,*) "ARRAKY= ", ARRAKY
The compiler, quite rightly, objects, telling meC:F90DFCODEVintegercharacterintegercharacter.f90(26) : Error: A CHARACTER data type is required in this context. [NEWCOL]
ARRAKY=NEWCOL
---------------^
Error executing df.exe.
integercharacter.obj - 1 error(s), 0 warning(s)

So it is a mystery to me that you can get your code to even compile.
0 Kudos
Les_Neilson
Valued Contributor II
5,630 Views

Looking at the second piece of code you posted

character*16 arraky

arraky = ' '

write(arraky,*) newcollision

arraky = trim(arraky)//char(0)

If newcollision is 20 then arraky should be 10 spaces followed by '20' followed by char(0) (I've just written a small test program to do just that)

Where are you "printing" the value of arraky?Could you be passing a string of length 16 (arraky) to a subroutine but in that subroutine you have declared the dummy argument to be longer than 16 andprintingthat string? which produces the "squares" (which are merely a substitute for unprintable characters) If so then you should declare the dummy argument to be character(*) string_name.

Another thought : with the internal write you could replace the * with '(i0)' which will left justify the string if you required that.

Les

0 Kudos
patuco
Beginner
5,630 Views
Anthony it was the first approach ive tryed before started. Both of you were right in using write, what is what i am trying to do, but as i comment in the last post, some character are being added and these are making me crazy because the program is been blocked
0 Kudos
patuco
Beginner
5,630 Views

Gracias, Les, i think u found the problem with the squares, the LVG have the Character butwith a size of72, so if i am not wrong i should declared in newcol as 72.

Another point just because ive no idea how char * works in Fortran, instead of declaring the char 72 i can do it like char *, but shouldn't i to reserve the memory, like in C using malloc??

Thanks.

0 Kudos
Les_Neilson
Valued Contributor II
5,630 Views

OK. You should either :

declare arraky as character(72)

or change LVG to declare the passed in string as character(*) (always assuming the LVG routine is also Fortran)

The second option is better since you call LVG from elsewhere

ie from SETMOL (and possibly other places?) where NEWMOL is declared as character(20). If you cannot change LVG for some reason,then you need to change NEWMOL to character(72) AND change whatever subroutine(s) calls SETMOLso that theypass a character(72) string and so on up the chain.

You do not need to "malloc" any space in Fortran forthe character string as the declaration "CHARACTER(72) :: ARRAKY" does it for you.

If you can get the Fortran routines sorted out then you can start to look at the interface to the C routines. Though it might be worth pointing out that the string coming from C will presumably have a char(0) at the end of it. This won't cause any problem to Fortran but you may need to process the string to replace it with a blank and pad the remainder of the string with blanks too.Alsoif you are passing a string from Fortranto C to allow an extra character for the null terminator.

Les

0 Kudos
patuco
Beginner
5,630 Views

Thanks a lot guys,

as i wrote, your suggestion are working, and you save my head. Thanks

I do not want to be exasperating, but i have to implement a last thing i am getting some troubles. I am sending some char * to fortran from c but fortran is receiving again some unreadable messages. I can not find the sol.

Thanks

0 Kudos
Les_Neilson
Valued Contributor II
5,630 Views

OK I have something where I call Fortran from c++ but should be similar.

Fortran code :

integer*4 function DFOpenClt(cltFileSpec, bIsNew)

character(len=200), intent(in):: cltFileSpec

integer*4, intent(in) :: bIsNew

... code ...

end function

c++ code

extern "C" {

int __stdcall DFOpenClt(char* FileSpec, UNIT iLen, int isnew)

}

char sFile[200];

int lWriteFile = 1;

(build file name in sFile and set iLen to length of string)

nError = DFOpenClt(sFile, iLen, &lWriteFile);

(where iLen is the length of the string sFile)

Hope this helps

Les

0 Kudos
Reply