<?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[Design-Frage: Config-File-Klasse]]></title><description><![CDATA[<p>Hi,</p>
<p>ich bin dabei eine Config-File-Klasse zu schreiben. Ich bin was Desing angeht nicht so fit und poste das Ganze einfach mal hier:</p>
<pre><code class="language-cpp">#ifndef CONFIG_H
#define CONFIG_H

#include &lt;map&gt;
#include &lt;string&gt;

class Config
{
private:
  std::string filename;
  void readFile(std::string const&amp;); // reads in the file 'filename'
  std::string&amp; trim(std::string&amp;);   // removing whitespace

protected:
  std::map&lt;std::string,std::string&gt; variables;  // contains variables name and values

public:
  Config(std::string const&amp;);

  void writeToFile(std::string const&amp;, std::string const&amp;);

  // Overloaded operator () - Example:
  //   Config config(myConfigFile);
  //   cout &lt;&lt; &quot;Some_Variable=&quot; &lt;&lt; config(&quot;Some_Variable&quot;) &lt;&lt; endl;
  std::string const&amp; operator()(std::string const&amp;);

  friend std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const Config&amp; config);
};

std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const Config&amp; config);

#endif
</code></pre>
<p>Die Dateien haben momentan folgende Form:</p>
<blockquote>
<p># ***************************************************<br />
# *** Configuration file ...<br />
# ***************************************************</p>
<p># ein Deluxe-Kommentar: wird direkt ignoriert<br />
Variable = /home/karl/Dev/irgendwas</p>
<p>eine_andere_Variable = TRUE</p>
</blockquote>
<p>Bisher werden alle Parameter als std::strings gelesen und geschrieben.<br />
Ist natürlich nicht so spitze. Schöner wäre, wenn man auch bool int und double schreiben bzw. könnte.</p>
<p>Jetzt könnte man ein getInt(std::string variable) und setInt(std::string variable, int value) und entsprechende Funktionen für alle Typen machen. Ist sowas ok?<br />
Oder wie könnte man das noch machen? Vielleicht irgendwie mit Templates?</p>
<p>Ich bitte um konstruktive Kritik (aber nicht zu hart <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /> )</p>
<p>Gruss, KB</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/136031/design-frage-config-file-klasse</link><generator>RSS for Node</generator><lastBuildDate>Sat, 29 Aug 2026 10:24:56 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/136031.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 06 Feb 2006 19:24:47 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Design-Frage: Config-File-Klasse on Mon, 06 Feb 2006 19:32:21 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>ich bin dabei eine Config-File-Klasse zu schreiben. Ich bin was Desing angeht nicht so fit und poste das Ganze einfach mal hier:</p>
<pre><code class="language-cpp">#ifndef CONFIG_H
#define CONFIG_H

#include &lt;map&gt;
#include &lt;string&gt;

class Config
{
private:
  std::string filename;
  void readFile(std::string const&amp;); // reads in the file 'filename'
  std::string&amp; trim(std::string&amp;);   // removing whitespace

protected:
  std::map&lt;std::string,std::string&gt; variables;  // contains variables name and values

public:
  Config(std::string const&amp;);

  void writeToFile(std::string const&amp;, std::string const&amp;);

  // Overloaded operator () - Example:
  //   Config config(myConfigFile);
  //   cout &lt;&lt; &quot;Some_Variable=&quot; &lt;&lt; config(&quot;Some_Variable&quot;) &lt;&lt; endl;
  std::string const&amp; operator()(std::string const&amp;);

  friend std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const Config&amp; config);
};

std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const Config&amp; config);

