Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Razzeeyy
30 / 7 / 2
Регистрация: 01.03.2011
Сообщений: 95
#1

"вставка" с "заменой" текста в файле. - C++

01.10.2011, 18:59. Просмотров 967. Ответов 6
Метки нет (Все метки)

Здравствуйте.
Решил для обретения бесценного опыта написать свой простенький парсер конфигов.
Вообщем читает вполне себе читает конфиг.. пишет его... но вот столкнулся с вопросом, который вновинку и ума не приложу как это реализовать.

Надо мне сделать так, что если в конфиг пишутся две одинаковые строки, то одна другую "затирает".
Как это реализовать? емнип в классе fstream нету что то вроде find() чтобы найти вхождение строки в файл.


P.S. для большего пояснения, у меня конфиг по структуре выглядит примерно так

Код
section "default"
value1 "1"
value2 "anything else"
more "something"
section может быть сколько угодно много, есть функция которой определяем с какой секцией мы решили работать. эта самая функция построчно анализирует файл и если найдено вхождение с "section \"+name+"\"" то парсит имя параметра и его значения в map <string, string> section_buf.
вот думаю как же делать так чтобы при записи секции обратно в файл она корректно заменяла другую...
пробегала мысль складывать всё содержимое файла в какой нибудь string buffer и уже по нему потом искать и с ним работать. а при завершении работы просто перезаписывать файл содержимым string buffer.
но мне не кажется что это будет оптимально, думаю в языке есть какие-то "стандартные" средства для решения моей проблеммы.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.10.2011, 18:59
Здравствуйте! Я подобрал для вас темы с ответами на вопрос "вставка" с "заменой" текста в файле. (C++):

В зависимости от времени года "весна", "лето", "осень", "зима" определить погоду "тепло", "жарко", "холодно", "очень холодно" - C++
В зависимости от времени года &quot;весна&quot;, &quot;лето&quot;, &quot;осень&quot;, &quot;зима&quot; определить погоду &quot;тепло&quot;, &quot;жарко&quot;, &quot;холодно&quot;, &quot;очень холодно&quot;. Я так...

Дан текст, хранящийся в текстовом файле f, каждый символ которого может быть малой буквой, цифрой или одним из знаков "+", "-", "*". - C++
Дан текст, хранящийся в текстовом файле f, каждый символ которого может быть малой буквой, цифрой или одним из знаков &quot;+&quot;, &quot;-&quot;, &quot;*&quot;. Групой...

Реализовать классы "Воин", "Пехотинец", "Винтовка", "Матрос", "Кортик" (наследование) - C++
Разработать программу с использованием наследования классов, реализующую классы: − воин; − пехотинец(винтовка); − матрос(кортик). ...

Переписать в файл О все элементы файла К с заменой в них символа "0" на символ "1" и наоборот - C++
Помогите. Нужно создать файл К,элементы которого являются символами. Переписать в файл О все элементы файла К с заменой в них символа 0 на...

Переписать в файл О все элементы файла К с заменой в них символа "0" на символ "1" и наоборот - C++
Помогите создать файл К,элементы которого являются символьными. Переписать в файл О все элементы файла К с заменой в нх символа 0 на символ...

