Форум программистов, компьютерный форум, киберфорум
Кроссплатфор­менная разработка
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Мастер кустарных методов
 Аватар для LEQADA
232 / 227 / 17
Регистрация: 09.11.2010
Сообщений: 680

Парсинг config-файла на C++

09.11.2010, 19:49. Показов 4413. Ответов 0
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет! Дали итоговое задание в универе. Всё написал. Осталось припаять парсер config-файла (это самое сложное). Покопался в нете и нашёл код. Компилируется. Но вот :

Помогите исправить пожалуйста.
main.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
using namespace std;
 
#include "config.h"
 
//int main(int argc, char* argv[], char* envp[])
int main(char* envp[])
{
/*  cout << "config demo program" << endl;
    cout << "(c) 2008 Kai G. Schwebke" << endl;
    cout << "This code is licensed under LGPL and comes with no warranty;" << endl;
    cout << "see COPYING for details." << endl;
    cout << endl;
*/
    // read config file with environment variable expansion support
    Config config("demo.config", envp);
    
    // basic usage of properties
    if (config.pBool("showHello")) {
        int cnt = config.pInt("helloCount");
        string msg = config.pString("helloMessage");
        for (int i = 0; i < cnt; ++i) {
            cout << msg << endl;
        }
        cout << endl;
    }
 
    // properties with expanded names (no difference in using)
    cout << "tempFolder    = '" << config.pString("tempFolder") << "'" << endl;
    cout << "tempSubFolder = '" << config.pString("tempSubFolder") << "'" << endl;
    cout << endl;
 
    // get properties for all subgroups starting with prefix
    map<string, Config*> messages = config.getGroups(); // all groups
    const string messagePrefix = "message"; // prefix for group name
    for (map<string, Config*>::iterator i = messages.begin(); i != messages.end(); ++i) {
        string groupName = i->first;
        Config* group = i->second;
 
        // test group name for prefix
        if (groupName.substr(0, messagePrefix.length()) == messagePrefix) {
            // display group contents
            cout << group->pString("name") << ":" << endl;
            cout << "   " << group->pString("text") << endl;
        }
    }
 
    return 0;
}

config.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#include "config.h"
 
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
 
#include "log.h"
 
Config::Config(string name, string parentDebugInfo) {
    debugInfo = parentDebugInfo + ", " + name;
}
 
Config::Config(string configFile, char** envp) {
    while (*envp) {
        string envEntry = *envp;
        size_t pos = envEntry.find('=');
        if (pos != string::npos) {
            string name = envEntry.substr(0, pos);
            string value = envEntry.substr(pos+1, string::npos);
            envSymbols[name] = value;
            logDebug(cout << "environment symbol: '" << name << "' = '" << value << "'" << endl);
        }
        ++envp;
    }
 
    debugInfo = configFile;
    groupStack.push_front(this);
 
    FILE* in = fopen(configFile.c_str(), "r");
    if (!in) {
        cerr << "cannot open input file '" << configFile << "'" << endl;
        exit(2);
    }
 
    char buff[1024];
    while (fgets(buff, 1024, in)) {
 
        string line=buff;
        if ( (line.length() > 2) && (line[0] != '#') && (line.find(')') == string::npos) ) {
            string name;
            string value;
            split(line, name, value, '=');
 
            if (value == "(") {
                logDebug(cout << "   config: new group '" << name << "'" << endl);
                Config* newGroup = new Config(name, debugInfo);
                groupStack.front()->groups[name] = newGroup;
                groupStack.push_front(newGroup);
            } else {
                for (list<Config*>::reverse_iterator i = groupStack.rbegin(); i != groupStack.rend(); ++i) {
                    (*i)->symbolExpand(value);
                }
                envSymbolExpand(value);
                logDebug(cout << "   config: name = '" << name << "', value = '" << value << "'" << endl);
                groupStack.front()->add(name, value);
            }
        }
        if ( (line.length() > 0) && (line[0] != '#') && (line.find(')') != string::npos) ) {
            logDebug(cout << "   end of group" << endl);
            groupStack.pop_front();
        }
    }
 
    fclose(in);
}
 
Config::~Config() {
    for (map<string, Config*>::iterator i = groups.begin(); i != groups.end(); ++i) {
        delete i->second;
    }
}
 
void Config::add(string name, string value) {
    symbols[name] = value;
}
 
void Config::split(string in, string& left, string& right, char c) {
    size_t pos = in.find_first_of(c);
    if(pos == string::npos) {
        left = in;
        trim(left);
        right = "";
    } else if (pos <= 1) {
        left = "";
        right = in.substr(pos+1, string::npos);
        trim(right);
    } else {
        left = in.substr(0, pos-1);
        trim(left);
        right = in.substr(pos+1, string::npos);
        trim(right);
    }
}
 
void Config::trim(string& s) {
    while ( (s.length() > 1) && ( (s[0] == ' ') || (s[0] =='\t') ) ) {
        s = s.substr(1, string::npos);
    }
    while ( (s.length() > 1) &&
            ( (s[s.length()-1] == ' ') ||
              (s[s.length()-1] == '\t') || 
              (s[s.length()-1] == '\n') || 
              (s[s.length()-1] == '\r') ) ) {
        s = s.substr(0, s.length()-1);
    }
    if ( (s.length() > 1) && (s[0] == '"') ) {
        s = s.substr(1, string::npos);
    }
    if ( (s.length() > 1) && (s[s.length()-1] == '"') ) {
        s = s.substr(0, s.length()-1);
    }
}
 
void Config::symbolExpand(string& s) {
    symbolExpand(symbols, s);
}
 
void Config::envSymbolExpand(string& s) {
    symbolExpand(envSymbols, s);
}
 
void Config::symbolExpand(map<string, string>& symbols, string& s) {
    bool expanded;
    do {
        expanded = false;
        for (map<string, string>::iterator i = symbols.begin(); i != symbols.end(); ++i) {
            string search = "%" + i->first + "%";
            string replace = i->second;
            size_t pos = s.find(search);
            if (pos != string::npos) {
                expanded = true;
                s.replace(pos, search.length(), replace);
            }
        }
    } while (expanded);
}
 
string Config::pString(string name) {
    map<string, string>::iterator i = symbols.find(name);
    if (i == symbols.end()) {
        logError(cout << "access of missing property '" << name << "' (" << debugInfo << ")" << endl);
        exit(4);
    }
    return i->second;
}
 
bool Config::pBool(string name) {
    string val = pString(name);
 
    if ( (val == "yes") ||
         (val == "Yes") ||
         (val == "YES") ||
         (val == "true") ||
         (val == "True") ||
         (val == "TRUE"))
    {
        return true;
    }
 
    return false;
}
 
double Config::pDouble(string name) {
    string val = pString(name);
 
    return atof(val.c_str());
}
 
int Config::pInt(string name) {
    string val = pString(name);
 
    return atoi(val.c_str());
}

config.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#ifndef IncConfig
#define IncConfig
 
#include <string>
#include <map>
#include <list>
using namespace std;
 
/*
   Config
 
   Parse structured config files
 
   Config files contains lines with name-value assignements in the form "<name> = <value>".
   Trailing and leading whitespace is stripped. Parsed config entries are stored in
   a symbol map.
   
   Lines beginning with '#' are a comment and ignored.
 
   Config files may be structured (to arbitrary depth). To start a new config sub group
   (or sub section) use a line in the form of "<name> = (".
   Subsequent entries are stured in the sub group, until a line containing ")" is found.
 
   Values may reuse already defined names as a variable which gets expanded during
   the parsing process. Names for expansion are searched from the current sub group
   upwards. Finally the process environment is searched, so also environment
   variables may be used as expansion symbols in the config file.
 
   Errors and warnings are handled by emitting logging messages (see log.h/log.cpp)
   or by calling exit() for severe errors. Depending on project needs this may be replaced
   by exeptions, error return codes, ...
 */
 
class Config {
    public:
        /* Parse config file 'configFile'. If the process environment
         * is provided, environment variables can be used as expansion symbols.
         */
        Config(string configFile, char** envp = 0);
 
        ~Config();
        
        // get string config entry
        string pString(string name);
 
        /* get boolean config entry
         * A value of Yes/yes/YES/true/True/TRUE leads to true,
         * all other values leads to false.
         */
        bool pBool(string name);
 