#endif
</code></pre>
<p>Die Dateien haben momentan folgende Form:</p>
<blockquote>
<p># ***************************************************<br />
# *** Configuration file ...<br />
# ***************************************************</p>
<p># ein Deluxe-Kommentar: wird direkt ignoriert<br />
Variable = /home/karl/Dev/irgendwas</p>
<p>eine_andere_Variable = TRUE</p>
</blockquote>
<p>Bisher werden alle Parameter als std::strings gelesen und geschrieben.<br />
Ist natürlich nicht so spitze. Schöner wäre, wenn man auch bool int und double schreiben bzw. könnte.</p>
<p>Jetzt könnte man ein getInt(std::string variable) und setInt(std::string variable, int value) und entsprechende Funktionen für alle Typen machen. Ist sowas ok?<br />
Oder wie könnte man das noch machen? Vielleicht irgendwie mit Templates?</p>
<p>Ich bitte um konstruktive Kritik (aber nicht zu hart <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /> )</p>
<p>Gruss, KB</p>
]]></description><link>https://www.c-plusplus.net/forum/post/987923</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/987923</guid><dc:creator><![CDATA[Karl Blau]]></dc:creator><pubDate>Mon, 06 Feb 2006 19:32:21 GMT</pubDate></item><item><title><![CDATA[Reply to Design-Frage: Config-File-Klasse on Mon, 06 Feb 2006 19:50:30 GMT]]></title><description><![CDATA[<p>Karl Blau schrieb:</p>
<blockquote>
<p>Ich bitte um konstruktive Kritik (aber nicht zu hart <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /> )</p>
</blockquote>
<p>Hallo Karl,</p>
<p>so rein optisch würde ich es begrüßen, wenn die public-Member oben in der Klasse beschrieben sind. Das ist schließlich das was den Kunden - also den, der nur die public's nutzen darf - interessiert.</p>
<p>Bei der Definition der Methoden, bietet es sich an, aussagekräftige Variablennamen zu verwenden; statt gar keine. Also z.B.:</p>
<pre><code class="language-cpp">std::string const&amp; operator()( std::string const&amp; key ); // key; also der Schlüssel für den gewünschten Wert
</code></pre>
<p>Ich halte es für einen Vorteil, Member-Variablen immer besonders zu kennzeichnen. Entweder mit vorangestellten 'm_' oder mit angehängtem '_'; ist beides üblich. Das ist positiv für die Lesbarkeit des Codes.</p>
<p>Dein Konstruktor ist implizit. Das könnte gefährlich sein. Besser das Key-Wort explicit verwenden.</p>
<pre><code class="language-cpp">public:
  explicit Config( std::string const&amp; filename );
</code></pre>
<p>Die Methode write_to_file und der operator&lt;&lt; scheint mir irgendwie doppelt. Im allgemeinen bietet es sich an, immer std::istream und std::ostream als IO-Schnittstelle zu definieren. Das bringt mehr Flexibilität.</p>
<p>Karl Blau schrieb:</p>
<blockquote>
<p>Jetzt könnte man ein getInt(std::string variable) und setInt(std::string variable, int value) und entsprechende Funktionen für alle Typen machen. Ist sowas ok?<br />
Oder wie könnte man das noch machen? Vielleicht irgendwie mit Templates?</p>
</blockquote>
<p>gibt es. Im Prinzip geht das so:</p>
<pre><code class="language-cpp">class Config
{
public:
    explicit Config( std::string const&amp; filename );

    template&lt; typename T &gt;
    T get( std::string const&amp; key )
    {
        std::stringstream buf( variables[key] );
        T x;
        if( !(buf &gt;&gt; x) )
            throw std::runtime_error( &quot;kann Variable nicht lesen&quot; );
        return x;
    }
    // ...
</code></pre>
<p>und der Aufruf ist dann:</p>
<pre><code class="language-cpp">Config cfg(&quot;config.ini&quot;);
    int i = cfg.get&lt; int &gt;( &quot;eine_int_Variable&quot; );
</code></pre>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/987989</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/987989</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Mon, 06 Feb 2006 19:50:30 GMT</pubDate></item><item><title><![CDATA[Reply to Design-Frage: Config-File-Klasse on Tue, 07 Feb 2006 16:16:27 GMT]]></title><description><![CDATA[<p>Vielen Dank für die Hinweise.</p>
<p>Doku habe ich gemacht.</p>
<p>Wegen write_to_file und der operator&lt;&lt;:<br />
write_to_file schreibt den Übergebenen Wert in die Datei, d.h. eine Variable wird neu belegt. operator&lt;&lt; wurde für die Ausgabe am Bildschirm überladen: eine übersichtliche tabellarische Übersicht über die in der Datei enthaltenen Variablen.<br />
Scheinbar ist die Namensgebung aber nicht so gelungen - sonst wäre die Frage erst garnicht aufgetreten.</p>
<p>Schönen Dank!</p>
<p>Ich versuche mich noch an einer Set-Funktion. Ich poste hier irgendwann mal was ich gemacht habe...</p>
<p>Gruss, KB</p>
]]></description><link>https://www.c-plusplus.net/forum/post/988679</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/988679</guid><dc:creator><![CDATA[Karl Blau]]></dc:creator><pubDate>Tue, 07 Feb 2006 16:16:27 GMT</pubDate></item><item><title><![CDATA[Reply to Design-Frage: Config-File-Klasse on Tue, 07 Feb 2006 21:29:23 GMT]]></title><description><![CDATA[<p>Karl Blau schrieb:</p>
<blockquote>
<p>ich bin dabei eine Config-File-Klasse zu schreiben.</p>
</blockquote>
<p>Hehe, da arbeiten wir wohl momentan an der gleichen Sache. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Karl Blau schrieb:</p>
<blockquote>
<p>Bisher werden alle Parameter als std::strings gelesen und geschrieben.<br />
Ist natürlich nicht so spitze. Schöner wäre, wenn man auch bool int und double schreiben bzw. könnte.</p>
<p>Jetzt könnte man ein getInt(std::string variable) und setInt(std::string variable, int value) und entsprechende Funktionen für alle Typen machen. Ist sowas ok?<br />
Oder wie könnte man das noch machen? Vielleicht irgendwie mit Templates?</p>
</blockquote>
<p>Ja, ist durchaus ok. Zumindest werde ich es in ähnlicher Form für alle meine Typen (boolean, integer, real, (character), string) machen. Die gepostete Version von Werner mit den Stringstreams ist zwar einfach, mir aber zu unflexibel. ZB bekommt man schon hier Probleme damit:</p>
<pre><code>fullscreen = false
</code></pre>
<p>Evtl. werde ich hier auf ein entsprechendes Design Pattern, zB Strategy, zurückgreifen, damit die einzelnen Funktionen eine Ebene runter rutschen und für den Anwender unsichtbar bleiben. Darüber muss ich mir aber erst noch ein paar Gedanken machen, inwiefern das machbar und sinnvoll ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/988991</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/988991</guid><dc:creator><![CDATA[groovemaster]]></dc:creator><pubDate>Tue, 07 Feb 2006 21:29:23 GMT</pubDate></item><item><title><![CDATA[Reply to Design-Frage: Config-File-Klasse on Tue, 07 Feb 2006 21:50:42 GMT]]></title><description><![CDATA[<p>groovemaster schrieb:</p>
<blockquote>
<p>Die gepostete Version von Werner mit den Stringstreams ist zwar einfach, mir aber zu unflexibel. ZB bekommt man schon hier Probleme damit:</p>
<pre><code>fullscreen = false
</code></pre>
</blockquote>
<p>keineswegs <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f576.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--sunglasses"
      title=":sunglasses:"
      alt="🕶"
    /></p>
<p>Wenn bool's immer als true oder false angegeben werden, so füge einfach den Manipulator boolalpha hinzu</p>
<pre><code class="language-cpp">T get( std::string const&amp; key )
    {
        std::stringstream buf( variables[key] );
        T x;
        if( !(buf &gt;&gt; std::boolalpha &gt;&gt; x) ) ..
</code></pre>
<p>Anwendung wie gehabt:</p>
<pre><code class="language-cpp">bool fullscreen = cfg.get&lt; bool &gt;( &quot;fullscreen&quot; );
</code></pre>
<p>.. und wenn das auch nicht reicht, so schreibst Du Dir Deinen eigenen Typ</p>
<pre><code class="language-cpp">struct MySuperBool
{
    bool as_bool() const { return m_flag; }
    bool m_flag;
};
std::istream&amp; operator&gt;&gt;( std::istream&amp; in, MySuperBool&amp; b )
{
     // hier kannst Du jetzt aus 'in' einlesen, was immer Du magst
     b.m_flag = ..;
     return in;
}
</code></pre>
<p>Und die Anwendung:</p>
<pre><code class="language-cpp">bool fullscreen = cfg.get&lt; MySuperBool&gt;( &quot;fullscreen&quot; ).as_bool();
</code></pre>
<p>wieviel Flexibilität willst Du noch?</p>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/989010</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/989010</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Tue, 07 Feb 2006 21:50:42 GMT</pubDate></item><item><title><![CDATA[Reply to Design-Frage: Config-File-Klasse on Tue, 07 Feb 2006 22:12:45 GMT]]></title><description><![CDATA[<p>Werner Salomon schrieb:</p>
<blockquote>
<p>wieviel Flexibilität willst Du noch?</p>
</blockquote>
<p>Viel mehr. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>ZB wird es bei mir Ganzzahlen, basierend auf einem variablen Zahlensystem, geben.</p>
<blockquote>
<p>flags = 19 # wird ganz normal als dezimaler Wert interpretiert<br />
flags = 2x10011 # wird als Binärzahl interpretiert</p>
</blockquote>
<p>Und was ist zB mit unquote? Strings werden bei mir wie folgt angegeben:</p>
<blockquote>
<p>user = &quot;Al Bundy&quot;</p>
</blockquote>
<p>Zudem soll es später auch einfache Verknüpfungen geben:</p>
<blockquote>
<p>user_1 = &quot;Al Bundy&quot;<br />
user_2 = &quot;Peggy Bundy&quot;<br />
group = user_1 &amp; &quot;;&quot; &amp; user_2</p>
</blockquote>
<p>Für all die Sachen muss ich schwerere Geschütze als Stringstreams auspacken. Für meinen Fall sind sie jedenfalls relativ ungeeignet. Wenn überhaupt, dann nur für spezielle Teile.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/989019</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/989019</guid><dc:creator><![CDATA[groovemaster]]></dc:creator><pubDate>Tue, 07 Feb 2006 22:12:45 GMT</pubDate></item><item><title><![CDATA[Reply to Design-Frage: Config-File-Klasse on Tue, 07 Feb 2006 22:23:00 GMT]]></title><description><![CDATA[<p>groovemaster schrieb:</p>
<blockquote>
<p>Für all die Sachen muss ich schwerere Geschütze als Stringstreams auspacken. Für meinen Fall sind sie jedenfalls relativ ungeeignet. Wenn überhaupt, dann nur für spezielle Teile.</p>
</blockquote>
<p>Ehrlich gesagt, verstehe ich Dich nicht. Ich kann Dir für jedes Deiner Beispiele eine Implementierung hinschreiben.<br />
Du kannst auch innerhalb eines selbstgeschriebenen Streaming-Operators mit Sachen wie regex oder Spirit auf den Input losgehen und ein Objekt von der Klasse Deiner Wahl zurückgeben.<br />
Deine Schnittstelle ist auch kein stringstream sonern ein istream; und ein ifsream ist auch nur ein istream. Also was bitteschön willst Du machen, was nicht innerhalb eines Streaming-Operators zu lösen wäre?</p>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/989026</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/989026</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Tue, 07 Feb 2006 22:23:00 GMT</pubDate></item><item><title><![CDATA[Reply to Design-Frage: Config-File-Klasse on Wed, 08 Feb 2006 15:39:57 GMT]]></title><description><![CDATA[<p>Frage für &quot;get&quot;:</p>
<p>val soll in temp geschrieben werden:</p>
<pre><code class="language-cpp">std::string temp;
std::stringstream buf(temp);
if (!(buf &lt;&lt; val))
  std::cout &lt;&lt; &quot;aus val=&quot; &lt;&lt; val &lt;&lt; &quot; mach &quot; &lt;&lt; temp &lt;&lt; std::endl;
</code></pre>
<p>Funktioniert so nicht. Es kommt nichts in temp an...</p>
<p>Mache ich was falsch (bestimmt ...)</p>
<p>Gruss, KB</p>
]]></description><link>https://www.c-plusplus.net/forum/post/989437</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/989437</guid><dc:creator><![CDATA[Karl Blau]]></dc:creator><pubDate>Wed, 08 Feb 2006 15:39:57 GMT</pubDate></item><item><title><![CDATA[Reply to Design-Frage: Config-File-Klasse on Wed, 08 Feb 2006 20:24:56 GMT]]></title><description><![CDATA[<p>Karl Blau schrieb:</p>
<blockquote>
<p>Frage für &quot;get&quot;:<br />
val soll in temp geschrieben werden:</p>
</blockquote>
<p>.. dann meins Du set - oder?</p>
<p>Karl Blau schrieb:</p>
<blockquote>
<pre><code class="language-cpp">std::string temp;
std::stringstream buf(temp);
if (!(buf &lt;&lt; val))
  std::cout &lt;&lt; &quot;aus val=&quot; &lt;&lt; val &lt;&lt; &quot; mach &quot; &lt;&lt; temp &lt;&lt; std::endl;
</code></pre>
<p>Funktioniert so nicht. Es kommt nichts in temp an...</p>
<p>Mache ich was falsch (bestimmt ...)</p>
</blockquote>
<p>Äh! - ja.<br />
Besser:</p>
<pre><code class="language-cpp">std::stringstream buf;  // leerer Stringstream
if ( buf &lt;&lt; val )       // hinein mit 'val'
{
    // ja, es ist gutgegangen
    std::string temp = buf.str();   // Inhalt in Form eines 'std::string' wieder rausholen
    std::cout &lt;&lt; &quot;aus val=&quot; &lt;&lt; val &lt;&lt; &quot; mach &quot; &lt;&lt; temp &lt;&lt; std::endl; // und dem werten User sichtbar machen
</code></pre>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/989706</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/989706</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Wed, 08 Feb 2006 20:24:56 GMT</pubDate></item><item><title><![CDATA[Reply to Design-Frage: Config-File-Klasse on Thu, 09 Feb 2006 07:51:30 GMT]]></title><description><![CDATA[<p>Werner Salomon schrieb:</p>
<blockquote>
<p>Ehrlich gesagt, verstehe ich Dich nicht. Ich kann Dir für jedes Deiner Beispiele eine Implementierung hinschreiben.</p>
</blockquote>
<p>Ja und jedesmal wie du das mit MySuperBool gemacht hast, richtig? Dann sind Stringstreams aber keine Universallösung mehr. Ob du dann für jeden Typ eine eigene Klasse machst, eigene Funktionen, überladene Operatoren oder was auch immer, ist ja erst mal nebensächlich. Du musst jedenfalls jeden Typ gesondert behandeln. Und darauf bezog sich wohl Karls Frage, wenn ich ihn richtig verstanden habe.</p>
<p>Werner Salomon schrieb:</p>
<blockquote>
<p>Du kannst auch innerhalb eines selbstgeschriebenen Streaming-Operators mit Sachen wie regex oder Spirit auf den Input losgehen und ein Objekt von der Klasse Deiner Wahl zurückgeben.</p>
</blockquote>
<p>Regex? Spirit? Boost? Ne, so schwere Geschütze müssen es dann auch wieder nicht sein. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/989833</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/989833</guid><dc:creator><![CDATA[groovemaster]]></dc:creator><pubDate>Thu, 09 Feb 2006 07:51:30 GMT</pubDate></item></channel></rss>