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

How to remove NUL character from end of variable in output file

Bakhbergen
Novice
4,663 Views

I am using yamajun's program to get MAC ADDRESS by Fortran:
https://software.intel.com/en-us/forums/intel-fortran-compiler/topic/299146
https://fortran66.hatenablog.com/entries/2008/02/28
https://software.intel.com/en-us/forums/intel-fortran-compiler/topic/297960
Sending the results to output *.txt file
WRITE (18,'(8A)') AdapterInfo(i)%IpAddressList%IpAddress, AdapterInfo(i)%IpAddressList%IpMask
gives the following:
...
0.0.0.0NULNULNULNULNULNULNULNULNUL0.0.0.0NULNULNULNULNULNULNULNULNUL
...
XXX.XXX.X.XXXNULNULNULXXX.XXX.XXX.XNULNULNUL
where X denotes different numbers.
I would like to see only addresses in the file. Please advise how to remove null string characters.
 

0 Kudos
12 Replies
Arjen_Markus
Honored Contributor I
4,663 Views

You will have to replace the NUL characters by, say, spaces - or if the length of the addresses is constant, you could write a substring instead.

Most general:

function removenuls( string) 
   character(len=*) :: string
   character(len=len(string)) :: removenuls

   integer :: pos

   pos = index( string, achar(0) )
   if ( pos > 0 ) then
       removenuls = string(1:pos)
   else 
       removenuls = string
   endif
end function removenuls

It does assume that there are no meaningful characters after the first NUL, but that is generally the case with strings coming from C. An alternative to achar(0) is the c_null_char parameter from ISO_C_BINDING.

 

0 Kudos
Steve_Lionel
Honored Contributor III
4,663 Views

Really the right way to do this is to use INDEX to find the first NUL, use that to compute the length of the actual text, and write only the substring. Don't rely on characters following the first NUL to be anything specific.

0 Kudos
Bakhbergen
Novice
4,663 Views

Arjen, Steve, thanks. I've tried the following:
WRITE (18,'(8A)') AdapterInfo(i)%IpAddressList%IpAddress(1:INDEX(AdapterInfo(i)%IpAddressList%IpAddress, ACHAR(0))-1), AdapterInfo(i)%IpAddressList%IpMask(1:INDEX(AdapterInfo(i)%IpAddressList%IpMask, ACHAR(0))-1)
which causes the following errors:
*.f90(119): error #6514: A substring must be of type CHARACTER.   [IPADDRESS]
*.f90(119): error #6362: The data types of the argument(s) are invalid.   [INDEX]
*.f90(119): error #6514: A substring must be of type CHARACTER.   [IPMASK]
*.f90(119): error #6362: The data types of the argument(s) are invalid.   [INDEX]

0 Kudos
Arjen_Markus
Honored Contributor I
4,663 Views

You should use INDEX(AdapterInfo%lpAddressLIst^%lpAddress,ACHAR(0) ) -1 as the end value, Note the location of the -1.

0 Kudos
Steve_Lionel
Honored Contributor III
4,663 Views

FWIW, I wrote a proposal for Fortran 202X that would make dealing with C strings easier.

0 Kudos
Paul_Curtis
Valued Contributor I
4,663 Views

The following code, abstracted from a larger program, accomplishes what the OP asked for:

MODULE MAC  
    USE ifwinty  
    USE charfunc
    IMPLICIT NONE 
    PUBLIC GetMacInfo       
    PRIVATE
    SAVE
    
    INTEGER, PARAMETER :: MAX_ADAPTER_DESCRIPTION_LENGTH = 128  
    INTEGER, PARAMETER :: MAX_ADAPTER_NAME_LENGTH        = 256  
    INTEGER, PARAMETER :: MAX_ADAPTER_ADDRESS_LENGTH     =   8  
    INTEGER, PARAMETER :: MIB_IF_TYPE_ETHERNET           =   6  ! Ipifcons.h

    TYPE IP_ADDRESS_STRING  
        CHARACTER(LEN=16) :: String  
    END TYPE IP_ADDRESS_STRING
     
    TYPE IP_MASK_STRING  
        CHARACTER(LEN=16) :: String  
    END TYPE IP_MASK_STRING
      
    TYPE t_IP_ADDR_STRING   
        INTEGER (LPLONG)         :: pNext  
        TYPE (IP_ADDRESS_STRING) :: IpAddress  
        TYPE (IP_MASK_STRING)    :: IpMask  
        INTEGER (DWORD)          :: Context  
    END TYPE t_IP_ADDR_STRING
    
    TYPE t_IP_ADAPTER_INFO  
        INTEGER(LPLONG)         :: pNext   
        INTEGER(DWORD)          :: ComboIndex  
        CHARACTER(LEN=MAX_ADAPTER_NAME_LENGTH+4)        :: AdapterName  
        CHARACTER(LEN=MAX_ADAPTER_DESCRIPTION_LENGTH+4) :: Description  
        INTEGER(UINT)           :: AddressLength  
        INTEGER(BYTE)           :: Address(MAX_ADAPTER_ADDRESS_LENGTH)  
        INTEGER(DWORD)          :: Index  
        INTEGER(ULONG)          :: iType  
        INTEGER(ULONG)          :: DhcpEnabled  
        INTEGER(LPLONG)         :: pCurrentIpAddress   
        TYPE(t_IP_ADDR_STRING)  :: IpAddressList  
        TYPE(t_IP_ADDR_STRING)  :: GatewayList  
        TYPE(t_IP_ADDR_STRING)  :: DhcpServer  
        INTEGER(BOOL)           :: HaveWins  
        TYPE(t_IP_ADDR_STRING)  :: PrimaryWinsServer  
        TYPE(t_IP_ADDR_STRING)  :: SecondaryWinsServer  
        INTEGER(ULONG)          :: LeaseObtained  
        INTEGER(ULONG)          :: LeaseExpires  
    END TYPE t_IP_ADAPTER_INFO
     
    !   must link with IpHlpApi.lib to access this API function;
    !   this interface is not included in ifwinty
    INTERFACE  
        INTEGER(BOOL) FUNCTION GetAdaptersInfo (arg1, arg2)  
            USE ifwinty  
            !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'GetAdaptersInfo' :: GetAdaptersInfo  
            INTEGER(LPLONG) :: arg1  
            INTEGER(LPLONG) :: arg2  
        END FUNCTION  
    END INTERFACE
    
CONTAINS  
     
    
    SUBROUTINE GetMacInfo (hwnd, id)
        USE contwrap
        IMPLICIT NONE
        
        !   dialog window handle and set of static-text IDs for display
        INTEGER(HANDLE), INTENT(IN)         :: hwnd
        INTEGER, INTENT(IN), DIMENSION(4)   :: id 
            
        CHARACTER(LEN=200)                  :: msg
        INTEGER                             :: i, nc, count
        INTEGER, PARAMETER                  :: acount = 16
        TYPE(t_IP_ADAPTER_INFO),ALLOCATABLE :: ai(:)  
        
        count = 0
        
        !   allow for multiple adapters
        ALLOCATE (ai(acount))
        nc = SIZEOF(ai)
        IF (GetAdaptersInfo(LOC(ai), LOC(nc)) == 0) THEN  
            
            DO i = 1, acount
                SELECT CASE (ai(i)%iType)
                CASE (MIB_IF_TYPE_ETHERNET)
                    
                    !   line 1: description and MAC address
                    !nc = INDEX(ai(i)%Description, CHAR(0)) - 1
                    !WRITE (msg, '(A,",  ",5(Z2.2,"-"),Z2.2)') &
                    !    ai(i)%Description(1:nc),              &
                    !    ai(i)%Address(1:ai(i)%AddressLength)
                    nc = INDEX(ai(i)%Description, CHAR(0))
                    msg = ai(i)%Description(1:nc)
                    count = count + 1
                    CALL StaticSetText (hwnd, id(count), msg)
                    CALL ControlSetVisible (hwnd, id(count), .TRUE.)
                    
                    !   line 2: IP and Gateway addresses
                    WRITE (msg, '("IP Addr: ",A,"  Gateway: ",A)')  &
                        ai(i)%IpAddressList%IpAddress%string,       &
                        ai(i)%GatewayList%IpAddress%string
                    CALL remove_nulls (msg)
                    count = count + 1
                    CALL StaticSetText (hwnd, id(count), msg)
                    CALL ControlSetVisible (hwnd, id(count), .TRUE.)
                    
                    IF (count >= 4) EXIT
                END SELECT
                IF (ai(i)%pNext == NULL) EXIT  
            END DO
        
        END IF
        DEALLOCATE (ai)
    
    END SUBROUTINE GetMacInfo
    
    
     
    
      
END MODULE MAC  

 

0 Kudos
JohnNichols
Valued Contributor III
4,661 Views

In the Intel Fortran Forum -- I get an error on trying to post a new topic 

Old form please resubmit  

I have rebooted and done a scannow and it still happens -- I am not sure if this work as I have tried many times - so I posted to the MKL as well 

This is my last go -- fingers crossed 

 

any ideas?

0 Kudos
jimdempseyatthecove
Honored Contributor III
4,663 Views

On 5/11/20 I experienced several dropped contacts with the IDZ forums (aliens screen) . A few times after composing a lengthy post. I am in the habit of copying post to paste buffer before clicking on Submit, so I don't lose my effort. In one or two minutes connection is reestablished and I can re-post via paste buffer.

Jim Dempsey

0 Kudos
Bakhbergen
Novice
4,663 Views

I appreciate everyone's effort in helping to resolve this.
After a few more attempts last week, I decided to leave it as it is because I found that NULs disappear when *.txt file is open using Notepad and WordPad.
Note that earlier I was using Notepad++, which shows some NULs in the output *.txt file.

0 Kudos
GVautier
New Contributor II
4,664 Views

Bekbauov, Bakhbergen wrote:

NULs disappear when *.txt file is open using Notepad and WordPad.

NULL characters doesn't disappear they just are not shown. With Notepad++, you can choose to show special characters or not. See in the display menu for special characters item.

0 Kudos
Bakhbergen
Novice
4,664 Views

Vautier, Gilles wrote:

0 Kudos
Bakhbergen
Novice
4,664 Views

Gilles, sure, you're right. I should probably have written that NULs "disappear" when *.txt file is open using Notepad and WordPad with default settings.

0 Kudos
Reply