Click here to Skip to main content
Licence CPOL
First Posted 18 May 2002
Views 77,573
Bookmarked 25 times

Utility - Helper Functions

By | 18 May 2002 | Article
Useful utility functions to simplify developement and eliminate errors

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Matt Gullett

Web Developer

United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralFixing the = in conditional context for ever Pinmembernde_plume2:13 31 Jan '06  
GeneralAnother thought behind disabled edit controls PinmemberChris Conn8:33 11 May '05  
GeneralBug PinmemberRejeesh.T.S0:49 15 Jul '04  
Generalconsntants Pinmember_Abe_11:47 18 Jun '02  
QuestionWhy not use a template? PinmemberJason King10:01 20 May '02  
AnswerRe: Why not use a template? PinmemberMatt Gullett12:17 20 May '02  
GeneralRe: Why not use a template? Pinmemberkilowatt10:50 21 May '02  
GeneralRe: Why not use a template? PinmemberMatt Gullett10:56 21 May '02  
GeneralRe: Why not use a template? Pinmemberkilowatt11:58 21 May '02  
GeneralRe: Why not use a template? PinmemberMatt Gullett12:48 21 May '02  
GeneralRe: Why not use a template? Pinmemberkilowatt17:52 21 May '02  
No I haven't used the IsEqual template like you do. but I do use some of the tricks that you mention like placing constants on the left in an equality statement.
 
However when you use STL, sometimes it is necessary to specialize a template for the containers to compare the two objects.
 
In most cases the default that STL uses is suitable, which is simply the < operator. However, for two character pointers you need to use strcmp, or something similar. So I am just familiar with some of the pitfalls that exist.
 
About the thunking library, it is a fairly recent addon that you can download. If you look in MSDN, they now talk a little bit about it.
 
Also, if you define your functions with the LPTSTR, you really should use the _tcsXXX version of the string functions, because your code will break if it is ever compiled in UNICODE. Therefore if you only want to use the strXXX version of functions, you should declare your string pointers as LPSTR.

 

Build a man a fire, and he will be warm for a day
Light a man on fire, and he will be warm for the rest of his life!

GeneralRe: Why not use a template? PinmemberMatt Gullett4:24 22 May '02  
AnswerRe: That's why... Pinmemberpeterchen22:14 3 Feb '03  
AnswerWhy not use #define PinsussAnonymous13:49 7 Jul '05  
GeneralNice but... PinmemberMaximilian Hänel9:35 19 May '02  
GeneralRe: Nice but... PinmemberMatt Gullett9:39 19 May '02  
GeneralRe: Nice but... PinmemberMatt Gullett9:50 19 May '02  
GeneralRe: Nice but... PinmemberMaximilian Hänel10:00 19 May '02  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120529.1 | Last Updated 19 May 2002
Article Copyright 2002 by Matt Gullett
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid