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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [C++] Работа с символьными данными, работа с символьными данными 
:(
    Опции темы
LerokSA
Дата 14.6.2010, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



помогите, пожалуйста:

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

можете подсказать, в каком диапазоне лежат знаки пунктуации?? smile 
PM MAIL   Вверх
azesmcar
Дата 14.6.2010, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


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

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



Код

#include <iostream>
#include <fstream>
#include <vector>
#include <functional>
#include <algorithm>
#include <string>

struct is_punct_sign : std::unary_function<char, bool>
{
    bool operator()(char symbol)
    {
        return (symbol == ',' || symbol == ';');
    }
};

struct compare : std::binary_function<std::string, std::string, bool>
{
    bool operator()(const std::string& l, const std::string& r)
    {
        return
            std::count_if(l.begin(), l.end(), is_punct_sign()) <
            std::count_if(r.begin(), r.end(), is_punct_sign());
    }
};

int main()
{
    std::ifstream stream("D:\\lines.txt");
    if (!stream)
    {
        std::cerr << "Cannot open file" << std::endl;
        return EXIT_FAILURE;
    }
    std::vector<std::string> sentences;
    std::string temp;
    while (std::getline(stream, temp, '.'))
        sentences.push_back(temp);

    std::cout << *std::max_element(sentences.begin(), sentences.end(), compare()) << std::endl;
}


Добавлено через 50 секунд
LerokSA

Дополни список знаков пунктуации.
PM   Вверх
ИванМ
Дата 14.6.2010, 20:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



azesmcar, красиво, но не правильно.
1. выводится только одно предложение, если даже предложений с одинаковым количеством знаков больше одного
2. происходит постоянное перераспределение памяти, из-за того, что используется vector.
3. весь файл загоняется в оперативную память, что неприемлемо для больших файлов

мой вариант:
Код

#include <iostream>
#include <fstream>
#include <list>
#include <functional>
#include <algorithm>
#include <string>
#include <iterator>

struct is_punct_sign : std::unary_function<char, bool>
{
    bool operator()(char symbol)
    {
        return (symbol == ',' || symbol == ';');
    }
};

int main()
{
    std::ifstream stream("D:\\lines.txt");
    if (!stream)
    {
        std::cerr << "Cannot open file" << std::endl;
        return EXIT_FAILURE;
    }
    std::list<std::string> sentences;
    size_t max_p=0;
    std::string temp;
    while (std::getline(stream, temp, '.'))
    {
        size_t cnt=std::count_if(temp.begin(), temp.end(), is_punct_sign());
        if(cnt==max_p)
        {
            sentences.push_back(temp);            
        }
        else if(cnt>max_p)
        {
            max_p=cnt;
            sentences.clear();
            sentences.push_back(temp);            
        }
    }
    std::copy(sentences.begin(), sentences.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
    system("pause");
}


Это сообщение отредактировал(а) ИванМ - 14.6.2010, 20:52
PM MAIL   Вверх
azesmcar
Дата 14.6.2010, 21:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


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

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



Цитата(ИванМ @  14.6.2010,  20:48 Найти цитируемый пост)
1. выводится только одно предложение, если даже предложений с одинаковым количеством знаков больше одного

а автору предложения надо

Цитата(LerokSA @  14.6.2010,  16:53 Найти цитируемый пост)
выводит на экран предложения

только что заметил, всего один символ, а как меняется смысл smile 

Цитата(ИванМ @  14.6.2010,  20:48 Найти цитируемый пост)
2. происходит постоянное перераспределение памяти, из-за того, что используется vector.

vector можно заменить на list или раз так волнует оптимизация заранее выделить память под 100-200 объектов, чтобы не было перераспределения, но это ведь домашнее задание, а не олимпиада по программированию. Скажем так, для маленьких файлов я бы о всех этих пунктах вообще не задумывался, чем проще и читабельнее код - тем лучше. А про большие файлы ничего не говорилось.

В вашем варианте есть ошибка в логике выполнения.

Цитата(ИванМ @  14.6.2010,  20:48 Найти цитируемый пост)
 size_t max_p=0;
    std::string temp;
    while (std::getline(stream, temp, '.'))
    {
        size_t cnt=std::count_if(temp.begin(), temp.end(), is_punct_sign());
        if(cnt==max_p)
        {
            sentences.push_back(temp);            

вот тут

допустим при первом же входе в цикл
cnt = 0, max_p = 0, ни одного знака пунктуации в предложении нет, но оно все равно заноситься в список.

Код

#include <iostream>
#include <fstream>
#include <map>
#include <list>
#include <functional>
#include <algorithm>
#include <string>
#include <iterator>

struct is_punct_sign : std::unary_function<char, bool>
{
    bool operator()(char symbol)
    {
        return (symbol == ',' || symbol == ';');
    }
};

typedef std::list<std::string> StringList;
typedef std::map<int, StringList> SentenceMap;

int main()
{
    std::ifstream stream("D:\\list.txt");
    if (!stream)
    {
        std::cerr << "Cannot open file" << std::endl;
        return EXIT_FAILURE;
    }
    SentenceMap sentences;
    std::string temp;
    while (std::getline(stream, temp, '.'))
        sentences.insert(SentenceMap::value_type(
            std::count_if(temp.begin(), temp.end(), is_punct_sign()), StringList())).first->second.push_back(temp);
    
    const StringList& r = sentences.rbegin()->second;
    std::copy(r.begin(), r.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}


можно например как-то так...

Это сообщение отредактировал(а) azesmcar - 14.6.2010, 21:19
PM   Вверх
Dov
Дата 14.6.2010, 21:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(azesmcar @  14.6.2010,  17:18 Найти цитируемый пост)
Код

return (symbol == ',' || symbol == ';');

Цитата(azesmcar @  14.6.2010,  17:18 Найти цитируемый пост)
Дополни список знаков пунктуации.


Код
return (ispunct(symbol));




--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
ИванМ
Дата 14.6.2010, 22:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(azesmcar @  14.6.2010,  21:03 Найти цитируемый пост)
допустим при первом же входе в цикл
cnt = 0, max_p = 0, ни одного знака пунктуации в предложении нет, но оно все равно заноситься в список.

По-моему, все логично. Что если во всех предложениях нет ни одного знака пунктуации?

На счет вашего нового варианта - красота безукоризненна, но вот производительность...

Ладно, плюнем на память и производительность)) Еще как вариант:

Код

#include <iostream>
#include <fstream>
#include <map>
#include <list>
#include <functional>
#include <algorithm>
#include <string>
#include <iterator>

struct out : std::unary_function< std::pair<int, std::string>, void >
{
    void operator()(const std::pair<int, std::string>& pair)
    {
        std::cout<<pair.second<<std::endl;
    }
};

typedef std::multimap<int, std::string> SentenceMap;
int main()
{
    std::ifstream stream("D:\\lines.txt");
    if (!stream)
    {
        std::cerr << "Cannot open file" << std::endl;
        return EXIT_FAILURE;
    }
    SentenceMap sentences;
    std::string temp;
    while (std::getline(stream, temp, '.'))
        sentences.insert(SentenceMap::value_type(
            std::count_if(temp.begin(), temp.end(), ispunct), temp));
    
    std::for_each(sentences.lower_bound(sentences.rbegin()->first), sentences.upper_bound(sentences.rbegin()->first), out());
    system("pause");
}



Это сообщение отредактировал(а) ИванМ - 14.6.2010, 23:03
PM MAIL   Вверх
ИванМ
Дата 14.6.2010, 23:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Вот еще неплохой вариант. С памятью лучше работает и проще.
Код

#include <iostream>
#include <fstream>
#include <set>
#include <list>
#include <functional>
#include <algorithm>
#include <string>
#include <iterator>

struct compare : std::binary_function<std::string, std::string, bool>
{
    bool operator()(const std::string& l, const std::string& r)
    {
        return
            std::count_if(l.begin(), l.end(), ispunct) <
            std::count_if(r.begin(), r.end(), ispunct);
    }
};

int main()
{
    std::ifstream stream("D:\\lines.txt");
    if (!stream)
    {
        std::cerr << "Cannot open file" << std::endl;
        return EXIT_FAILURE;
    }
    std::string temp;
    std::multiset<std::string, compare> sentences; 
    while (std::getline(stream, temp, '.'))
    {        
        sentences.insert(temp);        
        sentences.erase(sentences.begin(), std::max_element(sentences.begin(), sentences.end(), compare())); 
    }
    std::copy(sentences.begin(), sentences.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

    system("pause");
}


Это сообщение отредактировал(а) ИванМ - 15.6.2010, 00:17
PM MAIL   Вверх
LerokSA
Дата 15.6.2010, 05:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



всё это, конечно, здорово)) спасибо, но половину кода я не поняла ^^ 
можете пояснить,
Цитата

sentences.insert(temp);        
        sentences.erase(sentences.begin(), std::max_element(sentences.begin(), sentences.end(), compare())); 

и
Цитата

 std::copy(sentences.begin(), sentences.end(), std::ostream_iterator<std::string>(std::cout, "\n"));


я на Си еще не работала особо с конструкторами и векторами.. мне просто еще блок-схему по коду писать, а я понятия не имею КАК с векторами это делать О_0  поэтому можете комментарии оставить или упростить код хоть как-то? ну пожаааааааааааалуйста smile 
PM MAIL   Вверх
azesmcar
Дата 15.6.2010, 05:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


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

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



Dov

Надо же, не знал про такую функцию smile 

Цитата(ИванМ @  14.6.2010,  22:07 Найти цитируемый пост)
По-моему, все логично. Что если во всех предложениях нет ни одного знака пунктуации?

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

Цитата(ИванМ @  14.6.2010,  23:55 Найти цитируемый пост)
Вот еще неплохой вариант. С памятью лучше работает и проще.

а вы не работу с памятью сравнивайте а сложность алгоритмов.

Цитата(LerokSA @  15.6.2010,  05:18 Найти цитируемый пост)
я на Си еще не работала особо с конструкторами и векторами

я кстати тоже, в Си векторов нет smile это C++.

комментарии позже добавлю.
PM   Вверх
azesmcar
Дата 15.6.2010, 08:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


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

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



Код

#include <iostream>
#include <fstream>
#include <map>
#include <list>
#include <algorithm>
#include <string>
#include <iterator>
#include <cctype>

// определяем тип для хранения списка строк
typedef std::list<std::string> StringList;

// определяем тип для хранения ассоциативного массива (карты) "количество символов пунктуации -> список предложений"
typedef std::map<int, StringList> SentenceMap;

int main()
{
    // пытаемся открыть файл
    std::ifstream stream("D:\\lines.txt");

    // если не смогли открыть файл
    if (!stream)
    {
        // вывести ошибку
        std::cerr << "Cannot open file" << std::endl;

        // выйти из программы
        return EXIT_FAILURE;
    }

    // создаем обьект ассоциативного массива
    SentenceMap sentences;
    
    // создаем переменную, для чтения предложений из файла
    std::string temp;

    // читаем из файла функцией getline до того, как встретим символ . (конец предложения)
    // повторяем циклом до конца файла
    while (std::getline(stream, temp, '.'))
        // для каждого предложения считаем количество символов пунктуации функцией count_if
        // и создаем соответственную ассоциацию методом insert
        // если ассоциация уже сущетвует - метод insert возвращает iterator на существующий элемент
        // вносим предложение в список методом push_back
        sentences.insert(SentenceMap::value_type(
            std::count_if(temp.begin(), temp.end(), ispunct), StringList())).first->second.push_back(temp);

    // если полученный ассоциативный массив не пуст
    if (!sentences.empty())
    {
        // берем последний элемент (rbegin - reverse begin)
        // поскольку ассоциативные массивы в C++ храняться в отсортированном виде
        // последний элемент будет иметь наивысшее значение числа повторений символов пунктуации
        const StringList& r = sentences.rbegin()->second;

        // выводим список предложений для наивысшего числа повторений символов пунктуации
        // методом копирования в std::cout и используя \n как разделитель
        std::copy(r.begin(), r.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
    }
}

так пойдет?
PM   Вверх
ИванМ
Дата 15.6.2010, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(azesmcar @  15.6.2010,  05:31 Найти цитируемый пост)
скажем так - в первом предложении нету знаков пунктуации, а во втором их 12. Все равно первое будет занесено в список.

Да, но не забывайте, что в том моем алгоритме используется clear после того, как найдено новое максимальное значение.
Цитата(azesmcar @  15.6.2010,  05:31 Найти цитируемый пост)
а вы не работу с памятью сравнивайте а сложность алгоритмов

А на память плюнуть?
PM MAIL   Вверх
azesmcar
Дата 15.6.2010, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


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

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



Цитата(ИванМ @  15.6.2010,  13:31 Найти цитируемый пост)
А на память плюнуть? 

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

Цитата(ИванМ @  15.6.2010,  13:31 Найти цитируемый пост)
Да, но не забывайте, что в том моем алгоритме используется clear после того, как найдено новое максимальное значение.

ах да, только заметил.

Это сообщение отредактировал(а) azesmcar - 15.6.2010, 13:54
PM   Вверх
ИванМ
Дата 15.6.2010, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(azesmcar @  15.6.2010,  13:50 Найти цитируемый пост)
о таких вещах надо думать тогда, когда это действительно важно, а не просто так, оптимизация ради оптимизации не имеет никакого смысла

Но, согласитесь, писать изначально универсальный код с точки зрения производительности и экономии памяти хорошее дело.

Цитата(azesmcar @  15.6.2010,  05:31 Найти цитируемый пост)
чтобы найти все максимальное, сперва надо найти максимальное значение, а потом взять все равные ему. Ну или хранить все предложения для каждого числа знаков пунктуации, как сделал я.

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

Но, с точки зрения краткости кода, соглашусь, что ваш код лучше. 
Хотя, если подумать, ни ваш ни мой вариант под текущую задачу (программа для студента) не подходит, потому что они не изучали STL и преподаватель вряд ли примет.
Но наше дело написать правильный код, а все остальное уже дело не наше  smile 

Это сообщение отредактировал(а) ИванМ - 15.6.2010, 15:01
PM MAIL   Вверх
azesmcar
Дата 15.6.2010, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


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

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



Цитата(ИванМ @  15.6.2010,  15:00 Найти цитируемый пост)
Но, согласитесь, писать изначально универсальный код с точки зрения производительности и экономии памяти хорошее дело.

естественно, если это не влияает на качество и читабельность кода smile 

Цитата(ИванМ @  15.6.2010,  15:00 Найти цитируемый пост)
Но наше дело написать правильный код, а все остальное уже дело не наше  smile 

это тоже не наше дело если быть откровенным, но когда не лень мы закрываем на это глаза в разделе "Центр помощи".

Это сообщение отредактировал(а) azesmcar - 15.6.2010, 15:12
PM   Вверх
LerokSA
Дата 16.6.2010, 01:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата

я кстати тоже, в Си векторов нет  это C++.


я в курсе вообще-то
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

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

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


 




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


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

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