Thread: Interesting Problem: sprintf does not work

  1. #1
    Registered User
    Join Date
    Mar 2004
    Posts
    19

    Interesting Problem: sprintf does not work

    Hello All,

    This is the code that does not work properly:

    Code:
    char dbszSQL[1024];
    
    IString theStartDate("2004-01-01-00.00.00.000000"), theEndDate("2005-01-01-00.00.00.000000");
    
    sprintf(dbszSQL, " hello %s AND %s ", theStartDate, theEndDate);
    
    cout<< dbszSQL<< endl;
    This is what gets printed on the screen:

    hello ð%2È AND 2004-01-01-00.00.00.000000

    This is what I expect:

    hello Surinder 2004-01-01-00.00.00.000000 AND 2005-01-01-00.00.00.000000

    After the sprintf executes I check the values for the two IString objects which look normal. My IString class is a wrapper around STL:string and I do have a conversion operator defined and this is what it looks like:

    Code:
    IString::operator char*() const
    {
      return (char *) buffer.data();
    }
    now buffer is the stl string object. Does anyone know what I might be missing?

    Here is the debugger printout for startDate and endDate:

    Code:
    (dbx) p theEndDate                                             
    (buffer = 
                      _String_base:)
                  _String_val<char,std::allocator<char> >:(_Alval = ))
              (npos = 4294967295, _Ptr = "2005-01-01-00.00.00.000000", _Len = 26, _Res = 31)) 
    (dbx) p theStartDate                                           
    (buffer = 
                      _String_base:)
                  _String_val<char,std::allocator<char> >:(_Alval = ))
              (npos = 4294967295, _Ptr = "2004-01-01-00.00.00.000000", _Len = 26, _Res = 31))

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    What's the relationship between buffer.data() and buffer._Ptr
    Because I can't see a data() in the dbx debug output.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >sprintf(dbszSQL, " hello %s AND %s ", theStartDate, theEndDate);

    This should be:
    sprintf(dbszSQL, " hello %s AND %s ", theStartDate(), theEndDate());

  4. #4
    Registered User
    Join Date
    Mar 2004
    Posts
    19
    Thanks for your response but why should I have to add '()' to the end of the variable.

    How do I default the conversion of an IString object to char*?

    I want to be able to call sprintf like this:

    sprintf(buffer, "hello %s and %s", str1, str2);

    where str1 and str2 are IString objects and they automatically get converted to char* through a default conversion operator like:

    IStringerator char* cost
    {
    return buffer.data();
    }

    I have this operator alongwith other conversion operators defined but it does not automatically convert to char* in the above case.

  5. #5
    C++ Developer XSquared's Avatar
    Join Date
    Jun 2002
    Location
    Ontario, Canada
    Posts
    2,718
    >Thanks for your response but why should I have to add '()' to the end of the variable.
    You shouldn't.

    >How do I default the conversion of an IString object to char*?
    Try making a function which returns a char *. Like getChar() or something.
    Naturally I didn't feel inspired enough to read all the links for you, since I already slaved away for long hours under a blistering sun pressing the search button after typing four whole words! - Quzah

    You. Fetch me my copy of the Wall Street Journal. You two, fight to the death - Stewie

  6. #6
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >Thanks for your response but why should I have to add '()' to the end of the variable.

    It would call this member function which you posted:
    Code:
    IString::operator char*() const
    {
      return (char *) buffer.data();
    }
    >How do I default the conversion of an IString object to char*?
    Good question. I'm afraid I don't know the answer.

  7. #7
    Registered User
    Join Date
    Mar 2004
    Posts
    19
    Mr. XSquared,

    I want to be able to call sprintf like this:

    sprintf(buffer, "hello %s and %s", str1, str2);

    so why are you telling me to write another function that returns a char*. All I am asking is how to make the above call work and I know that it is possible.

    Thanks!

  8. #8
    Registered User
    Join Date
    May 2004
    Posts
    127
    Post a short example program that doesn't work. That way everyone can compile, test, and stop guessing.

  9. #9
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    [edit] Nevermind that..

    Post the code and I'll take a look. Specifically your IString implementation.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  10. #10
    Registered User
    Join Date
    Mar 2004
    Posts
    19
    As per popular demand here it is:

    The stripped version of my IString class:

    Code:
    ///////////////////////////////////////////////////////////////////////
    // istring.hpp
    ///////////////////////////////////////////////////////////////////////
    #include <string>
    #include <istream>
    
    using namespace std;
    
    class IString
    {
    	private:
    		string buffer;
    		
    	public:
    	
    		IString();
    		IString (char* str);
    		IString(const char* pChar);
    		operator char*          ( ) const;
    };
    
    
    
    ///////////////////////////////////////////////////////////////////////
    // istring.cpp
    ///////////////////////////////////////////////////////////////////////
    #include <istring.hpp>
    
    IString::IString()
    {
    }
    
    IString::IString(char * str)
    {
     	buffer = str;
    }
    
    IString::IString(const char* pChar)
    {
    	buffer = pChar;
    }
    
    IString::operator char*() const
    {
    	return (char *) buffer.data();
    }
    This is the code that calls it:

    Code:
    #include <iostream>
    #include <fstream>
    #include <istring.hpp>
    
    using namespace std;
    using std::ifstream;
    
    
    int main()
    {
    char dbszSQL[1024];
    IString theStartDate("2004-01-01-00.00.00.000000"), theEndDate("2005-01-01-00.00.00.000000");
    sprintf(dbszSQL, " hello IString %s AND %s ", theStartDate, theEndDate);
    
    cout<< dbszSQL<< endl;
    cout<<theStartDate<<endl;
    cout<<theEndDate<<endl;
    return(0);
    
    }
    This is the output I get:

    hello IString D AND 2004-01-01-00.00.00.000000

    This is the output I expect:

    hello IString 2004-01-01-00.00.00.000000 AND 2005-01-01-00.00.00.000000

  11. #11
    Registered User
    Join Date
    May 2004
    Posts
    127
    Force the conversion with a cast.
    Code:
    sprintf(dbszSQL, " hello IString %s AND %s ", (char *)theStartDate, (char *)theEndDate);
    And you should also consider using c_str() on this line
    Code:
    return (char *) buffer.data();
    data() isn't guaranteed to return a valid null terminated string, but c_str() is.

  12. #12
    Registered User
    Join Date
    Mar 2004
    Posts
    19
    Kip,

    I don't want to to do that. I want to be able to call it with the objects.

  13. #13
    Registered User
    Join Date
    May 2004
    Posts
    127
    Quote Originally Posted by mangoMan
    Kip,

    I don't want to to do that. I want to be able to call it with the objects.
    You are calling it with the objects. However, the C I/O functions aren't very smart. They work with what you tell them to work with, and they don't look below the surface to work with what you really wanted. If you want everything to be hidden behind your back then use stringstreams instead of sprintf. Otherwise, you should consider some of the suggestions that have been offered to you because unless I'm mistaken, the code I have works while yours does not. You aren't exactly in a position to be finicky.

  14. #14
    Registered User
    Join Date
    Mar 2004
    Posts
    19
    Kip,

    I appreciate your help. But the problem is that I am working with old code that cannot be changed. I am removing an old IString class, provided by the IBM open class library, and replacing it with a new IString class wrapped around STL string that mimics the functionality of the old IBM IString class. When we use the old class sprinf works like a charm but the new class must be missing something and I can't figure out what even after digging through the IBM source code with is quite complex. Anyhow I am hoping that someone knows how to make this happen.

    Thanks!

    --m

  15. #15
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    This is what happens when you call sprintf with the IString object:
    Code:
    void sprintf( char** pstr);
     
    //In main
    IString istr = "Petter";
    sprintf( static_cast<char**>(&istr) );
    The first four bytes (on Win32) of the IString object becomes a C-style string pointer.

    You see the problem? No high-level C++-conversion operators matter.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. problem getting structure to work in my function
    By Tom Bombadil in forum C Programming
    Replies: 18
    Last Post: 05-28-2009, 09:53 AM
  2. Multithreading problem
    By Bacardi34 in forum C Programming
    Replies: 5
    Last Post: 09-02-2004, 02:26 PM
  3. fopen();
    By GanglyLamb in forum C Programming
    Replies: 8
    Last Post: 11-03-2002, 12:39 PM
  4. Interesting Multithreading Problem :: MFC
    By kuphryn in forum Windows Programming
    Replies: 4
    Last Post: 04-22-2002, 02:28 PM
  5. Interesting problem with file I/O...
    By skillet in forum C++ Programming
    Replies: 12
    Last Post: 02-20-2002, 11:14 AM