Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Wczytywanie konfiguracji z pliku

Ostatnio zmodyfikowano 2014-01-30 12:53
Autor Wiadomość
alixir
» 2014-01-29 07:26:56
Wczytujesz pierwszą linię i odrazu w pętli masz warunek:

C/C++
if( name.compare( option_name ) ) {
    return option_value;
} else {
    return 0;
}

Jeśli nie ma tu szukanego wyrazu to funkcja się kończy 'return 0'.
Przesuń
return 0;
 poza pętlę while, a w jego miejsce wstaw
continue;

A ogólnie to według mnie twoja metoda ma wadę, dlatego że uwzględnia/nieuwzględnia spacji.
Co się stanie gdy w pliku konfigracyjnym zamiast:
ts3_stop = stop
będzie
ts3_stop  =  stop
lub
ts3_stop=stop
P-103483
RazzorFlame
» 2014-01-29 09:34:33
C/C++
while( std::getline( file, line ) ) {
    if( !line.length() ) continue;
   
(...)
program wczytuje tylko pierwszą linijkę pliku
A co chciałeś osiagnąć? Przecież program wczyta pierwszą linijkę która nie jest pusta i od razu sprawdza warunek, powinieneś sprawdzać czy podana nazwa wartości jest w danej linijce a jeżeli nie to przejdź do dalszej linijki (a nie wyjdź z programu - return).
P-103484
--Smigol--
Temat założony przez niniejszego użytkownika
» 2014-01-29 13:40:08
Zrobiłem tak jak napisał Alixir i wszystko działa - dzięki wielkie.
Jeśli masz jakiś pomysł jak to poprawić, żeby działało nawet ze spacjami, to chętnie się czegoś nauczę.
Pozdrawiam.
P-103505
alixir
» 2014-01-30 12:53:00
Nie jestem dobrym nauczycielem, bo sam się szkolę, ale napisałem sobie taki przykładowy programik. Może dzięki jego analizie wpadną ci do głowy nowe pomysły.

C/C++
#include <iostream>
#include <string>
#include <limits>
#include <fstream>
#include <sstream>
#include <vector>

struct sConfig {
    std::string name, value;
};

void PressEnter();
void removeSpaces( std::string & );
int readConfig( std::string, std::vector < sConfig > * );

int main() {
   
    // Zmienne
    std::string file_name = "config.txt";
    std::vector < sConfig > vConf;
   
    if( readConfig( file_name, & vConf ) ) {
       
        // Wyswietlamy dane z wektora
        for( int i = 0; i < vConf.size(); i++ ) {
            std::cout << "Name = " << vConf[ i ].name;
            std::cout << "\tValue = " << vConf[ i ].value << std::endl;
        }
    }
   
    PressEnter();
    return 0;
}

void PressEnter() {
    std::cout << "Press ENTER to continue...";
    std::cin.clear();
    std::cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' );
}

void removeSpaces( std::string & text ) {
    while( text.find( ' ' ) != std::string::npos )
         text.erase( text.find( ' ' ), 1 );
   
}

int readConfig( std::string fname, std::vector < sConfig > * vec ) {
   
    std::ifstream h_file( fname.c_str() );
    if( !h_file.good() ) {
        std::cout << "Error reading the config file. Check path and permissions." << std::endl;
        return 0;
    }
   
    std::string buff;
    bool fail = false;
    int line_nr = 1;
   
    while( std::getline( h_file, buff ) ) { // wczytujemy linie do bufora
       
        // Usuwamy komentarze niezaleznie od ich polozenia
        size_t pos = buff.find( "#" );
        if( pos != std::string::npos )
             buff.erase( pos, buff.length() - pos );
       
        // Usuwamy wszystkie spacje
        removeSpaces( buff );
       
        // Dzielimy wczytane dane na ich nazwy oraz wartosci
        std::istringstream ss( buff );
        std::string token;
        sConfig conf;
        int counter = 0;
        while( std::getline( ss, token, '=' ) ) {
            if( token.length() == 0 ) { // jesli token jest pusty
                std::cout << "Error in config file. Line nr: " << line_nr << " (name missing)" << std::endl;
                fail = true;
                break;
            }
            if( counter == 0 ) // pierwsze przejscie
                 conf.name = token;
            else if( counter == 1 ) // drugie przejscie
                 conf.value = token;
            else { // kolejne przejscia niedozwolone
                std::cout << "Error in config file. Line nr: " << line_nr << " (using twice '=')" << std::endl;
                fail = true;
                break;
            }
            counter++;
        }
        if( counter == 1 ) { // jesli petla przeszla tylko 1 raz tzn. ze nie bylo nic do wczytania po znaku =
            std::cout << "Error in config file. Line nr: " << line_nr << " (value or '=' missing)" << std::endl;
            fail = true;
        }
       
        if( fail ) { // jesli byl blad - zakoncz wczytywanie
            h_file.close();
            return 0;
        }
        line_nr++;
       
        if( counter == 0 ) continue; // Pomijamy puste linii
       
        vec->push_back( conf ); // zapisujemy dane w wektorze
    }
   
    h_file.close();
    return 1;
}

Plik na którym testowałem:
Możesz potestować usuwając co się da i jak się da (nie zawiera oczywiście wszelkich zabezpieczeń, ale ma zobrazować sytuację)


# Comment 1
  game_start = start#
game_stop = stop
   # Comment 2
game_player = player1, player2, player3
game_speed =    100 # comment 3
game_status = ready
P-103573
1 « 2 »
Poprzednia strona Strona 2 z 2