McIDAS Programmer's Manual
Version 2006

[Search Manual] [Table of Contents] [Go to Previous] [Go to Next]


Conversion utilities

The McIDAS-X library provides many practical conversion utilities for your applications. These functions were developed because the standard Fortran and C libraries didn't provide sufficient routines for performing the conversions needed in McIDAS-X.

This section describes the functions available in for performing these tasks:

 

For additional information about the conversion functions described in this section, see the online man pages provided with the McIDAS-X software.

Byte- and word-level manipulation

When writing applications for McIDAS-X, you may find it necessary to manipulate information at the byte level. This section describes the McIDAS-X library functions that provide byte-level manipulation for Fortran routines and gives examples of specific byte-level operations.

When writing C functions, you can usually use the byte manipulation routines provided in the standard C library. However, you may also want to use some of the functions presented here since they have special features. Most of the byte moving routines in this section are Fortran-callable functions written in C that use the byte manipulation routines provided with the standard C library.

This section contains some terms that may be unfamiliar to you. They are defined below.

Be careful when using the byte manipulation functions below. Most do not protect against memory overflow.

Fortran function Description

alit

copies four bytes of a character string to a single precision floating-point variable

clit

copies four bytes of an integer value to a 4-character string variable

crack

copies a specified number of consecutive bytes from a source buffer into an array of words; each word is a 32-bit- long memory segment; the resulting byte values are stored in the least significant byte for each element of the word array

dlit

copies eight bytes of a character string to a double precision floating-point variable

ic

returns the value at a specific byte location (0-based) in a buffer

lit

copies four bytes of a character string to a 1-word integer variable

movb

copies a number of bytes from a source buffer to a specified, 0-based offset in a destination buffer

movblk

copies a number of elements of a specified size from a source buffer to a destination buffer with incremental offsets for both the source and destination buffers (0-based)

movc

copies a number of bytes beginning at a specified byte location in a source buffer (0-based) to a specified offset in a destination buffer (0-based)

movcw

copies the entire contents of a character string buffer to an integer buffer

movh

copies a number of half-words from a source buffer to a destination buffer with half-word increments

movpix

copies a number of elements from a source buffer to a destination buffer with incremental offsets for both the source and destination buffers

movw

copies a number of words from a source buffer to a destination buffer

movwc

copies the contents of an integer buffer to a character string buffer, copying as many bytes as can be stored in the destination string

mpixel

copies elements of a specified size in a source buffer to a destination buffer with elements of a specified size

mpixtb

like mpixel, but additionally converts variable-sized elements in a buffer based on a lookup table

pack

moves the least significant byte from each element of a word array and compresses it into consecutive bytes in a buffer

pack2

moves the least significant byte from each element of a half-word array and compresses it into a consecutive byte string

stc

places a byte value into a specified, 0-based byte location in a buffer

swbyt2

switches the byte ordering of a half-word to big-endian; this function has no effect on a machine that uses big-endian as its native storage format

swbyt4

switches the byte ordering of a word to big-endian; this function has no effect on a machine that uses big-endian as its native storage format

zeros

sets a number of bytes in an array to zero

Below are some code segments demonstrating the byte manipulation utilities. Similar functions are grouped together. The more commonly used functions are discussed first. Note that some of the byte manipulation functions will behave differently on big- and little-endian machines. All the examples in this section assume big-endian.

 

For more information about these byte manipulation functions, see the online man pages provided with the McIDAS-X software.

Extracting and inserting a byte value

The ic function lets you extract the value of individual bytes within a memory segment, as shown in the sample code below. It is useful when checking for ASCII control characters in a byte stream, for example.

c---   function ic example 

    integer oldval
    integer val
    data oldval/z'abcdef01'/

    val = 0

c---    extract the second byte, 0-based, from 'oldval' and
c---    place the result in 'val'

    val = ic (oldval, 2)


c---    the resulting value in 'val' will be:
c---        hex
c---        000000ef

The stc function lets you insert a byte value in a particular location in a memory segment. It is useful for substituting control characters with a blank before sending the output to a printer, for example.

c---   function stc example

    integer src
    data src/z'000000ba'/

    val = 0

c---    place the byte value from 'src' into the second byte, 
c---    0-based, in 'val

    call stc (src, val, 2)

c---    the resulting value in 'val' will be:
c---        hex
c---        0000ba00

Switching the byte ordering

When you develop applications that read data from a remote data file or data stream, you usually need to know the byte ordering of the source data. In general, IBM-RISC, SUN, SGI and HP are big-endian machines, and DEC and Intel are little-endian machines.

The swbyt2 and swbyt4 functions have no effect on big-endian machines; however, they flip the bytes on little-endian machines, making the least significant byte the most significant byte. Because this byte ordering is transparent, you only have to maintain one set of source code for both types of architecture. When transferring data between systems, call swbyt# before writing and after reading.

Use the swbyt# calls on known integer values only; don't use them to process character strings.

c---   function swbyt4 example

    integer src(2)
    data src/Z'abcdef01',Z'23456789'/

c---    if applicable, flip the 2 elements of the array 'src'
c---    into network-byte ordering. 
    
    call swbyt4 (src, 2)

c---    Because swbyt4 is a machine-dependent operation the
c---    outcome of this call will vary. On big-endian machines,
c---    swbyt4 will not modify the values in the buffer 'src'.
c---    On little-endian machines it will.
c---          big-endian    little-endian
c---  src()   input value   input value     output value
c---  1       abcdef01      01efcdab        abcdef01
c---  2       23456789      89674523        23456789

c---    function swbyt2 example

    integer*2 src(4)
    data src/Z'abcd',Z'ef01',Z'2345',Z'6789'/
    
c---    if applicable, flip the 4 elements of the array 'src'
c---    into network-byte ordering. 
    
    call swbyt2 (src, 4) 

c---    Because swbyt2 is a machine-dependent operation the
c---    outcome of this call will vary. On big-endian machines,
c---    swbyt2 will not modify the values in the buffer 'src'.
c---    On little-endian machines it will.
c---          big-endian    little-endian
c---  src()   input value   input value    output value
c---  1       abcd          cdab           abcd
c---  2       ef01          01ef           ef01
c---  3       2345          4523           2345
c---  4       6789          8967           6789

Copying bytes

The McIDAS-X library contains several functions for copying bytes. Some are simple copy routines, while others provide for more complicated byte moving operations.

movb and movc

The movb and movc functions copy a specified number of bytes from one buffer to another. The only difference between the two is that movb only lets you specify a destination buffer offset, while movc also lets you specify an offset from the source buffer.

c---   function movb example

    integer src(4)
    integer dest(4)
    data src/Z'abcdef01',Z'23456789',Z'fedcba98',Z'09080706'/

    call zeros (dest, (4 * 4))

c---    copy 15 bytes from the array 'src' into the array 'dest'
c---    beginning at byte 1.

    call movb (15, src, dest, 1)

c---    The resulting value in 'dest' will be:
c---        dest()  hex
c---        1   00abcdef
c---        2   01234567
c---        3   89fedcba
c---        4   98090807

c---    function movc example

    integer src(4)
    integer dest(4)
    data src/Z'abcdef01',Z'23456789',Z'fedcba98',Z'09080706'/

    call zeros (dest, (4 * 4))

c---    copy 14 bytes from the array 'src' beginning at byte 5
c---    into the array 'dest' beginning at byte 2.

    call movc (14, src, 5, dest, 2)

c---    The resulting value in 'dest' will be:
c---        dest()  hex
c---        1   00004567
c---        2   89fedcba
c---        3   98090807
c---        4   06050403

movcw

The byte copying function movcw lets you move a character string into an integer buffer. This function doesn't convert the value stored in a string to its integer representation. It merely moves the bytes into an integer buffer.

Before using this function, verify that the destination buffer is as least as large as the source string, as movcw will move the entire source string to the destination address without protecting against buffer overflow.

c--    function movcw example

    integer dest(3)
    character*12 cvar12

    call zeros (dest, (4 * 3))

    cvar12 = 'June Cleaver'
       call movcw (cvar12, dest)

c---    The resulting elements of the array 'dest' will be:
c---        dest()  hex         string
c---        1   4a756e65    June
c---        2   20436c65     Cle
c---        3   61766572    aver

movblk and movpix

Use the byte-copying functions movblk and movpix for complicated byte copying operations. These functions let you specify the following:

Both the movblk and movpix functions let you copy bytes from one buffer to another with incremental offsets for both the source and destination buffers. However, the movblk function has an additional feature that lets you specify the length of each source element to move. The movpix function has a fixed, source-byte length of one and includes parameters for sampling bytes and moving a buffer in reverse order.

The movblk function is shown in the sample code below.

c---   function movblk example

    integer src(16)
    integer dest(32)
    data src/Z'abcdef01',Z'23456789',Z'fedcba98',Z'09080706',
         Z'05040302',Z'010a0b0c',Z'0d0e0f11',Z'22334455',
         Z'66778899',Z'aabbccdd',Z'eeff1213',Z'14151617',
         Z'18191a1b',Z'1c1d1e1f',Z'21232425',Z'26272829'/

    call zeros (dest, (4 * 32))

c---    copy 4 elements that are 3 bytes long beginning at byte 1
c---    in 'src' into 'dest' beginning at byte 6. The increment
c---    between elements in the source buffer is 2 bytes, the
c---    increment between bytes in the destination buffer is
c---    7 bytes.

    call movblk (4, 3, src, 1, 2, dest, 6, 7)

c---    The resulting elements of the array 'dest' will be:
c---        dest()  hex
c---        1   00000000
c---        2   0000cdef
c---        3   01000000
c---        4   00012345
c---        5   00000000
c---        6   45678900
c---        7   00000089
c---        8   fedc0000

The movpix function is shown in the sample code below.

c---   function movpix example

    integer src(16)
    integer dest(32)
    data src/Z'abcdef01',Z'23456789',Z'fedcba98',Z'09080706',
         Z'05040302',Z'010a0b0c',Z'0d0e0f11',Z'22334455',
         Z'66778899',Z'aabbccdd',Z'eeff1213',Z'14151617',
         Z'18191a1b',Z'1c1d1e1f',Z'21232425',Z'26272829'/

    call zeros (dest, (4 * 32))

c---    copy 5 elements beginning at byte 1 in 'src' into 'dest'
c---    beginning at byte 6. the increment between elements in 
c---    the source buffer is 2 bytes, the increment between bytes
c---    in the destination buffer is 7 bytes.

    call movpix (5, src, 1, 2, dest, 6, 7)

