Solved

How to accumulate and display all error messasges using one variable

Posted on 2014-01-15
11
417 Views
Last Modified: 2014-01-28
I’m looking for some example, in C or C++, as to how I can accumulate all the error codes in one variable then at the end of a function display all the error codes in one shot.

I tried using an int variable, like:

int nError = 0;

if(some error1)
      nError |= m_Error_1;
if(some errorx)
      nError |= m_Error_x;

DisplayErrors(nError); // see function definition below

defines for errors:

int m_Error_1       = 0xAA;
int m_Error_2      = 0xAB;
int m_Error_x       = 0xAC;

I would have a two element  array for the error codes and strings:

struct ErrorMsg{
      int nError;
      const char *pErrorMsg;
};

 And my struct array would be like:

struct ErrorMsg messages[] = {
        { m_Error_1;,      “Error one”},
        { m_Error_1;,      “Error two”},      
 { m_Error_x;,      “Error x”}
};

Then when I went to display my errors I would use the following function:

int DisplayErrors(int nErrorCode)
{
      int nStatus = 0;
      char *pMsg = NULL;
      wstring wsMsg;

      int nArraySize = sizeof(messages)/sizeof(ErrorMsg);

      // there could be multiple messages so let’s display them all
      for(int k=0; k<= nArraySize; k++)
      {
            if(nErrorCode & messages[k].nError)
            {
                  wsMsg = s2ws(messages[k].pErrorMsg);

                  if(!wsMsg.empty())
                        MessageBox(NULL , wsMsg.c_str(), _T("ERROR"), MB_OK);

                  // clear the current message
                  nErrorCode &= ~messages[k].nError;

                  if(0 == nErrorCode)
                        break;
            }
      }

      return nStatus;
}

The problem is that the function DisplayErrors would display more errors than what I had bitwised into the variable nError.
Can someone show me what I am doing wrong or suggest another way to load up all the possible errors and display them after all the errors have been discovered?

Thanks
0
Comment
Question by:atomicgs12
  • 4
  • 2
  • 2
  • +3
11 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 39784117
If you want that to work (and it will), you just need to limit your error codes to have exactly one single bit set, i.e. instead of

int m_Error_1       = 0xAA; // 10101010
int m_Error_2      = 0xAB; // 10101011
int m_Error_x       = 0xAC; // 10101100

Open in new window


use e.g.

int m_Error_1       = 0x01; // 00000001
int m_Error_2      = 0x02; // 00000010
int m_Error_x       = 0x04; // 0000100

Open in new window

0
 

Author Comment

by:atomicgs12
ID: 39784133
So I could have the most then is 99 error codes?
0
 
LVL 86

Expert Comment

by:jkr
ID: 39784138
Well, that's the downside of this approach. But it's not 99, it's 32 or 64.
0
 
LVL 86

Expert Comment

by:jkr
ID: 39784144
BTW, you could remedy that by categorizing your errors (no function will probably produce all errors) on a per-function basis, with categories being the set of errors that can occur in funciton 'a()' or function 'b()'. E.g.

struct ErrorMsg messages_a[] = {
        { m_Error_1;,      “Error one”},
        { m_Error_2;,      “Error two”},      
 { m_Error_x;,      “Error x”}
};

struct ErrorMsg messages_b[] = {
        { m_Error_1;,      “Error one”},
        { m_Error_2;,      “Error two”},      
 { m_Error_x;,      “Error x”}
};

