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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Подсчёт каждого символа в заданной строке. 
V
    Опции темы
ANT1
Дата 11.6.2010, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Пожалуйста помогите.
Задание:
Подсчитать сколько раз встречается каждый символ в заданной строке, представленной в виде последовательности символов.
Также: нельзя использовать циклы, а нужно использовать алгоритмы стандартной библиотеки.
Вот, что написал я. Но здесь подсчёт введённого с клавиатуры символа, а мне именно нужно подсчитать кол-во каждого символа в строке.
Код
//streampotok.h
#ifndef streampotok_h
#define streampotok_h
#include <istream>

template <class T> class StreamPotok
{
public:
    StreamPotok( std:: istream & i );
    StreamPotok( const StreamPotok & obj );//конструктор копий
    T operator ()();
private:
    std:: istream& is;//ссылка на объект класса istream
};
template <class T>
StreamPotok <T> :: StreamPotok (std :: istream& i)
: is(i)
{}
template <class T>
StreamPotok <T> :: StreamPotok ( const StreamPotok& obj)
: is(obj.is)
{}
template <class T>
T StreamPotok <T> :: operator ()()
{
    T temp;
    is >> temp;
    return temp;
};
#endif
Код
#include "streampotok.h"
#include <list>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <vector>

using namespace std;

void readdata ( list <char>& source, char& search );//ввод исходных данных
void processing ( list <char>& source, char search );//подсчёт символов
void outputresults ( int& result );// вывод количества найденных символов

void readdata ( list <char>& source, char& search )
{
    cout << "Vvedite kolichestvo elementov:";
    unsigned kolvo;
    cin >> kolvo;
    cout << "Vvedite znachenia elementov:";
    generate_n ( back_inserter (source), kolvo,StreamPotok <char>(cin));
    cout << "Vvedite simvol dla poiska:";
    cin >> search;
    return;
}
void processing ( list <char>& source, char search )
{
    count( source.begin(), source.end(), search );
    return;
}
void outputresults ( int& result )
{
    cout << "Resultat:";
    cout << result << endl;
    return;
}

int main()
{
    list <char> source;
    char search;
    readdata ( source, search );
    int result;
    processing ( source, search );
    outputresults ( result );
    return 0;
}


Добавлено @ 13:25
Скорей всего здесь понадобится ассоциативный массив.



Модератор: не забываем пользоваться кнопочкой "Код"

Это сообщение отредактировал(а) bsa - 11.6.2010, 13:45
PM MAIL   Вверх
bsa
Дата 11.6.2010, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



Цитата(ANT1 @  11.6.2010,  14:24 Найти цитируемый пост)
Скорей всего здесь понадобится ассоциативный массив
я бы решал через массив счетчиков. Где индексом массива служил бы код символа. Это самое быстро работающее решение. Но за это надо платить памятью. Можно через std::map - памяти будет кушаться меньше (для малого набора разных символов), но скорость доступа уже будет не константной, а логарифмической...

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


Новичок



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

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



А можете привести реализацию через контейнер: ассоц-й массив? А то у меня не получается. 
PM MAIL   Вверх
bsa
Дата 11.6.2010, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



Как-то так:
Код
typedef std::map<char,size_t> CharCountMap;
struct IncCounter
{
    explicit IncCounter(CharCountMap &ccm) : ccm_(ccm) {}
    void operator()(char c) const { ++ccm_[c]; }
private:
    CharCountMap &ccm_;
};

struct PrintCounter
{
    explicit PrintCounter(std::ostream &stream) : stream_(stream) {}
    void operator()(const CharCountMap::value_type &v) const {
         stream_ << '\'' << v.first << "': " << v.second << '\n';
    }
private:
    std::ostream &stream_;
};

int main()
{
   CharCountMap ccm;
   std::string text = "some text";
   std::for_each(text.begin(), text.end(), IncCounter(ccm));
   std::for_each(ccm.begin(), ccm.end(), PrintCounter(std::cout));
   return 0;
}


Это сообщение отредактировал(а) bsa - 11.6.2010, 16:37
PM   Вверх
ANT1
Дата 11.6.2010, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Что-то сложновато написано. А можно произвести доработку по моему примеру? Например оставить полностью класс шаблон и функцию ввода. Скопировать из контей-ра список в контейнер ассоц-й массив. Потом произвести обработку( изменить ф-ии: обработки и вывода ).

Добавлено через 2 минуты и 18 секунд
И если возможно, то с комментариями, был бы очень благодарен.
PM MAIL   Вверх
bsa
Дата 11.6.2010, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



СЛОЖНО?!?  smile 
куда уж проще!
IncCounter - функтор, который увеличивает счетчик соответствующий символу. И ТОЛЬКО!
PrintCounter - функтор, который выводит элемент ассоциативного контейнера в поток. И ТОЛЬКО!
содержимое main() должно быть понятно без комментариев.
PM   Вверх
ANT1
Дата 11.6.2010, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(bsa @ 11.6.2010,  16:06)
СЛОЖНО?!?  smile 
куда уж проще!
IncCounter - функтор, который увеличивает счетчик соответствующий символу. И ТОЛЬКО!
PrintCounter - функтор, который выводит элемент ассоциативного контейнера в поток. И ТОЛЬКО!
содержимое main() должно быть понятно без комментариев.

Мне ваш код непонятен вообще.
откуда тип struct? откуда секция public, если нет класса?
Можете переделать именно мой вариант, т.к. ваш я не могу понять?
PM MAIL   Вверх
bsa
Дата 11.6.2010, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



причем тут public? у меня в коде этого нет.
struct от class отличается только тем, что struct по умолчанию public, а класс - private.
Мой код от твоего отличается использованием STL. Раз не понимаешь этот код, значит ты не знаешь язык. А лезть в шаблоны не зная основ языка - глупо.
PM   Вверх
ANT1
Дата 11.6.2010, 16:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



т.е. можно написать 2 класса, вместо структур?
Может всё-таки сделаете построчные комментарии?
PM MAIL   Вверх
bsa
Дата 11.6.2010, 17:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



Код
#include <map> //для std::map
#include <string> //для std::string
#include <algorithm> //для std::for_each
#include <iostream> //для std::cout, std::ostream

typedef std::map<char,size_t> CharCountMap; //создаем новый тип ассоциативного контейнера (ключ - символ, значение - счетчик)

//функтор увеличения счетчика, соответствующего символу
struct IncCounter
{
    //конструктор функтора - передается только ссылка на контейнер
    explicit IncCounter(CharCountMap &ccm) : ccm_(ccm) {}
    //метод, который будет вызываться функцией for_each для каждого символа
    void operator()(char c) const { ++ccm_[c]; }
private:
    CharCountMap &ccm_;  //ссылка на контейнер
};

//функтор вывода элемента контейнера в поток
struct PrintCounter
{
    //конструктор функтора - передается только ссылка на поток вывода
    explicit PrintCounter(std::ostream &stream) : stream_(stream) {}
    //метод, который будет вызываться функцией for_each для каждого элемента контейнера
    void operator()(const CharCountMap::value_type &v) const {
         stream_ << '\'' << v.first << "': " << v.second << '\n'; //выводим в таком виде: '<символ>': <количество>
    }
private:
    std::ostream &stream_; //ссылка на поток вывода
};
int main()
{
   CharCountMap ccm; //создаем контейнер
   std::string text = "some text"; //создаем некую строку, символы в которой будем считать
   std::for_each(text.begin(), text.end(), IncCounter(ccm)); //заполняем контейнер
   std::for_each(ccm.begin(), ccm.end(), PrintCounter(std::cout)); //выводим содержимое контейнера на экран
   return 0; //успешное завершение программы
}


Это сообщение отредактировал(а) bsa - 11.6.2010, 17:21
PM   Вверх
ANT1
Дата 11.6.2010, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Большое спасибо. Запустил, работает. 
Только захотел строку вручную вводить, уже после пробела почему-то не считает.
Код
int main()
{
   CharCountMap ccm; //создаем контейнер
   string text;
   cout << "Vvedite stroku" << endl;
   //std::string text = "some text"; //создаем некую строку, символы в которой будем считать
   cin >> text;
   for_each(text.begin(), text.end(), IncCounter(ccm)); //заполняем контейнер
   for_each(ccm.begin(), ccm.end(), PrintCounter(std::cout)); //выводим содержимое контейнера на экран
   return 0; //успешное завершение программы
}


Можете объяснить, как осуществляется поиск?
И что это такое: explicit? 


Модератор: не забываем пользоваться кнопочкой "Код"

Это сообщение отредактировал(а) bsa - 11.6.2010, 18:20
PM MAIL   Вверх
bsa
Дата 11.6.2010, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



читаем внимательно документацию на потоковый ввод. Там черным по белому написано, что оператор >> читает только СЛОВО (т.е. то, что между пробельными символами)! Если тебе надо читать строку, используй getline, описание - в документации.
Какой поиск?!? Если ты про ассоциативный контейнер, то "поиск" зашит в него. Строчка 14 моего кода (++ccm_[c]). Читаем документацию на map
explicit - это запрет компилятору преобразования {Class x = y} в {Class x(y)}.

PM   Вверх
ANT1
Дата 11.6.2010, 21:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Уважаемый bsa вот я переделал немного ваш код, и разбил его на загол. файл и файл реализацию:
Код
//Potok.h
#ifndef Potok_h
#define Potok_h
#include <map> //для std::map
//#include <string> //для std::string
//#include <algorithm> //для std::for_each
#include <iostream> //для std::cout, std::ostream
using namespace std;
typedef map<char,size_t> CharCountMap; //создаем новый тип ассоциативного контейнера (ключ - символ, значение - счетчик)
//функтор увеличения счетчика, соответствующего символу
class IncCounter
{
public:    
    //конструктор функтора - передается только ссылка на контейнер
    IncCounter(CharCountMap &i) //!!!
        : ccm(i) {}
    //метод, который будет вызываться функцией for_each для каждого символа
    void operator()(char c) const  //!!!
    { 
        ++ccm[c]; 
    }
private:
    CharCountMap &ccm;  //ссылка на контейнер
};
//функтор вывода элемента контейнера в поток
class PrintCounter
{
public:   
    //конструктор функтора - передается только ссылка на поток вывода
    PrintCounter(ostream &os)  //!!!
        : stream(os) {}
    //метод, который будет вызываться функцией for_each для каждого элемента контейнера
    void operator()(const CharCountMap :: value_type &v) const  //!!!
    {
         stream << '\'' << v.first << "': " << v.second << '\n'; //выводим в таком виде: '<символ>': <количество>
    }
private:
    ostream &stream; //ссылка на поток вывода
};
#endif

//value_type

Код
#include "Potok.h"
#include <map> //для std::map
#include <string> //для std::string
#include <algorithm> //для std::for_each
#include <iostream> //для std::cout, std::ostream

using namespace std;

int main()
{
   CharCountMap ccm; //создаем контейнер
   string text;
   cout << "Vvedite stroku" << endl;
   //string text = "some text"; //создаем некую строку, символы в которой будем считать
   cin >> text;
   for_each(text.begin(), text.end(), IncCounter(ccm)); //заполняем контейнер !!!
   for_each(ccm.begin(), ccm.end(), PrintCounter(cout)); //выводим содержимое контейнера на экран !!!
   //int a;
   //cin >> a;
   return 0; //успешное завершение программы
}


Вы не могли бы мне объяснить пошагово работу программы в выделенных строчках? Именно глубоко, а то я её не допонимаю. Я бы был вам очень благодарен.И ещё как можно доработать функтор увеличения счётчика до класса шаблона? 


Модератор: СКОЛЬКО РАЗ МОЖНО УЖЕ ПОВТОРЯТЬ ПРО КНОПКУ "КОД"?!?

Это сообщение отредактировал(а) bsa - 11.6.2010, 22:48
PM MAIL   Вверх
bsa
Дата 11.6.2010, 22:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



Извини, я не могу тебе объяснить азы языка. У меня на это нет времени. Купи книжку.

Код
class A
{
   A(int x) : y(x) {} //это инициализация в конструкторе члена класса/структуры
private:
   int y;
};

int main()
{
   A(1); //это создание временного объекта класса A
}


про for_each написано тут: http://www.cplusplus.com/reference/algorithm/for_each/
PM   Вверх
ANT1
Дата 11.6.2010, 23:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Тогда скажите для чего нужно: value_type,typedef.
Как происходит именно подсчёт одинаковых символов?
Почему мы в качестве счётчика устанавливает size_t, а не конкретный тип данных при создании контейнера?
А first и second итераторы на символы и счётчики( мы их используем при выводе)?
Скажите пожалуйста.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

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

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


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

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


 




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


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

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