        // get double config entry; value is parsed using atof()
        double pDouble(string name);
 
        // get int config entry; value is parsed using atoi()
        int pInt(string name);
 
        // get the symbol map (e.g. for iterating over all symbols)
        inline map<string, string>& getSymbols() {
            return symbols;
        }
 
        // get config sub group
        inline Config* group(string name) {
            return groups[name];
        }
 
        // get config sub group map (e.g. for iterating over all groups)
        inline map<string, Config*>& getGroups() {
            return groups;
        }
 
    private:
        // private constructor for sub groups
        Config(string name, string parentDebugInfo);
 
        // helper functions for parsing
        void add(string name, string value);
        void split(string in, string& left, string& right, char c);
        void trim(string& s);
        void symbolExpand(string& s);
        void symbolExpand(map<string, string>& symbols, string& s);
        void envSymbolExpand(string& s);
        
        // config group symbol map
        map<string, string> symbols;
 
        // environment symbol map
        map<string, string> envSymbols;
 
        // config sub group map
        map<string, Config*> groups;
 
        // stack of config groups for parsing (only used in top config element)
        list<Config*> groupStack;
 
        // debug info used for logging messages
        string debugInfo;
};
 
#endif

log.cpp
C++
1
2
3
#include "log.h"
 
LogLevel logLevel = LOG_INFO;

log.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef IncLog
#define IncLog
 
enum LogLevel { LOG_QUIET, LOG_ERROR, LOG_INFO, LOG_DEBUG };
 
extern LogLevel logLevel;
 
#define logError(A) ((logLevel >= LOG_ERROR)?((A),0):(0))
#define logInfo(A) ((logLevel >= LOG_INFO)?((A),0):(0))
#define logDebug(A) ((logLevel >= LOG_DEBUG)?((A),0):(0))
 
void debugBreak();
 
#endif
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.11.2010, 19:49
Ответы с готовыми решениями:

Парсинг .obj файла
при парсенге файла столкнулся с серьёзной проблемой, а именно у треугольника три нормали пример: f 309//309 387//387 312//312 f...

Парсинг IP из двоичного файла
День добрый. Как произвести парсинг IP адреса который расположен где-то в тексте двоичного файла? Были задумки, находить первое вхождение...

Парсинг XML файла и сохранение информации из файла в структуре или массиве
Доброго времени суток. Пытаюсь распарсить XML файл и вытащить оттуда все данные, а после записать их в структуру или массив. Файл парсится...

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
09.11.2010, 19:49
Помогаю со студенческими работами здесь

Парсинг файла
Здравствуйте, есть такой файл с расширением *.par(в итоге это обычный .txt) с следующим содержанием к примеру : PROV_IM7 = 0 ...

Парсинг txt файла
Добрый день! Просьба помочь в написании класс для парсинга тестового файла. Файл содержит строки с примерным содержанием: аааааа бббббб...

qt - парсинг большого файла
теперь у меня такая проблема. Имеется txt файл в unicode, в нем 120 000 строк текста вида слово=транскрипция, как бы мне находить...

Простой парсинг файла
Здравствуйте. Есть непонимание, как сделать следующую штуку. Есть файл примерно такого содержания Line Col1 Col2 Col3 ...

Почему приложение ищет ИмяСборки.exe.config вместо app.config?
Вот с какого перепугу приложение ищет ИмяСборки.exe.config вместо app.config?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
Новые блоги и статьи
Отправка уведомления на почту при изменении наименования справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере изменения наименования типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
Контроль уникальности заводского номера - вариант №2
Maks 24.03.2026
В отличие от предыдущего варианта добавлено прерывание циклов, также добавлены новые переменные для сохранения контекста ошибки перед прерыванием цикла: Процедура ПередЗаписью(Отказ, РежимЗаписи,. . .
SDL3 для Desktop (MinGW): Вывод текста со шрифтом TTF с помощью библиотеки SDL3_ttf на Си и C++
8Observer8 24.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-text-sdl3-c. zip finish-text-sdl3-cpp. zip
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
Контроль уникальности заводского номера - вариант №1
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере нетипового документа выдачи шин для спецтехники с табличной частью, разработанного в конфигурации КА2. Данные берутся из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru