Solved

Length of Expanded Formatting String

Posted on 2004-09-30
10
236 Views
Last Modified: 2010-04-15
Experts,

I am trying to fill a character array using vsnprintf, but need to know how much space to allocate for the array.  On some platforms vsnprintf returns the length of the expanded string so you can call vsnprintf with the length of the current array, re-allocate to the size of the new string (if necessary) and then call it again with to actually fill the array knowing before hand that there is enough space allocated.  Unfortunately on some unix platforms and windows vsnprintf (_vsnprintf in MS) just returns a -1 if the array is not long enough.  Does anyone know a function that will return the size of an expanded format string?  For example. how long will the resulting string of the following be:
("This string is %d characters long.", nCharacters)

Thanks,
David Johns
0
Comment
Question by:david_johns
  • 5
  • 2
  • 2
  • +1
10 Comments
 
LVL 45

Expert Comment

by:Kdo
Comment Utility
Hi David,

I'm not aware of any ANSI routine that will return the length of the resultant string without actually doing the conversion, too.

My suggestion is to have a "guaranteed large enough" buffer and strdup() the result.

char Buffer[1000];
int    Length;
char *String;


  Length =  sprintf (Buffer, "This string is %d characters long.", nCharacters);
  String = strdup (Buffer);


Of course, in this example, nCharacters has not been set.
Kent
0
 

Author Comment

by:david_johns
Comment Utility
I guess I am a bit of a perfectionist on things like this.  I just hate the idea of having to impose a static limit.  One alternative I had thought of is figuring out a way to redirect stdout somewhere where it won't bother me and using vprintf then directing stdout back to the console.  Or perhaps use a vfprintf somehow directed to a memory buffer or something.  I know how to direct stdout to a file, or I could even more easily just send it directly to a temp file using vfprintf, but is there a way to in a sense send the stream to NULL (because I don't actually need the string yet) just so I could get the length?  Spark any ideas?

Thanks,
David
0
 
LVL 45

Accepted Solution

by:
Kdo earned 125 total points
Comment Utility

You could build your own function to do this.  It's not particularly difficult, but it IS tedious, and definitely a re-inventing of most of the wheel.

On today's systems, memory is cheap.  I keep a 256 character "scratch" buffer in most every task/thread/module that I create simply for formatting message.  The extra memory doesn't hurt a thing and 256 bytes ensures that as long as I'm formatted visual messages the buffer will be sufficiently large.

Of course the ..nprintf() variant ensures that even a generously proportioned buffer that is somehow "too small" doesn't adversely affect the rest of the application.


If you think that it's worth the trouble, get a copy of the printf() source from any of the linux distributions and canibalize it.


Good Luck,
Kent
0
 
LVL 22

Expert Comment

by:grg99
Comment Utility
How about we all mull over these points:

(1)  printf() is usually used to format text.

(2) the text often, but not always, is going to be displayed on just a few lines, maybe 10 max lines would
cover 99.9% of the cases?

(3) Screen widths and resolutions differ, but it's unlikely that anyone is going to have more than 500 characters per line

(4) Memory is about 12 cents a megabyte these days, and getting cheaper...

(5) So a 10 line buffer, at 500 chars per line, is 5000 bytes, which is 1/200th of a megabyte,
so this printf buffer costs you (transiently) 12 cents/200 or 0.06 cents.

You can't afford to tie up 0.06 cents for a few nanoseconds? :)





0
 
LVL 22

Expert Comment

by:NovaDenizen
Comment Utility
%d will be longest when you print out the minimal integer value.  It's a fairly safe assumption that this value is (-MAXINT-1),  but I don't know of the best standard name for the minimal integer value.  On my solaris box there is INT32_MIN, INT_LEAST32_MIN, INT_MIN, MIN_INT that all have the same value of -2^31.

Anyway, this minimal value printed out as "%d" will have (ceil(log(-INT_MIN) / log(10.0)) + 1) characters.  For 32-bit twos-complement numbers, this is 11.  The quantity resulting from ceil will be the number of digits, and +1 for the minus sign.
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 45

Expert Comment

by:Kdo
Comment Utility

Hi grg99,

You were doing so well.  Right up until you injected the "time is money" angle.

:)

0
 
LVL 22

Expert Comment

by:NovaDenizen
Comment Utility
One way to anticipate the buffer length is to assume worst case and use the maximal length for each %d.  Another way is to calculate the length for each individual int.

If you want to know the length of an arbitrary int for %d, this slow function ought to do the trick:
#include <math.h>

int integer_length(int x) {
   int result = 0;
   if (x < 0) {
        x = -x;
        result = 1;
    }
   while (x >= 1000) {
        x /= 1000;
        result += 3;
   }
   while (x >= 10) {
        x /= 10;
        result++;
    }
    result++;
    return result;
}
0
 
LVL 45

Expert Comment

by:Kdo
Comment Utility

Hi Nova,

This gets you the length of the display value of an integer, but what if the format specifier is a different size?

The bottom line is that the conversion will have to be parsed and the characters counted, then an ample buffer assigned, and finally the conversion parsed again with character substitution.

A scratch buffer is a lot easier and will certainly result in few "wasted" machine cycles.


Kent
0
 
LVL 22

Expert Comment

by:grg99
Comment Utility
>You were doing so well.  Right up until you injected the "time is money" angle.

Well, what is specifically wrong with measuring the memory usage in that way?


Waay back in the days of steam-powered computers, I worked on a system that charged you 3 cents for each CPU second, and 0.04 cents for every kiloword-second of core (at least they were 60-bit words).  The maximum amount of core you could request was 20K decimal, so that's 3.8 cents per whole-hog computer second.

If we assume the 12 cents/megabyte memory will last 5 years, that's about 40,000 hours, or 145,000,000 seconds, so a megabyte is costing us 12/145 millionths of a cent per second, call it a tenth of a millionth of a cent per megabyte-second.  Assuming the printf() routine takes oh, say a microsecond (about 5000 instructions on a two-pipe Pentium these days), 5000 bytes costs 1/1000 of 1/200th of a tenth of a millionth of a cent. That's one two-trillionth of a cent per call, or 0.5 x 10^-14 $/call.  

If I got the decimal points right, you could call this routine a million million times for a penny.

0
 
LVL 45

Expert Comment

by:Kdo
Comment Utility

Hi Grg99,

It was just a bit of tongue-in-cheek humor.  Guess it didn't come off that way.


>Waay back in the days of steam-powered computers, I worked on a system that charged you 3 cents for each CPU second, and 0.04 cents for every kiloword-second of core (at least they were 60-bit words).  The maximum amount of core you could request was 20K decimal, so that's 3.8 cents per whole-hog computer second.

I happen to have a couple of core planes from one of those systems on my desk.  :)  A single plane (and its 128 bytes of storage) is larger and weighs as much as a modern SIMM.  Looking at this in the right light, 1 million of these planes has the equivalent storage as a 128MB SIMM.  Of course, it would take several rooms full of these planes to actually achieve this much storage and several additional rooms of support materials to run these.

But it does make modern memory quite the bargain!


Grg99, my e-mail address is in my profile.  How about sending me a quick note so I can send something your way?  It's related to those old systems, not the boards.

Kent



0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.

762 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now