• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1566
  • Last Modified:

Universal MessageBox

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
khampton
Asked:
khampton
  • 64
  • 48
  • 24
  • +7
1 Solution
 
IainHereCommented:
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
 
AxterCommented:
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
 
nietodCommented:
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
nietodCommented:
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
 
AxterCommented:
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
 
nietodCommented:
>>  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
 
AxterCommented:
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
 
AxterCommented:
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
 
nietodCommented:
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
 
AxterCommented:
>> 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
 
AxterCommented:
Why don't we just let the questioner decide what's best for him/her.
0
 
AxterCommented:
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
 
nietodCommented:
>> 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
 
khamptonAuthor Commented:
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
 
AxterCommented:
>>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
 
khamptonAuthor Commented:
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
 
AxterCommented:
>>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
 
AxterCommented:
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
 
nietodCommented:
>> 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
 
AxterCommented:
>>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
 
nietodCommented:
>> 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
 
nietodCommented:
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
 
AxterCommented:
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
 
AxterCommented:
>>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
 
nietodCommented:
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
 
AxterCommented:
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
 
AxterCommented:
You still have not given an example of the extra work that you're talking about.
0
 
khamptonAuthor Commented:
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
 
AxterCommented:
I believe you need to add #include <sstream>

change stream to stringstream
0
 
AxterCommented:
There's also a type-o on the while loop.
You're missing right ")"
0
 
AxterCommented:
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
 
AxterCommented:
I notice that nietod's code lets a bad charactor get through at the end of the string.
0
 
khamptonAuthor Commented:
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
 
AxterCommented:
//************************************
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
 
AxterCommented:
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
 
nietodCommented:
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
 
nietodCommented:
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
 
AxterCommented:
>>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
 
AxterCommented:
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
 
AxterCommented:
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
 
wkmatt42Commented:
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
 
DanRollinsCommented:
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
 
AxterCommented:
>>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
 
nietodCommented:
>> 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
 
AxterCommented:
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
 
AxterCommented:
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
 
nietodCommented:
>> _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
 
khamptonAuthor Commented:
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
 
AxterCommented:
>>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
 
AxterCommented:
>>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
 
AxterCommented:
//**************************************
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
 
AxterCommented:
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
 
nietodCommented:
>> (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
 
nietodCommented:
>>  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
 
AxterCommented:
>>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
 
AxterCommented:
>>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
 
AxterCommented:
>>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
 
nietodCommented:
>> 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
 
wkmatt42Commented:
>> 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
 
AxterCommented:
>>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
 
nietodCommented:
>> 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
 
AxterCommented:
>> '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
 
nietodCommented:
>> 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
 
khamptonAuthor Commented:
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
 
AxterCommented:
>>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
 
nietodCommented:
>> 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
 
AxterCommented:
>>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
 
AxterCommented:
>>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
 
nietodCommented:
>> 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
 
nietodCommented:
>> 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
 
AxterCommented:
>>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
 
AxterCommented:
>>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
 
AxterCommented:
>> 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
 
AxterCommented:
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
 
nietodCommented:
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
 
nietodCommented:
>> 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
 
AxterCommented:
>>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
 
AxterCommented:
>>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
 
AxterCommented:
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
 
nietodCommented:
>> 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
 
nietodCommented:
>> 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
 
AxterCommented:
>>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
 
wkmatt42Commented:

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
 
wkmatt42Commented:
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
 
AxterCommented:
>>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
 
AxterCommented:
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
 
AxterCommented:
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
 
wkmatt42Commented:
That was well worth twenty points!
0
 
AxterCommented:
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
 
AxterCommented:
>>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
 
jasonclarkeCommented:
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
 
nietodCommented:
>> >>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
 
AxterCommented:
>>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
 
AxterCommented:
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
 
Kisses93834Commented:
>>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
 
Zulma9999Commented:
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
 
jasonclarkeCommented:
> 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
 
nietodCommented:
>> 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
 
nietodCommented:
>>  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
 
jasonclarkeCommented:
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
 
nietodCommented:
>>  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
 
AxterCommented:
jasonclarke,
I like to see that review.  Can you please direct me to it.
Is it available on the web?
0
 
jasonclarkeCommented:
0
 
khamptonAuthor Commented:
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
 
AxterCommented:
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
 
AxterCommented:
jasonclarke,
Thanks

khampton,
Agree
0
 
AxterCommented:
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
 
nietodCommented:
>> )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
 
nietodCommented:
>> 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
 
wkmatt42Commented:
>> 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
 
jasonclarkeCommented:
> 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
 
wkmatt42Commented:
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
 
nietodCommented:
>> 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
 
wkmatt42Commented:
>> 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
 
nietodCommented:
>> 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
 
DanRollinsCommented:
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
 
AxterCommented:
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
 
nietodCommented:
S << "The result was " << szResult << "' return code: " << nRet << " (" <<setw(4) << hex << nRet << ")";
MessageBox("Title",S);

>> Typing that is so much easier than anything possible with stream syntax
>> that it hardly needs analysis.
I'm going to have to stop typing now and let my blistered fingers heal.

In addition t being about the same length, it is far more expressive.  "hex" is alot more obvious than "%x.   "4.4" is not vvery clear--actually I'm not 100% sure i transalated that part right--but setw() and or setprecission() is very clear.

And there is no risk of type errors.

>> Programming is about getting it done -- not about some esoteric baloney.
Absolutely.  STL was developed in order to get the job done.  To get it done fast and to get it done safely.
0
 
nietodCommented:
Try this example.

class AbstactClass
{
   *  *  *
};


void BadObjectNotification(const AbstractClass &Object)
{
    stringstream S;
    S << "Sorry, an oject was found to be invalid" << endl
        << "Additional Information: "
        << Object;
    MessageBox("Uh-oh",S);
}

Note that the concrete classes derived from AbstractClass will be defined later.  Some may be defined as add-ins (plugg-ins) written after the program is finished and distributed.
0
 
AxterCommented:
Before I unsubscribe from this thread, I like to point out something.
I can accept jasonclarke's argument, far better then nietod.
Why???
Because he backs it up with "GOOD" references.
A link to an objective site (ACCU).  Further posting a link to Stroustrup site pointing to the ACCU site.
He doesn't make an attempt to put more into a situation then what is actually there.
Example
Comments from nietod:
>>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.


Comments from jasonclarke:
>>I never said it was definitive, any review is clearly an
>>opinion.  However, IMO anyway, it is written by a
>>reviewer who I respect

nietod's comment makes it sound like a C++ saint, who can do no wrong made the critic.

Anyone with half a brain can look at these two comments and pick out which one is a lot of hot air, and which one has a degree of objectiveness and honesty.

Nietod, if your goal is really an attempt to convince someone of the correctness of you viewpoint, then you can learn some lesson from jasonclarke.

Posting comments that make it sound like you and your references can do no wrong, does not add to the legitimacy of your comments.  Instead, it invalidates your comments, and makes you sound bias, unconvincing, and fraudulent.
Using references that have to be interpret, and in which you force a specific interpretation, also makes your comments unconvincing.
Using an author, or another expert to support your viewpoint without have an exact specific quote, also invalidates your comments.

Any professional will use facts to support an argument, and not subjective data that requires interpretation.  Furthermore, a true expert will not use an author's name without supplying an exact quote, referencing the book, page, and author.  And the quote should not require any interpretation to support the viewpoint.
0
 
nietodCommented:
>> Because he backs it up with "GOOD" references.
Unlike quotes from Stroustrup and Meyers?

>> nietod's comment makes it sound like a C++ saint,
>> who can do no wrong made the critic.
This is a person that has spend years workig witht he language and contributing to it.  There probalby are a few thousand individuals that understand the language like he does.  Yet you would dissagree with him, without being able to post counter arguments

>> you can learn some lesson from jasonclarke.
I have.   I have learned a great deal from him.

have you learned anything?

>> Posting comments that make it sound like you
>> and your references can do no wrong,
I posted arguments based on sound principles.  but those aren't of any value since they are soley mmy own opinion, no one else holds them.
I posted quites that support them, but thos aren't ov value since you can find some hack that posts the oposite and because you can missinterpret an very clear post from Stroustrup.
I posted code, but that doesn't count since you hold the international patent on loops.

what do you want?

>> Using references that have to be interpret
"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."

How hard is this to interpret?  Hoes inheriently dangerious mean its a good thing?  Does avoid mean you should or shouldn't use them?  You're stuburn, not stupid.  I think you can handle it.

>> you force a specific interpretation,
How else can you interpret it?  What have I posted that I forced an unintended interpretation?  You are the one that tried to pass off a quote from Stroustrup as encouraging the use of C I/O when that clearly is not the case.  he was saying that it was a reality becauseof mixed language requirements and because some programmers are unwilling to change.  In think I know a few of those!

>> Any professional will use facts to support an argument,
that is what I've been psoting?  expalainstions, principles, facts, quotes.    In return I've been getting insults.  How does the counter argument?

>>  a true expert will not use an author's name without
>> supplying an exact quote, referencing
>> the book, page, and author.  
You got me there.  I'm not an expert.   I forgot to include page numbers.   Heck I don't know anything at all about programming.

>> And the quote should not require any interpretation to support the viewpoint.
That is impossible.  Unless somehow it can be beamed into your head directly.
0
 
AxterCommented:
>>This is a person that has spend years workig witht he
>>language and contributing to it.  There probalby
>>are a few thousand individuals that understand the
>>language like he does.  Yet you would dissagree with
>>him, without being able to post counter arguments
Where did I say I disagree with this critic?
You are now being dishonest or stupid.  One or the other.

How do you know how many years he has spend?  How do you know what his ability is to understand the language?
How do you know that he is not bias?
Give details, not subjective opinions that cannot be verified.  When you give information that can only be viewed as subjective, that only makes for an unconvincing argument.

Information that cannot be verified cannot be accepted without skepticism.
If you want to remove the skepticism, introduce factual, verifiable information.
When I quoted Stroustrup, I gave you book title, and page.  You did no such thing.
When I quoted Overland, I gave you book title and page.  Again, you made no such attempt in any of your references.

>>I posted quites that support them, but thos aren't ov
>>value since you can find some hack that posts
It's not valued because you did not give your exact source.  Book?? Title?? Page??
Furthermore, your quote required interpretation to support your viewpoint.

>>How else can you interpret it?  What have I posted that
>>I forced an unintended interpretation?  
Lets look at your quote:
//*************************************
"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."
//*************************************

Fist of all, no title or page reference.
This could mean if you want a certain functionallity, and you can get it without using unchecked function arguments, then you should not use unchecked function arguments.
However, if you want the following functionallity, then you should handle it with special care.
XMessageBox(NULL,"My Caption", MB_OK, "Hello %s. Test num %i",name,num);

So that could be interpret to say be careful when using the above function.
That quote can be intrepet many ways, and if you weren't so hard headed, I wouldn't even have to explain this to  you.

>>that is what I've been psoting?  
You did not post one single verifiable fact.  Not one that can be verified.

I posted references with book title, author name, and page.

If you can not give that type of complete reference, then you shouldn't be quoting anyone.
0
 
AxterCommented:
nietod,
Just incase you are too obtuse to understand what verification means, I'll explain.

Verification is when you say Stroustrup said "bla bla bla" in book title "C++ God" page 233.
And then I can go to book titled "C++ God" and page 233, and verify that you are giving an exact quote from the author, and that the quote has not been taken out of content.
0
 
nietodCommented:
>>  a true expert will not use an author's name without supplying an
>> exact quote, referencing the book, page, and author

>> Verification is when you say
And that fact that I didn't include that information means that I am not an expert.  That makes perfect sense.  I didn't include page numbers, therefore I don't know anything about C++.  

Now Jason clarke on the other hand is an expert because he.   opps.  Apparently we are both clueless.

If you had asked for the references, I could have provided them.  But seeing as the quotes don't prove anything anyways, why bother?
0
 
AxterCommented:
>>If you had asked for the references, I could have
>>provided them.  
I did ask you for this information in my comment dated:(06/28/2001 12:10PM PST)

>>If this is not just your opinion, can you quote some
>>references?  (author, book, and page)?......

If you can't accurately read the above simple comments, how do you expect us to rely on you to correctly interpret and transfer information from a source?

>>And that fact that I didn't include that information
>>means that I am not an expert.  
Yes.  You should not give a quote, if you can't give a reference.

When I asked jasonclarke for his source, he gave it to me promptly.
Whe I asked you for a source, I got nothing.

Who's data you think I'm going to trust.
0
 
wkmatt42Commented:
>> I said if the test was fair.  The stream code is being forced to do considerabely more work.

The stream code is not FORCED to do considerably more work. It simply does more work because that is what is designed to do. If I know I don't need all that work done, why waste the cycles to do it?


And if I could afford an F-18, the odds that I would do my own grocery shopping is pretty slim. :) Not that I grocery shop anyway.
0
 
nietodCommented:
>> The stream code is not FORCED to do considerably more work.
You choose the 2nd fastest C I/O function and the slowest C++ stream function (operation really).  And you are not suprprised that there is a difference?

>> It simply does more work because that is
>> what is designed to do
You could say that about printf() too, but strangely you didn't use printf in your test.

If I compare the printf() to the formatted stream I/O I get that the stream object I/O is about 20% slower.   If I compare the unformatted stream I/O to printf()--which I know is an unfair test, but the same could be said of yours--then I find that the stream object is slightly faster.  
0
 
wkmatt42Commented:
What is all this "unfair" crap? I want to cut the time it takes to get my data into a file so I can move on to other things. How is it unfair to pick the function or set of functions to do that does that best?

I opted to use fputs (the printf thing was a brainfart - it happens) because it is a closer match to what the stream insertion operator does with a string. Namely, to keep inserting data into the file until a null character is reached. In production, I'd have opted for fwrite since the records are fixed length. But I didn't want to be too "unfair" to your precious streams.

>>You could say that about printf() too, but strangely you didn't use printf in your test.
That's EXACTLY why I didn't use printf() - it does more than I need to do so it wastes valuable resources.

Duh.
0
 
nietodCommented:
>> I want to cut the time it takes to get my data into a file so I can
>> move on to other things. How is it unfair to pick the function or
>> set of functions to do that does that best?
Well, why didn't you use fprintf() to place the text in the file?   Because you know that it is significantly slower than fputs().   Why didn't you give the same consideration to the stream object test?   Because you wanted to prove that there is a huge difference in speed?   You choose the slowest way possible to ouput information with a stream object and nearly the fastest way poossible to do so with a FIE *.   If you think that is fair, fine.  But then the only resonable conclusion is that stream objects are FASTER then C I/O.  Why?  The same approach in reverse gives that result.

>> because it is a closer match to
>> what the stream insertion operator does with a string
You don't think write(), for example, is a closer match?  Operator << has to do many things that fputs() does not, like check width and add padding if needed.  printf() has to do that too.  fputs() does not.

>>  it does more than I need to do so it wastes valuable resources.
Right.  But you didn't give that consideration to the stream object.  And that seems fair?

>>  I'd have opted for fwrite since the records are fixed
>> length. But I didn't want to be too "unfair" to your precious streams.
They are both performing equivalent tasks.  what's unfair about it?   It gives me a difference of about 20%--in favor of C I/O naturally.

I don't think we're going to get anywhere.
0
 
Computer101Commented:
Hello all,
khampton has asked that a split between Axter and nietod.  I am going to refund 50 points back to khampton, let them accept one of your comments as an answer and than they can post another 50 point quetion in this topic area.

Thank you
Computer101
Community Support Moderator
0
 
wkmatt42Commented:
>>You don't think write(), for example, is a closer match?

I was wrong - now you actually are being stupid.

ostream::write() is NOT the equivalent of fputs. fputs puts a null-terminated string into a stdio stream: "put s"tring - get it? To insert a null-terminated string into a C++ stream, you would use the insertion operator: insert/insertion operator - get it? It was YOU that originally proposed the use of insertion operators in this discussion, so the benchmarking I performed was to show the difference between your proposition and the equivalent stdio operation.

ostream::write() IS as close an equivalent to fwrite as I'm aware of, since both place a specified number of bytes into a stream regardless of content. (But write() doesn't have the flexibility that yammered on about streams having - you'd need the insertion operator to get that.) But just to make sure I'm not still being "unfair", I've done some benchmarking on all four possibilities.

(These tests are under windows, since I don't feel like going into or dialing into work. That's why I ran new benchmarks for fputs() and the insertion operator.)

fstream::operator<<    147.75 (60% slower than optimal)
fstream::write         135.11 (46% ...)

fputs                  95.46s (3% ...)
fwrite                 92.39s <-- optimal

In fairness, you did adjust your original assessment of 5% to 10% slower to 20% slower (You didn't come anywhere near the actual disparity, but I don't think anyone expected you to anyway.)
0
 
nietodCommented:
>> ostream::write() IS as close an equivalent to fwrite as I'm aware of,
>> since both place a specified number
>> of bytes into a stream regardless of content.
Thanks fo the tip.  If I hadn't mentioned that earlier, it would really be shocking news.

>> But write() doesn't have the flexibility that yammered
>> on about streams having - you'd need the insertion operator
>> to get that.)
Right!  and fputs doesn't have that flexibilty either.   You have to compare similar operations.   Compare << with fprinf(), not with something lesss powerful.   Compare fwrite() with write(), not something more powerful.  

>> n fairness, you did adjust your original assessment of
>> 5% to 10% slower to 20% slower
I didn't adjust anything.   I said that overal streams tend to be about 5% to 10% slower than C I/O.  This is from empirical studies of numerious real-world programs--Not my research.  In one specific case, fwrite() verses write(), it was about 20% slower, that was a specific case I measured.  That hardle suggests that the other findings ar in error or that I am somehow lieing.    

and these results make sense.  Most real-world programs are going to perform a lot of binary to ASCII conversions during I/O.  this will add a nearly the same overhead to both C++ and C I/O and thus reduces the percent difference between them.  The simple case you tested is likely to maximize the differences in speed, as it is mostly a measure of the additional buffering and additional translation performed by the C++ I/O.

>> You didn't come anywhere near the actual disparity,
>> but I don't think anyone expected you to anyway.)
The actual disparity?  You mean there is some sort of universally right figure for how much slower C++ I/O is than C I/O and I missed it?  

If you mean that your tests produced different results than mine, that is not surprissing, If you are using a different compiler, different hard driver, different O/S etc that is certanly possible.  It hardly means that your results are the universal truth and mine are mistaken.

Some things to consider, did you remember to run the test in an optimized, non-debug mode?  the C++ code is template code, not pre-compiled library code.  It runs much faster in an optimized, non-debug mode.
0
 
wkmatt42Commented:
Who would be stupid enough to use fprintf(fp, "%s", psz) when fputs(psz, fp) produces the exact same output for a fraction of the cost?

>>Most real-world programs are going to perform a lot of binary to ASCII conversions during I/O

Something like converting numbers to their fixed-length ascii represenations? We've already established that strings/streams will only increase the disparity.

Bottomline - stdio is much faster than C++ i/o, but C++ i/o is much more flexible. That's the trade-off, and the developers that ask these questions would be better off understanding that than listening to zealots ramble about how Bjarne, Scott, and Herb prefer C++ i/o so that's what they ought to use. As I've said before, I use both, but because I understand the trade-offs, when I need something fast, stdio always wins.
0
 
nietodCommented:
>> Who would be stupid enough to use fprintf(fp, "%s", psz) when fputs(psz, fp)
>> produces the exact same output for a fraction of the cost?
Any person that is stupid enough to use << when write() does the same job at a fraction of the cost.  

Yes I understand that printf() is slow compared to fputs().  That is my point.  You chose the fast operation for the C streams and the slow one for the C++ stream objects and claim that C++ stream objects are so much slower.  when you compare similar operations you get much smaller differences.

>> We've already established
>> that strings/streams will only increase the disparity.
No.  That was comparing sprintf() with a string stream.  try comparing fprintf() with fstream.  The difference is far less.

>>  stdio is much faster than C++ i/o
yes, the fast operations of C I/O are much faster than the slow operations of C++ I/O.  schocking?  If you compare similar operations you don't find that huge a difference and overall the difference should be in the vacinity of 10%  (maybe pluss or minus 20% for comiler variations).  

>> developers that ask these questions would be
>> better off understanding that
They would be better of understanding the material than making conclussions from clearly biased tests.  From tests whose biases were suspected by me before you ever even presented the details.
0
 
jasonclarkeCommented:
> when I need something fast

but your point seems to be that because something is faster, it is always better.  You said before that (in your words):

'performance always matters ... it doesn't really take a lot of effort to type 10 lines of code'

does this mean you never use a vector where an array will do?  You never value type-safety or extensibility over a perceived (potential) speed up from using more primitive types?

The golden rule of everything I have ever read about code optimisation is that you should never do it until you know there is a problem.  Tell me something different, or will you just rely on your notion of programming pragmatism again?  

Applications that just write out millions of lines of text to a file are not common (in my experience, at least).  In cases where it is important, you will probably also find that there are better ways than using stdio.  There are system dependant routines for this kind of thing,  if you write your application properly then it should be easy to swap out stream I/O for stdio for non-portable I/O.  

My contention is that it is far better to rely on good, maintainable code than to worry about performance at the expense of good code.  I think that streams are more conducive to good code, nothing more (and I suspect nietod would agree) - stdio has a place (occasionally) but given free choice I would prefer streams.
0
 
wkmatt42Commented:
Jason -

I wouldn't characterize stdio as not "good code", but I suppose that's a personal thing. But at least you are aware of what the tradeoff actually is - neitod is still having some trouble with that.

And we have actually tested asynch i/o on our AIX machines and we improved our i/o by an additional 30% or so. But, again, we had to examine the tradeoffs. First, the implementation of asynch i/o on AIX is crappy mostly because its signal support is not up to POSIX standards. Second, portability is an issue since we have to share some code between Sun and AIX boxes. So we're sticking with stdio for now. We still hide most of the icky stuff in classes, but the classes are typically abstractions of the data we process (as opposed to general i/o classes).

Finally, I still contend that performance always matters. But other things matter too, including maintainablility. In the sprintf vs stream/string discussion we had earlier, sprintf (and the custom code) should have been preferred because they gave a dramatic performance boost with no more effort than the stream/string option. I only give streams and strings an advantage if I need to pass those things around as part of an interface. (I don't pass FILE pointers, etc around.) But in the specific question we were dealing with, everything was inside another function so we could work without regard to any outside influence.

And I always use vectors over simple arrays (except character arrays, of course) because when optimized the lookups are just as fast.
0
 
jasonclarkeCommented:
> I wouldn't characterize stdio as not "good code",

that's not what I said, I said, IMO, streams were more conducive to good code.  It is clearly possible to write reasonable code with stdio - there is a lot of C code that would testify to this (and equally a lot that wouldn't!).  However, it is my opinion that it is easier to write good I/O code using streams.

> because when optimized the lookups are just as fast.

is that the only reason?  Isn't there any benefit to the much simpler, more maintainable code that comes from using vectors over arrays?
0
 
wkmatt42Commented:
For the last freakin' time - write() is NOT the equivalent of fputs!! The closest you could get is passing write(psz, strlen(psz)).

What is biased about comparing the raw throughput of write() vs fwrite or fputs vs <<? I even posted my code so every rational person in this discussion could see what the test actually compared. I even reran all four options back-to-back so you could compare any set you want. You should probably look up bias - it does not mean "getting different results than neitod wants, particularly when they contradict him".

And take one last look:

fstream::operator<<    147.75 (60% slower than optimal)
fstream::write         135.11 (46% ...)

fputs                  95.46s (3% ...)
fwrite                 92.39s <-- optimal

I've tried and tried but can't seem to get 10% +/- 20% to add up to either 46% or 60%. But I'll keep trying.
0
 
wkmatt42Commented:
>>is that the only reason?  Isn't there any benefit to the much simpler, more maintainable code that comes
from using vectors over arrays?

Exactly - I should have explained myself better. The fact that they are just as fast means there is no performance issue to consider if such lookups are in a critical path. Hence, the simple (or at least standard - simple is relative) more maintainable option (vectors) will win every time.
0
 
nietodCommented:
>> But at least you are aware of what the tradeoff actually is -
>> neitod is still having some trouble with that.
Is this nietod any relation to the one that said that VA might be acceptible in very limited cases, ones that coudl be well-encapsulated and tested?  Or the one that uses sprintf() as a int to ASCII conversion--encapsulated.  Or how about the one that uses OS-specific file operations exclusuvely in his code--encapsulated?

Or is the nietod that said that C I/O is always 5% to 10% slower than C++ so C++ I/O shoudl always be used.  Wait a second.  he never said that???

>> I still contend that performance always matters.
even if it is impossible to measure?   Woudl you take an additonal risk, additional development time, possible additional future modification time in favor of a speed gain you can't measure.   That is contrary to the accepted wisdom of the ages.   it only makes sense to optimize your bottlenecks.  Everywhere else write for fast development.  the time you save writting the other portions is best spend optimizing your bottlenecks, not optimizing other portions of the code.

>> sprintf (and the custom code) should have
>> been preferred because they gave a dramatic performance
>> boost with no more effort than the stream/string
Except if it is used incorrectly that can cause bugs and crashes that are far more of a problem than the code bieng slow.  These bugs might be almost impossible to track down--iif you corrupt past the end of a dynamcially allocated string the program might not crash until a completely unrelated block of memroy is deleted.  How can you trace that bck ot an errant sprintf()!   And what do you get in return.  A dramatci performance boost?  Are you sure?  If you don't profile it you don't know that.   its extremely unlikely to be a measurable boost unless this is occuring an enourmouse number of times in a tight loop.  otherwise, you can't measure the increase, that is not dramatic.

>> we could work without regard to any outside influence.
if you don't make mistakes.    But as I said, I use sprintf() in one specific instance.  But I encapsulated that code in another function and tested is extremely well.

>>  I always use vectors over simple array
yet simple arrays are faster.  That is inconssitent.  At the veyr least you have the overhead of allocation and deletion in every vector.   But again, if not in a loop, you can't measure it....
0
 
jasonclarkeCommented:
> The fact that they are just as fast means there is
> no performance issue to consider if such lookups are in
> a critical path

we could debate this, I suspect that  typically they are not just as fast.  If used simply there would be likely to be some performance degradation due to reallocation and checking, or are you telling me you always use a custom allocator?  Or are you saying you only use the [] operator and never push_back?
0
 
wkmatt42Commented:
Good software development theory - write slow code unless your end result is slow, in which case find out why it's slow and fix it? I can already tell you why it's slow - you wrote slow code.

You are generalizing the 80/20 rule way too much. Do you really think it took more than a minute to write translateIntToChar()? Or do you think it wasted more development time writing a one line call to sprintf than it took to write four or five lines of "C++" code?

The kind of time-wasting practices the 80/20 rule warns us involves much more complicated processes than that. Its intent is to prevent us from spending two days figuring out how to process a command-line a few milliseconds faster when processing a file takes an hour. We gain nothing. We should invest our time and energy speeding up the file processor instead.

Fortunately, we have things called libraries where we can store all of the optimizations we've had to perform in the past. Once we've created a faster data translator, why not use it in the future rather than opting for something slower? It doesn't make much sense to write potentially slow code that we may or may not have to rewrite after profiling if we can either leverage something we've already written or can write now with minimal effort.
0
 
jasonclarkeCommented:
> than a minute to  write translateIntToChar()

right, but translateIntToChar is a potential source of bugs.  My code:

template <typename T>
std::string translateValueToChar(T value, size_t minSize = 0, char padChar = ' ')
{
  std::ostringstream os;
  os << std::setw(minSize) << std::setfill(padChar) << value;  
  return os.str();
}

is a lot easier to use, and a lot more generic, and much less likely to be a source of bugs.  How will you generalise your function to also handle floats, or complex numbers?  
0
 
wkmatt42Commented:
I work for a wireless company so most of the things I use arrays for are lookups based on area code/exchange, etc. The information is usually loaded into arrays (and often lists and hash tables) at program startup so we keep our database traffic to a minumum. Since the communication with the server is much slower than anything the vector needs to do, it's not a major concern. I also sometimes set the capacity of the vector when it is created if I already know I need exactly 1000 elements (e.g. area codes 0-999).

Thereafter, the [] operator is all we need. That's why I mentioned only the performance of the lookup.

(And that's why it's not inconsistent, neitod. But then you haven't quite gotten a handle on the whole trade-off thing yet, have you?)
0
 
nietodCommented:
>> For the last freakin' time - write() is NOT the equivalent of fputs!!
I already stated that!    Do you think a test of write() verses fputs() is unfair?  Of course.  so why is a test of fputs verses << fair?  It isn't.  A test of printf vs << is fair and a test of fwrite() verses write() is fair.  but you don't want to do that, because you see ipnly about a 20% difference  (in the case of fwrite vs write().

>> What is biased about comparing the raw throughput of write() vs fwrite or fputs vs <<?
its comparing apples and oranges.  Its like comparing a bicicle trip to the store and a car trip to the next state and saying the bicycle is faster.  operator << is performing a lot of extra work that fputs doesn't do.  not because its inneficient, but beceause it performes formatted I/O--like printf().

>> I even reran all four options back-to-back so you could
>> compare any set you wan
Its getting to be a little hard to trust your findings at this point.  You concluded that

>> In the sprintf vs stream/string discussion we had earlier, sprintf (and the
>> custom code) should have been preferred
which is again a very missleading conclussion since it was testing sptrinf agains a stringstream and you generalized that result to printf() vs any stream.  Its very clear that stringstream will be slower--especially for short operations because it has the overhead of memory allocaiton and deletion.  But that does not apply to other uses of stream objects, so generalizing this result is again completely missleading.

when I compare fwrite verses write I got about 20% slower.   That should not be a surprising result.  

>> no performance issue to consider if such lookups are in a critical path.
Your logic is still inconsistent.  the lookup algorithms are no faster with vectors than they are with arrays.  (You know you can use most of the container algorithms with ordinary arrays?)  Overall, vector is slower than an array--not much, but some.  by your logic you should be using arrays.
0
 
jasonclarkeCommented:
0
 
jasonclarkeCommented:
0
 
nietodCommented:
>> Good software development theory - write slow code unless your end
>> result is slow, in which case find out why it's slow and fix it? I can
>> already tell you why it's slow - you wrote slow code.
Good development practice.  Make it work correctly and safely.  If needed, find out where it is slow, then fix it.  

I recommend you read a good book on optimization.  I lke "The Zen of Code Optimization".  I think you will learn a lot.  (Unlike some individuals that can read a book like that and learn only what they alread knew.)

>> Do you really think it took more than a minute to
>> write translateIntToChar()?
Of course not.  As I said I use that same approach in a library procedure.   Its worth doing in a well encapsulated peice of code.   but I wouldn't employee that tecnique--calling VA procedures--throughout a program.  I would either encapsulate it or use it directly in a place that I knew to be a bottleneck--if there was empritical evidence that it was a bttleneck and employing it made a measurable gain.  

>> ts intent is to prevent us from spending two days figuring out
>> how to process a command-line
Its much more than that.  Its also to prevent you from wating time writting code and debugging code.    Read a good book on it.

>>  we have things called libraries where we can store all of
>> the optimizations we've had to perform in the past
Agreed.  But even then fast is far less important than correct.  Ciorrect first, fast second--especially if you don't suspect speed will be important--like if it is an command-line parsing function.

>> And that's why it's not inconsistent, neitod.
This time you chose a safer, more programmer friendly solution instead of the faster one right?   That is inconsistent.  if you really feel that you should choose speed at every turn then you should be using arrays over vectors--not a good choice, I realize and so do you.
0
 
wkmatt42Commented:
>>Its very clear that stringstream will be slower

My point exactly.

Consider this:

If you needed to insert a null-terminated string into a file, how would you do it using C++ i/o? Not using write(), because write() can't tell where the end of the string is - you'd have to tell it. You'd use the insertion operator since that is what it is for. In fact, that's exactly what you did. (You could actually use the write() method, but that would sort of kill the whole point of using streams anyway since you'd lose the flexibility that the insertion operator gives you.) I know your code actually addressed a generic stream rather than a file stream directly, but I don't imagine you'd suggesting using C++ i/o one way for a file and another for a generic stream, particularly since, given nothing but a reference to a generic stream, you have no idea whether it was actually a file stream.

If you needed to insert the same null-terminated string into a file, how would you do it using stdio? You'd use fputs() because that's what it's for. (Again, you could opt for fwrite() but, again, you'd have to tell it the length of the string. Why iterate the string twice?

Hence, the initial benchmarking of fputs() vs the insertion operator.

>>This time you chose a safer, more programmer friendly solution instead of the faster one right?   That
is inconsistent.

What I did was compare the pros and cons of each solution and each situation and chose what I thought was best under the circumstances. That is NOT inconsistent. For what I use vectors for, there is no real performance issue to consider. (As I explained already and, since Jason seemed to understand it, I probably didn't to poor of a job.)

>>Good development practice.  Make it work correctly and safely.  If needed, find out where it is slow,
then fix it.

Better development practice. Make it work correctly, safely, and fast so neither you nor the poor bastard who has to maintain your code has to rewrite it. If you develop with all three things in mind, there will be probably be fewer occasions where you'll have to go back and fix slow code.

If it took 40 lines of obfuscated code to write efficient software, you'd have a point. But I've been doing this a long time and I've somehow managerd to produce a lot more code of much higher quality and with much better performance than anyone I've had the pleasure to work with. All that without ever having picked up "Zen" (though it sounds like a good read).
0
 
wkmatt42Commented:
Though I apparently haven't managed to learn to type without the occasional type.
0
 
wkmatt42Commented:
Though I apparently haven't managed to learn to type without the occasional typo.
0
 
nietodCommented:
>> Consider this:
Stop a second and listen.  Yes there are times when the difference between the speed of the C and C++ I/O is very large.  I NEVER siad that was not true.  What I said was that overall the difference is only a few percent.  Yes you can create cases where the C I/O will be enourmously faster.   But as I showed you, you can also create cases where C++ I/O is faster.  Neither proove much.   You need to either look at your exact needs at the time, or you need to consider the overall difference, which is not veyr significant.

> You'd use the insertion operator since that is what it is for.
You can play this game the other way around.  Sure C++ streams don't have features for efficiently reading/writting NUL-terminated strings, there is very little reason to every use NUL-terminated strings in C++.  So turn it around.  Write a string object to a file.  Now C++ I/O has the advantage.  You will need to conver the stringobject to a NUL-terminated string before writting it with C i/O.   Now C++ I/O does better.   Does that proove anything?   just as much as your test--nothing.

>>  I don't imagine you'd suggesting
>> using C++ i/o one way for a file and another for a generic stream
I'm not.   I'm sayign that most stream operations involve formatted I/O, especially conversion of binary to aSCII.  Under those circumstances, the difference between the C and C++ I/O will be greatly reduced.   That is in keeping with the empirical research that finds the overall difference to be realtively minor.

>> Why iterate the string twice?
Why iterate it once?  if you use a string object you don't have to, that is why C++ I/O can be faster--in an unfair test.

>> Better development practice
Read!

In addition to books on optimization, try ones on the developlment of programming languages and their history.  Despite what most programmers think, customers don't care much about speed, they want suftware that works--no bugs.  C++ was developed toward that end, with only minimal costs in speed.

>> it sounds like a good read).
Keep an open mind, you may be very surprised
0
 
nietodCommented:
>> Consider this:
Stop a second and listen.  Yes there are times when the difference between the speed of the C and C++ I/O is very large.  I NEVER siad that was not true.  What I said was that overall the difference is only a few percent.  Yes you can create cases where the C I/O will be enourmously faster.   But as I showed you, you can also create cases where C++ I/O is faster.  Neither proove much.   You need to either look at your exact needs at the time, or you need to consider the overall difference, which is not veyr significant.

> You'd use the insertion operator since that is what it is for.
You can play this game the other way around.  Sure C++ streams don't have features for efficiently reading/writting NUL-terminated strings, there is very little reason to every use NUL-terminated strings in C++.  So turn it around.  Write a string object to a file.  Now C++ I/O has the advantage.  You will need to conver the stringobject to a NUL-terminated string before writting it with C i/O.   Now C++ I/O does better.   Does that proove anything?   just as much as your test--nothing.

>>  I don't imagine you'd suggesting
>> using C++ i/o one way for a file and another for a generic stream
I'm not.   I'm sayign that most stream operations involve formatted I/O, especially conversion of binary to aSCII.  Under those circumstances, the difference between the C and C++ I/O will be greatly reduced.   That is in keeping with the empirical research that finds the overall difference to be realtively minor.

>> Why iterate the string twice?
Why iterate it once?  if you use a string object you don't have to, that is why C++ I/O can be faster--in an unfair test.

>> Better development practice
Read!

In addition to books on optimization, try ones on the developlment of programming languages and their history.  Despite what most programmers think, customers don't care much about speed, they want suftware that works--no bugs.  C++ was developed toward that end, with only minimal costs in speed.

>> it sounds like a good read).
Keep an open mind, you may be very surprised
0
 
wkmatt42Commented:
>>But as I showed you, you can also create cases where C++ I/O is faster

When? The closest case you even mentioned was 20% slower.

>>customers don't care much about speed

Huh? Mine always want bug-free software that's fast. And, oddly enough, I've always managed to deliver it.

>>Keep an open mind, you may be very surprised

I have an open mind - I wasn't being facetious.

>>Why iterate it once?  if you use a string object you don't have to, that is why C++ I/O can be faster--in
an unfair test.

The question was about a null-terminated string. If I were using a string object with stdio, I could simply fwrite(str.data(), str.length(), 1, fp) and still come out better than the string class' insertion operator. (And the string had to have been iterated at least once, or it wouldn't know how long it was. The fact that it happened during construction - even construction of another object from which it was copied - doesn't mean it didn't happen.)

C++ i/o will always have a performance hit when compared to stdio simply because there is a price to pay for the flexibility that C++ i/o offers. To continue to fight that is just stupid. It's a fact.

The question is whether that price is worth paying and,
unless you're processing a huge amount of data, it probably is. Of course, most enterprise software processes a huge amount of data, in which case the price may be too high. In any case, the tradeoff is speed for flexibility (and, arguably, maintainability, though a decent programmer shouldn't have any trouble with well written code regardless of its implementation).
0
 
nietodCommented:
>> The closest case you even mentioned was 20% slower.
No that was a relatively fair test.   That was fwrite vs write.   Compare write() verses printf() and C++ wins.  Its not fair, but it wins.

>>  have an open mind - I wasn't being facetious.
I realize that.  There are some "experts" that I have no respect for, but that is not true of all.

>> The question was about a null-terminated string.
When did it become about a NUL-terminated string?  I originally said that

   emperical studies have found that for performing equivalent tasks,
   stream objects tend to be no more than about 5% to 10% slower.  

You attempted to prove that wrong.  You can find indiividual cases where that is not true, but this is about an overall affect.   when did this become about just oen case?

>> I could simply fwrite(str.data(), str.length(), 1, fp) and still come out
>> better than the string class' insertion operator.
yes. 55, maybe 20%.  Nothing increadible.

>> there is a price to pay for the flexibility that C++ i/o offers.
>> to continue to fight that is just stupid. It's a fac
I said that up-front.   But the point is the price is reasonabley minimal.  You can always find outragous claims that C++ XXX is 100 times slower than C XXX.  but its virtually always due to an unfair test.   I expected that would occur before ou ever posted your code.   if you write efficient C++ code, it tends to be only slightly slower and greatly simpler and safer than the C code.

>> The question is whether that price is worth paying
If an I/O operation is critical enought that the differnce betwen C and C++ matters, then it probably is critical enough that  OS-specific techniques should be used.  Othtside of those critical areas, it really shoudln't matter.  If you need to log a message for the user, the safety of C++ I/O more than makes up for the immeasurable speed difference of C I/O.


>>  (And the string had to have been iterated at least once, or it
>> wouldn't know how long it was.
string object's don't use NUL termiantors--in fact a NUL can be stored in a string as a valid character, they are not iterated to determine their length..
0
 
jasonclarkeCommented:
I think we are never likely to agree on this, but as one final attempt consider this,  this code is presented by BS in a comparative article to show differences between modern C++ and C.  This is supposedly, the code you might write for your 2nd ever C++ program:

#include <iostream>
#include <string>

int main()
{
   using namespace std;

   cout << "Please Enter your First Name: \n";
   string name;
   cin >> name;
   cout << "Hello " << name << "\n";
}

Think about what you might have to do to reproduce this functionality with stdio.  
 
According to BS, the nearest equivalent is this:

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

void quit()         // write error message and quit
{
    fprintf(stderr,"memory exhausted\n") ;
    exit(1);
}

int main()
{
    int max = 20;
    char* name = (char *) malloc(max);
    if (name == 0) quit();

    printf("Please enter your first name: \n");

    while (true) {
        int c = getchar();
        if (c == EOF) break;
        if (!isspace(c)) {
            ungetc(c,stdin);
            break;
        }
    }

    int i = 0;
    while (true) {
        int c = getchar();
        if (c == '\n' || c == EOF) {
            name[i] = 0;
            break;
        }

        name[i] = c;

        if (i== max-1) {
            max = max + max;
            name = (char*) realloc(name,max);
            if (name == 0) quit();
        }

        ++i;
    }
    printf("Hello %s\n",name);
    free(name);
    return 0;
}

Can you not even conceive of the fact that there might be some positive aspect to the former?
0
 
wkmatt42Commented:
As a general rule, I never get user input from stdin, but if someone with a gun to my head told me to get input I'd always choose the first code block. Since the user is the bottleneck, no optimized i/o would help.

If, however, I had to read, translate, and store 10 million telephone switch records (which we do several times daily), I would (and do) stick with stdio.

BTW - you could use scanf too, but I hate that function almost as much as the second code block.

neitod - I know how string works. What do you suppose happens when you do either of the following?

string str("Some string");

or

fstr >> str;
0
 
nietodCommented:
>>  I had to read, translate, and store 10 million telephone switch
>> records (which we do several times daily), I would (and do)
>> stick with stdio.
For fast file I/O, there is no substitute for direct file access.  Our fast DB operations are the selling point of out software and certainly don't use C++ or C I/O.  Yet are portable to other Oss with probably a at most an hour or two of work.

>> BTW - you could use scanf too,
It still works with a fixed length string.  You can use the width  field specifier to insure that scanf() doesn't overflow the string its reading into and corruopt memory.  (And few programmers take this precaution--string errors seem to be an accepted part of live in the C programmer's world. )   But you still can't make it expand the storage space as needed for any lengh string.

>> What do you suppose happens when you do either of the following?
>> string str("Some string");
the strig object, str, can store NUL characters.  If it is initialized with a character array, that array is terminated with a NUL.  But that is just a matter of initialization or assignment form character arrays, it does not mean that strings cannot support NUL characters within them or that they use the NUL characters as terminators.

fstr >> str;
I'm not sure what you think happens, but it has nothing to do with a NULcharacter.  the stream will (optionally) skip whitespace characters--whcih might not be space, tab, and newline, depending on the string's element type) then it read data into the string until it comes to a whitespace or the end of the file.

Your description suggested that the length of the string had to be determined by iteration.  that is not true.  
0
 
wkmatt42Commented:
My point was that someone is counting the characters at least once to get the length.
0
 
AxterCommented:
khampton,
Did you understand what the EE Moderate said about splitting the points?
She said to accept one of the comments here as an answer, and post an additional 50 point question for the other expert.
0
 
DanRollinsCommented:
(cough) (cough)
Try this:

CStreamMsgBox msgBox;
msgBox
<< "There are over " << nTooMany
<< " posts here that have gone off topic!" << endl
<< showIcon << hIconBadFinger
<< PlayWave(PW_VOLUME_LOUD, PW_BRASSY) << "Taps.wav"

Just an idea.

-- Dan

P.S. I considered locking this question, but I think we need some more expert input.

0
 
jasonclarkeCommented:
> (cough) (cough)

another self-appointed moderator?

> Since the user is the bottleneck, no optimized i/o
> would help.

and yet you insist that a message box function should be coded using stdio...
0
 
wkmatt42Commented:
I never said that - in fact, I specifically said that in this particular case, "you're simply preparing a dialog box, [so] that argument is pretty insignificant". My point about speed was more of a general one, since no one seemed to have mentioned to that point that it sometimes matters.

About the original question itself, I would have recommended (I was enjoying the discussion too much to actually address the question - oops) simply overloading the message box function to implement both the VA and the stream solution since both are useful.

Finally, I'd have to agree with the suggestion that this question be closed for no other reason that it's now taking about 30 seconds to refresh it every time there is an update. I have a feeling we'll get a chance to continue along these lines in the not-too-distant future.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 64
  • 48
  • 24
  • +7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now