Solved

Universal MessageBox

Posted on 2001-06-27
163
1,490 Views
Last Modified: 2013-12-14
I would like to build a "universal" messagebox that will accept any type (and number) of args. This routine will convert the args (if necessary), concatinate them and then show them via the messagebox... I would like to use STL but I really don't have deep experiece with C++ and could use some help...

example:

//prototype:
void UMsgBox(...)

void UMsgBox(...)
{
   string s;
   string convArg;
   //loop thru each argument:

   for( int i = 0; i < nArgs; ++i )
   {
     //get an arg:
     ---
     //convert it to a string type:
     convArg = ---
     //concatenate the arg to the cumulative string:
     s=s+convArg;
    }
   messagebox(NULL,s,"",MB_OK);
}

Note: I would like the args to be of any type, including pointers (in which case you would be printing an adress).

the caller would just use UMsgbox like this:

UMsgbox(V1," Hi Mom! ",T2,s," pointer: ",pData);

Please help me by suppling or substituting the necessary code.

Thanks in advance!
       
   
   

   

0
Comment
Question by:khampton
  • 64
  • 48
  • 24
  • +7
163 Comments
 
LVL 4

Expert Comment

by:IainHere
Comment Utility
I guess your problem is "how do you know the type of each parameter?".  In that case, you could create a ConvertToString() function, which can accept any of the input types you would like as a parameter.  I've never thought of doing this before, and haven't the time to implement it, but it might work...

