McIDAS Programmer's Manual
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:
- manipulating information at the byte level
- handling character strings
- converting day and time formats
- converting latitude and longitude formats
- converting physical units such as speed and temperature
|
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.
- A buffer is any memory storage.
- A byte is an 8-bit memory segment; a half-word is a 16-bit memory segment; a word is a 32-bit memory segment.
- An element refers to a collection of one or more bytes.
- 0-based is a counting sequence that begins with zero; 1-based is a counting sequence beginning with the number one.
- Big-endian and network-byte-order are used interchangeably
to mean the most significant byte in a word comes first; little-endian means the least significant byte is first. For example, the byte ordering for the integer value 12 appears as 0000000c on big-endian machines and 0c000000 for little-endian machines.
- Memory overflow refers to writing beyond the memory allocated for a variable.
Be careful when using the byte manipulation functions below. Most do not protect against memory overflow.
|
|
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:
- the segment sizes to copy
- the number of bytes to skip between source bytes
- the number of bytes to skip between destination bytes
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:
- provide better error codes than those available in the standard language libraries
- accommodate a McIDAS-X-specific syntax for some commonly used parameters unknown to the standard language libraries
- control differences in the way that the C and Fortran languages treat character strings
This section contains some terms that may be unfamiliar to you. They are defined below.
- Blank-padded describes the practice of replacing unused characters at the end of a string with space characters.
- Double-precision usually describes a two-word storage representation for floating-point numbers.
- Whitespace is a subset of the ASCII (American Standard Code for Information Interchange) character set that includes space, end-of-line, vertical tab, horizontal tab and form-feed characters.
- Null-terminated describes the practice of placing a zero (ASCII NULL character) at the end of a character string; this is the standard representation in the C language.
The string manipulation functions are listed alphabetically in the table below with a brief 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.
- Mcstrtodhr returns time values in units of hours as a double- precision value.
- Mcstrtoihr returns an integer representation of time in the format hhmmss .
- Mcstrtodll returns latitude or longitude in double-precision values.
- Mcstrtoill returns a scaled integer representation of latitude and longitude in the integer format dddmmss .
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:
- cc is the century
- yy is the year in the century
- ddd is the day number for the year, 1-based
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:
- determines the amount of memory required to store the string
- allocates that amount of memory
- converts the Fortran character string to a C character string
- assigns the new string to a character pointer variable
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.
|
|
|
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
|
mcdhrtoihr
|
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
|
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:
- Mcgetday retrieves the current system Julian day.
- Mcgettime returns the current system time in UTC.
- Mcgetdaytime retrieves both.
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.
- Mccydtoyd converts the 7-digit Julian day format to the 5-digit representation.
- Mcydtocyd converts the 5-digit Julian day format to the 7-digit version.
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:
- flalo converts an integer representation of latitude or longitude
in the format dddmmss to a single-precision representation, in degrees.
- ilalo converts a single-precision latitude or longitude to a scaled- integer value in the format dddmmss.
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:
- mcucvtd converts a list of double-precision values from one physical unit to a different physical unit.
- mcucvtr converts a list of single-precision values from one physical unit to a different physical unit.
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.
|
|
|
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.
|