Introduction
In my earlier article "The Standalone Programmer", I mentioned that
I have a bad habit of accidentally using the set operator (=) in if statements
where I intend to use the equality operator (==). To put an end to this
habit, I have written some simple helper functions to eliminate this problem
altogether. I decided to write this simple article and post the code for
these functions (and a few others) in the hopes that someone else will find them
useful.
My primary objective in writing these functions was to eliminate some of my
most common programming mistakes and to simplify some of the more common tasks I
find myself performing. I have provided the code in the form of 2 files:
HelperFunctions1.h and HelperFunctions1.cpp.
The Equality Operator
As I said, I have a bad habit of using the set operator incorrectly in
conditional statements. I can't remember how many times I have written
code like the code below and it has bitten me badly on occasion.
if (iValue1 = iValue2)
{
...bla.bla.bla
}
One good habit to get into is to always put constant values on the left side
of such conditionals because the compiler will detect the problem before the
code ever gets executed. This is a good habit, but is limited to
situations where a constant is involved. Many (if not most) of the
situations I encounter involve 2 non-const variables. To combat this
issue, I have written several simple helper functions to use in place of the
equality operator. Below is a list of these functions. Each is inline so
that they do not adversely impact performance. Each of these functions
take 2 const parameters of a specific data type and perform an equality
comparison on them. The string related functions use the strcmp
and
stricmp
operators. (I chose to write the string comparison functions
because I also misuse these operators by expecting a
bool
return value instead
of an int.) The function names and prototypes should be self explanatory.
IsEqual |
bool
IsEqual(LPCTSTR lpszComp1, LPCTSTR lpszComp2) |
IsEqualI |
bool
IsEqualI(LPCTSTR lpszComp1, LPCTSTR lpszComp2)<br>Case insensitive string compare. |
IsEqual |
bool
IsEqual(const int iComp1, const int iComp2) |
IsEqual |
bool
IsEqual(const __int64 iComp1, const __int64 iComp2) |
IsEqual |
bool
IsEqual(const long lComp1, const long lComp2) |
IsEqual |
bool
IsEqual(const double dblComp1, const double dblComp2) |
IsEqual |
bool
IsEqual(const float fComp1, const float fComp2) |
IsEqual |
bool
IsEqual(const short sComp1, const short sComp2) |
IsEqual |
bool
IsEqual(const UINT uiComp1, const UINT uiComp2) |
IsEqual |
bool
IsEqual(const DWORD dwComp1, const DWORD dwComp2) |
IsEqual |
bool
IsEqual(const WORD wComp1, const WORD wComp2) |
IsEqual |
bool
IsEqual(const void* pComp1, const void* pComp2) |
IsEqualDate |
bool
IsEqual(const COleDateTime& dtComp1, const COleDateTime& dtComp2) |
IsEqualTime |
bool
IsEqual(const COleDateTime& dtComp1, const COleDateTime& dtComp2) |
IsEqualDateTime |
bool
IsEqual(const COleDateTime& dtComp1, const COleDateTime& dtComp2) |
With these operators I can now write code like the code below eliminating the
problems with the equality operator.
if (IsEqual(iValue1, iValue2))
{
...bla.bla.bla
}
Type Conversions
Less of a problem but still irritating to me is situations where I need to
convert a string to a numeric value or visa-versa. I like many of you must
program in C++ and VBScript/VB on any given day. I often find myself
writing code in VB with semi-colons and C++ without them. Also, I have
become accustomed to some of the simple type conversion functions provided by VB
such as CInt
, CLng
, CDbl
, CStr
. To simplify my development I created
companion functions in C++ to implement support for these functions (or a basic
variant of these functions). Several of these functions just call other
functions. I decided to wrap these functions for the sole purpose of
simplification. These functions are listed below. The function names
and prototypes should be self explanatory.
CInt |
int
CInt(LPCTSTR lpszValue) |
CLng |
long
CInt(LPCTSTR lpszValue) |
CDbl |
double
CInt(LPCTSTR lpszValue) |
CStrFromLong |
CString CStrFromLong(const long
lValue) |
CStrFromInt |
CString CStrFromInt(const int
lValue) |
CStrFromDouble |
CString CStrFromDouble(const double
dblValue) |
Other General Functions
In addition to the equality operator and the type conversion operators I
mentioned above, there are a few other functions I use quite often and have
included here. You may or may not need any of these functions, but if you
do I think they will simplify your life. These functions perform various
operations and I am going to provide a description of each function to help you
understand them.
IsInteger | bool
IsInteger(LPCTSTR lpszVL)
Returns TRUE if the string specified by lpszVL contains only numbers and
optionally a negative sign. |
IsDecimal | bool
IsDecimal(LPCTSTR lpszVL)
Returns TRUE if string specified by lpszVL contains only numbers, no more
than one decimal and optionally a negative sign. |
GetBoolFromChar | bool
GetBoolFromChar(LPCTSTR lpszValue)
Returns TRUE if the string specified is "YES", "Y",
"TRUE", or "ON". On various occasions I have
needed to work with databases setup by others and these are the scenarios
I have encountered for representing boolean values in a database. |
GetCharFromBoolean | char GetCharFromBoolean(bool
bValue)
Returns 'Y' if the bValue is TRUE, otherwise returns 'N'. Again,
this is to assist with some database related work I need to do often. |
ProcessKeyStrokeForNumeric | bool ProcessKeyStrokeForNumeric(MSG
*pMsg)
I often have edit boxes which need to only accept numbers for input.
The DDV_ function from MFC sucks and the number option (on control
properties) isn't much better. To make things work the way I want
them to I override the PreTranslateMessage function of my container class
and call ProcessKeyStrokeForNumeric anytime I get a WM_CHAR, WM_KEYDOWN or
WM_KEYUP message for a numeric only control. This gives me the
functionality I desire.
BOOL CSomeWnd::PreTranslateMessage(MSG* pMsg)
{
if (::GetDlgCtrlId(pMsg->hwnd) == IDC_NUMERIC_CONTROL)
{
if (!ProcessKeyStrokeForNumeric(pMsg))
return TRUE;
}
return CWnd::PreTranslateMessage(pMsg);
}
|
IsEditMsg | bool IsEditMsg(MSG* pMsg)
I don't like the way that edit boxes get grayed out when they are
disabled. The gray background can make it difficult for some users
to read the contents of the control. Also, when disabled the scroll
bars no longer work. This is a pain when the control contains useful
information that extends beyond the visible screen. To make things
work the way I want them to I override the PreTranslateMessage function of
my container window and call IsEditMsg for all messages directed at the
read only control. This gives me the functionality I desire.
BOOL CSomeWnd::PreTranslateMessage(MSG* pMsg)
{
if (::GetDlgCtrlId(pMsg->hwnd) == IDC_NUMERIC_CONTROL &&
IsEditMsg(pMsg))
return TRUE;
return CWnd::PreTranslateMessage(pMsg);
}
|
MFC Support/Requirement
As you've probably already noticed a couple of the functions I provide
require MFC to work. These use the CString
class. By default,
support for these functions is not included. To use these functions you
need to define FPS_HELPER_MFC_SUPPORT
somewhere appropriate in your code.
Many of you probably already have a favorite string class for your non-MFC
projects. Changing this code to use your favorite string class should be a
very simple matter.
How to Use These Functions In Your Application
There are 2 files included with this article. The first step is to add
these 2 files (HelperFunctions1.h and HelperFunctions1.cpp) to your
project. Once you have added these files to your project you need to
include the HelperFunctions.h file in an appropriate place. I typically
include this file in my stdafx.h file so that my entire project has access to
these functions without more coding.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.