|< C Run-Time 3 | Main | C & Win32 Programming 1 >| Site Index | Download |


 

MODULE B1

IMPLEMENTATION SPECIFIC

MICROSOFT C Run-Time 4

 

 

 

 

My Training Period:      hours

 

Note:

This Module is a continuation from the previous one.  More C Run-time program examples, compiled using Visual C++ .Net (Visual studio .Net 2003).  It is low-level programming and the .Net used is Unmanaged (/clr is not set: Project menu → your_project_name Properties… sub menu → Configuration Properties folder → General subfolder → Used Managed Extension setting set to No).  All programs are in debug mode, run on Windows 2000 and Xp Pro.

 

Abilities

 

         Able to recognize the standard and implementation specific C.

         Able to find and collect the required and related information in order to use functions to accomplish your tasks.

         Able to understand and use functions that available in the libraries in your own programs.

 

Simple Searching and Sorting

 

-      The following functions used for searching and sorting.  It is very limited and basic :o).

 

Searching and Sorting Functions

 

Function

Search or Sort

bsearch()

Binary search.

_lfind()

Linear search for given value.

_lsearch()

Linear search for given value, which is added to array if not found.

qsort()

Quick sort.

 

Table 12:  Search and sort functions.

 

-      The following Table is an example of the needed information in order to use the bsearch() function.

 

Information

Description

The function

bsearch().

The use

Performs a binary search of a sorted array.

The prototype

void *bsearch( 
   const void *key,
   const void *base,
   size_t num,
   size_t width,
   int (__cdecl *compare) (const void *, const void *));

Example

int compare(char **arg1, char *arg2[]);

char *key = "red";

bsearch((char *) &key, (char *)argv, argc, sizeof(char *), (int (*)(const void*, const void*))compare);

The parameters

key - Object to search for.

base - Pointer to base of search data.

num - Number of elements.

width - Width of elements.

compare - Callback function that compares two elements. The first is a pointer to the key for the search and the second is a pointer to the array element to be compared with the key.

The return value

Returns a pointer to an occurrence of key in the array pointed to by base. If key is not found, the function returns NULL.  If the array is not in ascending sort order or contains duplicate records with identical keys, the result is unpredictable.

The header files

<stdlib.h> and <search.h>

 

Table 13:  bsearch() function information.

 

-      The bsearch() function performs a binary search of a sorted array of num elements, each of width bytes in size.

-      The base value is a pointer to the base of the array to be searched, and key is the value being sought.

-      The compare parameter is a pointer to a user-supplied routine that compares two array elements and returns a value specifying their relationship.

-      bsearch() calls the compare routine one or more times during the search, passing pointers to two array elements on each call.

-      The compare routine compares the elements, and then returns one of the following values:

 

Value returned by compare routine

Description

< 0

element1 less than element2

0

element1 equal to element2

> 0

element1 greater than element2

 

-      The following program example reads the command-line parameters, sorting them with qsort(), and then uses bsearch() to find the word "red".  This program was run at the command prompt lol!

 

/*****program example using bsearch()*****/

/*****If it is C++, better to use STL****/

#include <search.h>

#include <string.h>

#include <stdio.h>

 

/*A compare function prototype*/

int compare(char **arg1, char *arg2[]);

 

int main(int argc, char *argv[])

{

   char **result;

   char *key = "red";

   int i;

 

   /*Sort using qsort algorithm*/

   qsort((void *)argv, (size_t)argc, sizeof(char *), (int (*)(const void*, const void*))compare);

 

   /*Output the sorted list */

   for(i = 0; i < argc; ++i)

   printf("%s ", argv[i]);

 

   /*Find the word "cat" using a binary search algorithm*/

   result = (char **)bsearch((char *) &key, (char *)argv, argc, sizeof(char *), (int (*)(const void*, const void*))compare);

   if(result)

   printf("\n\'%s\' word found at address: %p\n", *result, result);

   else

      printf("\n\'%s\' word not found!\n", *result);

   return 0;

}

 

int compare(char *arg1[], char *arg2[])

{

   /*Compare all of both strings*/

   return _strcmpi(*arg1, *arg2);

}

 

The output:

 

G:\vcnetprojek\mcruntime\Debug>mcruntime blue yellow red black white

black blue mcruntime red white yellow

'red' word found at address: 00320CF4

 

Time

 

-      These functions used to get the current time and convert, adjust, and store it as necessary.  The current time is the system time.

-      The _ftime() and localtime() functions use the TZ, the environment time variable (look like it stands for Time Zone).

-      If TZ is not set, the run-time library attempts to use the time-zone information specified by the operating system specified in the Control Panel's Date/Time application.  If this information is unavailable, these functions use the default value of PST8PDT, which signifies the Pacific Time zone (Daylight Saving Time – DST and three letters for daylight-saving-time zone – PDT).

 

Time Functions

 

Function

The Use

asctime(), _wasctime()

Convert time from type struct tm to character string.

clock()

Return elapsed CPU time for process.

ctime(), _ctime64(), _wctime(), _wctime64()

Convert time from type time_t or __time64_t to character string.

difftime()

Compute difference between two times.

_ftime(), _ftime64()

Store current system time in variable of type struct _timeb or type struct __timeb64.

_futime(), _futime64()

Set modification time on open file.

gmtime(), _gmtime64()

Convert time from type time_t to struct tm or from type __time64_t to struct tm.

localtime(), _localtime64()

Convert time from type time_t to struct tm or from type __time64_t to struct tm with local correction.

mktime(), _mktime64()

Convert time to calendar value.

_strdate(), _wstrdate()

Return current system date as string.

strftime(), wcsftime()

Format date-and-time string for international use.

_strtime(), _wstrtime()

Return current system time as string.

time(), _time64()

Get current system time as type time_t or as type __time64_t.

_tzset()

Set external time variables from environment time variable, TZ.

_utime(), _utime64(), _wutime(), _wutime64()

Set modification time for specified file using either current time or time value stored in structure.

 

Table 14:  Time management functions.

 

-      In all versions of Microsoft C/C++ except Microsoft C/C++ version 7.0, and in all versions of Microsoft Visual C++, the time() function returns the current time as the number of seconds elapsed since midnight on January 1, 1970.

-      In Microsoft C/C++ version 7.0, time() returned the current time as the number of seconds elapsed since midnight on December 31, 1899.

-      The following Table is an example of the needed information in order to use the time() and _time64() functions.

 

Information

Description

The function

time(), _time64().

The use

Get the system time.

The prototype

time_t time(time_t *timer);

__time64_t _time64(__time64_t *timer);

The parameters

timer – Is a pointer to the storage location for time.

Example

__time64_t lgtime;

_time64(&lgtime);

The return value

Return the time in elapsed seconds.  There is no error return.

A call to time() or _time64() can fail, however, if the date passed to the function is:

     Before midnight, January 1, 1970.

     After 19:14:07, January 18, 2038, UTC (using time and time_t structure).

     After 23:59:59, December 31, 3000, UTC (using _time64 and __time64_t structure).

The header files

<time.h>

 

Table 15:  time(), _time64() functions information.

 

-      The time() function returns the number of seconds elapsed since midnight (00:00:00), January 1, 1970, coordinated universal time (UTC), according to the system clock.

-      The return value is stored in the location given by timer.  This parameter may be NULL, in which case the return value is not stored.

-      Other information needed is the structures used for the time functions.  For this thingy, you have to find it yourself in the documentation :o).

-      Let try using the functions in a program example.

 

/*Playing with time. Program example for

time management functions...*/

#include <time.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/timeb.h>

#include <string.h>

 

int main()