Создать класс "Книга" с полями "название книги", "количество страниц", "год издания" - C++
Создать класс Книга поля: название книги,количество страниц,год издания методы: вычислить сколько лет книге и количество дней прошедших...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
-=ЮрА=-
Заблокирован
Автор FAQ
01.10.2011, 19:10 #2
Цитата Сообщение от Razzeeyy Посмотреть сообщение
fstream нету что то вроде find()
- зато есть tellg(возврат позиции курсора в файл) и seekg перемещение курсора в заданную позицию. Установив курсор на нудное место в файле, осуществите в него вывод и посмотрите что будет...
0
Razzeeyy
30 / 7 / 2
Регистрация: 01.03.2011
Сообщений: 95
01.10.2011, 19:37  [ТС] #3
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
зато есть tellg(возврат позиции курсора в файл
и как это делать? по символьно читать файл и анализировать толи это что нам надо, а потом возвращать обратно на n считанных символов курсор? да не, это ужас.
К тому же емнип, если записываемый сектор будет больше того который был, то он еще и затрёт несколько символов другого (информация не переносится относительно)
0
xAtom
915 / 740 / 60
Регистрация: 09.12.2010
Сообщений: 1,346
Записей в блоге: 1
01.10.2011, 20:10 #4
Цитата Сообщение от Razzeeyy Посмотреть сообщение
мысль складывать всё содержимое файла в какой нибудь string buffer и уже по нему потом искать и с ним работать. а при завершении работы просто перезаписывать файл содержимым string buffer
Надо именно так делать, если конфиг-файл весил бы до 100MB то можно было просто работать с файлом, сам по себе файл не может сжиматься или расширяться только затирать старое значение пробелами или нулями любым символом, в итоге будут создаваться множество пустых фрагментов ну как в БД боряться с фрагментацией. Одно дело БД другое килобайтный конфиг-файл, вот пример набросал в начале весь конфигурационный файл считывается в карту map, уникальными ассоциативными ключами далее пример сохранения карты в конфиг с перезаписью всего файла. как и должно быть, не надо постоянно головку диска гонять если озу-память за 1GB переваливает, да и скорость работы диска на много медленнее озу.
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
#include <fstream>
#include <map>
#include <iostream>
#include <string>
using namespace std;
 
map<string, string> config;
 
int  main(void) {
 
    fstream  fp("D:\\config.txt", fstream::in); 
    if(! fp.is_open())
         exit(1);
 
    string line;
    char key[64], value[255];
    while(! fp.eof()) {
          getline(fp, line);
          if(sscanf(line.c_str(), "%[^ ]%*[^\"]\"%[^\"]\"", key, value) >= 2) 
                 config[key] = value;
     }
     fp.clear();
     fp.close();
 
      // вот так получать доступ по имени ключа
     cout << '\t' << config["section"].c_str() << endl;
     cout << '\t' << config["value1"].c_str()  << endl;
 
     // показать пары ключ = значение
     map<string, string>::iterator iter = config.begin();
     while(iter != config.end()) {
             cout << iter->first.c_str() << '\t' << iter->second.c_str() << endl;
             *iter++;
     }
 
     // записываем новые значения
    config["section"] = "MySQL and DB2";
    config["more"]    = "sub systems";
    config["value1"]  = "200";
    config["value2"]  = "7";
 
    // файл будет перезаписан
    fp.open("D:\\config.txt", fstream::out | fstream::trunc);
    for(iter = config.begin(); iter != config.end(); *iter++) {
          line = iter->first + " \"" + iter->second + "\"\n";
          fp.write(line.c_str(), line.length());
    }
    fp.flush();
    fp.close();
    config.clear();
    cin.get();
    return 0;
}
0
Razzeeyy
30 / 7 / 2
Регистрация: 01.03.2011
Сообщений: 95
01.10.2011, 22:48  [ТС] #5
xAtom, спасибо. но у меня там section отмечает имя секции поэтому у меня наверно будет общая карта map<string, map> и под карты (map<string, string>) с каждой секцией.
Цитата Сообщение от xAtom Посмотреть сообщение
"%[^ ]%*[^\"]\"%[^\"]\""
я вот только эту штуку непонял, это RegEx надо полагать?

а то я у себя вообще ужасным кодом вычленяю параметр и значение
0
-=ЮрА=-
Заблокирован
Автор FAQ
02.10.2011, 14:04 #6
Razzeeyy, напишите конкретно что у вас в файле, что вам заменить и какой длинній заменяющий блок, ві задали общий вопрос, я вам дал общий ответ...
0
accept
4822 / 3243 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
03.10.2011, 07:25 #7
Цитата Сообщение от Razzeeyy
это RegEx надо полагать?
это не regexp, но это устроено проще

C89(draft) 4.9.6.2 fscanf
[ Matches a nonempty sequence of characters from a set of expected
characters (the scanset ). The corresponding argument shall be a
pointer to the initial character of an array large enough to accept
the sequence and a terminating null character, which will be added
automatically. The conversion specifier includes all subsequent
characters in the format string, up to and including the matching
right bracket ( ] ). The characters between the brackets (the
scanlist ) comprise the scanset, unless the character after the left
bracket is a circumflex ( ^ ), in which case the scanset contains all
characters that do not appear in the scanlist between the circumflex
and the right bracket. As a special case, if the conversion specifier
begins with [] or [^] , the right bracket character is in the scanlist
and the next right bracket character is the matching right bracket
that ends the specification. If a - character is in the scanlist and
is not the first, nor the second where the first character is a ^ ,
nor the last character, the behavior is implementation-defined.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.10.2011, 07:25
Привет! Вот еще темы с ответами:

Создать класс "Вентилятор" содержащий в себе классы: "Двигатель", "Контроллер", "Пульт управления" - C++
Помогите с кодом написания задачи, не понимаю как написать классы в классе. Нужно создать класс &quot;вентилятор&quot; содержащий в себе классы:...

Создать абстрактный класс "Издание" и производные классы "Книга", "Статья", "Электронный ресурс" - C++
1. Создать абстрактный класс Издание с методами, позволяющими вывести на экран информацию об издании, а также определить является ли данное...

Определить тип данных "Запись", имеющий поля "Фамилия", "Пол", "Зарплата" - C++
определить тип данных запись имеющий поля фамилия пол зарплата. определить массив из 10 записей. в программе ввести в массив данные и...

Структура «Преподаватель» с полями "ФИО", "стаж", "категория", "нагрузка" - C++
Функция - расчёт зарплаты по нагрузке и оплате часа для определенной категории. Категория Оплата часа Вторая 150 Первая 200 ...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
03.10.2011, 07:25
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru