Variablen aus .conf File auslesen



  • Hallo,

    als völliger Neuling in C-Programmierung habe ich folgendes Problem:

    Aus einer Datei logger.conf möchte ich Werte auslesen, die anschließend im c-Programm weiterverarbeitet werden.

    logger.conf

    #BlaBla
    loginterval = 60
    
    #Blabla
    DBName = solarmax
    DBUser = solaruser
    DBPass = test
    
    #BlaBla
    AnzahlWR = 2
    
    ##Anhängig von AnzahlWR kommen nun die Variablen Hostname und Hostport n-mal.
    Hostname1 = 192.168.25.1
    Hostport1 = 12345
    ##Bla
    Hostname2 = 192.168.25.2
    Hostport2 = 23456
    

    Die config-Datei ist gespickt mit Kommentaren (#...)

    Meine bisherigen Versuche beschränken sich darauf, wenigstens einen Wert aus der Datei zu lesen und in eine Variable zu schreiben.

    logger.c

    #include <stdio.h>
    
    char* config_file_name = "/usr/local/etc/logger.conf";
    
    int main(int argc, char **argv) {
        FILE *fp = fopen(config_file_name, "r");
        char var[512],
             line[512];
    
        if (fp) {
            while (fgets(line, sizeof(line), fp)) {
               if (sscanf(line, "DBPass = %[^\n]", var)) {
                    printf("Datenbank-Passwort = %s\n", var);
               }
            fclose(fp);
        }
        return 0;
      }
    }
    

    Leider sind meine Versuche bisher nicht von Erfolg gekrönt. 😞

    Die weiteren Schritte sollen dann sein:
    - alle Variablen auslesen
    - den Dateinamen optional aus Aufrufparameter auszulesen

    Hoffentlich kann mir hier jemand helfen.

    Vielen Dank im Voraus.



  • Texte in C parsen ist schrecklich. Ich würde was fertiges suchen, z.B:
    http://www.compuphase.com/minini.htm
    🙂



  • Ich habe irgendwann vor vielen Jahren mal sowas geschrieben. Ich habe allerdings nur noch eine .patch Datei davon, daher hier mal die Datei: http://feig.privatepaste.com/3951c6f9ea

    Irgendwo ab "Config Parser (configfile.c)" beginnt der Code.

    if(strstr(buffer, "\";"))
        sscanf(buffer, "%[^= ] = \"%[^\";]", key, data);
    

    ist dabei quasi das, was du suchst. Dabei müsste die Config so aussehen:

    // Kommentar
    abc = "def";

    Vielleicht hilft dir der Code ja ein bisschen weiter, auch wenn er schon etwas älter ist.



  • Ich bin nun insofern ein Stück weiter, als dass ich zumindest die gleichbleibenden Variablen-Namen (global-settings) abfragen kann.

    logger.conf

    #Settings for the Solarmax Watcher
    
    #Global-settings
    loginterval=60
    DBUser=solaruser
    DBName=solarmax
    DBPass=test
    Inverter_count=3
    
    #Inverter1
    Hostname1=192.168.25.2
    Hostport1=12345
    
    #Inverter2
    Hostname2=192.168.25.3
    Hostport2=23456
    
    #Inverter3
    Hostname3=192.168.25.4
    Hostport3=34567
    

    Wie kann ich die denn nur erfragen?

    Hier mein bisheriger Code (logger.c)

    #include <stdio.h>
    #include <string.h>
    
    char* config_file_name = "/usr/local/etc/logger.conf";
    
    int main(int argc, char **argv) {
        FILE *fp = fopen(config_file_name, "r");
        char var1[512],
             var2[512],
             var3[512],
             var4[512],
             var5[512],
             line[512];
    
        if (fp) {
            while (fgets(line, sizeof(line), fp)) {
               if (sscanf(line, "DBName=%[^\n]", var1)) {
                    printf("DBName = %s\n", var1);
               }
               if (sscanf(line, "DBUser=%[^\n]", var2)) {
                    printf("DBUser = %s\n", var2);
               }
               if (sscanf(line, "DBPass=%[^\n]", var3)) {
                    printf("DBUPassword = %s\n", var3);
               }
               if (sscanf(line, "loginterval=%[^\n]", var4)) {
                    printf("LogInterval = %s\n", var4);
               }
               if (sscanf(line, "Inverter_count=%[^\n]", var5)) {
                    printf("Anzahl Wechselrichter = %s\n", var5);
               }
        }
        return 0;
      }
      fclose(fp);
    }
    

    Vielen Dank für die bisherigen Hinweise 🙂



  • Alles sehr einfach, z.B.:

    int lies(const char *fname,Paar *conf,size_t cs)
    {
      int r=0;
      char zeile[1000],*p;
      FILE *f=fopen(fname,"rt");
      if(!f) return perror(fname),r;
      while( fgets(p=zeile,1000,f) )
      {
        if( strchr(p,'\n') ) *strchr(p,'\n')=0;
        if( p=strchr(zeile,'='),1==sscanf(zeile,"%[^ \t#]=",zeile) )
        {
          size_t i=cs;
          while( i-- )
            if( !strcmp(conf[i].key,zeile) )
              ++r,sprintf(conf[i].val,"%.*s",sizeof conf->val-1,p+1);      
        }
      }
      fclose(f);
      return r;
    }
    

    und aufrufen z.B.:

    typedef struct { char key[20],val[100]; } Paar;
    ...
    Paar conf[]={{"DBName"},{"DBUser"},{"DBPass"}};
    size_t s=sizeof conf/sizeof*conf;
    lies("conf.txt",conf,s);
    while( s-- )
      puts(conf[s].key),puts(conf[s].val);
    

    Anpassen müsstest du noch, falls du Sektionen "[]" in deiner ini-Datei nutzt.



  • @wutz ich finde deinen code nicht so schön, musst du immer alles in eine zeile quetschen? das machts doch nicht wirklich lesbarer...

    kann nur hoffen dass ein compiler das raus optimieren kann...

    if( strchr(p,'\n') ) *strchr(p,'\n')=0;
    


  • @Wutz:

    Wow, das überfordert mich total. Hab verducht deinen Code in mein Programm zu integrieren. Ich weiss aber gar nicht so recht wie, da ich den Code nicht verstehe. Sorry, bin halt noch ein Grünschnabel.



  • Dazu sind Funktionen übrigens da, dass sie Funktionalitäten kapseln.
    Der Anwender, also du braucht sich nur um den aufrufenden Kontext sprich um seine eigentlichen Sachen kümmern, womit er meist genug zu tun hat und sich nicht um solche Basisfunktionalitäten kümmern.

    2x Copy+Paste sollten doch wohl nicht zuviel verlangt sein; die Funktion gibt die Zahl der erfolgreichen Zuordnungen zurück und prüft auch noch auf val-Länge und schneidet wenn nötig ab.


Anmelden zum Antworten