Good luck.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
You can use some of the CString::Format() function code:
void CString::FormatV(LPCTSTR lpszFormat, va_list argList)
{
      ASSERT(AfxIsValidString(lpszFormat));

      va_list argListSave = argList;

      // make a guess at the maximum length of the resulting string
      int nMaxLen = 0;
      for (LPCTSTR lpsz = lpszFormat; *lpsz != '\0'; lpsz = _tcsinc(lpsz))
      {
            // handle '%' character, but watch out for '%%'
            if (*lpsz != '%' || *(lpsz = _tcsinc(lpsz)) == '%')
            {
                  nMaxLen += _tclen(lpsz);
                  continue;
            }

            int nItemLen = 0;

            // handle '%' character with format
            int nWidth = 0;
            for (; *lpsz != '\0'; lpsz = _tcsinc(lpsz))
            {
                  // check for valid flags
                  if (*lpsz == '#')
                        nMaxLen += 2;   // for '0x'
                  else if (*lpsz == '*')
                        nWidth = va_arg(argList, int);
                  else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0' ||
                        *lpsz == ' ')
                        ;
                  else // hit non-flag character
                        break;
            }
            // get width and skip it
            if (nWidth == 0)
            {
                  // width indicated by
                  nWidth = _ttoi(lpsz);
                  for (; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
                        ;
            }
            ASSERT(nWidth >= 0);

            int nPrecision = 0;
            if (*lpsz == '.')
            {
                  // skip past '.' separator (width.precision)
                  lpsz = _tcsinc(lpsz);

                  // get precision and skip it
                  if (*lpsz == '*')
                  {
                        nPrecision = va_arg(argList, int);
                        lpsz = _tcsinc(lpsz);
                  }
                  else
                  {
                        nPrecision = _ttoi(lpsz);
                        for (; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
                              ;
                  }
                  ASSERT(nPrecision >= 0);
            }

            // should be on type modifier or specifier
            int nModifier = 0;
            if (_tcsncmp(lpsz, _T("I64"), 3) == 0)
            {
                  lpsz += 3;
                  nModifier = FORCE_INT64;
#if !defined(_X86_) && !defined(_ALPHA_)
                  // __int64 is only available on X86 and ALPHA platforms
                  ASSERT(FALSE);
#endif
            }
            else
            {
                  switch (*lpsz)
                  {
                  // modifiers that affect size
                  case 'h':
                        nModifier = FORCE_ANSI;
                        lpsz = _tcsinc(lpsz);
                        break;
                  case 'l':
                        nModifier = FORCE_UNICODE;
                        lpsz = _tcsinc(lpsz);
                        break;

                  // modifiers that do not affect size
                  case 'F':
                  case 'N':
                  case 'L':
                        lpsz = _tcsinc(lpsz);
                        break;
                  }
            }

            // now should be on specifier
            switch (*lpsz | nModifier)
            {
            // single characters
            case 'c':
            case 'C':
                  nItemLen = 2;
                  va_arg(argList, TCHAR_ARG);
                  break;
            case 'c'|FORCE_ANSI:
            case 'C'|FORCE_ANSI:
                  nItemLen = 2;
                  va_arg(argList, CHAR_ARG);
                  break;
            case 'c'|FORCE_UNICODE:
            case 'C'|FORCE_UNICODE:
                  nItemLen = 2;
                  va_arg(argList, WCHAR_ARG);
                  break;

            // strings
            case 's':
                  {
                        LPCTSTR pstrNextArg = va_arg(argList, LPCTSTR);
                        if (pstrNextArg == NULL)
                           nItemLen = 6;  // "(null)"
                        else
                        {
                           nItemLen = lstrlen(pstrNextArg);
                           nItemLen = max(1, nItemLen);
                        }
                  }
                  break;

            case 'S':
                  {
#ifndef _UNICODE
                        LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
                        if (pstrNextArg == NULL)
                           nItemLen = 6;  // "(null)"
                        else
                        {
                           nItemLen = wcslen(pstrNextArg);
                           nItemLen = max(1, nItemLen);
                        }
#else
                        LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
                        if (pstrNextArg == NULL)
                           nItemLen = 6; // "(null)"
                        else
                        {
                           nItemLen = lstrlenA(pstrNextArg);
                           nItemLen = max(1, nItemLen);
                        }
#endif
                  }
                  break;

            case 's'|FORCE_ANSI:
            case 'S'|FORCE_ANSI:
                  {
                        LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
                        if (pstrNextArg == NULL)
                           nItemLen = 6; // "(null)"
                        else
                        {
                           nItemLen = lstrlenA(pstrNextArg);
                           nItemLen = max(1, nItemLen);
                        }
                  }
                  break;

            case 's'|FORCE_UNICODE:
            case 'S'|FORCE_UNICODE:
                  {
                        LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
                        if (pstrNextArg == NULL)
                           nItemLen = 6; // "(null)"
                        else
                        {
                           nItemLen = wcslen(pstrNextArg);
                           nItemLen = max(1, nItemLen);
                        }
                  }
                  break;
            }

            // adjust nItemLen for strings
            if (nItemLen != 0)
            {
                  if (nPrecision != 0)
                        nItemLen = min(nItemLen, nPrecision);
                  nItemLen = max(nItemLen, nWidth);
            }
            else
            {
                  switch (*lpsz)
                  {
                  // integers
                  case 'd':
                  case 'i':
                  case 'u':
                  case 'x':
                  case 'X':
                  case 'o':
                        if (nModifier & FORCE_INT64)
                              va_arg(argList, __int64);
                        else
                              va_arg(argList, int);
                        nItemLen = 32;
                        nItemLen = max(nItemLen, nWidth+nPrecision);
                        break;

                  case 'e':
                  case 'g':
                  case 'G':
                        va_arg(argList, DOUBLE_ARG);
                        nItemLen = 128;
                        nItemLen = max(nItemLen, nWidth+nPrecision);
                        break;

                  case 'f':
                        {
                              double f;
                              LPTSTR pszTemp;

                              // 312 == strlen("-1+(309 zeroes).")
                              // 309 zeroes == max precision of a double
                              // 6 == adjustment in case precision is not specified,
                              //   which means that the precision defaults to 6
                              pszTemp = (LPTSTR)_alloca(max(nWidth, 312+nPrecision+6));

                              f = va_arg(argList, double);
                              _stprintf( pszTemp, _T( "%*.*f" ), nWidth, nPrecision+6, f );
                              nItemLen = _tcslen(pszTemp);
                        }
                        break;

                  case 'p':
                        va_arg(argList, void*);
                        nItemLen = 32;
                        nItemLen = max(nItemLen, nWidth+nPrecision);
                        break;

                  // no output
                  case 'n':
                        va_arg(argList, int*);
                        break;

                  default:
                        ASSERT(FALSE);  // unknown formatting option
                  }
            }

            // adjust nMaxLen for output nItemLen
            nMaxLen += nItemLen;
      }

      GetBuffer(nMaxLen);
      VERIFY(_vstprintf(m_pchData, lpszFormat, argListSave) <= GetAllocLength());
      ReleaseBuffer();

      va_end(argListSave);
}
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
How about using streams for this.  Write a function like

StreamMessage(hwnd WndHnd,const string &Title,stream &Msg)
{
   string MsgStr;

   // Get the message out of the stream.
   while (!Msg.eof()
      MsgStr += (char) Msg.get();

    MessageBox(WndHnd,MsgStr.c_str(),Title.c_str(),MB_OK);
}

This produces a message box from the contents of a stream object.  (you might wnat to add more features to ths function, like control of the buttons etc.  and or you might want to consider making it into a class member.)


Then you can use the existing features of a stream class to make this work.  Like

stringstream  S;  

itn x = 0;
int y = 5;

S << x << " " << y << someobject << endl;
StreamMessage(WndHnd,"A message",S);

You coudl produce a message from a file doing somethign like

fstream Fil("filename.txt");
StreamMessage(WndHnd, "A message",Fil);

using streams in this way is a very well known and very powerful technique.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
I would strongly recommend you don't use variable argument (VA) functions, like CString's format(), or one you might write yourself.  They _appear_ to make your life easier.  Inevitabely they do not.  They provide no type safety which leads to nasty bugs that may be very hard to detect.  Further they are not extensible solutions.   If someone ceeates a new data typoe they cannot use that data type with the format() function or other VA functions unless those functiosn are changed to support that new data type.  

streams do not suffer from these limitations, which is why they were created.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
I think the questioner is looking for a one line method for the MessageBox()
You can't do that with streams.

The stream method would just make using MessageBox function more complicated, which I don't think is the questioners goal.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>>  think the questioner is looking for a one line method for the MessageBox()
that doesn't mesh with "I would like to use STL"

However it would be possible to create a "one line" solution.  You could create a message box stream class.  i.e. it would collect the data to be displayed and then would display the data in a message box when the stream was ended.

However, that sort of approach is hard to do well and nearly impossible to do perfectly.  There is always little bits and peices that don't quite work logically.  If you work hard enough you can always break the solution, find weaknesses in it. But if you stick to its intended use,  you can usually come up with something pretty useful.

>> The stream method would just make using MessageBox function more complicated,
Looks pretty simple to me.  Use a stream like usual, then call a function to display the message box from that stream.  What part is complex?

0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
khampton,

Try the following set of functions:
int UMsgBoxV(HWND hWnd, LPCTSTR lpCaption, UINT uType, const char * lpszFormat, va_list argList)
{
     char TmpStr[1600]="";
     vsprintf(TmpStr,lpszFormat, argList);
     return ::MessageBox(hWnd,TmpStr,lpCaption,uType);
}
int UMsgBox(HWND hWnd, LPCTSTR lpCaption, UINT uType, const TCHAR * lpszFormat, ...)
{
     va_list argList;
     va_start(argList, lpszFormat);  //Although this is the msdos syntax, this syntax still works with most unix compilers/platforms
     int rtrnValue = UMsgBoxV(hWnd,lpCaption,uType,lpszFormat, argList);
     va_end(argList);
     return rtrnValue;
}

The following is an example as to how to use the above functions:


int main(int argc, char* argv[])
{
     char name[32] = "David";
     int num = 33;
     UMsgBox(NULL,"My Caption", MB_OK, "Hello %s. Test num %i",name,num);
     return 0;
}
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
khampton,
That one comment about unix, shouldn't have been there.  I copied and paste this from some other code, and I forgot to take that out.

As you can see, in order to use ellipsis(...) arguments I had to move the last two arguments to the front, and the lpText variable to the end.
UMsgBox(
HWND hWnd,          // handle of owner windowLPCTSTR lpCaption,  // address of title of message box
UINT uType          // style of message box
const char*FormatBuf//
... //The arguments that are to go into the FormatBuf
);
 
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
You might want to try

   char name[32] = "David";
   int num = 33;
   UMsgBox(NULL,"My Caption", MB_OK, "Hello %s. Test num %i",num,name);

too.  No type safety.   No extensiblity.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>> No type safety.   No extensiblity.

14 years of programming and counting.  And I have never had a debug problem with ellipsis(...) arguments that I didn't pick up almost immedietely.

If you're having this much problem with debugging your code, then I think you should try reading some debug books.

It has been my experience that ellipsis(...) does not cause the debug problems you're talking about.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
Why don't we just let the questioner decide what's best for him/her.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
Here's another example:
int XMessageBoxV(HWND hWnd, LPCTSTR lpCaption, UINT uType, const char * lpszFormat, va_list argList)
{
     char TmpStr[1600]="";
     vsprintf(TmpStr,lpszFormat, argList);
     return ::MessageBox(hWnd,TmpStr,lpCaption,uType);
}
int XMessageBox(HWND hWnd, LPCTSTR lpCaption, UINT uType, const TCHAR * lpszFormat, ...)
{
     va_list argList;
     va_start(argList, lpszFormat);
     int rtrnValue = XMessageBoxV(hWnd,lpCaption,uType,lpszFormat, argList);
     va_end(argList);
     return rtrnValue;
}

int XMessageBox(LPCTSTR lpCaption, UINT uType, const TCHAR * lpszFormat, ...)
{
     va_list argList;
     va_start(argList, lpszFormat);
     int rtrnValue = XMessageBoxV(NULL,lpCaption,uType,lpszFormat, argList);
     va_end(argList);
     return rtrnValue;
}

int XMessageBox(UINT uType, const TCHAR * lpszFormat, ...)
{
     va_list argList;
     va_start(argList, lpszFormat);
     int rtrnValue = XMessageBoxV(NULL,"",uType,lpszFormat, argList);
     va_end(argList);
     return rtrnValue;
}

#define XMessageBox_(name) \
int MessageBox##name(const TCHAR * lpszFormat, ...) \
{ \
     va_list argList; \
     va_start(argList, lpszFormat); \
     int rtrnValue = XMessageBoxV(NULL,"",MB_##name,lpszFormat, argList); \
     va_end(argList); \
     return rtrnValue; \
} \

XMessageBox_(OK);//MessageBoxOK
XMessageBox_(OKCANCEL);//MessageBoxOKCANCEL
XMessageBox_(RETRYCANCEL);//MessageBoxRETRYCANCEL
XMessageBox_(YESNO);//MessageBoxYESNO
XMessageBox_(YESNOCANCEL);//MessageBoxYESNOCANCEL


int main(int argc, char* argv[])
{
     char name[32] = "David";
     int num = 33;
     XMessageBox(NULL,"My Caption", MB_OK, "Hello %s. Test num %i",name,num);
     XMessageBox("My Caption2", MB_OK, "Hello %s. Test num %i",name,num);
     XMessageBox(MB_OK, "Hello %s. Test num %i",name,num);
     MessageBoxOK("Hello %s. Test num %i",name,num);
     return 0;
}

I added some overloaders so you can use the XMessagebox functions with minimal arguments if desire.

I also added some special functions like MessageBoxOK and MessageBoxYESNO.  The special functions will let you use it with out having to enter a window handle, Window caption, and style.
For simplification purposes, I used a #define to create the special functions.

Now nietod will probably tell you that the world as we know it, will come to an end if you use #define in your C++ code.  Take the advise with a grain of salt, and decide what's best for you.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> 14 years of programming and counting.  And I have never had a
>> debug problem with ellipsis(...) arguments
>> that I didn't pick up almost immedietely.
But you are perfect and the rest of us are not.  VA mistakes are one of the top ten most common mistakes made in C.  That is the reason that streams were developed.  It wasn't because they were really fancy cool stuff.  It was for the purpose of providing type safety (and extensiblity) to I/O.

>> If you're having this much problem with debugging your code
None at all.

>> It has been my experience that ellipsis(...) does not cause the
>> debug problems you're talking about.
but that is not typical experience.  Plus C++ adds features that makeit even more dangerious than C.  What is the error in

somefunction (int w, int x, int &y, int *z)
{
    printf("%i %d %i %i",w,x,y,*z);
}

plus how do you putput new data types?  What about polymorphic ones?

>> Why don't we just let the questioner decide what's best for him/her.
II'm not doign anythign to prevent that.  I can't do anythign to prevent that.   but I don't fair to let him/her use a dangerious solution without being made fully aware of the dangers.  If you want to ignore the warnings that is your perogrative, but not everyone is a risk taker.

>> Now nietod will probably tell you that the world as we know it, will
>> come to an end if you use #define in your C++ code.  Take the advise
>> with a grain of salt, and decide what's best for you.
Nope.   How about if Scott Meyers does.

"Prefer the compiler to the pre-procssor"
"this little number [the max macro] has so many drawbacks, it's painful just to think about them."
"You're better of playing in the freeway during rush hour."
"But if you get that right, look at all the weird things that can happen"

Of course, I doubt if Standands committee member, Programming book author, CUJ editor, and accademic like Scott Meyers really knows half as much about C++ as Axter thinks he does.

But maybe more importantly, why even use a #define for that!  It could be handled though perfectly legitiamte C++, like a template or a simple default parameter, or maybe just a regular every-day parameter!
0
 
LVL 1

Author Comment

by:khampton
Comment Utility
Thanks to all commentors...This is a lot of code to evaluate.  I will try to check it out tonight when I get home.

Incredible...
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>Nope.   How about if Scott Meyers does.
I have no idea of what context you're taking that out of.  But it looks to me like it's referring to a particular macro, and not all macros.
If that is the case, then that did little to support your viewpoint.

I have yet to see anything specific from a Reputable Author, that definitely supports your position.  I am interested to know the true source of your viewpoint on macros.


khampton,
Feel free to ask any questions.
0
 
LVL 1

Author Comment

by:khampton
Comment Utility
Just a quick follow-up comment. I really appreciate the debate going on between Axter and nietod.  I've been a systems designer and programmer for years but nearly all of my work has been with high-level languages like Fortran, Cobol, Visual Basic (ie: pointerless stuff).

I've just started working with C++ about 6 months ago and I've got to say - its a jungle out there...
Just when I think I'm doing alright - bam - I get hit with a problem that would be real easy to solve in VB but real, real hard in VC.

I need to hear from the experts about the "traps of bad programming choices..."

Thanks again.

0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>plus how do you putput new data types?
You can use a wrapper class, functors, and special operators for new data types.  That's not rocket science?

>>What about polymorphic ones?
What about it?
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
khampton,
One of the tips I give to all new C++ programmers is to master your pointers & reference variables.
Pointers & reference are the biggest source of problems for newbies.
If you master them, you'll save yourself a lot of heart aches in the future.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> I need to hear from the experts about the "traps of bad programming choices..."
The best source for that is the Scort Meyers books.  "Effective C++" and "More Effective C++".  These are probably the 2 most respected books in the field.  I've never head any expert say they were no essential reading.  Each one deals with about 25 common mistakes that programmer make when they move into advanced C++--like using classes, templates etc etc.  A third book, Effective STL should be available now.  I have not seen it.  

>> You can use a wrapper class, functors, and special operators for new
>> data types.  That's not rocket science?
Its certainly extra work.  but more importantly, now does it work?

Say I have class point

class Point
{
   int x,
   int y;
   // all the standard stuff.
};

If I make Point insertable and extactable, which is a good practice for any program that uses STL, then I can place a point in a message box for "free"  Or in a file, or in a string, or ...

But how do I make your code print a point?  its extra programming and it solves only one problem.

>> >>What about polymorphic ones?
>> What about it?
How could your approach ever handle polymorphic data types?  i..e you have an indirection to a base class and must print the information from the derived class.  Well, I giess there are ways, but with streams it works automatically.  

0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>But how do I make your code print a point?  its extra
>>programming and it solves only one problem.
Just use the members directly.  I'm not sure I get the problem you're presenting here.
class Point
{
  int x,
  int y;
  // proper constructor
};

CPoint cp(33,44);
MessageBoxOK("My CPoint is %i x %i",cp.x,cp.y);

>>Its certainly extra work.  but more importantly, now >>does it work?
It's extra work for the rare times that you need to do this.
The stream method is extra work all the time.

>>Well, I giess there are ways, but with
>>streams it works automatically.  
Yes there are ways, and you're right that streams do this automatically, but how often is this going to be required for a function like MessageBox.  Not very often.
The stream method is appropriete for a class or function that needs to work with any type, but I think this is overkill for a MessageBox function.
The stream method adds extra work, and the chances of using the benifits from it, are slim to none for a MessageBox function.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> Just use the members directly
And if there are 100s of them?  That is lots of work.  That is why insertion operators are created.

>> The stream method is extra work all the time
It allows you to write the insersion once--which your probably have to do anyways, then use it everywhere.  How is that more work all of the time.

>> ow often is this going
>>to be required for a function like MessageBox.
3000+ times in one specific type of case in a program I wrote.  There are other types of cases.

If an exception occurs in my program I can << any of the classes involved to log run-time information about that class to document the nature of the exceptionall condition.  The extra cost?  none.  I have to be able to provide << for object permenance anyways.

The difference is that the work to provide a working operator << is done once but can be used for many many different parts of the program.  iPlust it can be amde to work polymorphically.  it is well encapsilated int the class.  Your approach would not be encapsulated.  You need to repeat the logic everywhere the object is outputted.  the code you write only works for a single speciific type of need.  It doesn't help you to make objext permance work.  It doesn't help you to close objects.  it doesn't help you to write the data to a file.  And so on.

>> but I think this is overkill for a MessageBox
At worst it is overkill with extra type safety.  At best it is an easy solution compared to a hard one.

But more importantly, it is not just for producing messages.  Its much more powerful than that.  It helps solve many problems.  
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
And have you spotted that error in the printf() yet?   It will at the very least cause informatio to be pritned wrong.  it might cause a crash.   Tthe compiler not catch it.  Can you?   And when you do.  Are you sure you never made it?
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
I still don't see the extra work you're talking about.
Can you give an example of this?  
Can you give an example of some class in which you would have to do extra work in order to pass it to a ellipsis(...) function?
I'm having a hard time seen this extra work you're talking about.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>Tthe compiler not catch it.  Can you?  
As I stated previously, I've never had a hard time catching an error in printf or any other ellipsis(...) function?
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
So you did catch that error then.   What was it?  

In case you've forgottin the function was

void somefunction (int w, int x, int &y, int *z)
{
   printf("%i %d %i %i",w,x,y,*z);
}

(I forgot the void before, but that isn't the error).
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
I didn't get that you were asking me about a perticular code.

No, I don't see an error in the somefunction function.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
You still have not given an example of the extra work that you're talking about.
0
 
LVL 1

Author Comment

by:khampton
Comment Utility
Ok, I'm starting to evaluate the code samples and I thought I'd start with the smallest one by nietod BUT because I'm a newbe - I'm having trouble:

// UnivMsgBox_Demo.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <string>
#include <stdio.h>
using namespace std;

//prototypes:
StreamMessage(HWND WndHnd,const string &Title,stream &Msg);


int main(int argc, char* argv[])
{



     stringstream  S;  

    int x = 0;
    int y = 5;

    S << x << " " << y << " hi mom!" << endl;
    StreamMessage(WndHnd,"A message",S);

     return 0;
}


StreamMessage(HWND WndHnd,const string &Title,stream &Msg)
{
  string MsgStr;

  // Get the message out of the stream.
  while (!Msg.eof()
     MsgStr += (char) Msg.get();

   MessageBox(WndHnd,MsgStr.c_str(),Title.c_str(),MB_OK);
}


When I compile, I get the following errors:

Compiling...
StdAfx.cpp
Compiling...
UnivMsgBox_Demo.cpp
Z:\VC++Demos\UnivMsgBox_Demo\UnivMsgBox_Demo.cpp(11) : error C2061: syntax error : identifier 'stream'
Z:\VC++Demos\UnivMsgBox_Demo\UnivMsgBox_Demo.cpp(19) : error C2079: 'S' uses undefined class 'basic_stringstream<char,struct std::char_traits<char>,class std::allocator<char> >'
Z:\VC++Demos\UnivMsgBox_Demo\UnivMsgBox_Demo.cpp(24) : error C2297: '<<' : illegal, right operand has type 'char [2]'
Z:\VC++Demos\UnivMsgBox_Demo\UnivMsgBox_Demo.cpp(25) : error C2065: 'WndHnd' : undeclared identifier
Z:\VC++Demos\UnivMsgBox_Demo\UnivMsgBox_Demo.cpp(31) : error C2061: syntax error : identifier 'stream'
Z:\VC++Demos\UnivMsgBox_Demo\UnivMsgBox_Demo.cpp(36) : error C2065: 'Msg' : undeclared identifier
Z:\VC++Demos\UnivMsgBox_Demo\UnivMsgBox_Demo.cpp(36) : error C2228: left of '.eof' must have class/struct/union type
Z:\VC++Demos\UnivMsgBox_Demo\UnivMsgBox_Demo.cpp(37) : error C2146: syntax error : missing ')' before identifier 'MsgStr'
Z:\VC++Demos\UnivMsgBox_Demo\UnivMsgBox_Demo.cpp(37) : fatal error C1903: unable to recover from previous error(s); stopping compilation
Error executing cl.exe.

UnivMsgBox_Demo.exe - 9 error(s), 0 warning(s)

I probably don't have the headers right...Please comment.

Thanks!

0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
I believe you need to add #include <sstream>

change stream to stringstream
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
There's also a type-o on the while loop.
You're missing right ")"
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
The following is nietod's code without the type-O, and the correct #include

#include <windows.h>

#include <string>
#include <sstream>

using namespace std;

//prototypes:
int StreamMessage(HWND WndHnd,const string &Title,stringstream &Msg);


int main(int argc, char* argv[])
{
     stringstream  S;  
     int x = 0;
     int y = 5;
     S << x << " " << y << " hi mom!" << endl;
     StreamMessage(NULL,"A message",S);
     return 0;
}


int StreamMessage(HWND WndHnd,const string &Title,stringstream &Msg)
{
     string MsgStr;
     while (!Msg.eof()) MsgStr += (char) Msg.get();
     return MessageBox(WndHnd,MsgStr.c_str(),Title.c_str(),MB_OK);
}
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
I notice that nietod's code lets a bad charactor get through at the end of the string.
0
 
LVL 1

Author Comment

by:khampton
Comment Utility
Thanks Axter for the fix.  I too notice the extra char - I get an umlot y char...

Other than the extra char, nietod's code seems good ... but will it display the address of a pointer?  I'll try that later.

Ok, on to the next code example........
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
//************************************
int UMsgBoxV(HWND hWnd, LPCTSTR lpCaption, UINT uType, const char * lpszFormat, va_list argList)
{
    char TmpStr[1600]="";
    vsprintf(TmpStr,lpszFormat, argList);
    return ::MessageBox(hWnd,TmpStr,lpCaption,uType);
}
int UMsgBox(HWND hWnd, LPCTSTR lpCaption, UINT uType, const TCHAR * lpszFormat, ...)
{
    va_list argList;
    va_start(argList, lpszFormat);
    int rtrnValue = UMsgBoxV(hWnd,lpCaption,uType,lpszFormat, argList);
    va_end(argList);
    return rtrnValue;
}
//************************************
//The above section is the only part you need.


int main(int argc, char* argv[])
{
    char name[32] = "David";
    int num = 33;
    UMsgBox(NULL,"My Caption", MB_OK, "Hello %s. Test num %i",name,num);
    return 0;
}
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
Something else to consider is the extra code involved with the other method when you want to do precsion.

Example:
int main(int argc, char* argv[])
{
   float money = 33.34234;
   float barrel = 1.4567856;
   UMsgBox(NULL,"My Caption", MB_OK,
              "Exon paid $%3.2f per %1.4 barrels of oil",money,barrel);
   return 0;
}
 
Even though money has five digits to the right of the decimal, UMsgBox function was still able to display it correctly by putting 2 in the precsion field.  The barrel field also had another precsion.

This can be done with nietod's method, but it requires several extra steps.

Using this method, it's all in one step.
This also applies if you want to use hex numbers or octal.
In this method it's all in one step.
The other method, you have to use multiple steps to accomplish the same thing.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
My code was not meant to be a complete working solution, only a sketch/outline.

>> I believe you need to add #include <sstream>
Yes.

>> change stream to stringstream
I'm not sure where you mean, but probably not.  

>> nt StreamMessage(HWND WndHnd,const string &Title,stringstream &Msg);
That should not be stringstream, only stream.  Why Limit it to using string stream?   by using stream you can use any type of stream class.  A file stream would alow you to produce messages from a file.  A serial stream would allow you to produce messages from a serial port etc etc.

>> I notice that nietod's code lets a bad charactor get
>> through at the end of the string.
bad character! bad character!. sit! stay!    

What sort of bad character?

>> but will it display the address of a pointer?
anything you can do with a stream.  So for example

int i;
int *iptr = &i;
stringstream S;
 
S << hex << (int) iptr;

Once you know STL streams, you will know how to do that sort of thing.  And you can use that knowledge for many different situations.

>> The other method, you have to use multiple steps to
>> accomplish the same thing.
About 400 of the mostly top programming minds in the country developed STL and they couldn't come up with a good solution.  That is sad.

Well the do provide very easy to use--and extremely clear ways to set the precision--which is not true of sprintf(), you need to remember the syntax and codes for all that stuff.

But How about something better than that?  does your coede even work?  Always?  Does it work in Germany?  Do they  use "." as a decinmal point ot to seperate the thousands?  What about in England?  They don't use $ there.

Streams provide international support--al at no extra "cost"  code like

typedef ostream_iterator<char> ChrStmItr;
ChrStmItr OutItr(cout);

const std::money_put<char,ChrStmItr> &mp = std::use_facet<std::money_put<char,ChrStmItr> >(cin.getloc(),NULL,true);
mp.put(OutItr,false,cout,' ',12.34);

Allows you to ouput information in local-specific ways.  Taht uses the money_put facet for properly formatting monetary numbers.  There are facets for regular numbers, dates, times etc etc.  (And that is only one small aspect of the monetary facet.)

Hard to do that with sprintf!

I have to go.  I'll look into that extra character later.

0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
I should mention that facets tuff there is VERY ungly.  You don't usually use it like that.  You can easily encapsulate it to make it simple to use.  It is uglly because it is so very general in nature.  it can be used in an increadible variety of ways and thuse there are a tremendous number of parameters.  But for a particular sitaution you can easily trim it down.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>Does it work in Germany?
The above code you posted does not show how you're going to make that work with the StreamMessage() function.

Unless you can make it work with the StreamMessage() the code is useless.

You still have not shown an example as to the advantage of using your method over my proposed method.

I have posted examples on how to implement my method, and the advantages of implementing my method.
For example, can you post example code that can do the following using your method?
int main(int argc, char* argv[])
{
float money = 33.34234;
float barrel = 1.4567856;
UMsgBox(NULL,"My Caption", MB_OK,
  "Exon paid $%3.2f per %1.4 barrels of Oil",money,barrel);
return 0;
}

Lets see you do the above using your method.

Also why don't you show a working example code using your method, that will highlight some benifit.

I have not seen that yet, and I think it would help the questioner decide which is the better method.

I see my method as being much more function, and easier to use.  Other then type-safty, I cannot see any other benifit in using your method over mine.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
Also, it might be helpful to the questioner if you post a working example of your proposed method.  One with the corrections you preferred.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
Here's wrapper function that will let you use stringstream to pass a string to MessageBox function.

template<class T>
string StreamTostring(T data)
{
    stringstream  S;
     S << data;
    string RetrnStr;
     do
     {
          char x = (char) S.get();
          if (!S.eof()) RetrnStr += x;
     }while (!S.eof());
     return RetrnStr;
}

Code example:
int main(int argc, char* argv[])
{
   char name[32] = "David";
   int num = 33;
   UMsgBox(NULL,"My Caption", MB_OK,
       "Hello %s. Test num %i",
       StreamTostring(name).c_str(),num);
   return 0;
}

Using the StreamTostring wrapper function, any data type that can be passed to a stream, can be passed to an ellipsis(...) function.

For simple data types, the ellipsis(...) function is far better.  
If you have complex data types, you can still use the ellipsis(...) function by using the StreamTostring wrapper function.

nietod,
If you still think your method has some extra functionallity (other then type-safty) that mine does not, please post a complete example.  Not a partial example that doesn't work.
0
 

Expert Comment

by:wkmatt42
Comment Utility
I'm sorry I missed this particular question during the day - it looks like it might have been as entertaining as another religious war I had just the other day.

For what it's worth, any C programmer should know the semantics of the printf format codes like the back of his hand (or at least have a handy reference within reach). I use them in every single program I've ever written because my log class is built on top of them. Well, that and a handy set of macros.

And debugging them is about the easiest debugging task you're ever likely to encounter. All you have to do is look at your output - if it's messed up, the odds are that you missed a %, forgot to pass an argument, or simply misplaced one.

Oh - and they're typically faster (often by at least an order of magnitude) than doing things with streams and/or strings. In this particular case, since you're simply preparing a dialog box, that argument is pretty insignificant. But I know too many people who constantly choose the latter (to be more C++-like) and their software suffers for it.

Not that streams and strings don't have there places. I also use them all the time, but for some situations, other tools are more appropriate.

And one comment about Scott Meyers. His books are certainly two (can't wait for three) of the most valuable tomes on my shelf, but notice that he says to "prefer" one method over another, where some zealouts seem to think he says "always, under any circumstance regardless of the tradeoffs, use" this method to the exclusion of all others. And, of course, where he suggests that implementing min as a macro is a stupid thing to do, he's right. But if someone were to suggest the same about the handy, cut-my-debugging-time-in-half TRACE macros, they should be slapped.
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
Streams are a royal pain to use and read.  The extra effort is simply not worth it (perhaps too many of the great minds had a hand it its formulation).  

I'd go with the vsprintf solution.  A few lesser minds put their heads together on this and it's passed the test of time.

But I'd go one step further.  Use MFC's CString::Format() fn.  In debug mode, it ASSERTs on the most common types of programmer error.  And you don't need to worry about maxing out the length of the result buffer.  

-- Dan
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>But I'd go one step further.  Use MFC's CString::Format
>>() fn.

That's not a bad idea, but then it won't work on non-MFC applications.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> The above code you posted does not show how you're going to
>> make that work with the StreamMessage() function.
it does require a little thought!

put() outputs its result usign a interator.  If you use an iterator from a stream it places the result in the stream.  If you then use that stream to generate a message box....

I/O iterators, locales, streams STL very powerful stuff.  

>> Unless you can make it work with the
>> StreamMessage() the code is useless
Of course it is uselss.  I only mention useless stuff.  

>> the advantages of implementing my method.
The advantagees being?

>> Lets see you do the above using your method.
Of course I can!   Why don't we see what knampton wants.  

>>  cannot see any other benifit in using your method over mine.
!.  Tremendous amount of code reuse.   (uses insertions that exist, or forces you to write insertsions that can be reused.  You method forces you to rwite the equivalendt code but makes reuse impracticle, you have to write it again and again.

2. output.of polymorphic types.

3. internationalization.

4.  message data can come from any stream source, like a file, serial port, etc etc

>> for simple data types, the ellipsis(...) function is far better.
If you don't make a mistake.  if you know your code will never ben internationalized.  

>> ny C programmer should know the semantics of the printf
>> format codes like the back of his hand
Any every C++ programmer should avoid using it except in extreme cases.  Not just my opinion.  Bjarne Sroustrup and most of the rest of the standard committe share this opinion.  Its not some weird bias.  its based on understanding of what causes problems in C and what will cause even more problems in C++.  They delayes the C++ standard for an extra 5 years in order to develop STL.  they didn't do that becauswe it was really cool.  They did that because it was very important.

>> All you have to do is look at your output - if it's messed up, the odds
>> are that you missed a %, forgot to pass an argument, or simply
>> misplaced one.
Very easy?   No one has spotted the bug in the example I posted.  That bug wasn't know a few years ago.  I published a tip about it in CUJ.  

>> Oh - and they're typically faster (often by at least an order
>> of magnitude) than doing things with streams
>> and/or strings.
As you said this is for displaying a message in a message box.  The computter will spend 100s of order of magnitiude more waiting around for the user to press okay.  You could never measure this effect.  You could ouput the data 1000 extra (uncessary) times and not notice the effect.  Even if the data was 100s of k.

>> But I know too many people who constantly choose the latter
>> (to be more C++-like) and their software suffers for it.
There are reasons why is C++-like.  If you intend to use polymorphism, if you intend to use templates, if you intend to use refrerences, if you intend to use internationalization, then you are using C++ and you are goign to be much better of using C++ I/O.  The best argument for C I/O in C+++ is "I don't know C++ I/O"  That is not a good excuse.

>> but for some situations,
>> other tools are more appropriate.
I wuld use printf() in very specific instances.  L:ike when it is extremely well encapsulated so that I know that it can be thourugly tested.  Like in customer procedure to convert a number to ASCII it might make sense.  But to try to employee a VA procedure throughout a program is asking for problems.  

>> but notice that he says to "prefer" one method over another
Waht that means is that there has to be an indisputable argument to use the less prefered option.   Ignorance doesn't qualify.   I tight bottleneck might, if the code can be well encapsulated and tested.  A user interface where the user actuyally chooses the format at run-time might be a good justification--but talk about dangerious!  

>> cut-my-debugging-time-in-half
>> TRACE macros, they should be slapped.
Not necessarily!  In line functions might do better.  They obey scope for example. With optimizations on and conditional compilation to remove the "guts" of them, you will usually find that the function call dissaprears completely, so there is no speed/size penalty.

>> Streams are a royal pain to use and read.
I can't image an easier to read system.  And it requires nearly no memorization of specification fules.   the dissadvantage is that it does takeup a lot more "room" than a printf() statement.  but that is what makes it clearer to read.  i.e. setprecision() is pretty clear, compared to a number in a string of symbols.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
nietod,
>>Not just my opinion.  
If this is not just your opinion, can you quote some references?  (author, book, and page)?......

>>They delayes the C++ standard for an extra 5 years in
>>order to develop STL.  STL.  they didn't do that
>>becauswe it was really cool.  
STL=Standard Template Library.  What does that have to do with stream?  It was delay for templates, not stream.  Stream is included in the STL, but it's not the STL...

>>They did that because it was very important.
STL is very important.  Not stream.

>>Waht that means is that there has to be an indisputable
>>argument to use the less prefered option.  
This is your interpretation of the meaning.  This is not a fact.

>>And it requires nearly no memorization of specification
>>fules.
It's worse, because with streams you have to memorize multiple classes, and functions.
And you do have to memorize rules.  When to use "<<" or ">>";
You have to memorize endl, ends, flush, put, seekp, sentry, tellp, write, wcin, wcout, clog, wclog, cerr, wcerr,  stringstream, iostream, istream, ostream, string::c_str(), operator<<, operator>>, getline, read, peek, get, tellg, ignore, ect....... a lot more.....

That doesn't seem like less memorization to me.

Stream also has it's potential bugs, that can be harder to detect.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
If you want to handle multiple languages, the code can easily be changed to use _stprintf instead of sprintf.
_stprintf is a VC++ macro that uses the correct char/wchar_t type depending on the project.
So this can not be used as reason to justify using stream.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> _stprintf is a VC++ macro that uses the correct char/wchar_t type depending on the project.
That doesn't begin to solve the problem.  Does it make dates appear in the correct order?  i.e. DD/MM/YY  instead of MM/DD/YY when needed?   Does it display time in AM/PM or 24 hour time as appropriate?  does it know to use a "," as a decimal point in languages that do so?  does it know to use the pound symbol for currency in England instead of a $?   And what about colation?  What about extraction as opposed to insertion?  I don't think the standards committe  would have spent 5 years on it if sprintf() coudl just have been made wide-cjharacter compatible!

wchar is only a tiny tiny part of internationalization?

0
 
LVL 1

Author Comment

by:khampton
Comment Utility
This question has invoked more drama than a soap-opera...I love the passion you all have for your craft!

Let me give a little more clarification:

I want to produce a drop-in class that will display data & messages at run-time.  I will be using this UMsgBox function for debugging mostly BUT I will also use it as an "official" dialog to the user when needed.

My roots are in VB development and as you know, we don't have to worry as much about type safety...so I'm trying to make my debugging life easier with this function. (ie: I won't have to look up all of the type conversion routines - uuggg).

I love using c++ for developing API style routines.  I prototype them in VB and convert them to c++ .dlls.  They run faster and are real easy to work with.  (NO registration required).  This UMsgBox will be of tremendous benefit...

I'm going to let this debate go on a while longer and then I will award my points.

Can I split the points?  Both Axter and nietod have contributed far more than I expected...Thanks!



0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>5 years on it if sprintf()
I've already stated that it did NOT spend 5 years on stream.
I see you choose to ingnore that.
All those features can easily be done with the stream wrapper I posted earlier, and I highly doubt it will be required for MessageBox function.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>Can I split the points?  Both Axter and nietod have
>>contributed far more than I expected...Thanks!
Yes, you can split the points.  Just post a request with a link to this question in the Comunity Support topic area.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
//**************************************
Author: Brian Overland
Title:C++ in Plain English (Second Edition)
Page 87:
Most books on C++ tend to favor one approach and dismiss the other as wrong-headed.
    There's a good reason for this (it's not only that the authors are stubborn, biased lot!).
    The truth is that you can write equally efficient, readable, and elegant code either way.  The stream objects are, arguably, easier to use in simple cases.  On the other hand, use of prinf and scanf can make for more-readable code when significant formatting is involved.
//**************************************

nietod,
I've shown you my reference, I still have not seen yours.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
nietod,
So far the only book I found that supports your position, is written by an author who you previously stated stinks!
[Herbert Schildt] (C++ The Complete Reference) 3rd Edition

I guess you're right, he does stink!
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> (author, book, and page)?...
Bjarne Stroustrup
"The general advantae of the stream output functions over the C standard library function printf() is that the stream functions are type safe and have a common style for specifying outputs of obkects of built-in and user-defined types."

"C's prinff family of functions is an effective and often convenient I/O mechanism.  It is not, however, type-safe or extensible to user defined types.  I started looking for a type-safe, terse, extensible, and efficient alternative....

"Unions and the use of ellipsis to suppress type checking of function arguments provide other loopholes in the protection "

"Programmers should know that unions and unchecked function aguments are inheriently dangerious, should be avoided wherever possible, and should be handled with special care when actually needed."

I think that last one really summs it up well!!!  

>>  It was delay for templates,
>> not stream.  
Not templates.  The primary delay was to standardize the STL.  Read Design and evolution of C++.

>> This is your interpretation of the meaning.
How else can you intrpete it.  Prefer X over Y means use X unless you feel like using Y?  

>> It's worse, because with streams you have to memorize multiple classes, and functions.
You have those classes and functions anyways!  Its not added.

>> You have to memorize endl, ends, flush, put, ...
True but it is much more intuitive.  What is the character used to end a file?  It that "\e"?  "\z"?  "^z"?  Actually is there such a character?   But "ends" for endstream.  That's prety clear.    What about to end a line?  It is a line feed or a carriage return?  that is is it "\n" or "\r"?  hard to remember.  Specially if you do lots fo hardware work!   but "endl" that is clear?   flush?  is that harder to rmember than fflush()?    etc

>> Stream also has it's potential bugs, that can be harder to detect.
Oh?   What?

And what is the problem in the code I posted.  You can spot errors in VA procedures.  What is the error?
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>>  guess you're right, he does stink!
I don't dissagree with his ideas and I never said he stinks.  I said that the general opinion among other accademcs has been that his books have caused students a lot of confussion and missunderstanding.  i.e. you might say I dissagreee with his teaching mentods, not the material.

>> I've shown you my reference, I still have not seen yours.
Of course he hasn't addressed any of the points that Bjarne Stroustrup did!
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>Of course he hasn't addressed any of the points that
>>Bjarne Stroustrup did!
And you have not address anything from Bjarne Stroustrup that pertains to this question and/or justifies your position.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>And what is the problem in the code I posted.  You can
>>spot errors in VA procedures.  What is the error?
I already stated that I saw no errors in the LAST code you posted.
I'm still waiting for you to say what error is in there.

I did however, see plenty of errors in the stream code you posted. Hmmmm.... :-)
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>What about to end a line?  It is a line feed or a
>>carriage return?  that is is it "\n" or "\r"?  hard to
>>remember.  

std::endl is equal to "\n".
What exactly do you think you're gaing by using std::endl.
More text to type, and if you need both a catridge return and an end-line, it's more complicated to do in stream.
Example:
Non-stream code: printf("Hello\r\n");

Stream code: s << "Hello\r" << endl;

So with the stream code you have to memorize both the non-stream format and the stream format.....

That does not look easier to me.....
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> And you have not address anything from Bjarne Stroustrup that
>> pertains to this question and/or justifies
>> your position.
Well I mentioned type safety.  But that certainly isn't important.
I mentioned extensiblity.  but that's useless  No one ever wants to use user-defined tyes.
I mentioned internationlization, but we know that everyone in the world speaks English use the same notation as Americans.

>> 'm still waiting for you to say what error is in there.
References.  Does a VA funtion receive a reference or a value when passed a reference?  And when you solve that, there's another pitfall ready for you.  VA doesn't work well with C++'s extensions.

>> I did however, see plenty of errors in the stream code you posted. Hmmmm....
That was not production code.  I hust quickly sketcted it out.  I never even compiled it.

>> What exactly do you think you're gaing by using std::endl
Clarity.  You know from experience that end of line is \n.    Do you think a novice would have an easier time remembering \n or endl?  Especially when there are others to remember.    Claridy and expressiveness was another reason that streams were developed.  

>>  and if you need both a catridge return and an end-line,
>> it's more complicated to do in stream.
Is this a joke?   There is no point in debating this stuff if you are going to be rediculous.
0
 

Expert Comment

by:wkmatt42
Comment Utility
>> The best argument for C I/O in C+++ is "I don't
>>know C++ I/O"  That is not a good excuse.
There's always the argument that stream i/o can be 5 (using Visual C++) to as much as 25 times slower (on AIX) then the printf family.

And what's with your (nietod) annoying habit of quoting comments out of context? I thought I was pretty clear when I said:

"Oh - and they're typically faster (often by at least an order of magnitude) than doing things with streams
and/or strings. In this particular case, since you're simply preparing a dialog box, that argument is
pretty insignificant."

You opted to cut and paste the first sentence then proceeded to lecture that since it's not bottleneck, it didn't matter. If you had bothered to read the next sentence, you would have seen that, in the context of the user's question, I had already made that point.

And the following exchange:

>>>>(Axter)  It was delay for templates,
>>>> not stream.  
>> (nietod) Not templates.  The primary delay was to standardize the >>STL.  Read Design and evolution of C++.

Axter's point was that five years were not spent developing streams. The fact that they didn't spend it all on templates either hardly diminishes that point.

I really don't particular care if you use streams and strings - I use them myself. But I more often than not prefer to use stdio, character arrays, and macros when they make life easier. Your continuous rant about how we're somehow defying the gods of C++ (i.e. Bjarne, Scott Meyers, etc.) simply because we interpret their suggestions and warnings as just that can be a bit tiresome.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>Is this a joke?   There is no point in debating this
>>stuff if you are going to be rediculous.
Seems like something someone would say when proven wrong, and can't think of a way to academically defend a viewpoint.

>>I mentioned extensiblity.  
>>I mentioned internationlization  
You've mentioned a lot of insignificant information, but you have not given one example to back up your position.
If you believe what you say, prove it.

Please show us the light Oh Yee mighty C++ God!
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> 25 times slower
>> (on AIX) then the printf family.
At 1000 times slower it doesn't matter.  if it is being written to a file, the file i/O is the bottleneck.  so much so you coudl never measure it.  If it is being written for display, then the user is the bottelneck.    its woudl be very rare when there are circumstances where this might be a bottleneck.  If it isn't a bottleneck, then efficiency is the last consideration not the first.  that is the 80-20 rule.

>>  If you had bothered to read the next sentence, you would have
>> seen that, in the context of the user's question, I had already
>> made that point.
That is why I said "As you said this is for displaying a message in a message box"  

>> Your continuous
>> rant about how we're somehow defying the gods of C++
I don't accept their points as dogma.   I study them.  i do research,  I study the litterature.  I experiment.  I inquire about their research.  I study the history of the langauge and the reasons for its designs.  

Use of VA is dangerious.  This is not some sort of superstition.  It is born out though emprical studies.  C++ was develeped in part to avoid these and other similar dangers.  This is not my beleif, this is a fact.  Streams was developed to deal specifically with the flaws in C I/O.  to deal with is lack of type-safety--a known cause of bugs and its lack of extensiblity, which whas recognized as a problem with the addition of classes.   This is not some blind belief.    

I have never said not ever use VA.  I have suggested a few times where it might be appropriate, where the risk can be minimized and where there might be a measurable advantage.  But suggesting that it be used as a widespread mechanism throughout a program is simply irresponsible.  If you choose to do that in your own code, I think you are a fool.  If you choose to tell someone else to do it, you are harmful!  

I know its hard to break with tradition, but tradition alone doesn't make something the right choice.  The recognized weaknesses in VA and C I/O should have people using them very nervious.  
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>> 'm still waiting for you to say what error is in there.
>>References.  Does a VA funtion receive a reference or a
>>value when passed a reference?  And when you
>>solve that, there's another pitfall ready for you.  VA
>>doesn't work well with C++'s extensions.
If you have a point to make here, make it.  Otherwize there's nothing wrong with the code you're refferring to.
When you attempt to make this point, make sure you have some type of refference to back it up.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> You've mentioned a lot of insignificant information,
Type safesty may be insigificant to you.  But its not to most people.  its not to Bjanre Stroustrup.  Bassically its very important to anyone that makes mistakes.

Extensiblity is't important/  will if all you need is char, int, and double I guess you could make that argument.  Most programms want more than that.

Polymorphism isn't important?  
Internationalizaton?
Exception safety?

Can you honestly tell me that none of that is important to a typical C++ programmer?

>> Seems like something someone would say
>> when proven wrong
You are just being stupid on purpose.  You work in DOS/Windows, you know that endl produces a carriage return line feed on file systems that require it.  As does \n for that matter.

>> If you believe what you say, prove it.
Proove what?  Prove that streams are type-safe?  That they are extensible?  That they support internationalization?  come on.  You either have to be a complete morron or you already know that and i actually don't think you are a moron1  But if you have any doubts, perhaps you should read some books on STL or atleast the quotes from Stroustrup above!
0
 
LVL 1

Author Comment

by:khampton
Comment Utility
nietod,

I know you are very busy and I really do appriciate all that you have contributed.

Could you suggest how I could "clean up" your code submission so that it would be production worthy?

For instance, how do I know when to strip off control chars (like endl which displays a wierd y)? Do I build a case if and fish for them? I'm not sure how to do it professionally...

Thanks.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>That is why I said "As you said this is for displaying a
>>message in a message box"  
You do this all the time.  Why bother to say it, if someone has already stated it.  You didn't add anything that wasn't already pointed out.

>>widespread mechanism throughout a program is simply
>>irresponsible.  
Will I guess there are 1000's and 1000's of irresponsible programmers out there, because this mechanism is used all the time for printf, sprintf, and CString::Format!
I guess they're all wrong, and you, (Oh Yee mighty C++ God) are right!

I think I'll take the word of a well published C++ author over yours (Oh Yee mighty C++ God)!
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> Otherwize there's nothing wrong with the code you're refferring to.
It passes a reference to a VA procedure!   That is a mistake and it is really hard to detect.  And it gets worse.   What if the value passed is a return value from a function?   Think about it.  A procedure could return by value originally and be used--safely--in a VA priocedure lurking somewhere in your program.  its tested many times and there is no problem.  Then someday someone changes the function to return a reference.  That should be a harmless act.  But now that VA procedure lurking somewhere is a time-bomb!

Any you are 100% sure you never made that mistake, and will never make it?

Ever pass a constant to scanf()?   There's another mistake!  Again it might be fine originally, but as the program is modified a seemingly innocent change causes a bug that the compiler can't detect and that a human woudl be increadibly unlikely to detect--until the symptoms are noticed.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>You work in DOS/Windows, you know that endl produces a
>>carriage return line feed on file systems that require
>>it.  
The endl works as carriage return line feed only on a file stream!!
It does not work like that on stringstream.  MessageBox is not a file stream.
This adds extra complications, and possible bugs to your program.
If you're using the data in stringstream for both displaying errors to the user, and then saving it to the hard drive, you end up saving text with missing carriage returns in your error-log file.

This is a good example of extra added bugs caused by using stream code.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>It passes a reference to a VA procedure!   That is a
>>mistake and it is really hard to detect.  
Show me a referrence for the C++ standards, that would imply this is a mistake.
I've already tested the code, and it works as is.  It passes the correct information to printf.

So if it passes the information correctly, and it's working properly, how can it be wrong????
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> You didn't add anything
>> that wasn't already pointed out.
Oh?  I thought so.

>> Will I guess there are 1000's and 1000's of irresponsible
>> programmers out there,
I would think the number is 100s of times that!   So its okay to be irresponsible then?

>> Iguess they're all wrong, and you, (Oh Yee
>> mighty C++ God) are right!
Not me.  People that study the language.  That study the programs developed in the langauge.  Researchers.   People like Bjarne Stoustrup, Scott Meyers, Herb Butter.  These are some of the most respected programmers alive.  They actually study problems and their solutions and make informed decissions about them.  They publish their findings so others can learn from them.   Do you read them?  

>> I think I'll take the word of a well published C++ author over yours
Well, I am a published author. 2 articles in press and a book in the works.   But honestly that doesn't necessarily mean anything.  (Especailly books since they are not peer-reviewed.)   But why won't you accept the advice of Bjarne Stroustrup and Scott Meyers then?  Those are just two of many top-thinkers in the field that have published this sort of advice.

>> Could you suggest how I could "clean up" your code submission

>> I'm not sure how to do it professionally...
The code was written pretty hastly and not tested.  The concept is good.  
>> so that it would be production worthy?
If you are really going to use it.  I sort of suspected that yuu would with go with Axter's solution.  

But I can't now.  I can latter tonight or tommorow.

>> For instance, how do I know when to strip off control chars
>> (like endl which displays a wierd y)
most likely just don't put them in the first place.  "endl" is used to place a line break in the stream.  You are probably getting that because of translations that are going on.   (the \n character is mapped to \r\n because this is DOS/windows, then doesn't get mapped back agian when we read it.   That is easy enough to fix.

0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> Show me a referrence for the C++ standards, that would imply this is a mistake.
Exactly!  Its not in there!

I pointed this out in a "article"  its unclear what it shoudl do.  It might pass a value and it might pass a reference.  This is implimentation defined.  Worse.  If it passes a reference--which some do--you are really in trouble.  You can't mae the VA macros work correctly.  Why?  sizeof() applied to a reference is the size of the data being refered to, not the binary size of the reference (pointer) on the stack  So the VA macros get screwed up and it is impossible to correctly obtain the parameters.

opps.

J.P. Plauger--another insigificant name--said that references were part of the C++ not C realm and that VA was really just provided for C legacy and that it wasn't compatible with C++ in lots of ways and this was just one more.    But Lets face, what does he know?
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>2 articles in press
Two articles doesn't mean anything.  Neither does a book on the works.
I'll take the view of a publish author before I take the view of 2-articles & bk in the works.

>>But why won't you accept the advice of Bjarne Stroustrup
>>and Scott Meyers then?  
I have not seen you post anything from them to support your view point.
I haven't seen you post anything that would confirm that you are speaking for the majority of C++ programmers.

So far you're the only one on this thread that supports this view.  This would lead me to believe that clearly you do not speak for the majority of C++ programmers.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>J.P. Plauger--another insigificant name
You're right, it is another insigificant name.  Moreover, you give no mention of where you're referencing this from.  What book? What Article? What Page??
Nothing!  Which is about how much value I would have to place on the words.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>> Show me a referrence for the C++ standards, that would
>>imply this is a mistake.
>>Exactly!  Its not in there!

Then there's nothing wrong with it.
Can you name a compiler in which this does not work?
I don't think so.

Can Oh Yee Might C++ God post some objective facts, instead of speculation, here-say, subjective and biased information!!
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
khampton,
You can use the algorithm in the following code to get rid of the extra charactor you're getting when using neitod's code.
template<class T>
string StreamTostring(T data)
{
   stringstream  S;
    S << data;
   string RetrnStr;
    do
    {
         char x = (char) S.get();
         if (!S.eof()) RetrnStr += x;
    }while (!S.eof());
    return RetrnStr;
}

Just replace the loop in neitod's code with the loop in the above code.  That should get rid of the extra charactor.
0
 
LVL 22

Accepted Solution

by:
nietod earned 50 total points
Comment Utility
here is a short working example.   The line that is commented out in MessageBox() is used to copy the message from the stream to the string object.  Unforunately VC's string class is missing the push_back() function that this requires--it shoudl be there!  So that line won't compile in VC and the while() loop had to be used instead.  (But that line should give you an idea of some of the tremendous power in STL.  

All thpse "std::"'s could be removed if you want by adding

using namespace std;

#include <windows.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <iterator>
#include <sstream>

int MessageBox(const std::string &Title,std::istream &MsgStm,HWND WndHnd = NULL,UINT MsgTyp = MB_OK)
{
   std::string Msg;

//   std::copy(std::istream_iterator<char>(MsgStm),std::istream_iterator<char>(),std::back_inserter(Msg));
   while (true)
   {
      char Chr = MsgStm.get();
      if (MsgStm.eof())
         break;
      Msg += Chr;
   }
   return MessageBox(WndHnd,Msg.c_str(),Title.c_str(),MsgTyp);
}

int main()
{

   std::stringstream S;

   S << "line one" << std::endl << "line two" << std::endl << 123.456;
   int i = MessageBox("Message Box Title",S);

   return 0;
}


>> Two articles doesn't mean anything.  Neither does a book on the works.
>> I'll take the view of a publish author before I take the view of 2-articles
>> & bk in the works.
Articles are peer reviewed.  books are not.  I can publish a book that says black is white.   Articles must meet much more rigorous standards.  but as I said.  Why don't you trust the published works of well regarded individuals?  

>>  have not seen you post anything from them to support your view point.
Nothing?  just quotes right?  So when Stroustrup says.

"Programmers should know that unions and unchecked function aguments are inheriently dangerious, should
be avoided wherever possible, and should be handled with special care when actually needed."

that clearly means that you should use VA parameters even if there is an alternative.  Even if that alternative has all the same functionallity.  Even if the alternative has otyher advatnaes.     That seems pretty clear.  

>> Moreover, you give no mention of where you're referencing
>> this from.  What book? What Article? What Page??
That was paragprased form a personal coorespondance with him.  he was senior edotor of CUJ at the time and was one of the editors responsible for reviewing my submission.  

But of course I have no proof of that.  So it can be dismissed since it clearly is a lie!

>> Can you name a compiler in which this does not work?
>> I don't think so.
BCB, I think version 3.  Maybe other versions.  Note that it isn;t that it doesn't work.  There is no provision in the standard stating what should occur when it is attempted.

>> post some objective facts, instead of speculation,
That's all I've been posting.

Here's another one.  Try.passing a reference to a string object as the last named parameter to a VA function.   It won't work.  sizeof() used by the VA macros fails.   solution?  there is none.
              }
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> You can use the algorithm in the following code
>> to get rid of the extra charactor
How do you intend to use that?  i.e. what is  "T Data"

I got rid of the character in a pretty direct way in the sampel above.  But using the copy() algorithm woudl have been nicer.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>Even if that alternative has all the same
>>functionallity.
It does not have all the functionallity of VA.

The quote you posted from Stroustrup, doesn't say to use stream over C style I/O.
You're putting more into it then what it states.

//**********************************************
Author: Stroustrup
Title: The C++ Programming Language (Special Edition)
Page 651 : 21.8
Because C++ and C code are often intermixed, C++ stream I/O is sometimes mixed with the C printf() family of I/O functions.  The C-style I/O functions are presented by <csdio> and <stdio.h>.  Also, because C functions can be called from C++ some programmers may prefer to use the more familiar C I/O functions.
//**********************************************

Stroustrup's book has a whole chapter on stream.  No were in this chapter does he make any attempt to recommend using stream over C-style I/O.
Furthermore, the above paragraph certainly does not make it seem as if he recommends using stream over C-style I/O.
Moreover, I would think if this author truly believed that C-style I/O's should not be used, that he would at least mention it once in the entire chapter.  He does not.  Instead he acknowledges that both styles are used.

So please stop miss-quoting Stroustrup, and stop claming that he supports using stream over C-style I/O.
This is just your miss-interpretation, and it is not a fact.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>How do you intend to use that?  i.e. what is  "T Data"
>>I got rid of the character in a pretty direct way in the
>>sampel above.  But using the copy() algorithm
>>woudl have been nicer.

nietod, your really have some nerve!
You are using the same algorithm that was inside my code.
The very same algorithm you have the nerve to ask how do I intend to use???

You talk about plagiarism.  What you did above is big time plagiarism.

Look at your code:
  while (true)
  {
     char Chr = MsgStm.get();
     if (MsgStm.eof())
        break;
     Msg += Chr;
  }

Look at my code:
   do
   {
        char x = (char) S.get();
        if (!S.eof()) RetrnStr += x;
   }while (!S.eof());

You basically copied the same algorithm, and just change the loop!
Plagiarism!
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
nietod,
Don't ever wine to me about me using stuff from your comment and not given you credit for it.  Especially a comment that I didn't even read.

Quote from neitod:
>>Even if the post is _more_ than
>>the post previously submitted, if it contains the the
>>information of the previous post, we recognize
>>that fact.  To not do so is plagerism.

Another Quote from neitod:
>>Plagerism does not have to be
>>intentional.  If you publish a paper that duplicates
>>another paper in part or in whole because you failed to
>>research it is plagerism.  

Those who live in glass houses should not throw stones.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> The quote you posted from Stroustrup, doesn't say to use stream over C style I/O.
No it doesn't.  It doesn't say to stand on your head either.  What is your poit?    it says to avoid using VA wherever possible.  i.e. if you have an elaborate system-wide feature that uses VA and a alternative that gives you the same functionality, you coose the alternative.

>> t does not have all the functionallity of VA.
What one feature does it not have?  

Besides type safety, your solution lacks, internationalization support, polymorphic suppport, extensibility, and a great deal of code reuse.  

This is stupid!  Do you even try to understand this stuff?

>> Also, because C functions can be called from C++ some programmers
>> may prefer to use the more familiar C I/O functions.
Right!   A dozen different places he says how dangerious VA is.  But then he also says that because of familiarity, some programs might want to continue to use the old system.  He's not saying its better.  He's not saying its as good.  (he's clear said its worse)  he is saying because programs are familiar with it and might not want to change, they might continue to use a more problematic approach.  

From that you conclude that you should encorage new programmers to use this approach?  
That you should write elaborate, system-wide features that use it?  

He certainly is not encouraging that!

And did you read any of that section?  He ges on to talk about the advantages of streams over printf().   Then he goes on to talk about the advantages of printf() over streams.  Opps no I'm wrong.  He doesn't mention any advantages of printf() over streams, but he does mention the advantages of streams over printf!   Basically the only advantage he mentions to C I/O is "familiarity"  In other words, its for programmers that are too set in their ways to learn something new.

>> Moreover, I would think if this author truly believed that C-style I/O's
>> should not be used, that he would at least mention it once in the
>> entire chapter.  He does not.  Instead he acknowledges that both
>> styles are used.
And why does he say that both are used?  Two reasons.  Because C code is intermixed with C++ code (far less true these days, i might add) and programmers familarity with the C I/O.   Not because of any advantage to them.  Take a look at what he says, you posted it.

>> So please stop miss-quoting Stroustrup,
Where did I missquote him?  I simply took the time to _listen_ to him.  My argument is right there in what you posted and in the paragraphs that follow.

And if you think that it so important to use C and C++ I/O in a single program, can you explain why the standards committee reversed an earlier decission and choose to not syncronize C and C++ I/O by default?   That is a pretty signifcant decision.  
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> nietod, your really have some nerve!
>> You are using the same algorithm that was inside my code.
I wrote that code independantly and before your post was even vissible to me.  

The code is not the same, although it is similar.  but considering its simplicity, it almost has to be similar.  There aren't too many ways to write it!

And as you notice, I actually wrote a very very different algorthhm that was not VC compatible.

or maybe you are right?  Maybe I couldn't write that code by myself.  I admit it.  I can;t write a loop to copy information from a stream to a string!

>>  You basically copied the same algorithm, and just change the loop!
the nature of the loop.  and the termination condition.  I remove the unneessary cast.

Your loop tests eof() twice in each iteration.  Mine tests it only one time.

Do these look the same to you?   Considering the simplicity of the situation, its hard to iamge how they coudl be more different.

But by all means report this to CS.


In the meantime.  Do you haveythign _reasonable_ to say?   you know, things envolving OOP theory and practice?  Principles of program design?   That sort of thign?    
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>How do you intend to use that?  i.e. what is  "T Data"
You still haven't explain why you asked the above question, and then you follow it with code using the same algorithm....
Hmmmm....
"This is stupid!  Do you even try to understand this stuff?"
I think your above quote applys here.

And you're still mis-interpreting Stroustrup, and putting words in his mouth.  He is not saying anything of the kind.
No were in his book does he recommend not useing C-style I/O.  No where.
You're twisting one comment, to mean something completely different.


You also have not posted where you got the quote from exactly.
What page, what book?

I like to see that for myself.  Seeing how you mis-interpret so much here, I wouldn't be surprise if his actual words look no were near what you're posting here.
0
 

Expert Comment

by:wkmatt42
Comment Utility

From neitod:
>>I wrote that code independantly and before your post was even vissible to me.  

Also from neitod:
>>Plagerism does not have to be
>>intentional.  If you publish a paper that duplicates
>>another paper in part or in whole because you failed to
>>research it is plagerism.  


Hmmm....
0
 

Expert Comment

by:wkmatt42
Comment Utility
Sorry - I couldn't resist. I was stuck in a meeting all afternoon and then had to go buy a car, so I missed all the fun.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>Also from neitod:
>>Plagerism does not have to be
>>intentional.  If you publish a paper that duplicates
>>another paper in part or in whole because you failed to
>>research it is plagerism.
 
It's hard to believe someone can take such an extremist view, and then still not believe that they're plagiarizing when they are clearly performing the exact same behavior.

>>I wrote that code independantly and before your post was
>>even vissible to me.  
This is bull.  In order for you to put your code into the comment block, you would have had to been able to see my comment.
My comment has a time stamp that is two hours earlier then your posted code.
According to your plagerism comment, it's your responsibility to do the research.  So ignorance is no excuse.
Also in accordance with your own comment, it is plagerism weather you use the whole thing, or part of it.

So either admit you plagerized, or admit that your previous plagerizm statement is bull.
One or the other.  You can't have both.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
nietod,
And before you say that the code is not exactly the same, remember that in the question you accuse me of plagerism, you did not right any code at all.
I had a complete class that was written long before you posted your comment, and just because your comment said something about CreateProcess() and SuspendThread, and my code had the functions that you mention, you accuse me of plagerism.
To refresh your memory, see following question:
http://www.experts-exchange.com/jsp/qShow.jsp?ta=cplusprog&qid=20140846

The last comment you made in the above question, states the following:
>>From nietod,
>>perhaps you take the time to read other poeple's
>>comments.   I am certanly not the only one that
>>feels that this is important.

Hmmm....
Well it does not look like you took the time to read other peoples comment in this question.
Doesn't look like you practice what you preach........
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
Oh one more thing.
The second to the last comment you make in the above link, states the following:
>>If you can't bother to read the entire question--
>>including its , you should probably stay out of it.
>> There may be important stuff in there.  Otherwise its
>>like coming into the middle of a conversation.

So maybe you should take your own advice, and stay out of it....
0
 

Expert Comment

by:wkmatt42
Comment Utility
That was well worth twenty points!
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
Ok, one last nietod quote, which I really think is funny considering your above comments.

//*************************************************
Author: nietod
The point is that Axter's solution used the very same
techniques I had suggested.  He didn't point this
out.  Many clients would thus choose to give the points to me--but not necesesarily.  But in any case
it is still propper to point this out.  
//*************************************************
[http://www.experts-exchange.com/jsp/qShow.jsp?ta=cplusprog&qid=20140846]

Sorry nietod, but considering the irony of your words, I couldn't resist. LOL :-) :-0 LOL
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>That was well worth twenty points!

Considering what he said in that PAQ, doesn't he have some nerve trying to defend himself here. LOL again....

He really has some big ones.... LOL
0
 
LVL 9

Expert Comment

by:jasonclarke
Comment Utility
I have to add a little to this.   I have *never* seen anything from any respected C++ expert that recommends the use of stdio over streams.  Here are a few references that I found with minimal searching:

From C++ FAQs, 2e, Marshall Cline et. al.

FAQ <36.08> '...<iostream> is safer that <stdio.h>...'
FAQ <36.09> '...<iostream> is more extensible than <stdio.h>...'
FAQ <36.10> '...<iostream> is more flexible than <stdio.h>...'

More Effective C++, Item 23, Scott Meyers:

'...but operator<< is both type-safe and extensible, and printf is neither. '

The Design & Evolution of C++, Section 8.3.1, Bjarne Stroustrup

'C's printf family of functions is...not type-safe or extensible...'

this whole section then talks about the rationale and the how/why of stream I/O

Thinking in C++, 2e. Bruce Eckel:

'...A worse problem occurs because the evaluation of the format string doesn?t
happen until runtime: there can be no compile-time error checking...'

'...For C++, the most important problem is that the printf( ) family of
functions is not particularly extensible. They?re really designed to handle
the four basic data types in C...'

'...you need to learn to use iostreams. ...In addition to gaining a great deal of leverage and clarity in your dealings with I/O and
formatting, you?ll also see how a really powerful C++ library can work....'

In addition to this, if you take a look at some of the more recent stuff, like that in Herb Sutter's gotw archive, you will see that this is not even an issue.  They all accept that stream I/O is the way to go.  
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> >>Plagerism does not have to be
>> >>intentional.
For some strange reason Axter chose to post only part of the information I wrote about plagerism.  Inexplicably he forgot to mention that it does not apply to material that is common knowledge.  he also forgot to mention the part where I said that an author is required to make all reasonable attempts to research his material in order to ensure that it is not plagerism.   All reasonable attempts.   Axter's post came in while I was writting mine.   This happens in the accademic world too.  Two authors submit duplicate material at the same time to different journals.   Neither can be held responsible for not being able to predic thte future.

Furthermore, the code is actually very different in nature.  If you step through them the order in which things occur is different.  There is one eof() test per itearation n my code and there is two eof() tests per iteration in Axter's code.  That is actually very different.

>> It's hard to believe someone can take such an extremist view, and
>> then still not believe that they're plagiarizing when they are clearly
>> performing the exact same behavior.
Yopu think that's my view?   That I am the only one that has to worry about plagerism?   Every accademic in the world shares that view.  It is the accepted principles of our society.

>> This is bull.  In order for you to put your code into the
>> comment block, you would have had to been
>> able to see my comment.
Why would I lie?   Have you ever seen a case where I did?  Not where it servers you to accuse me of it, but where I actually lied?   Honestly.  DON'T POST AN ANSWER TO THAT.  Just think about it.  Do you really need to accuse me of it/

I wrote that code on my VC computer and transfered it here without every seeing your post.  

And honestly, do you think I needed to copy your code, like I couldn't figure out a loop on my own?  Well if so, then you copied yours from my earlier code.  I give you a lot more credit for intelligence than that..

>> Doesn't look like you practice what you preach........
I do all the time.  I did in this quesiton when I repeated wkmatt42's thoughts about efficiency.   But those were not genreral or common  knowledge and my post was similar to his/hers.  but my code is clearly not like yours and was arrived at from earlier code I posted.

>> you did not right any code at all.
Right I proposed a technique to solve a problem.  You then provided code that used the technique.  That is plagerism.  Here I proposted a technique and posted code.  You then posted code that corrected a problem in it.  I posted different code that was A) based on my earlier code and B) does not really duplicate yoru code.  


>> So maybe you should take your own advice, and stay out of it....
I've read every word here.




****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************

Khampton, you can see what is happeniong here.   I've mentioned many fundamental reasons why variable arguments and things like printf() are to be avoided whereever possible in C++.   I've provided quotes to support that view from very reputable names in the C++ world.   The counter arguments are...supported by missunderstoood quotes, and a single quote from a comparitively unknown author, the rest tend to involve accusations of my lieing and stealing of ideas rather than any principle of program design, which is sometimes the only way to win an argument if the facts don't support yoru position.   Jason clarke is another top expert ont he site (Don't let points convince you of an expert's skills.   If Jason isn't the best here, he's close to it.  (Similarly there are some high point experts that aren't so good.))   Despite what Axter will problably say he, does not share my view on this.   His own view, based on many years of study and practice coincides with mine.  And Bjarne Stroustrup's and Scott Meyer's etc etc.

I'm sorry you have to read all this, but I hope you can make an informed decision

If you need any more help on my solution, you can e-mail at nietod@journey.com.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>Axter's post came in while I was writting mine.  
>>Neither can be held responsible for not being able
>>to predic thte future.

Will, that would be like me saying, I wrote my c++ CreateProcessMngr class, long before you posted your comment in the following link:
http://www.experts-exchange.com/jsp/qShow.jsp?ta=cplusprog&qid=20140846

Since I can not predict that you were going to write your comment, I should not be responsible for making any referrence to it.

>>Furthermore, the code is actually very different in
>>nature.  
To quote your phrase, "Axter's solution used the very same
techniques".
Your code has the same exact algorithm as what I posted before you.  I'm sure you understand the meaning of algorithm.

>>Why would I lie?   Have you ever seen a case where I
>>did?  Not where it servers you to accuse me of
>>it, but where I actually lied?   Honestly.  
Don't ask me a question, if you don't want to hear the answer.  And believe me, you don't want me to answer this question.  I'm being 100% honest.

>>I wrote that code on my VC computer and transfered it
>>here without every seeing your post.  
I truely do believe you did write the code with out stealing it from my code.  My point is, so did I in the above link.  I wrote my CreateProcessMngr class long before you ever posted your comment.  You can verify that by looking at the date fo your comment, and the date of the link to the class.
Yet under the same cercumstance, you still accused me of plagerism, furthermore, you still will not admit that you have performe the same offence.
You want to apply one set of rules for others, and another set of rules for yourself.


>>But those were not genreral or common  knowledge
It's also general and common knowledge to use CreateProcess() funtion to launch another program.
So what does that have to do with the price of bean?

>>but my code is clearly not like yours and was arrived at
>>from earlier code I posted.
You didn't even post code in the comment you accuse me of plagerizm in.  You gave a vague description, and you claim that description was similar to my CreateProcessMngr class.

There are much more similarities between our algorithm here, and your vague description vs my CreateProcessMngr class.
Much more similarities.  So you come far closer to fitting the bill of plagerism then I do.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
nietod,
I'm sure by now that you don't truly believe that I stole your common knowledge CreateProcess() function idea to make my CreateProcessMngr class.

You can't have it both ways.  Either we both have plagiarized each other, or neither of us has plagiarized.
Which one is it?  
In either case, I would like you to either apologize for previously accusing me of plagiarism, or apologize for your plagiarism here.
0
 

Expert Comment

by:Kisses93834
Comment Utility
>>I have *never* seen anything from any respected C++
>>expert that recommends the use of stdio over streams.  
>>Here are a few references that I found with minimal
>>searching:
I'm sure the only experts you consider respectable, are those that agree with your viewpoint.

Although I have never seen an expert recommend using stdio over streams, I have seen many experts recommend using both, or which ever one is appropriate or efficient for the code.
To say you should only use one, is like saying I?ll cut off my left arm, because my right arm is better.


0
 

Expert Comment

by:Zulma9999
Comment Utility
nietod,
Can you tell me the title of the book you're writing.
I want to make sure that I never consider purchasing it.
If the comments on this question is an example of what you have in the book I can't say I can put much value in it.
0
 
LVL 9

Expert Comment

by:jasonclarke
Comment Utility
> To say you should only use one,
> is like saying I?ll cut off my left arm

This is nonsense.  I am not saying you should *never* use stdio,  I am stating that for most it is the *preferred* solution where you have a choice.

There maybe good reasons for choosing stdio - maybe you have a library of existing software that uses it (mixing both to do the same I/O tasks *is* a bad idea - they can actually conflict, hence the need for the iostream sync_with_stdio method).

It is more like saying (assuming a right handed person) - it makes sense most often to use your right hand (streams) to write a letter, you could use your left but there is no good reason to do so.  There are cases where you have no choice (your right arm is broken).

> I'm sure the only experts you consider respectable, are > those that agree with your viewpoint.

Not true, the experts I consider respectable are those that I know have respect amongst the C++ community, that is those whose work is subject to good peer review, is widely quoted by other experts, etc. I am willing to be convinced otherwise, show me some examples of experts who do not share this view.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> I have seen many experts recommend
>> using both, or which ever one is appropriate or efficient for the code.
Good point.  In fact I made that point.    In very specific cases it might make sense to use VA or C I/O.  I gave specific recomndations about that above.    This case is far from qualifying!     Several of the quotes from Stoustrup and other reputable authors agree with this.

Does anyone have anything ov value to say?   Jason and I have proposed many reasons why Va should be avoided in cases like this and supported these point with fundamental principles of program design.   We've further posted quotes by some the most respected individuals in the field that support these points.

Are there any counter arguments that are not based on my character?
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>>  good peer review, is widely quoted by other experts, etc.
>> show me some examples of experts who do not share this view.
And "expert" here does not mean somone that has registered at EE.  It means a recognized expert.

0
 
LVL 9

Expert Comment

by:jasonclarke
Comment Utility
I couldn't resist this,  I looked up the ACCU review of Axter's source, reviewed by Francis Glassborow, who is IMO another respected expert, two particular pearls from the review are these:

'He tediously introduces you to C's printf and scanf and later tries to justify it on the grounds that using C's i/o mechanism or C++'s is a matter of personal taste. There are so many practical reasons to choose the C++ mechanism when writing C++ that it beggars belief that anyone could seriously wish to defend the C mechanism in a C++ context. Just let me give you two: the C++ mechanism is type- safe, the C++ mechanism can be extended to user-defined types.'

and...

'Quite apart from the fact that the author seems to be confused as to whether he is writing about C or C++ his knowledge of C++ seems weak.'



0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>>  the C++ mechanism is type- safe,
>> the C++ mechanism can be extended to user-defined types.'
Those are good points.  I wish I had mentioned those!!!!

Thanks Jason!
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
jasonclarke,
I like to see that review.  Can you please direct me to it.
Is it available on the web?
0
 
LVL 9

Expert Comment

by:jasonclarke
Comment Utility
0
 
LVL 1

Author Comment

by:khampton
Comment Utility
Wow...this has really been fun.  I am sending a note to Customer Service to split the points between Axter and nietod - both have proposed workable solutions and I thank them both very much.

My take on the debate:

1)C/C++ is such a robust language that a solution can take many different flavors (and philosphies).

2)Using C++ streams are safer then using c style i/o but slower...if speed doesn't matter and backwards compatability is not required, C++ streams might be a better choice (but not always...).

3)The industry is (slowly) moving away from c style i/o.

4)Use of VA functions (VA_List for instance) can be very effective when used correctly -BUT- has some inherent risks associated with them.  Has some known bugs.  Also provides (possibly) too much freedom and too little accountability thereby letting programmers hang themselves with their own rope...

5)The world would suffer if we outlawed VA functions. On the other hand, we should justify their use.

6)Experts disagree!

Thanks again...
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
nietod AKA plagiarist,
I notice you have ignored my previous request for an apology.
I'm still waiting for your apology, and an acknowledgement of wrongdoing.

An honest person would admit when they are wrong.

A dishonest person would fail to reply, or give really poor excuses for their poor behavior.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
jasonclarke,
Thanks

khampton,
Agree
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
I looked at the link, and it's not what I thought it would be.
First of all, this review is on the first edition.  I have the second edition.
Next, I thought it would have multiple reviews, but it only had one review by one person.
This person's bias is obviously going to be part of his judgment in reviewing the book.

Non-the less, it's a good link to put on my favorites, and I don't think the review should be dismiss.
But you just can't accept every critic's word as gospel truth.  You should use it as part of your decision making process, and not as your complete decision making process.

I'm sure you've heard critics down play a movie that you thought was great.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> )Using C++ streams are safer then using c style i/o but slower..
emperical studies have found that for performing equivalent tasks, stream objects tend to be no more than about 5% to 10% slower.  Its not a huge difference.   Sometimes stream objects are even faster, but overalll they are a little slower.  When people point to their huge differences, it tends to be when performing much more complicated things with streams.  For example, comparing stringstream with sprintf() is hardly a fair comparison.   stringstream dynamically allocates memory for storing the results whereas sprintf() uses a previously suplied buffer.  Stringstream has to do do much more work and does so because it is much safer (sprintf() used incorrectly can corrupt memory, you can't do that with strignstream.)

>> 3)The industry is (slowly) moving away from c style i/o.
That is certainly the trend, but I would hope not slowly!  The standsrds committe made the decission to not sync with the C I/o) several years ago.  That decission was made because studies showed that the majority of C++ programmers we not using the two mecnanisms, but rather that new development was largely using C++ I/O and C I/O was largely confined to legacy apps.

>> 5)The world would suffer if we outlawed VA
>> functions. On the other hand, we should justify their use.
you ARE a programmer.  Only a programmer thinks-=-I mean knows--the world turns on these sorts of issues.  :-)

>> I'm still waiting for your apology, and an
>> acknowledgement of wrongdoing.
I have done nothing wrong.  This clearly is not plagerism.   The code is clearl unique an based on my earlier post.  If you dissagree, notify CS.  I don't want to hear about it.   If you have soemthing usefult to support your argument, that would be great.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> First of all, this review is on the first edition.  I have the second edition.
Did the content change?  Does no no longer push C I/O.  Did he correct the return valae on main?  Does he correctly use "using declaraion"

>> This person's bias is obviously going to be part of
>> his judgment in reviewing the book.
You are talking about someone whose ethics and dedication to the language are beyond approach.  Who helped shaped the language through donated hours of reasearch, thought, and committee service.  its not a bias, its based on indepth knowledge.

>> ust can't accept every critic's word as gospel truth.
He know that when he wrote it.  That is why he had numerious concrete examples.  If those were the only flaws int he book, it would make the book very questionable.  But he makes it clear that those are only some examples.

>> 'm sure you've heard critics down play a movie that you thought was great.
But that is entirely a matter of opinion.   its not a matter of opinion when a term is used incorrectly.  Its not a matter of opinion when code in a book is non-standard conforming.  
0
 

Expert Comment

by:wkmatt42
Comment Utility
>> comparing stringstream with sprintf() is hardly a fair comparison

Excuse me? You are suggesting we use the former pretty much to the exclusion of the latter. I'd say a comparison is appropriate. And I think you'll recall a recent discussion where we did just that, and the performance differences in that case were not 5 or 10% - they were in excess of 1000%.

0
 
LVL 9

Expert Comment

by:jasonclarke
Comment Utility
> I looked at the link, and it's not what I thought it would be.

I never said it was definitive, any review is clearly an opinion.  

However, IMO anyway, it is written by a reviewer who I respect (and not just me, other people also agree, try this link from Bjarne Stroustrup's home page: http://www.research.att.com/~bs/3rd_glassboro.html, and he was involved in the C++ standards process), it deals largely in matters of fact (it says that the reference section is sloppy, and gives several examples) - things that would lead me to suspect both the book and the author at very least.

Take a look at the reviews for some of my favourite books on the site:  Accelerated C++ (Koenig), Effective C++ (Meyers), C++ Primer (Lippman), Exceptional C++ (Sutter), The C++ Standard Library (Josuttis) and you will find that the site is more than capable of good reviews.

0
 

Expert Comment

by:wkmatt42
Comment Utility
The previous benchmarks I mentioned were from a different discussion about the merits of strings/streams versus six lines of custom code versus sprintf. The simple custom code won, but sprintf was a very close runner-up, while the string/stream solution crawled at more than ten times slower then either. But, of course, that didn't matter because i/o would have been such a bottleneck that code that run ten times faster would make no significant contribution.

Though I'm sure you'll make something up to make it look like the stream version actually ran faster, here are a few little benchmarking results for file i/o.

Creating a file with 1000000 fixed length 1000-byte records:

1. stdio
       AIX          Sun
       ----------   ----------
real   1m27.75s     2m25.65s
user   0m05.16s     0m02.44s
sys    0m53.07s     0m10.03s

2. and stream

       AIX          Sun
       ----------   ----------
real   2m35.29s     5m08.00s
user   1m09.76s     0m33.76s
sys    1m22.85s     1m00.30s

In the real world, where we generate many files significantly larger than this, and where many processes have to compete for CPU time, that's pretty significant.

But now I suppose you'll tell me that if I/O isn't the bottleneck, it doesn't matter either.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> Excuse me? You are suggesting we use the former pretty
>> much to the exclusion of the latter. I'd say
>> a comparison is appropriate.
When your current car is worn, out will you be replacing it with a F-18?   They are much faster than any car.

The stream object is providing a great deal of extra features that printf() can't.   Safety is one.  but the ability to format dat of _any_ length (limited by avalable heap space).   If you write a printf() type function that does that the two will run at about the same speed.

>> they were in excess of 1000%.
Which is accordance wth that I said.   i.e. "When people point to their huge differences, it tends to be when performing much more complicated things with streams."  In an equvalent comparison you don't see differences any where near that.

>> make it look like the stream version actually ran faster,
Even though I specifically pointed out that it woudl be slower BEFORE you posted this?   Are you accusing me of being disshonest or stupid?  I'm neither.

>> Creating a file with 1000000 fixed length 1000-byte records:
What was the code?  Was it really equivlent?

0
 

Expert Comment

by:wkmatt42
Comment Utility
>> When your current car is worn, out will you be replacing it with a F-18
---
You're analogy is a backwards. It is you that is suggesting that stdio is "worn, out". But, since you asked, if money were no object I would much rather have an F-18.

>> "When people point to their huge differences, it tends to
be when performing much more complicated things with streams."  In an equvalent comparison you don't
see differences any where near that.
---
Actually, the 1000% difference was in a simple function to translate an integer into a character array. (The custom function actually padded the array as well so, in effect, it did more to accomplish the original goal.) The fact that the stream/string solution had to work harder and do more things to accomplish the same goal isn't a valid response. I could have put a huge for loop inside my function and it would have been doing more things and run slower, but the output would not have changed.

>> The stream object is providing a great deal of extra features that printf() can't.
---
If you understand your problem well enough to know that you will not need those features, why waste the cycles? I could have dropped an extra thousand dollars to get the 4WD version of the vehicle I bought yesterday, but I don't need them. Now I can use that $1000 to buy toys for the computer.

>>Even though I specifically pointed out that it woudl be slower BEFORE you posted this
---
I believe you said "stream objects tend to be no more
than about 5% to 10% slower". Look at the results again - if you think it's still only 5% to 10% slower, I'd have to go with stupid over dishonest. But if I thought you were stupid, I wouldn't have invested so much energy in debating this with you.

Finally, the code. Note that this is strictly a test of file i/o. The discrepancies would grow as more string/stream code was added to the first block and simpler character and stdio operations were added to the second.

static int createFile(const char* pszFilename, unsigned int cRecords, size_t sizeRecord)
{
    char* pszBuffer = new char [sizeRecord + 2];
    memset(pszBuffer, 'X', sizeRecord);
    *(pszBuffer + sizeRecord) = '\0';

#ifdef USESTREAM
    ofstream ofstr(pszFilename);

    for (int i = 0; i < cRecords; i++)
    {
        ofstr << pszBuffer << endl;
    }
#else
    FILE* fp = fopen(pszFilename, "w");

    for (int i = 0; i < cRecords; i++)
    {
        fputs(pszBuffer, fp);
        fputc('\n', fp);
    }

    fclose(fp);
#endif

    return 0;
}

I simply called this using a filename, 1000000, and 1000 as arguments. I have done more extensive benchmarking in the past because much of our software is i/o bound. The results are pretty much the same regardless of what arguments are passed.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> if money were no object I would much rather have an F-18.
I can agree to that, but is it a good replacement for a car?   Does you grocery store have a landing strip?  Does your gas station sell jet fuel.

>>   the 1000% difference was in a simple function to translate an integer
>> into a character array. (The custom function actually padded the array
>>  as well so, in effect, it did more to accomplish the original goal.)
The stringstream pbject allcoates memory to insure that there is never a chance of array overflow.  You didn't not have that same feature.  You may have been able to insure that there was no overflow in your specific test case, but that is extremely hard to do in general--in fact it basically isn't done which is why stringstream was created out of strstream.  That is why comparing stringstream to sprinf() is missleading.  Yes it is slower.  A fact that I stated BEFORE you posted anything about it.  But that means the comparison is missleading.  Especially if you try to gneralize it to other situations involving C and C++ I/O.  

>> if you think it's still only 5% to 10% slower,
I said if the test was fair.  The stream code is being forced to do considerabely more work.  You are using the _unformatted_ I/O for the C code and the _formatted_ I/O for the C++ code.  That is like comparing sprinf() and fwrite().  Which would you expect to be faster?  

>> if I thought you were stupid, I wouldn't have invested
>> so much energy in debating this with you.
Still?  I predicted that the test was unequivalent.   That is almost psychic, not psychotic.
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
neitod >> Are there any counter arguments that are not based on my character?

I think this speaks for itself:

MsgBoxPrintf(
  "The result was '%s' return code: %d (%4.4x)\n",
  szResult, nRet, nRet
);

Typing that is so much easier than anything possible with stream syntax that it hardly needs analysis.  

Programming is about getting it done -- not about some esoteric baloney.

-- Dan
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
nietod,
>>I don't want to hear about it.  
That's fine, then I don't ever want to hear you accuse me of plagerism again.  If you have a problem, bring to CS. Otherwise, keep it to yourself.
0
 
LVL 22