<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ersatz für vsnprinft --&amp;gt; ohne Zeichenanzahlbegrenzung, std::string, boot::format, ...]]></title><description><![CDATA[<p>Hallo.</p>
<p>Bei uns im Framework gibt es historisch bedingt eine Log-Methode, welche man im printf-Stil die Parameter übergibt, also einen format-string und eine Parameterliste.<br />
Eigentlich läuft alles ohne Problme, jedoch kommt nun der Wunsch, dass es keine Beschränkung hinsichtlich der Log-Zeichenlänge geben soll, mittels vsnprintf wird das ganze auf 250-Zeichen beschränkt.</p>
<p>Welche Möglichkeiten gibt es, dass man hier das ganze dynmisch angeht? Kann man boost::format auch eine va_list übergeben?</p>
<p>Ich habe das ganze schon auf auf folgende Arten getestet, jedoch bin ich da um &quot;Häuser&quot; langsamer als mit der normalen vsnprintf-Funktion</p>
<p>Meine simple Funktion wo mittels fixen buffer und vsnprintf ein string erzeugt wird.</p>
<pre><code class="language-cpp">std::string vsnchar(const char* format, ...) 
{ 
    va_list args; 
    std::string retval; 
    short strsize(250);
    char str[strsize];
    memset(str, '\0', strsize);

    va_start (args, format); 
    vsnprintf (str, strsize, format, args); 
    va_end (args); 

    retval = str;
}
</code></pre>
<p>Es wird mittels vsnprinft der benötige String-Länge ermittelt. Für die Länge gibt es noch eine andere Funktion, leider finde ich diese Alternative nicht mehr, vermutlich wird die performance nicht viel schneller/langsamer werden.</p>
<pre><code class="language-cpp">std::string vsnstring(const char* format, ...) 
{ 
    va_list args; 
    std::string retval; 

    va_start (args, format); 
    retval.resize (vsnprintf (0, 0, format, args)); 
    vsnprintf (&amp;retval[0], retval.capacity() + 1, format, args); 
    va_end (args); 

    return retval; 
}
</code></pre>
<p>Ich habe auch bei meiner suche im Internet eine Möglichkeit gefunden, dass man alles mittels vector machen soll, auch dies habe ich getestet.</p>
<pre><code class="language-cpp">std::string vsnvector(const char* format, ...) 
{ 
    va_list args;
    std::string str;

    va_start (args, format); 
    std::vector&lt;char&gt; buffer(vsnprintf (0, 0, format, args)); 
    vsnprintf(&amp;*buffer.begin(), buffer.size(), format, args);
    va_end (args); 

    std::string result(buffer.begin(), buffer.end()-1);
    return result; 
}
</code></pre>
<p>Obwohl hier nicht unbedingt Linux-Themen angesprochen werden sollen, jedoch ich unter Linux entwickle, habe ich auch open_memstream getestet.</p>
<pre><code class="language-cpp">std::string vsnfile(const char* format, ...) 
{ 
    va_list args; 
    std::string retval; 

    FILE *stream;
    char *buf;
    size_t len;

    stream = open_memstream (&amp;buf, &amp;len);
    if (stream == NULL)
        return retval;
    va_start (args, format);
    vfprintf(stream, format, args);
    va_end (args);
    retval.append(buf, len);
    fclose (stream);
    free (buf);
	return retval;
}
</code></pre>
<p>Fazit:<br />
Leider habe ich keine direkt gute Alternative gefunden. vsnfile ist nach vsnchar am schnellsten (1.000.000x werden die Funktionen aufgerufen)<br />
vsnfile benötigt ~1,8sec, vsnstring ~3,2sec, vsnvector ~3,3sec und vsnfile ~2,9sec<br />
Je größer die Logzeichenlänge wird, desto schneller nähern sich vsnfile und vsnchar an.<br />
Interessant ist auch, wenn vsnchar mit dem fixen buffer nicht auskommt (zb. buffer[3]), dann benötigt vsnchar nicht mehr ~1,8sec, sondern ~2,2sec</p>
<p><strong>MEINE FRAGE:</strong><br />
Gibt es eine Möglichkeit, dass man hier das ganze ohne fixem buffer macht und trotzdem fast so schnell ist wie mit einem fixen buffer?<br />
Unter boost gibt es ja boost::format, aber ich habe keine Möglichkeit gefunden, dass man hier eine va_list übergeben könnte.</p>
<p>Danke für eure Hinweise und Hilfe<br />
Johannes</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/282214/ersatz-für-vsnprinft-gt-ohne-zeichenanzahlbegrenzung-std-string-boot-format</link><generator>RSS for Node</generator><lastBuildDate>Sun, 23 Aug 2026 07:17:24 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/282214.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 16 Feb 2011 08:47:47 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Ersatz für vsnprinft --&amp;gt; ohne Zeichenanzahlbegrenzung, std::string, boot::format, ... on Wed, 16 Feb 2011 08:47:47 GMT]]></title><description><![CDATA[<p>Hallo.</p>
<p>Bei uns im Framework gibt es historisch bedingt eine Log-Methode, welche man im printf-Stil die Parameter übergibt, also einen format-string und eine Parameterliste.<br />
Eigentlich läuft alles ohne Problme, jedoch kommt nun der Wunsch, dass es keine Beschränkung hinsichtlich der Log-Zeichenlänge geben soll, mittels vsnprintf wird das ganze auf 250-Zeichen beschränkt.</p>
<p>Welche Möglichkeiten gibt es, dass man hier das ganze dynmisch angeht? Kann man boost::format auch eine va_list übergeben?</p>
<p>Ich habe das ganze schon auf auf folgende Arten getestet, jedoch bin ich da um &quot;Häuser&quot; langsamer als mit der normalen vsnprintf-Funktion</p>
<p>Meine simple Funktion wo mittels fixen buffer und vsnprintf ein string erzeugt wird.</p>
<pre><code class="language-cpp">std::string vsnchar(const char* format, ...) 
{ 
    va_list args; 
    std::string retval; 
    short strsize(250);
    char str[strsize];
    memset(str, '\0', strsize);

    va_start (args, format); 
    vsnprintf (str, strsize, format, args); 
    va_end (args); 

    retval = str;
}
</code></pre>
<p>Es wird mittels vsnprinft der benötige String-Länge ermittelt. Für die Länge gibt es noch eine andere Funktion, leider finde ich diese Alternative nicht mehr, vermutlich wird die performance nicht viel schneller/langsamer werden.</p>
<pre><code class="language-cpp">std::string vsnstring(const char* format, ...) 
{ 
    va_list args; 
    std::string retval; 

    va_start (args, format); 
    retval.resize (vsnprintf (0, 0, format, args)); 
    vsnprintf (&amp;retval[0], retval.capacity() + 1, format, args); 
    va_end (args); 

    return retval; 
}
</code></pre>
<p>Ich habe auch bei meiner suche im Internet eine Möglichkeit gefunden, dass man alles mittels vector machen soll, auch dies habe ich getestet.</p>
<pre><code class="language-cpp">std::string vsnvector(const char* format, ...) 
{ 
    va_list args;
    std::string str;

    va_start (args, format); 
    std::vector&lt;char&gt; buffer(vsnprintf (0, 0, format, args)); 
    vsnprintf(&amp;*buffer.begin(), buffer.size(), format, args);
    va_end (args); 

    std::string result(buffer.begin(), buffer.end()-1);
    return result; 
}
</code></pre>
<p>Obwohl hier nicht unbedingt Linux-Themen angesprochen werden sollen, jedoch ich unter Linux entwickle, habe ich auch open_memstream getestet.</p>
<pre><code class="language-cpp">std::string vsnfile(const char* format, ...) 
{ 
    va_list args; 
    std::string retval; 

    FILE *stream;
    char *buf;
    size_t len;

    stream = open_memstream (&amp;buf, &amp;len);
    if (stream == NULL)
        return retval;
    va_start (args, format);
    vfprintf(stream, format, args);
    va_end (args);
    retval.append(buf, len);
    fclose (stream);
    free (buf);
	return retval;
}
</code></pre>
<p>Fazit:<br />
Leider habe ich keine direkt gute Alternative gefunden. vsnfile ist nach vsnchar am schnellsten (1.000.000x werden die Funktionen aufgerufen)<br />
vsnfile benötigt ~1,8sec, vsnstring ~3,2sec, vsnvector ~3,3sec und vsnfile ~2,9sec<br />
Je größer die Logzeichenlänge wird, desto schneller nähern sich vsnfile und vsnchar an.<br />
Interessant ist auch, wenn vsnchar mit dem fixen buffer nicht auskommt (zb. buffer[3]), dann benötigt vsnchar nicht mehr ~1,8sec, sondern ~2,2sec</p>
<p><strong>MEINE FRAGE:</strong><br />
Gibt es eine Möglichkeit, dass man hier das ganze ohne fixem buffer macht und trotzdem fast so schnell ist wie mit einem fixen buffer?<br />
Unter boost gibt es ja boost::format, aber ich habe keine Möglichkeit gefunden, dass man hier eine va_list übergeben könnte.</p>
<p>Danke für eure Hinweise und Hilfe<br />
Johannes</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2021672</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2021672</guid><dc:creator><![CDATA[taff]]></dc:creator><pubDate>Wed, 16 Feb 2011 08:47:47 GMT</pubDate></item><item><title><![CDATA[Reply to Ersatz für vsnprinft --&amp;gt; ohne Zeichenanzahlbegrenzung, std::string, boot::format, ... on Wed, 16 Feb 2011 13:15:53 GMT]]></title><description><![CDATA[<p>Kannst du vasprintf verwenden?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2021787</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2021787</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Wed, 16 Feb 2011 13:15:53 GMT</pubDate></item><item><title><![CDATA[Reply to Ersatz für vsnprinft --&amp;gt; ohne Zeichenanzahlbegrenzung, std::string, boot::format, ... on Wed, 16 Feb 2011 14:34:22 GMT]]></title><description><![CDATA[<p>Danke! <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /><br />
gestern bin ich bei <a href="http://die.net" rel="nofollow">die.net</a> über diese Funktion gestolpert, aber irgendwie muss ich das ganze übersehen haben. DANKE <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
<p>meine Testfunktion schaut nun so aus:</p>
<pre><code class="language-cpp">std::string vasf(const char* format, ...) 
{
	va_list args; 
    std::string retval;
	int n(-1);
	char *pstr(NULL);

	va_start (args, format); 
    n = vasprintf (&amp;pstr, format, args); 
    va_end (args); 

	if(n &lt;= 0)
		return retval;

	retval.append(pstr, n);
	free(pstr);
	return retval;
}
</code></pre>
<p>Interessant ist, dass bei Ergebnissen wo zeichenketten von rund 100 zeichen rauskommen, diese funktion zu 90% schneller ist als ein fixer buffer und vnsprintf <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /><br />
Jedoch ist es auch so, wenn das Zeichenkettenergebnis eine Länge von 600 Zeichen hat, vsnprintf mit fixem buffer schneller ist im gegensatz zu vasprintf . grund ist jedoch hier folgender Befehl *retval.append(pstr, n);*ich möchte trotzdem mit std::string weiter arbeiten, gibt es noch einen trick, damit das kopieren schneller funktioniert?</p>
<p>Da ich nun schon einige Möglichkeiten getestet habe, stellt sich für mich noch immer die frage, bietet boost hier auch einen Lösungsweg?<br />
DANKE</p>
<p>lg<br />
lg</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2021833</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2021833</guid><dc:creator><![CDATA[taff]]></dc:creator><pubDate>Wed, 16 Feb 2011 14:34:22 GMT</pubDate></item><item><title><![CDATA[Reply to Ersatz für vsnprinft --&amp;gt; ohne Zeichenanzahlbegrenzung, std::string, boot::format, ... on Wed, 16 Feb 2011 14:55:15 GMT]]></title><description><![CDATA[<p>taff schrieb:</p>
<blockquote>
<p>ich möchte trotzdem mit std::string weiter arbeiten, gibt es noch einen trick, damit das kopieren schneller funktioniert?</p>
</blockquote>
<p>Probier mal das std::string objekt erst zu erstellen wenn du es brauchst:</p>
<pre><code class="language-cpp">string retval(pstr,n);
</code></pre>
<p>Ansonsten verwendet man für sowas auch öfters noch eine nocopy-string Klasse die eben nicht kopiert sondern den ownership von pstr übernimmt und am ende selber löscht.</p>
<p>Schau auch ob hier bei dir NRVO zieht - wenn nicht, dann das free uU in einen Destruktor verlagern.</p>
<blockquote>
<p>Da ich nun schon einige Möglichkeiten getestet habe, stellt sich für mich noch immer die frage, bietet boost hier auch einen Lösungsweg?</p>
</blockquote>
<p>Mir ist nichts bekannt. boost bietet eine alternative an, aber eben auch mit anderer syntax...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2021845</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2021845</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Wed, 16 Feb 2011 14:55:15 GMT</pubDate></item><item><title><![CDATA[Reply to Ersatz für vsnprinft --&amp;gt; ohne Zeichenanzahlbegrenzung, std::string, boot::format, ... on Wed, 16 Feb 2011 15:27:18 GMT]]></title><description><![CDATA[<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>Probier mal das std::string objekt erst zu erstellen wenn du es brauchst</p>
</blockquote>
<p>spielt eigentlich keine rolle -&gt; das ganze wird um 0,01 sec schneller.</p>
<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>Ansonsten verwendet man für sowas auch öfters noch eine nocopy-string Klasse die eben nicht kopiert sondern den ownership von pstr übernimmt und am ende selber löscht.</p>
</blockquote>
<p>schade, dass sowas std::string nicht kann.</p>
<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>Schau auch ob hier bei dir NRVO zieht - wenn nicht, dann das free uU in einen Destruktor verlagern.</p>
</blockquote>
<p>ich bin der meinung, dass NRVO zieht, außer es reicht wenn</p>
<pre><code class="language-cpp">void vasf(std::string &amp;str, const char* format, ...)
</code></pre>
<p>um 0,01-0,03sec schneller ist bei 500.000 aufrufe (stringlänge=600);</p>
<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>Mir ist nichts bekannt. boost bietet eine alternative an, aber eben auch mit anderer syntax...</p>
</blockquote>
<p>ok, schade, hätte noch gehofft, dass boost::format hier irgendwo doch noch was versteckt hat <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2021877</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2021877</guid><dc:creator><![CDATA[taff]]></dc:creator><pubDate>Wed, 16 Feb 2011 15:27:18 GMT</pubDate></item><item><title><![CDATA[Reply to Ersatz für vsnprinft --&amp;gt; ohne Zeichenanzahlbegrenzung, std::string, boot::format, ... on Wed, 16 Feb 2011 15:41:02 GMT]]></title><description><![CDATA[<p>taff schrieb:</p>
<blockquote>
<p>schade, dass sowas std::string nicht kann.</p>
</blockquote>
<p>Bist du wirklich auf std::string festgelegt?<br />
Deine Beschreibung klang so als ob es um die interna einer Log Funktion geht...</p>
<p>Prinzipiell kannst du ansonsten ja auch eine std::string-interface-kompatible Variante eines nocopy-strings schreiben und den verwenden. Oder wird der string irgendwann nach aussen gegeben? Das wäre dann natürlich doof.</p>
<p>Prinzipiell ist es aber komisch dass das kopieren in den String so lange dauert. hätte eher auf die allokationen in vasprintf getippt...</p>
<p>Notfalls den source code von vasprintf suchen und adaptieren dass direkt in den string allokiert wird...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2021887</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2021887</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Wed, 16 Feb 2011 15:41:02 GMT</pubDate></item><item><title><![CDATA[Reply to Ersatz für vsnprinft --&amp;gt; ohne Zeichenanzahlbegrenzung, std::string, boot::format, ... on Thu, 17 Feb 2011 08:33:03 GMT]]></title><description><![CDATA[<p>direkt festgelegt bin ich nicht, jedoch sind alle sachen die zusätzlich noch gemacht werden müssen mit dieser logzeile schon jetzt auf std::string aufgebaut bzw. es wird jetzt schon das ergebnis von vsnprinft+fixer buffer in einen std::string kopiert.</p>
<p>hab mir nun, so wie von dir empfohlen, den sourcecode von vasprintf rausgesucht<br />
ich hoffe, dass ist der richtige<br />
<a href="http://www.google.com/codesearch/p?hl=de#qoCVjtE_vOw/gcc/trunk/gcc-3.4.6/libiberty/vasprintf.c" rel="nofollow">http://www.google.com/codesearch/p?hl=de#qoCVjtE_vOw/gcc/trunk/gcc-3.4.6/libiberty/vasprintf.c</a><br />
vasprintf berechnet zuerst den größten möglichen speicher und reserviert diesen.beim return wird die eigentlich verwendete speicheranzahl zurückgegeben.</p>
<pre><code class="language-cpp">int int_vasprintf (char **result, const char* format, va_list args)
{
  const char *p = format;
  /* Add one to make sure that it is never zero, which might cause malloc
     to return NULL.  */
  int total_width = strlen (format) + 1;
  va_list ap;

  va_copy (ap, args);

  while (*p != '\0')
    {
      if (*p++ == '%')
        {
          while (strchr (&quot;-+ #0&quot;, *p))
            ++p;
          if (*p == '*')
            {
              ++p;
              total_width += abs (va_arg (ap, int));
            }
          else
            total_width += strtoul (p, (char **) &amp;p, 10);
          if (*p == '.')
            {
              ++p;
              if (*p == '*')
                {
                  ++p;
                  total_width += abs (va_arg (ap, int));
                }
              else
              total_width += strtoul (p, (char **) &amp;p, 10);
            }
          while (strchr (&quot;hlL&quot;, *p))
            ++p;
          /* Should be big enough for any format specifier except %s and floats.  */
          total_width += 30;
          switch (*p)
            {
            case 'd':
            case 'i':
            case 'o':
            case 'u':
            case 'x':
            case 'X':
            case 'c':
              (void) va_arg (ap, int);
              break;
            case 'f':
            case 'e':
            case 'E':
            case 'g':
            case 'G':
              (void) va_arg (ap, double);
              /* Since an ieee double can have an exponent of 307, we'll
                 make the buffer wide enough to cover the gross case. */
              total_width += 307;
              break;
            case 's':
              total_width += strlen (va_arg (ap, char *));
              break;
            case 'p':
            case 'n':
              (void) va_arg (ap, char *);
              break;
            }
          p++;
        }
    }

  va_end (ap);

  *result = (char *) malloc (total_width);
  if(*result != NULL)
	return vsprintf (*result, format, args);
  else
    return -1;
}
</code></pre>
<p>interessant ist, wenn ich eben statt</p>
<pre><code class="language-cpp">*result = (char *) malloc (total_width);
  if(*result != NULL)
	return vsprintf (*result, format, args);
  else
    return -1;
</code></pre>
<p>meine std::string ausführung mache:</p>
<pre><code class="language-cpp">result.resize(total_width);
  if (result.size() &gt; 0)
    return vsprintf (&amp;result[0], format, args);
  else
    return -1;
</code></pre>
<p>die std::string variante langsamer ist als eben int_vasprintf + str.append(pstr, n);<br />
ist das speicherreservieren beim std::string um so viel langsamer als ein malloc?<br />
bei meinem test ist somit ein malloc von 937 + std::string.append von der länge von 515 schneller wie das resize von 937 <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2022112</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022112</guid><dc:creator><![CDATA[taff]]></dc:creator><pubDate>Thu, 17 Feb 2011 08:33:03 GMT</pubDate></item></channel></rss>