Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Алгоритм, С++ 
:(
    Опции темы
lonevagrant
Дата 19.1.2010, 13:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 2.7.2009

Репутация: нет
Всего: нет



Здравствуйте. Меня постигла проблема.

Есть текст в нем макросы типо:
Код

Привет меня зовут [NAME]. Мне [AGE] лет. Живу в стране [COUNTRY].


В тексте могут быть еще макросы разнообразн.
Суть как будет наиболее быстродейственные заменить макросы.
Только средствами стандартн. библ. С++, без регексов.

Делал так:

1. Читал в буффер файл.
2. Создал структуру, затем функция проганяла весь буффер, на просмотр макросов весли такой есть, пишим в структуру.
3. И вот тут загвоздка, проганяя весь буффер в цыкле я проверял если мы на "[", затем плюсовал счетчику цикла +1. 

Вот пример:
Код

for (i;i<=buff2ln;i++)
{
    if(buf2[i]==comper[0]) // мы на "["
    {

if(name==true)
{

      if(buf2[i+1]=='N')                           //[NAME]
      {
            my_memcpy(buf,buf2,pos,i-pos-1);
            lstrcat(buf,replword);
            pos=i-1+6;
      }
}

if(age==true)               // [AGE]
{

      if(buf2[i+1]=='A')
      {


            my_memcpy(buf,buf2,pos,i-pos-1);
            lstrcat(buf,paste.c_str());
            pos=i-1+7;

      }
}

 
Есть ряд недостатков, скорость, кажен макрос должен быть с новой заглавной буквой, либо еще придется делать конструкцию if(){}.
Подскажите более оптимальный способ. Спасибо!
PM MAIL   Вверх
zim22
Дата 19.1.2010, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 24
Всего: 69



можешь использовать алгоритм быстрого нахождения подстрок
в твоём случае подстроки - это [ТЕГИ]

довольно быстро работает алгоритм QuickSearch и он прост в реализации.

после того, как позиции тегов найдены - замени их нужными тебе значениями.



--------------------
PM MAIL   Вверх
17dufa
Дата 19.1.2010, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: 3
Всего: 5



как вариант читать постепенно и записывать в выходной поток, при встрече макросов - заменять. что-то вроде
Код

while (!inputstream.eof())
{
  char c;
  inputstream >> c;
  if (c == '[')
  {
     std::string token = readtoken(inputstream); //считать в token макрос, из inputstream считать так же ']'
     std::string replacement = getreplacement(token); //найти слово, которым надо заменить token
     outputstream << replacement;
  }
  else
  {
     outputstream << c;
  }
}

PM MAIL   Вверх
W4FhLF
Дата 19.1.2010, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 20
Всего: 121



Ещё если текст большой, то его лучше обрабатывать построчно. Т.е. разделить сначала на строки, обработать строки, а потом соединить. 


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
lonevagrant
Дата 19.1.2010, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 2.7.2009

Репутация: нет
Всего: нет



Цитата(17dufa @ 19.1.2010,  14:09)
как вариант читать постепенно и записывать в выходной поток, при встрече макросов - заменять. что-то вроде
Код

while (!inputstream.eof())
{
  char c;
  inputstream >> c;
  if (c == '[')
  {
     std::string token = readtoken(inputstream); //считать в token макрос, из inputstream считать так же ']'
     std::string replacement = getreplacement(token); //найти слово, которым надо заменить token
     outputstream << replacement;
  }
  else
  {
     outputstream << c;
  }
}

тут опять нужно будет строить конструкцию if(){}.

нужно определить какой именно макрос, если я правильно понял это код будет действительным если все макросы нужно заменить одним словом.

Код

     std::string token = readtoken(inputstream);


Не понял это строку, гугл ничего не сказал о "readtoken", до какого символа он будет читать. (обьясните пожалуйста.)

P.S - текст от 6 кб до 50кб.
PM MAIL   Вверх
zim22
Дата 19.1.2010, 16:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 24
Всего: 69



Цитата(lonevagrant @  19.1.2010,  15:14 Найти цитируемый пост)
тут опять нужно будет строить конструкцию if(){}.

ну и что? if'ы, как и regexp,  тоже нельзя применять?


--------------------
PM MAIL   Вверх
lonevagrant
Дата 19.1.2010, 16:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 2.7.2009

Репутация: нет
Всего: нет



Просто хотел узнать, чем он будет ефективн. моего способа.
P.S - так и не нашел функцию "readtoken", мб плохо искал, тыкние ссылку.
PM MAIL   Вверх
xvr
Дата 20.1.2010, 12:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Используй std::map вместо пачки if'ов

PM MAIL   Вверх
17dufa
Дата 20.1.2010, 13:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: 3
Всего: 5



lonevagrant, readtoken тебе придется написать самому smile читает слово из входного потока до встречи ']' (сам символ ']' считывается из потока, но не включается в результирующую строку)
лучше твоего варианта тем, что не надо выделять память под считывание всего файла + не надо искать макросы по тексту, так как они найдутся в процессе чтения. 
нет ты понял не правильно, функция getreplacement (которую тебе так же предстоит написать) выдает подстановку по считанному макросу. никто не запрещает ей выдавать разные подстановки для разных макросов или даже разные подстановки для одного и того макроса smile тут уж только твоей фантазией ограничено.
чем тебя смутил if я так и не понял. можно и без if
Код

while (!inputstream.eof())
{
  char c;
  inputstream >> c;
  switch (c)
  {
  case '[':
    {
       std::string token = readtoken(inputstream); //считать в token макрос, из inputstream считать так же ']'
       std::string replacement = getreplacement(token); //найти слово, которым надо заменить token
       outputstream << replacement;
    }
    break;
  default:
    {
       outputstream << c;
    }
    break;
  }
}
 smile 

Это сообщение отредактировал(а) 17dufa - 20.1.2010, 14:01
PM MAIL   Вверх
lonevagrant
Дата 20.1.2010, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 2.7.2009

Репутация: нет
Всего: нет



Цитата(17dufa @ 20.1.2010,  13:47)
Код

while (!inputstream.eof())
{
  char c;
  inputstream >> c;
  switch (c)
  {
  case '[':
    {
       std::string token = readtoken(inputstream); //считать в token макрос, из inputstream считать так же ']'
       std::string replacement = getreplacement(token); //найти слово, которым надо заменить token
       outputstream << replacement;
    }
    break;
  default:
    {
       outputstream << c;
    }
    break;
  }
}
 smile

да if-ы меня не смущают.
Просто еще нужно будет определить что за макрос там или то [NAME] или [AGE] или [COUNTRY] или еще окло 10.

Код

while (!inputstream.eof())
{
  char c;
  inputstream >> c;
  switch (c)
  {
  case '[':
    {
      if(слудуйщий сивол =='N')  // мы на макрос [NAME] 
          {
       std::string token = readtoken(inputstream); //считать в token макрос, из inputstream считать так же ']'
       std::string replacement = getreplacement(token); //найти слово, которым надо заменить token // где-то здесь мы должн. заменить макрос на лоюбое имя
       outputstream << replacement;
         }
      if(слудуйщий сивол =='A')  // мы на макрос [AGE]  
          {
       std::string token = readtoken(inputstream); //считать в token макрос, из inputstream считать так же ']'  
       std::string replacement = getreplacement(token); //найти слово, которым надо заменить token  // где-то здесь мы должн. заменить макрос на любой возраст
       outputstream << replacement;
         }
.......................................
    }
    break;
  default:
    {
       outputstream << c;
    }
    break;
  }
}
 smile

Вот этот код нужно повторять еще около 10 раз.
А запись в структуру производит. для того что бы лишний раз не делать проверку макроса если его нету в тексте.
PM MAIL   Вверх
17dufa
Дата 20.1.2010, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: 3
Всего: 5



lonevagrant, ты что-то конкретно путаешь. не надо внутри while дублировать функционал readtoken и getreplacement.
readtoken тебе вернет например "NAME".
ты этот "NAME" передашь getreplacement.
она тебе вернет например строку "lonevagrant", которую ты в выходной поток и запишешь.
PM MAIL   Вверх
lonevagrant
Дата 20.1.2010, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 2.7.2009

Репутация: нет
Всего: нет



Я не пойму как тут будет идти проверка какой макрос вернул "readtoken(inputstream)".
Мне нужно на место макросов вставлять свои данные.
Код

       std::string token = readtoken(inputstream); 
        if(token==NAME)
{
       std::string replacement = getreplacement("Маша"); 
}
  if(token==AGE)
{
 std::string replacement = getreplacement("17"); 
}
       outputstream << replacement;


Как будет идти проверка на макросы?)
PM MAIL   Вверх
17dufa
Дата 20.1.2010, 15:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: 3
Всего: 5



ты конкретно не понимаешь моего предложения. еще раз - функция getreplacement принимает макрос и возвращает его подстановку. если входное значение "NAME" она вернет "Маша", если входное значение "AGE" она вернет "17". то есть, все эти if, которые ты нарисовал внутри while на самом деле живут в функции getreplacement. Вот в том коде, что ты привел - какой смысл ты вкладываешь в функцию getreplacement? Что она у тебя делает? Хотя я бы реализовывал getreplacement не через if а как поиск по таблице, в таблице 2 столбца - макрос и значение, которым этот макрос нужно заменить, логически таблица выглядела бы так:
"NAME" | "Маша"
"AGE"   | "17"
...
PM MAIL   Вверх
lonevagrant
Дата 20.1.2010, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 2.7.2009

Репутация: нет
Всего: нет



Вроде вьехал.
Попробую реализовать. Если есть еще варианты послушаю с радостью.
Спасибо всем.
Отдельное спасибо 17dufa

Это сообщение отредактировал(а) lonevagrant - 20.1.2010, 15:50
PM MAIL   Вверх
17dufa
Дата 20.1.2010, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: 3
Всего: 5



да. именно за этим макрос передается в функцию как параметр.
PM MAIL   Вверх
lonevagrant
Дата 21.1.2010, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 2.7.2009

Репутация: нет
Всего: нет



Извиняюсь за АП темы.
Вроде все ясно, но readtoken(inputstream);- натолкни как можно реализовать эту функцию.
спс.
PM MAIL   Вверх
17dufa
Дата 21.1.2010, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: 3
Всего: 5



Код

string readtoken(inputstream)
{
  string res = "";
  do
  {
    char c;
    inputstream >> c;
    if (c != ']')
    {
      res..push_back(c);
    }
  }
  while (c != ']' && !inputstream.eof());
  return res;
}

вроде так
PM MAIL   Вверх
lonevagrant
Дата 21.1.2010, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 2.7.2009

Репутация: нет
Всего: нет



Если я правильно понял.
Мы начинаем читать с начала файла, а не с того места где мы нашли '['.
И еще ожно этот "istream" использует буфферезацию файла, или нет.

Это сообщение отредактировал(а) lonevagrant - 21.1.2010, 13:56
PM MAIL   Вверх
17dufa
Дата 21.1.2010, 14:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: 3
Всего: 5



lonevagrant, слова читаю, а вот смысла понять не могу. перефразируешь?
PM MAIL   Вверх
lonevagrant
Дата 21.1.2010, 21:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 2.7.2009

Репутация: нет
Всего: нет



Код

while (!inputstream.eof())
{
  char c;
  inputstream >> c;
  switch (c)
  {
  case '[':
    {
       std::string token = readtoken(inputstream); //считать в token макрос, из inputstream считать так же ']'
       std::string replacement = getreplacement(token); //найти слово, которым надо заменить token
       outputstream << replacement;
    }
    break;
  default:
    {
       outputstream << c;
    }
    break;
  }
}


В это куске кода мы ище '[', затем когда мы нашли '[' мы вызываем функцию " readtoken(inputstream);"

Код

string readtoken(inputstream)
{
  string res = "";
  do
  {
    char c;
    inputstream >> c;
    if (c != ']')
    {
      res..push_back(c);
    }
  }
  while (c != ']' && !inputstream.eof());
  return res;
}


Тут вопрос, этот кусок функции начинает читать откуда, с начала файла, или же с "[".

PM MAIL   Вверх
xvr
Дата 22.1.2010, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата

Тут вопрос, этот кусок функции начинает читать откуда, с начала файла, или же с "[".
С текущей позиции стрима, т.е. сразу после '['

PM MAIL   Вверх
17dufa
Дата 22.1.2010, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: 3
Всего: 5



xvr +1
PM MAIL   Вверх
lonevagrant
Дата 25.1.2010, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 2.7.2009

Репутация: нет
Всего: нет



Соррь за АП.
Все вродь понятно, да и получается все. 
Только вот загвозка в том что все пробелы в тексте затираются, пробел в потоке означает его окончан., но как можно это предовратить.
Просто текст получается нечитабелен.
Спасибо!
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1503 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.