int DisplayErrors(int nErrorCode, strucr ErrorMsg* messages)
{
      int nStatus = 0;
      char *pMsg = NULL;
      wstring wsMsg;

      int nArraySize = sizeof(messages)/sizeof(ErrorMsg);

      // there could be multiple messages so let’s display them all
      for(int k=0; k<= nArraySize; k++)
      {
            if(nErrorCode & messages[k].nError)
            {
                  wsMsg = s2ws(messages[k].pErrorMsg);

                  if(!wsMsg.empty())
                        MessageBox(NULL , wsMsg.c_str(), _T("ERROR"), MB_OK);

                  // clear the current message
                  nErrorCode &= ~messages[k].nError;

                  if(0 == nErrorCode)
                        break;
            }
      }

// call that like

int nError = 0;

if(some error1)
      nError |= m_Error_1;
if(some errorx)
      nError |= m_Error_x;

DisplayErrors(nError,messages_a); // evaluate messages in context of 'a()'

Open in new window

0
 
LVL 34

Expert Comment

by:Duncan Roe
ID: 39784287
Instead of OR-ing error codes together, you could make a decision at compile time what is the maximum number of errors you wish to record and allocate an integer array of that size. Then use a count variable to append to it
int num_errors = 0;
int error_codes[99];
// Here with an error code in retcod
if (num_errors < sizeof codes)
  error_codes[num_errors++] = retcod;
// At the end of the program
if (num_errors > 0)
{
  printf("The following errors were encountered:\n");
  for (i = 0; i < num_errors; i++)
    printf("%s\n", strerror(error_codes[i]));
}

Open in new window

This assumes you are recording system error codes, which strerror will interpret. If you are recording codes which you have defined, you could write your own replacement for strerror, or display the codes numerically.
You can dimension the error_codes array to be any constant without affecting the rest of the code. If dimensioning / allocating with a variable, you must keep a copy of that variable and compare against it instead of using sizeof
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 28

Expert Comment

by:pepr
ID: 39784633
What about using std::vector? You can .push_back() new values. The vector grows automatically -- no problem with whatever number of recorded errors.

http://www.cplusplus.com/reference/vector/vector/
0
 
LVL 13

Expert Comment

by:frankhelk
ID: 39784916
Hmm ... instead of messing around with bitwise error things, how about using some object collection for it ?

I think of sth. like this (just a concept from memory, untested, please forgive syntax errors etc.):

void somefunction()
{
  // create stash for errors
  ArrayList errorstash;
  int errorcode;
  // Alternative: String errorcode = new String();

  errorstash = new ArrayList();

  // some code generating an error with code 99
  if (error) errorstash.Add(99);
  
  // Alternative and luxurious
  if (error) errorstash.Add("somefunction(): Ooops ... !")

  // more code / error additions ...

  // Display Time

  if (errorstash.Count > 0) 
    for (int i=0; i < errorstash.Count; i++)
    {
        errorcode = errorstash.ElementAt(i);
        printf("%i\n",errorcode);
        // Alternative: printf("%s\n",errorcode);
    }
}

Open in new window

The special charme of this is the nearly endless number of errors that could be recorded, the detection of repeated errors and the lack of need to mess around with bitfields.

The disadvatages are more overhead in ressources when managing the ArrayList object.

@pepr: I know, the ArrayList is from the VC++ environment and presumed to be Windows specific, but my example is generic ... I havn't used it before nor have I researched for that, but I presume that std::vector provides similar functionalities on non-Win-OS's.
0
 
LVL 32

Expert Comment

by:sarabande
ID: 39785693
to add to above:

you could collect all errors in a singleton class. that allows to add context information to each error, display them or write them to a log file.

class ErrorLog
{
    struct ErrorEntry
     {
        // error attributes
        int error;
        std::string info;
        // more attributes??
        // int severity;
        // std::string from;
     };
     std::vector<ErrorEntry> errors;
private:
    ErrorLog() { };  // private constructor makes it a singleton
 
public:
    
    static ErrorLog& instance() { static ErrorLog theErrorLog; return theErrorLog; }
    void log(int err, const std::string & inf)
       { errors.push_back(ErrorEntry()); ErrorEntry& ee = errors.back(); 
         ee.error = err; ee.info = inf;
       }
    void clear() { errors.clear(); }
    void display(); // shows the errors in the vector
    bool filelog(const std::string & logfile); // logs to file
};

Open in new window


you would use the above like

if(some_error1)
      ErrorLog::instance().log(err1, "some context info to error 1");
if(some_errorx)    
      ErrorLog::instance().log(errx, "some info to error x");

Open in new window


by using a macro like

#include <sstream>
...
#define ERROR(e, s) { std::ostringstream oss; oss << s; ErrorLog::instance().log(e, oss.str());}

Open in new window


you even could do like

char * firstname = "John";
    int age = 32;
    ...
    if (some_error1)
       ERROR(err1, "name=" << firstname << "  age=" << age << " something is wrong");

Open in new window

where you could add any variable contents to the info.

Sara
0
 

Author Comment

by:atomicgs12
ID: 39785903
jkr -

when you said "Well, that's the downside of this approach. But it's not 99, it's 32 or 64. " how did you come up with those numbers. If I were to use all 8 bits I thought there could be 255 error codes:
int m_Error_1       = 0x01; // 00000001
int m_Error_2      = 0x02; // 00000010
int m_Error_3      = 0x03; // 00000011
int m_Error_x       = 0x04; // 0000100
.
.
int mError_255 = 0xFF;// 11111111
0
 
LVL 86

Expert Comment

by:jkr
ID: 39785980
>>int m_Error_3      = 0x03; // 00000011

That one e.g. is ambiguous, since it's '0x00000001 | 0x00000010' - that's why you're getting double messages. Since your error codes need to be unique, only one bit has to be set. And the amount of 64 messages is because the maximum amount of bits that can be used on a 64bit CPU.
0
 
LVL 32

Expert Comment

by:sarabande
ID: 39786289
And the amount of 64 messages is because the maximum amount of bits that can be used on a 64bit CPU.

you could use more bits by using a bitset container.

#include <bitset>
...


// create error constants from 0 to 127
enum { error_1 = 0, error_2, error_3, error_4, ...., error_128, error_max};
// error_max is 128 if all numbers were added to the enum

std::bitset<error_max> errors; // creates a bitset for 128 bits
...
if (some_error_99)
{
    errors.set(error_99); // sets bit 98 to 1
    ...

// test on bits
if (errors.test(error_99) == true)
{
       ...

Open in new window


note, the error_max also could be used to set the size for a string array that defines a text for each possible error.

Sara
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

This is an explanation of a simple data model to help parse a JSON feed
Whether you’re a college noob or a soon-to-be pro, these tips are sure to help you in your journey to becoming a programming ninja and stand out from the crowd.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now