c---    The resulting elements of the array 'dest' will be:
c---        dest()  hex
c---        1   00000000
c---        2   0000cd00
c---        3   00000000
c---        4   00010000
c---        5   00000000
c---        6   45000000
c---        7   00000089
c---        8   00000000
c---        9   0000dc00

Converting byte values

The mpixtb function converts the contents of a buffer to new values based on a lookup table included in the calling sequence. Simultaneously, it optionally converts the 1-, 2- or 4-byte data to a different length. This function is used in satellite calibration routines when a lookup table is generated to convert data from one physical quantity to another, such as raw values to temperature. The valid length conversions are 1, 2 or 4 bytes.

c---   function mpixtb example

    integer src(16)
    integer lookup(16)
    data src Z'abcdef01',Z'23456789',Z'fedcba98',Z'09080706',
         Z'05040302',Z'010a0b0c',Z'0d0e0f11',Z'22334455',
         Z'66778899',Z'aabbccdd',Z'eeff1213',Z'14151617',
         Z'18191a1b',Z'1c1d1e1f',Z'21232425',Z'26272829'/
    data lookup/15, 14, 13, 12, 11, 10, 9, 8,
             0,  1,  2,  3,  4,  5, 6, 7/

c---    convert 8 1-byte elements beginning at src array element 4
c---    into 2-byte elements that have been modified by the lookup
c---    table.

    call mpixtb (8, 1, 2, src(4), lookup)

c---    The elements of the array 'src' will be:
c---        original    new
c---        value hex   value hex
c---        09080706    00010000
c---        05040302    00080009
c---        010a0b0c    000a000b
c---        0d0e0f11    000c000d

The mpixel function expands and packs the data values in place. If the source of the data is one byte, but the application expects it as four bytes, mpixel converts the data without needing an additional buffer.

Moving byte streams

The literal conversion functions alit, dlit and lit move the byte contents of character strings to the basic Fortran variable types.

c---   functions alit, clit, dlit and lit examples

    character*4        cvar4
    character*8        cvar8
    character*4        cval
    integer                int_dest
    double precision       dbl_dest
    real                   rel_dest

    cvar4   = 'FRED'
    cvar8   = '& GINGER'
    
       rel_dest = alit (cvar4)
       int_dest = lit (cvar4)
       dbl_dest = dlit (cvar8)
       cval = clit (int_dest)

The clit function moves the contents of an integer variable to a 4-character variable. These routines do not convert the string to its integer representation. They merely move the byte stream into the new variable. The resulting value may not even be a valid representation on the machine.

Occasionally, you may need to move a byte stream into whole or half-word integer variables and back into a byte stream. You can use the crack, pack and pack2 functions for this purpose, as shown in the sample code below.

    integer src(2)
    integer dest(8)
    data src /Z''abcdef01',Z'23456789'/

c---   function crack example 

       call zeros (dest, (4 * 8))
       call crack (7, src, dest) 

c---    The resulting elements of the array ''dest' will be:
c---    dest()  hex  
c---    1   000000ab
c---    2   000000cd
c---    3   000000ef
c---    4   00000001
c---    5   00000023
c---    6   00000045
c---    7   00000067

c---    function pack example

    integer src(4)
    integer val
    data  src/Z'010000cd',Z'020000ef',Z'03000001',Z'04000023'/

    val = 0
    call pack(4, src(2), val)

c---    The resulting value in ''val' will be:
c---        hex
c---        cdef0123

c---   function pack2 example

    integer*2 src(4)
    integer val
    data src /Z'0f0e',Z'0d0c',Z'0b0a',Z'0908'/
            
    val = 0
       call pack2 (4, src, val)

c---    The resulting value in 'val' will be:
c---        hex
c---        0e0c0a08

Character string manipulation

This section describes the primary interfaces that you will use with character strings in McIDAS-X. These character-string functions were developed to do the following:

This section contains some terms that may be unfamiliar to you. They are defined below.

The string manipulation functions are listed alphabetically in the table below with a brief description.

C function Fortran function Description

fsalloc

not available

copies the contents of a Fortran string to a C string, dynamically allocating the memory necessary to store the resulting string

fslen

not available

returns the logical length of a C string needed to contain a blank-padded Fortran string

not available

ischar

indicates whether a string of four characters contains all printable characters

not available

isdgch

determines whether a Fortran string contains all digits, all letters, a mixture of letters and digits, or other characters

Mclocase

mclocase

converts uppercase characters in a string to lowercase

Mcstricmp

not available

performs a case-independent comparison of two C character strings

Mcstrnicmp

not available

performs a case-independent comparison of a specified number of characters in two C strings

Mcstrtodbl

mcstrtodbl

converts a character string in decimal point format to a double-precision value

Mcstrtodhr

mcstrtodhr

converts a character string in time format to a double- precision value

Mcstrtodll

mcstrtodll

converts a character string in lat/lon format to a double-precision value

Mcstrtohex

mcstrtohex

converts a character string in hexadecimal to an integer value

Mcstrtohms

mcstrtohms

converts a character string in time format to its components: hours, minutes, seconds

Mcstrtoihr

mcstrtoihr

converts a character string in time format to an integer value in units of hours/minutes/seconds

Mcstrtoill

mcstrtoill

converts a character string in lat/lon format to an integer value in units of degrees/minutes/seconds

Mcstrtoint

mcstrtoint

converts a character string to an integer value

Mcstrtoiyd

mcstrtoiyd

converts a character string representing a day to an integer representation of Julian day

Mcstrtofs

not available

copies a C character string to a Fortran character string

Mcupcase

mcupcase

converts lowercase characters in a string to uppercase

not available

nchars

indicates the starting and ending character positions (1-based) and length of a Fortran string

stralloc

not available

concatenates a variable number of C character strings into a single string pointer

These string manipulation functions are further described below with sample code fragments. Functions that perform similar tasks are grouped together, based on whether they convert strings, analyze strings, build strings or serve as string utilities.

 

For more information about these string manipulation functions, see the online man pages provided with the McIDAS-X software.

Converting string formats to integer values

The Mcstrtoint function converts a variety of string formats to integer values and returns an error status value less than zero when the calling routine enters an invalid string. To get a list of the string formats, enter the command ARGHELP INTEGER from the McIDAS-X command line.

To convert a hexadecimal string with Mcstrtoint, prefix the string with a dollar sign ($). When converting exponential representations with Mcstrtoint, be aware that it returns an error status if the string can't be completely represented as an integer. The sample code below converts several string formats to integer values.

{
  char        src_string[20];
  int         val;
  int         status;

  /*
   * -- convert the character string '4321' to an integer
   */

  (void) strcpy (src_string, "4321");
  status = Mcstrtoint (src_string, &val);

  /* upon exit, the integer value stored in 'val' will be 4321 */

  /*
   * -- convert the hexadecimal character string '2f' to an integer
   */

  (void) strcpy (src_string, "$2f");
  status = Mcstrtoint (src_string, &val);

  /* upon exit, the integer value stored in 'val' will be 47 */

  /* 
   * -- convert the exponential character string '234e3' to an integer
   */

  (void) strcpy (src_string, "234e3");
  status = Mcstrtoint (src_string, &val);

  /* upon exit, the integer value stored in 'val' will be 234000 */

  /* 
   * -- convert the exponential character string 2340e-1 to an integer
   */

  (void) strcpy (src_string, "2340e-1");
  status = Mcstrtoint (src_string, &val);

  /* upon exit, the integer value stored in 'val' will be 234 */

  /*
   * -- convert the exponential character string 2340e-2 to an integer
   */

  (void) strcpy (src_string, "2340e-2");
  status = Mcstrtoint (src_string, &val);

  /* 
   * this call will return an error because the actual value '23.4'
   * cannot be represented as an integer variable
   */
}

Converting string formats to double-precision values

The Mcstrtodbl function converts a variety of string formats to double- precision values and returns an error status value less than zero when the calling routine enters an invalid string. To get a list of the string formats, enter the command ARGHELP DECIMAL on the McIDAS-X command line. The sample code below shows how to use Mcstrtodbl.

{
  char      src_string[20];
  double    val;
  int       status;

  /*
   * -- convert the character string '-4321.1' to a double
   */

  (void) strcpy (src_string, "-4321.1");
  status = Mcstrtodbl (src_string, &val);

  /* upon exit, the value stored in 'val' will be -4321.1 */

  /*
   * -- convert the exponential character string '321.2-e3' to a double
   */

  (void) strcpy (src_string, "321.2e-3");
  status = Mcstrtodbl (src_string, &val);

  /* upon exit, the value stored in 'val' will be .3212 */
}

Converting time and latitude/longitude formats

The four functions below convert a variety of McIDAS-X time and latitude/longitude formats to double-precision and integer values.

To get a list of the time formats, enter the command ARGHELP TIME on the McIDAS-X command line. To get a list of the latitude/longitude formats, enter the command ARGHELP LATLON.

If your input string for Mcstrtodhr or Mcstrtoihr is the NULL string or colon (:), the value returned is the current system time. If you always want the current system time, use the McIDAS-X library function Mcgettime.

The calling sequence and valid string formats for Mcstrtodll and Mcstrtoill are identical to Mcstrtodhr and Mcstrtoihr, except the former will not return the current system time if the NULL string or colon string are passed as input.

{
  char        src_string[20];
  double      dval;
  int         val;
  int         status;

  /*
   * -- convert the string '421.1321' to a time
   */

  (void) strcpy (src_string, "421.1321");
  status = Mcstrtodhr (src_string, &dval);
  status = Mcstrtoihr (src_string, &val);

  /*
   * upon exit, 'dval' will contain 421.321 and 'val' will contain
   * 4210756
   */

  /*
   * -- convert the string '21:32:12' to a time
   */

  (void) strcpy (src_string, "21:32:12");
  status = Mcstrtodhr (src_string, &dval);
  status = Mcstrtoihr (src_string, &val);

  /*
   * upon exit, 'dval' will contain 21.536 and 'val' will contain 213212
   */

  /*
   * -- get current system time by entering the special character ":"
   */

  (void) strcpy (src_string, ":");
  status = Mcstrtodhr (src_string, &dval);
  status = Mcstrtoihr (src_string, &val);

  /*
   * upon exit, 'dval' and 'val' will contain the current system time
   * in their respective formats
   */
}

Converting time to hours, minutes, seconds

The Mcstrtohms function converts a character string of the format hh:mm:ss into its components. It returns the current time if the input string is the NULL string or colon (:) and returns an error status value less than zero when the calling routine enters an invalid string. To list the valid time formats, enter the command ARGHELP TIME on the McIDAS-X command line.

The sample code below shows how to use Mcstrtohms.

{
  int  hour, minute, sec;
  int  status;
  char src_string[20];

  /*
   * -- convert the string '21:32:12' to its components; hours,
   *    minutes and seconds
   */

  (void) strcpy (src_string, "21:32:12");
  status = Mcstrtohms (src_string, &hour, &minute, &sec);

  /*
   * upon exit, hour = 21, minute = 32 and sec = 12
   */
}

Converting a date in string format to a Julian day

The Mcstrtoiyd function converts a character string for a given day to a Julian day with integer value representation.

The format is ccyyddd, where:

It returns the current Julian day if your input string is the NULL string or slash (/) and returns an error status value less than zero when the calling routine enters an invalid string.

If your entered string does not include the century, the current century is assumed. If you always want the current system day, use the McIDAS-X library function Mcgetday.

To list the valid date formats, enter the command ARGHELP DATE on the McIDAS-X command line.

The sample code below shows the use of the Mcstrtoiyd function.

{
  int  day;
  int  status;
  char src_string[20];

  /*
   * -- convert the string "03-APR-1995" to a Julian day
   */

  (void) strcpy (src_string, "03-APR-1995");
  status = Mcstrtoiyd (src_string, &day);

  /*
   * upon exit, 'day' will contain 1995093
   */

  /*
   * -- convert the string "96/04/13" to a Julian day
   */

  (void) strcpy (src_string, "96/04/13");
  status = Mcstrtoiyd (src_string, &day);

  /*
   * upon exit, 'day' will contain 1996104, assuming you are
   * currently in the 1900s
   */

  /*
   * -- convert the string "1995366" to a Julian day
   */

  (void) strcpy (src_string, "1995366");
  status = Mcstrtoiyd (src_string, &day);

  /*
   * status will be less than 0 because there was no day 366
   * in 1995
   */

}

 

 

For more information about dates and time, see the section Day and time in this chapter.

Converting a C character string to Fortran

Mcstrtofs converts a C character string to a Fortran character string. If the source string is shorter than the destination string, the remaining bytes in the destination string are filled with the ASCII space character. If the C string is longer than the Fortran string, it is truncated in the Fortran string.

character*24 fullname

call getname (fullname)
call sdest (fullname,0)
:
:

void getname_ (char *fname, FsLen len_name)
{
  char string[72];
  int  status;

  (void) strcpy (string, "Ted Williams");
  status = Mcstrtofs (fname, string, len_name);

  return;
}

Converting a Fortran character string to C

The fsalloc function, which is called from a C routine, performs these tasks:

The fsalloc function does not allocate memory to store whitespace bytes at the end of the original source string. Because this function dynamically allocates memory, the calling program is responsible for freeing up the memory when finished with it. If allocation fails, the returned value is (char *) NULL. Calling routines should always test for this condition.

The code fragment below shows you how to use fsalloc.

character*24 fullname
data fullname/'Joe Dimaggio'/

call printhof (fullname)
:
:

void printhof_ (char *fname, FsLen len_name)
{
  char *cname;

  cname = fsalloc (fname, len_name);

  /*
   * if the memory allocation is successful, 'cname' will point
   * to 13 bytes of memory that have been filled with the
   * characters 'Joe Dimaggio' for the first 12 bytes and the
   * NULL byte for the final value. note that it will not
   * allocate the full 24 bytes of memory for this example
   * because the final 12 bytes of the original character
   * string are whitespace characters.
   */

  if (cname != (char *) NULL)
  {
    Mcprintf ("Hall of Famer: %s\n", cname);
    free (cname);
  }

  return;
}

Determining the contents of a string

The ischar function tells the calling routine if a string of four characters is from the printable ASCII character set, including the space character. The isdgch function tells the calling routine if a string of characters contains all digits, all letters, a mixture of digits and letters, or other characters. The sample code below shows the use of both functions.

    character*4  cvar4
    character*12 cvar12
    integer      status

    cvar4  = 'AbcD'
       status = ischar (cvar4)

c---    upon return, 'status' will contain the value 1 indicating
c---    that all 4 characters are printable.

    cvar12 = '3214as231G'
       status = isdgch (cvar12)

c---    upon return,'status' will contain the value 0 indicating 
c---    that the string contains a mixture of letters and digits.

Determining the number of characters in a string

The nchars function returns the location of the first and last non-blank characters (1-based) along with the length of the printable characters in a string. This function does not consider space characters printable when determining the values to return for starting and ending positions.

    character*12 cvar12
    integer status
    integer begchr
    integer endchr
    integer length

    cvar12 = '  Ty Cobb'
       length = nchars (cvar12, begchr, endchr)

c---    upon exit, 'length' contains the value 7, 'begchr'
c---    contains the value 3, and 'endchr' contains the value 9.

Comparing two strings

Mcstricmp performs a case-insensitive string comparison between two entire strings. Mcstrnicmp performs a similar comparison, but only for the number of bytes specified by the calling routine. Both functions return a value less than zero if the lexical value of the first string is less than that of the second string. They return a value greater than zero if the lexical value in the first string is greater than that of the second string. They return the value zero if the strings are identical.

{
  char string1[20];
  char string2[20];
  int  status;
  
  (void) strcpy (string1, "BOB GIBSON");
  (void) strcpy (string2, "bob feller");

  /* compare the contents of 'string1' and `string2' */

  status = Mcstricmp (string1, string2);

  /*
   * because the string "bob feller" occurs earlier in an
   * alphabetic listing than "BOB GIBSON" the value of
   * 'status' would be greater than 0.
   */

  /* 
   * compare the first 3 characters of the variables
   * 'string1' and 'string2'
   */

  status = Mcstrnicmp (string1, string2, 3);

  /*
   * because the first 3 characters of both strings contain
   * the word "Bob", the value of 'status' would be 0.
   */
}

Concatenating a series of strings

The stralloc function has a variable number of calling parameters that concatenate a series of strings into a new string. The final parameter in the calling sequence must be the NULL pointer.

This function dynamically allocates memory for the resulting string. The calling function must free that block of memory when it is finished.

{
  char  t_string[20];
  char *string1;

  (void) strcpy (t_string, "WISCONSIN");
  string1 = stralloc ("ST", "=", t_string, (char *) NULL);

  /*
   * upon successful exit the 'string1' would point to a block 
   * of memory that is 13 bytes long and contain the following
   * string: "ST=WISCONSIN"
   */

  if (string1 != (char *) NULL)
  {
    Mcprintf ("%s\n", string1);
    free (string1);
  }

  string1 = stralloc ("CO=", "US", " ", "MX", " ", "UK", (char *) NULL);

  /*
   * upon successful exit the 'string1' would point to a block 
   * of memory that is 12 bytes long and contain the following string:
   * "CO=US MX UK"
   */

  if (string1 != (char *) NULL)
  {
    Mcprintf ("%s\n", string1);
    free (string1);
  }

  return;
}

Converting lowercase and uppercase characters

The Mclocase and Mcupcase functions convert the letters of a character string to all lowercase or uppercase respectively, as shown in the sample code below. Non-alphabetic characters in the string are unmodified.

{
  char name[20];

  (void) strcpy (name, "Hank Aaron!!");

  /* convert the contents of the character array 'name'
   * to lowercase
   */

  Mclocase (name);

  /*
   * upon exit, the content of the character array 'name'
   * will be: "hank aaron!!"
   */

  /* convert the contents of the character array 'name'
   * to uppercase
   */

  Mcupcase (name);
 
  /*
   * upon exit, the content of the character array 'name'
   * will be: "HANK AARON!!"
   */
  }

Day and time

Day and Time conversion utilities consist of the follwing:

All McIDAS-X applications use the Julian day format. To correctly represent both the twentieth and twenty-first centuries, the McIDAS-X library provides Julian day manipulation routines using the format ccyyddd where cc represents the century, yy is the year of the century and ddd is the day of the year, with January 1 being day one. For example, 17 January 1997 is represented as 1997017.

In addition, there is one more variant of the yyyddd format. This format represents the julian day of the year 1900+yyy. As examples, 99119 is day 119 of the year 1999, and 102231 is day 231 of the year 2002. This format is used in many McIDAS-X data structures for internal storage, but is usually coverted to ccyyddd for user listings.

Some of the functions described in this section still expect the older Julian day format, yyddd. However, they will be replaced with the new format.

The time utilities described in this section use the integer representation hhmmss for time and return the time in UTC, Coordinated Universal Time.

Below is an alphabetical listing of the day and time functions available in the McIDAS-X library, along with a short description.

C function Fortran function Description

Mccydok

mccydok

verifies that a Julian day in the form ccyyddd is correct

Mccydtodmy

mccydtodmy

converts a Julian day in the form ccyyddd to day, month and year

Mccydtodow

mccydtodow

converts date to day of the week

Mccydtoiyd

mccydtoiyd

converts date in ccyyddd format to yyyddd

Mccydtostr

mccydtostr

converts the Julian day in the form ccyyddd to a variety of character string formats

Mccydtoyd

mccydtoyd

converts a 7-digit Julian day to 5 digits

Mcdaytimetosec

mcdaytimetosec

converts a Julian day in the form ccyyddd and the time of day in the form hhmmss to seconds since 1 January 1970 at 00 UTC

Mcdhrtoihr

not available

converts hours stored in double precision to hours stored in an integer of the form hhmmss

Mcdmytocyd

mcdmytocyd

converts day, month and year to a Julian day in the form ccyyddd

Mcgetday

mcgetday

gets the current system Julian day in the form ccyyddd

Mcgetdaytime

mcgetdaytime

gets the current Julian day in the form ccyyddd and the current time of day in the form hhmmss

Mcgettim

gettime

gets the current time of day in the form hhmmss

Mchmsok

mchmsok

verifies that a time value in the form hhmmss is correct

Mchmstoihr

not available

converts hours, minutes and seconds to hhmmss format

Mchmstostr mchmstostr converts a time in the form hhmmss to a variety of character string formats

Mcincday

mcincday

increments/decrements a Julian day value

Mcinctime

mcinctime

increments/decrements a Julian day and time value

Mcisleap

mcisleap

checks to see if the four-digit field represents a leap year

Mcistimeofday

mcistimeofday

verifies the value given to be a valid time of day

Mciydtocyd

mciydtocyd

converts date in yyyddd format to ccyyddd

Mcsectodaytime

mcsectodaytime

converts seconds since 1 January 1970 to a Julian day in the form ccyyddd and a time in the form hhmmss

Mcydtocyd

mcydtocyd

converts a 5-digit Julian day to 7 digits

These functions are further defined below along with examples of sample code. The more commonly used functions are described first.

 

For more information on these day and time functions, see the online man pages provided with the McIDAS-X software.

Retrieving the current system day and time

The McIDAS-X library contains these three current day/time functions:

If you write applications that need both current day and time, use Mcgetdaytime. This function doesn't have the potential timing problem associated with retrieving the information in separate calls. This timing problem surfaces just before the Julian day changes. For example, if you call Mcgetday at 23:59:59 on a particular day but don't call Mcgettime until two seconds later, your day and time won't match because your time will read 00:00:01.

The sample code below shows the use of all three functions.

{
  int CurrentDay;
  int CurrentTime;
  int status;

  /* get current system day and time. this is the undesirable
   * manner
   */

  status = Mcgetday (&CurrentDay);
  status = Mcgettime (&CurrentTime);

  /*
   * CurrentDay will contain the current system day in the form
   * ccyyddd. CurrentTime will contain the current time in the
   * form hhmmss
   */

  /* get current system day and time. this is the preferred
   * manner
   */

  status = Mcgetdaytime (&CurrentDay, &CurrentTime);

}

Converting a 5-digit Julian day to 7-digit, and vice versa

You can use the Mccydtoyd and Mcydtocyd functions to transition your code from the previous 5-digit Julian day format, yyddd, to the new 7-digit format, ccyyddd, and vice versa.

The Mcydtocyd function assumes that if the year of the century (yy) in the 5-digit format is less than or equal to 69, it is the 21st century; if the year of the century is greater than or equal to 70, it assumes the 20th century.

See the sample code below.

{
  int status;
  int new_day;

  /* convert the day 1996017 to the 5 digit form of the Julian day */

  status = Mccydtoyd (1996017, &new_day);

  /* if successful, the contents of new_day will be 96017 */


  /* convert the day 96100 to the 7 digit form of the Julian day */

  status = Mcydtocyd (96100, &new_day);

  /* if successful, the contents of new_day will be 1996100 */


  /* convert the day 11100 to the 7 digit form of the Julian day */

  status = Mcydtocyd (11100, &new_day);

  /* if successful, the contents of new_day will be 2011100 */

}

Converting to and from dates in IYD and CCYYDDD format

When servers present grid image or point data, the date fields are usually passed in a yyyddd format, where yyy represents years since 1900 and ddd represents the day count from the beginning of the year (1-based).

When the data is presented, the dates are in ccyyddd format, where cc is the century field, yy is the year of the century field and ddd is the julian day of the year.

Two functions are used to convert the data: mciydtocyd, which converts from the yyyddd format to the ccyyddd format, and mccydtoiyd, which converts from the ccyyddd format to the yyyddd format.

The sample code below, from m0ptrdhdr, shows how to use Mciydtocyd.

c
c--- modify schema and creation date fields
c
      istat=mciydtocyd(header(3),temp_date)
      header(3)=temp_date

      istat=mciydtocyd(header(26),temp_date)
      header(26)=temp_date

The sample code below, from m0makara, shows how to use mccydtoiyd.

C --- Get, convert current ccyyddd to yyyddd
C --- Store time directly.

        ival=mcgetdaytime(century_date,aradir(18))
        if(ival.lt.0)  then
            call edest('Unable to write creation date',0)
            m0makara=-3
        endif
        ival = mccydtoiyd(century_date,adir_date)
        aradir(17) = adir_date

Converting a Julian day and time to seconds, and vice versa

Mcdaytimetosec and Mcsectodaytime convert Julian day and time to absolute times based from 1 January 1970 at 00 UTC, and vice versa. This standard is different from the McIDAS-X functions sksecs and skhms, which use 1 January 1972 as the base.

#include <time.h
{
  int day;
  int time;
  time_t seconds;
  int status;

  /* 
   * get the number of seconds since 1 January 1970 for Julian
   * day 1997017 at 12:30UTC
   */

  day  = 1997017;
  time = 123000;

  status = Mcdaytimetosec (day, time, &seconds);

  /* upon successful exit, the value of 'seconds' will be
   * 853584200
   */

  /*
   * convert 853584200 seconds since 1 January 1970 to a
   * Julian day and time
   */

  status = Mcsectodaytime (seconds, &day, &time);

  /* 
   * upon successful exit, the value of 'day' will be
   * 1997017 and the value of 'time' will be 123000
   */
}

Converting a Julian day to day/month/year, and vice versa

Mccydtodmy converts a Julian day to day, month and year, including the century. The month number returned is 1-based, meaning January is 1. Mcdmytocyd converts a day, month, year combination to a Julian day. Examples of both functions are shown in the code fragment below.

{
  int dayofmonth;
  int month;
  int year;
  int day;
  int status;

  /* convert the day 9 May 1996 to a Julian day */

  dayofmonth = 9;
  month      = 5;
  year       = 1996;

  status = Mcdmytocyd (dayofmonth, month, year, &day);

  /* upon successful completion 'day' will contain the
   * value 1996130
   */

  /* convert the day 29 February 1995 to a Julian day */

  dayofmonth = 29;
  month      = 2;
  year       = 1995;

  status = Mcdmytocyd (dayofmonth, month, year, &day);

  /* this conversion will fail because there was no
   * 29 February 1995
   */

  /* convert the Julian day 1996060 to a day, month and year */

  day = 1996060;

  status = Mccydtodmy (day, &dayofmonth, &month, &year);

  /*
   * upon successful completion 'dayofmonth' will contain 29,
   * 'month' will contain 2 and 'year' will contain 1996
   */
  
}

Converting a Julian day to a character string

Mccydtostr converts a Julian day to a variety of character strings representing the date, as shown in the code sample below.

{
  int   status;
  char *day_string;

  /*
   * convert the Julian day 1996017 to a character string of the
   * form nn mmm, ccyy
   */

  status = Mccydtostr (1996017, 4, &day_string);

  /*
   * upon successful completion, the contents of the variable 
   * day_string will be '17 Jan, 1996'. For a complete listing
   * of the output formats available, see the McIDAS API 
   * Reference Manual.
   */
}

Determining if a year is a leap year

You can use Mcisleap to determine if a four-digit year is a leap year. See the sample code below.

      iam=-1 

c --- get the current day
      i=mcgetday(kurrent_day)
      kurrent_year=kurrent_day/1000

      iam=mcisleap(kurrent_year)

      if(iam.eq.0)  then
         call sdest('Current year is not a leap year',0)
      elseif(iam.eq.1) then
         call sdest('Current year is a leap year',0)
       endif

Incrementing day and time

When writing applications for real-time data, you may need to increment day and time parameters to locate data for an application. However, when you work with the beginning or ending day of a particular year, you can't just add a one to a Julian day and expect the correct resulting date. Use the Mcincday function to increment and decrement a Julian day by days. Use the Mcinctime function to increment and decrement a day/time pair by a time increment. A positive increment value results in a future time; negative numbers result in a past time.

{
  int new_day;
  int new_time;
  int status;

  /* increment the Julian day 1996364 by 3 days */

  status  = Mcincday (1996364, 3, &new_day);

  /* 
   * upon successful completion, 'new_day' will contain
   * the value 1997001
   */

  /* decrement the day/time pair 1996002/12UTC by 78 hours */

  status = Mcinctime (1996002, 120000, -780000, &new_day, &new_time); 

  /*
   * upon successful completion, 'new_day' will contain the
   * value 1995364 and 'new_time' will contain the value 60000
   */
}

Latitude and longitude

The McIDAS-X library contains two utilities for converting latitude and longitude values:

Because workstations can represent floating-point values differently, most data requiring fractional representation, such as latitude and longitude, is stored as scaled integers. While scaled integers are adequate for data storage, performing mathematical operations on these values is difficult.

Use the flalo function to convert the scaled-integer representation of latitude and longitude into single-precision floating point numbers. Use the ilalo function to convert single-precision floating-point values to scaled-integer representation. The sample code below demonstrates the latitude and longitude conversion functions.

    integer lat
    real    flat

c---    convert 59 degrees 30 minutes to a single precision
c---    floating point value

    lat = 593000
       flat = flalo (lat) 

c---    upon successful completion, 'flat' contains the value 59.5

c---    convert the latitude value 45.75 to a scaled integer value

    flat = 45.75
       lat = ilalo (flat)

c---    upon successful completion, 'lat' contains the value 454500

 

For more information about these conversion functions, see the online man pages provided with the McIDAS-X software.

Physical units

The McIDAS-X library contains two utilities for converting physical units:

Unit conversion is a integral part of any user application because data is often stored in units that a user won't typically display. The mcucvtd and mcucvtr functions can convert the physical units shown in the table below; all McIDAS-X core datasets use this standard.

Attribute Valid units Interface representation

length

meters
kilometers
decameters
centimeters
millimeters
miles
nautical miles
yards
feet
inches
degrees of latitude

M
KM
DM
CM
MM
MI
NMI
YD
FT
IN
DEGL

speed

miles per hour
knots
meters per second
feet per second
kilometers per hour

MPH
KT or KTS
MPS
FPS
KPH

temperature

Kelvin
Fahrenheit
Celsius

K
F
C

pressure

millibars
inches of Mercury
pascals
hectopascals

MB
INHG
PA
HPA

time

hours
minutes
seconds
days
years

HR
MIN
SEC
DAY
YR

weight

grams
kilograms
pounds
ounces
tons

G
KG
LB
OZ
TON

The code segment below demonstrates these unit conversion routines.

    integer numval
    character*4 inunit
    character*4 outunit
    integer status
    double precision    outval

    numval = 1

c---    Convert 50 degrees fahrenheit to celsius

    inunit  = 'F'
    outunit = 'C'
       status = mcucvtd (numval, inunit, 50.d0, outunit, outval, 0)

c---    Upon successful completion, 'outval' will contain the
c---    value 10.0.

c---    Convert 50 degrees fahrenheit to feet

    outunit = 'FT'
       status = mcucvtd (numval, inunit, 50.d0, outunit, outval, 0)
    
c---    the value of 'status' will be -1 because you cannot 
c---    convert degrees fahrenheit to feet.

 

For more information about these conversion functions, see the online man pages provided with the McIDAS-X software.


[Search Manual] [Table of Contents] [Go to Previous] [Go to Next]