|< 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
- The following Table is an example of the needed information in order to use the bsearch() function.
|
||||||||||||||||||||||||||||||
- 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
- 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*/