Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 10.04.2012, 04:50   #1
waspyd
 
Регистрация: 06.04.2012
Сообщений: 3
По умолчанию ваше мнение?

Здравствуйте форумчане!
Начал разбираться с языком по учебнику Страуструпа
одно из упражнений:
Введите последовательность (возможно с символами-разделителями) пар (имя, значение), где имя является словом, отделяемым символами-разделителями, а значение- целым или числом с плавающей точкой. Вычислите и выведите сумму и среднее как для каждого отдельного имени, так и для всех имен

Подскажите пожалуйста как можно оптимизировать по скорости и памяти, использовал, как видно из кода, только STL. Например я использовал vector<double> для хранения всех значений, но в случае когда вводится множество целых значений память расходуется впустую. Заранее благодарен.

И как определить десятичный разделитель в системе?

собственно код:

Код:
#include <iostream>
#include <map>
#include <string>
#include <sstream>
#include <vector>

const char DELIM = ';';               //разделитель пар имя-значение
const char DECIMAL_DELIM = '.';  //десятичный разделитель

long double calc_sum(const std::vector<double> *values){
  long double sum=0;
  std::vector<double>::const_iterator vci= values->begin();
  while (vci != values->end()) {
    sum += *vci;
    vci++;
  }
  return sum;
}

double calc_avg (const std::vector<double> *values){
  return (values->size())?(double)calc_sum(values)/values->size():0;
}


//функция разбора ввода
std::pair<std::string,std::vector<double>*> 
parse_input (std::string *input){
  std::vector<double>* pvec = new std::vector<double>();
  std::pair<std::string,std::vector<double>*> elem;
  double val;
  std::istringstream is(*input);
  getline(is, elem.first, DELIM);
  is>>val;
  elem.second = pvec;
  pvec->push_back(val);
  
  return elem;
}


void show_result (std::map<std::string, std::vector<double>* > *set)
{
  std::map<std::string, std::vector<double>* >::const_iterator it = set->begin();
  long double overall_sum = 0, sum = 0;
  int value_count = 0;

  std::cout<<std::endl;

  while (it!=set->end()) {
    std::cout<<(const std::string) it->first<<":"<<std::endl;
    sum = calc_sum(it->second);
    std::cout<<"sum: "<<sum<<std::endl;
    overall_sum += sum;
    value_count++;
    std::cout<<"avg: "<<calc_avg(it->second)<<std::endl;
    it++;
  }
  std::cout<<"overall sum: "<<overall_sum<<std::endl;
  std::cout<<"overall avg: "<<overall_sum/value_count<<std::endl;
}

//проверка допустимого ввода
//string *str - строка для проверки
//bool* end - признак конца ввода
//string *vcbl - словарь допустимых символов
bool input_ok(std::string *str, bool* end, std::string *vcbl) {
  if (*str == "q" or *str == "Q"){ *end = true; return true;} // q и Q - конец ввода


  size_t delim_pos = 0;
  bool ok = ( (delim_pos = str->rfind(";") ) != std::string::npos);
  if (!ok) return ok;

  // проверка на значения double
  std::string::const_iterator cis = str->begin() + delim_pos + 1;  

  
  bool point_met = false; //был ли уже десятичный разделитель
  for (;cis != str->end() && ok; cis++) {
    if (*cis == DECIMAL_DELIM) {
      point_met ? ok=false : point_met=true;
      continue;
    }
    ok &= vcbl->find(*cis) != std::string::npos;
  }
  
  return ok;
}

int main()
{
  std::string* input = new std::string; *input = "";

  std::map<std::string, std::vector<double>* > *set= new std::map<std::string, std::vector<double>*>;
  std::map<std::string, std::vector<double>*>::const_iterator cim;

  std::string *vcbl = new std::string("0123456789"); //контейнер с допустимыми символами значений; 
                                                     //разделитель учтен в константе

  while (true){
    bool quit = 0;
    //ввод
    std::getline(std::cin, *input);
    if (input_ok(input, &quit, vcbl)){

      if (quit)
	break;
      else {
	std::pair<std::string, std::vector<double>*> p = parse_input(input);
	cim = set->find(p.first);
	if ( cim != set->end()) { 
	  cim->second->push_back(p.second->at(0)); // добавляем новое значение в вектор для существующего ключа 
	} else
	  set->insert(p);
      }

      
    } else  //bad input
      std::cout<<"input discarded: enter values as <key>"<<
	DELIM<<"<decimal value>"<<std::endl;
  }
  show_result(set);
  
  return 0;
}

Последний раз редактировалось waspyd; 10.04.2012 в 04:53.
waspyd вне форума Ответить с цитированием
Старый 10.04.2012, 10:35   #2
Rififi
Старожил
 
Регистрация: 19.08.2009
Сообщений: 2,120
По умолчанию

waspyd

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

судя по коду, совершенно ненужные выделения памяти типа
std::vector<double>* pvec = new std::vector<double>();
которые к тому же не освобождаются

и вообще, злоупотребление указателями. а кто все это освобождать будет, Пушкин? такое впечатление, что тебе шепнули на ухо что это круто, и чоткие патсаны только их и юзают, и ты бездумно налепил указателей везде где только можно.

> point_met ? ok=false : point_met=true;

обычно такая конструкция сразу указывает что код является претендентом на попадание на сайт govnokod.ru

использование велосипедов - собственный парсинг вместо штатных возможностей, игнорирование стандартных алгоритмов, вроде std::accumulate

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


как определить десятичный разделитель в системе?

#include <locale>
char sep = std::use_facet< std::numpunct<char> >(std::locale(тут локаль для которой определяем)).thousands_sep();

Последний раз редактировалось Rififi; 10.04.2012 в 10:38.
Rififi вне форума Ответить с цитированием
Старый 10.04.2012, 18:29   #3
waspyd
 
Регистрация: 06.04.2012
Сообщений: 3
По умолчанию

Цитата:
Сообщение от Rififi Посмотреть сообщение
судя по коду, совершенно ненужные выделения памяти типа
std::vector<double>* pvec = new std::vector<double>();
которые к тому же не освобождаются
Пары ключ-значение хранятся в отображении; ключом является строка, а значением указатель на vector<double>, память под который как раз здесь и выделяется. Память освобождается по завершении работы. Или лучше явно это сделать?

и сразу еще вопрос: в чем отличие:
std::vector<double>* pvec = new std::vector<double>();
от
std::vector<double>* pvec = new std::vector<double>;

Цитата:
и вообще, злоупотребление указателями. а кто все это освобождать будет, Пушкин? такое впечатление, что тебе шепнули на ухо что это круто, и чоткие патсаны только их и юзают, и ты бездумно налепил указателей везде где только можно.
вопрос: в каких случаях стоит/не стоит использовать указатели?

Цитата:

> point_met ? ok=false : point_met=true;

обычно такая конструкция сразу указывает что код является претендентом на попадание на сайт govnokod.ru
согласен
вопрос: в каких случаях эта конструкция допустима и полезна?

Цитата:

использование велосипедов - собственный парсинг вместо штатных возможностей, игнорирование стандартных алгоритмов, вроде std::accumulate
до алгоритмов пока не дошел, использовал только методы контейнеров. Займусь заполнением этого пробела в знаниях

Цитата:
также код трудно читать, пробелы и отступы и не ночевали, поэтому асилил только половину, дальше мучать себя не стал.
И на этом спасибо

Цитата:
как определить десятичный разделитель в системе?

#include <locale>
char sep = std::use_facet< std::numpunct<char> >(std::locale(тут локаль для которой определяем)).thousands_sep();
Благодарю.
waspyd вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ваше мнение MDS Софт 7 30.11.2009 17:14
Ваше мнение ArtiombI4 Помощь студентам 3 11.05.2009 16:24
ваше мнение Мамочка Свободное общение 0 08.05.2008 13:46