?
Solved

How to accumulate and display all error messasges using one variable

Posted on 2014-01-15
11
Medium Priority
?
428 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
  • 2
  • +3
11 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 2000 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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 35

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
 
LVL 29

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 14

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 35

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 35

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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

If you’re thinking to yourself “That description sounds a lot like two people doing the work that one could accomplish,” you’re not alone.
Q&A with Course Creator, Mark Lassoff, on the importance of HTML5 in the career of a modern-day developer.
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
Introduction to Processes
Suggested Courses

765 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