{

    char buff[128], ampm[] = "AM";

    __time64_t lgtime;

    struct __timeb64 timstruct;

    struct tm *today, *thegmt, xmas = {0, 0, 12, 25, 11, 90};

 

    /* Set time zone from TZ environment variable. If TZ is not set,

     * the operating system is queried to obtain the default value

     * for the variable.*/

    _tzset();

 

    /*Get UNIX-style time and display as number and string.*/

    _time64(&lgtime);

    printf("Time in seconds since UTC 1/1/70:\t%ld seconds\n", lgtime);

    printf("UNIX time and date:\t\t\t%s", _ctime64(&lgtime));

 

    /*Display UTC.*/

    thegmt = _gmtime64(&lgtime);

    printf("Coordinated universal time, UTC:\t%s", asctime(thegmt));

 

    /*Display operating system-style date and time.*/

    _strtime(buff);

    printf("OS time:\t\t\t\t%s\n", buff);

    _strdate(buff);

    printf("OS date:\t\t\t\t%s\n", buff);

 

    /*Convert to time structure and adjust for PM if necessary.*/

    today = _localtime64(&lgtime);

    if(today->tm_hour >= 12)

    {

       strcpy(ampm, "PM");

       today->tm_hour -= 12;

    }

  

    /*Adjust if midnight hour.*/

     if(today->tm_hour == 0)

        today->tm_hour = 12;

 

    /* Pointer addition is used to skip the first 11

     * characters and printf() is used to trim off terminating

     * characters.*/

    printf("12-hour time:\t\t\t\t%.8s %s\n", asctime(today) + 11, ampm);

 

    /*Print additional time information.*/

    _ftime64(&timstruct);

    printf("Plus milliseconds:\t\t\t%u\n", timstruct.millitm);

    printf("Zone difference in hours from UTC:\t%u hours\n", timstruct.timezone/60);

    printf("Time zone name:\t\t\t\t%s\n", _tzname[0]);

    printf("Daylight savings:\t\t\t%s\n", timstruct.dstflag ? "YES" : "NOT SET");

 

    /*Make time for noon on Christmas, 1990.*/

    if(_mktime64(&xmas) != (__time64_t)-1)

      printf("Christmas\t\t\t\t%s", asctime(&xmas));

 

    /*Use time structure to build a customized time string.*/

    today = _localtime64(&lgtime);

 

    /*Use strftime to build a customized time string.*/

    strftime(buff, 128, "Today is %A, day %d of %B in the year %Y.\n", today);

    printf(buff);

    return 0;

}

 

The output:

 

 

Time in seconds since UTC 1/1/70:       1116770651 seconds

UNIX time and date:                     Sun May 22 23:34:11 2005

Coordinated universal time, UTC:        Sun May 22 14:04:11 2005

OS time:                                23:34:11

OS date:                                05/22/05

12-hour time:                           11:34:11 PM

Plus milliseconds:                      453

Zone difference in hours from UTC:      4294967287 hours

Time zone name:                         AUS Central Standard Time

Daylight savings:                       NOT SET

Christmas                               Tue Dec 25 12:00:00 1990

Today is Sunday, day 22 of May in the year 2005.

Press any key to continue

 

Some Error Handling

 

-      The following Table lists the needed information in order to use the perror() function.

 

Information

Description

The function

perror().

The use

Print an error message.

The prototype

void perror( const char *string );

 

/*For wide character*/

void _wperror( const wchar_t *string );

The parameters

string - String message to print.

Example

perror("Using perror()");

The return value

void.

The header files

<stdio.h> or <wchar.h> (for _wperror()).

 

Table 16:  perror() function information.

 

-      The perror() function prints an error message to stderr_wperror() is a wide-character version of _perror().

-      The string argument to _wperror() is a wide-character string.  _wperror() and _perror() behave identically otherwise.

-      errno is set on an error in a system-level call.  Because errno holds the value for the last call that set it, this value may be changed by succeeding calls.

-      Always check errno immediately before and after a call that may set it.  All errno values, defined as manifest constants in errno.h, are UNIX-compatible.  The values valid for 32-bit Windows applications are a subset of these UNIX values.

-      The following errno values are compatible with 32-bit Windows applications.  Only ERANGE and EDOM are specified in the ANSI standard.

 

Constant

System error message

Value

E2BIG

Argument list too long

7

EACCES

Permission denied

13

EAGAIN

No more processes or not enough memory or maximum nesting level reached

11

EBADF

Bad file number

9

ECHILD

No spawned processes

10

EDEADLOCK

Resource deadlock would occur

36

EDOM

Math argument

33

EEXIST

File exists

17

EINVAL

Invalid argument

22

EMFILE

Too many open files

24

ENOENT

No such file or directory

2

ENOEXEC

Exec format error

8

ENOMEM

Not enough memory

12

ENOSPC

No space left on device

28

ERANGE

Result too large

34

EXDEV

Cross-device link

18

 

Table 17:  errno values.

 

-      The following Table lists the needed information in order to use the strerror(), _strerror(), _wcserror(), __wcserror() functions.

 

Information

Description

The function

strerror(), _strerror(), _wcserror(), __wcserror().

The use

Get a system error message (strerror(), _wcserror()) or prints a user-supplied error message (_strerror(), __wcserror()).

The prototype

char *strerror(int errnum);

char *_strerror(const char *strErrMsg);

wchar_t * _wcserror(int errnum);

wchar_t * __wcserror(const wchar_t *strErrMsg);

The parameters

errnum - Error number.

strErrMsg - User-supplied message.

Example

strerror(errno);

The return value

All these functions return a pointer to the error-message string.  Subsequent calls can overwrite the string.

The header files

<string.h>.

 

Table 18:  strerror() family functions information.

 

-      The strerror() function maps errnum to an error-message string, returning a pointer to the string. Neither strerror() nor _strerror() actually prints the message.

-      For this condition, you need to call an output function such as fprintf() as shown below.

 

if((_access("thefile.dat", 13)) == -1)

   fprintf(stderr, strerror(NULL));

 

-      If strErrMsg is passed as NULL, _strerror() returns a pointer to a string containing the system error message for the last library call that produced an error.

-      The error-message string is terminated by the newline character ('\n').  If strErrMsg is not equal to NULL, then _strerror() returns a pointer to a string containing (in order) your string message, a colon, a space, the system error message for the last library call producing an error, and a newline character.

-      Your string message can be, at most, 94 characters long.  Later on, in Win32 programming you will be introduced to another function, GetLastError().

-      The following program example uses the error message handling functions.

 

#include <fcntl.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <io.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

 

int main()

{

   char fname[20] = "testnofile.txt";

   int  fhndl;

   /*Try to open non-existing file*/

   if((fhndl = _open(fname, _O_RDONLY)) == -1)

   {

      /*Using the possible ways to create error message*/

      perror("Using perror()");

      printf("Using strerror(): %s\n", strerror(errno));

      printf(_strerror("_strerror()"));

      printf("There is some error opening %s file\n", fname);

   }

   else

   {

      printf("Open %s for reading succeeded!\n", fname);

      _close(fhndl);

   }

   return 0;

}

 

The output:

 

Using perror(): No such file or directory

Using strerror(): No such file or directory

_strerror(): No such file or directory

There is some error opening testnofile.txt file

Press any key to continue

 

-      Well, that all folks.  Hopefully you already knew how to find the needed information in order to use functions when developing your programs for Windows.  The next step, get the Visual C++/MSDN/SDK Platform documentations and start digging your own favorite and other categories of functions.

-      It seems that other than the Graphic User interface (GUI), just with C/C++, it is not enough to do the Windows programming that cover all aspect of the Windows OS.  In the next Module we will try the Win32 application programming interface (API).

-      For the .Net programming, keep in mind that there are C/C++ functions (run-time libraries) and the .NET framework equivalents, so dig it yourself!

-      If you already have the knowledge and skills how to program in C/C++, what have been discussed in this Module is nothing new isn’t it?  It should be a business as usual :o).

 

-------------------------------------Pre End----------------------------------------

 

Before we proceed to the next Module, Win32 programming, let have some thought about the following lousy search file program example.  This program example run at command prompt, compiled using VC++ .Net, empty console mode application on Win Xp Pro SP2.  A lot more things can be done to this program :o).  Have a nice thought!

 

Some silly thought:  The pseudo code/algorithm

 

Receive the filename as a command line argument, store it somewhere

First of all get all the available drives in the machine, use _getdrives()

   Translate all the bitmask to the respective drive.

For every found drive search the file, call user defined FindThePath()

       Strip the filename string, call the user defined TheRightSide()

       Test the filename string, call the user defined TestTheStrings()

               Test the wildcards/extensions if any

        If it is a directory, it is current working or parent directory (. and ..)?

        If it is a valid root/drive, search in the current root

        If not found, construct a path to traverse to other directories in finding the file

                      Recurse, call FindThePath()

         If found, construct the full path and display it/return.

                   /**************************************************

                    Optionally, implement other routines or function calls for the found file.

                   ***************************************************/

          If finish, no more files, no more directories in current drive, return to the main program's 

          loop

Repeat for other drives

 

Then, comes the silly program:

 

/*****  mysearch.cpp  *********/

/*Compiled using VC++ 7.0/.Net*/

/*Run at command prompt       */

/*Tested on Win Xp Pro machine*/