Solved

is there a function like sprtinf but only returns len of string

Posted on 2001-07-25
7
376 Views
Last Modified: 2007-12-19
is there a function like sprintf () but instead of copying to a buffer it just returns the len of the final string?

int i = 100, y;

y = somefunc ("%i", i);

now y equals 3 is there something like that?
0
Comment
Question by:Kitty__Kong
[X]
Welcome to Experts Exchange

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

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
7 Comments
 
LVL 10

Expert Comment

by:makerp
ID: 6316687
i do not think so,

char buffer[10];
sprintf(buffer,"%i",i);
printf("the string is %d long\n",strlen(buffer));

i would just do that
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 6316700
I agree with makerp, only the code can be made a bit easier:
char buffer[10];
int len = sprintf(buffer,"%i",i);
printf("the string is %d long\n",len);

ZOPPO
0
 
LVL 22

Accepted Solution

by:
nietod earned 40 total points
ID: 6316826
But if the goal is to learn how long the strign will be, so that you can supply a sufficiently long string to sprintf(), then this doesn't help.   If that is the case, you are stuck.   In general, there is no way to learn how long the string should be that you pass to sprintf().  This is one of MANY reasons why sprintf() is often unsafe to use.

Instead of using sprintf(), which has known flaws, why not switch to the C++ way of performign these operations, which were developed to correct the flaws?   You can use a C++ strignstream instead.  This allows you to format output just like sptrinf(), but the data is stored in a C++ string object.  Since strigns expand their storage requirements as needed, this allows the output string to be any length required.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

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

 
LVL 31

Expert Comment

by:Zoppo
ID: 6317115
Here's code which can be used to determine the expected length for a printf() as part
of CString-implementation of MFC:

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);
}

// formatting (using wsprintf style formatting)
void AFX_CDECL CString::Format(LPCTSTR lpszFormat, ...)
{
      ASSERT(AfxIsValidString(lpszFormat));

      va_list argList;
      va_start(argList, lpszFormat);
      FormatV(lpszFormat, argList);
      va_end(argList);
}

maybe it's a help,

ZOPPO
0
 
LVL 1

Expert Comment

by:Black_End
ID: 6318066
Why not use _snprintf
0
 
LVL 1

Expert Comment

by:llewelm
ID: 6318277
I'm assuming the goal based on the flow of the comments above but...If the goal is ultimately to store the formatted string into a buffer why not simply use the CString::Format function to format the string and store it within a CString object as follows.

CString lcsData;
int liValue = 10;

lcsData.Format ("My value is %d", liValue);

If you really want the length at that point just do:

printf ("Length = %d\n", lcsData.GetLength());
0
 
LVL 22

Expert Comment

by:nietod
ID: 6319112
>> Why not use _snprintf
That is not a standard function.  how do we know if Kittykong's compiler supports it?  And if todes, it it wise to use a non-portable function like that?

>> why not simply use the CString
Because CString is specific to MFC and there is no evidence that this pgrogram has anythign to do with MFC

however a string string object is portable.  it will owrk on all platforms and with all compilers.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

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

Question has a verified solution.

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

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

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

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

Join & Ask a Question