Вопрос к знатокам STL (VC++)
От: crazy25  
Дата: 19.02.04 08:35
Оценка:
Есть тривиальная задача: на cin подается текстовый файл, его нужно принять, отсортировать и выдать в cout.
Я давно пишу на C++, но STL никогда не использовал, поэтому сделал так, как приведено ниже.
А как это делается правильно и более оптимально с точки зрения STL ?
#include <iostream>
#include <string>
#include <vector>
#include <list>

using namespace std;

void main()
{
  list<string>vs;
  list<string>::iterator begin, end, it;
  string st;

  for (;;) {
    cin >> st;
    if (cin.eof()) break;
    vs.push_back(st);
  }

  vs.sort();

  begin = vs.begin();
  end = vs.end();
  for (it = begin; it != end; it ++)
    cout << it->c_str() << "\r\n";
}
Re: Вопрос к знатокам STL (VC++)
От: LaptevVV Россия  
Дата: 19.02.04 08:48
Оценка:
Здравствуйте, crazy25, Вы писали:

C>Есть тривиальная задача: на cin подается текстовый файл, его нужно принять, отсортировать и выдать в cout.

C>Я давно пишу на C++, но STL никогда не использовал, поэтому сделал так, как приведено ниже.
C>А как это делается правильно и более оптимально с точки зрения STL ?
C>
C>#include <iostream>
C>#include <string>
C>#include <vector>
C>#include <list>

C>using namespace std;

C>void main()
C>{
C>  list<string>vs;
C>  list<string>::iterator begin, end, it;
C>  string st;

C>  for (;;) {
C>    cin >> st;
C>    if (cin.eof()) break;
C>    vs.push_back(st);
C>  }

C>  vs.sort();

C>  begin = vs.begin();                     // объялять и присваивать отдельно - необязательно
C>  end = vs.end();                         // можно прямо в операторе цикла
C>  for (it = begin; it != end; it ++)     // пробел????  it ++
C>    cout << it->c_str() << "\r\n";
C>}
C>

1. Если в строке есть пробелы, то оператор
cin >> st;

введет только до пробела. Нужно использовать функцию getline
getline(st, cin);

2. выводить в цикле можно непосредственно string

cout << *it<< "\r\n";

3. Еще вместо list можно использовать vector и тогда можно сортировать внешней функцмией sort

Ну, еще товарищи добавят...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Вопрос к знатокам STL (VC++)
От: WolfHound  
Дата: 19.02.04 08:49
Оценка: 8 (1)
Здравствуйте, crazy25, Вы писали:

C>Есть тривиальная задача: на cin подается текстовый файл, его нужно принять, отсортировать и выдать в cout.

C>Я давно пишу на C++, но STL никогда не использовал, поэтому сделал так, как приведено ниже.
C>А как это делается правильно и более оптимально с точки зрения STL ?
Попробуй так
    std::list<std::string> strings;
    std::copy
        (std::istream_iterator<std::string>(std::cin)
        ,std::istream_iterator<std::string>()
        ,std::back_inserter(strings)
        );
    strings.sort();
    std::copy
        (strings.begin()
        ,strings.end()
        ,std::ostream_iterator<std::string>(std::cout)
        );
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Вопрос к знатокам STL (VC++)
От: Bell Россия  
Дата: 19.02.04 08:54
Оценка:
Здравствуйте, crazy25, Вы писали:


using namespace std;

int main()
{
   istream_iterator<string> b(cin), e;
   list<string> words;
   copy(b, e, back_inserter(words));

   words.sort();
   copy(words.begin(), words.end(), ostream_iterator<string>(cout, "\n"));

   return 0;
}


Только не надо забывать о том, что входная строка, состоящая из нескольких слов, разделенных пробелами, будет воспринята как набор отделных слов.
Любите книгу — источник знаний (с) М.Горький
Re[2]: Вопрос к знатокам STL (VC++)
От: Вадим Никулин Россия Здесь
Дата: 19.02.04 09:09
Оценка:
Здравствуйте, Bell, Вы писали:

B>
B>   istream_iterator<string> b(cin), e;
B>   list<string> words;
B>   copy(b, e, back_inserter(words));
B>


И все-таки, зачем list. Я так понимаю сортировка вектора эффективнее будет? (O(n*logn) по скорости, n по памяти)
Re[3]: Вопрос к знатокам STL (VC++)
От: Bell Россия  
Дата: 19.02.04 09:35
Оценка:
Здравствуйте, Вадим Никулин, Вы писали:

ВН>Здравствуйте, Bell, Вы писали:


B>>
B>>   istream_iterator<string> b(cin), e;
B>>   list<string> words;
B>>   copy(b, e, back_inserter(words));
B>>


ВН>И все-таки, зачем list. Я так понимаю сортировка вектора эффективнее будет? (O(n*logn) по скорости, n по памяти)

На самом деле все не так очевидно. При сортировке вектора с помощью std::sort будут выпонятся копирования/разрушения элементов при свапе этих элементов. В случае строк, это не не слишком-то дешево.
При сортировке списка встроенным методом sort таких копирований/разрушений элементов не будет.

ЗЫ
Сортировка вектора строк может быть существенно ускорено, если предоставить оптимизированную версию swap для строк. Но VC6 STL этого не делает.
Любите книгу — источник знаний (с) М.Горький
Re[4]: Вопрос к знатокам STL (VC++)
От: LaptevVV Россия  
Дата: 19.02.04 09:39
Оценка:
Здравствуйте, Bell, Вы писали:


B>ЗЫ

B>Сортировка вектора строк может быть существенно ускорено, если предоставить оптимизированную версию swap для строк. Но VC6 STL этого не делает.
А STLport?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[5]: Вопрос к знатокам STL (VC++)
От: Bell Россия  
Дата: 19.02.04 09:56
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Здравствуйте, Bell, Вы писали:



B>>ЗЫ

B>>Сортировка вектора строк может быть существенно ускорено, если предоставить оптимизированную версию swap для строк. Но VC6 STL этого не делает.
LVV>А STLport?

В STLport опримизированная swap для basic_string есть, но VC6 использовать ее все равно не может.
Любите книгу — источник знаний (с) М.Горький
Re[6]: Вопрос к знатокам STL (VC++)
От: LaptevVV Россия  
Дата: 19.02.04 10:09
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, LaptevVV, Вы писали:


LVV>>Здравствуйте, Bell, Вы писали:



B>>>ЗЫ

B>>>Сортировка вектора строк может быть существенно ускорено, если предоставить оптимизированную версию swap для строк. Но VC6 STL этого не делает.
LVV>>А STLport?

B>В STLport опримизированная swap для basic_string есть, но VC6 использовать ее все равно не может.

Почему? STLport же элементарно прикручивается к VC6
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Вопрос к знатокам STL (VC++)
От: Аноним  
Дата: 19.02.04 10:12
Оценка:
Здравствуйте, crazy25, Вы писали:

C>Есть тривиальная задача: на cin подается текстовый файл, его нужно принять, отсортировать и выдать в cout.

C>Я давно пишу на C++, но STL никогда не использовал, поэтому сделал так, как приведено ниже.
C>А как это делается правильно и более оптимально с точки зрения STL ?

#include <string>
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
    std::vector<std::string> vec(
        (std::istream_iterator<std::string>(std::cin)),
        (std::istream_iterator<std::string>()));
    std::sort(vec.begin(), vec.end());
    std::copy(vec.begin(), vec.end(),
        std::ostream_iterator<std::string>(std::cout, "\n"));
}

Гм... А в два statement'а кто-нибудь напишет?
Re[2]: Вопрос к знатокам STL (VC++)
От: Аноним  
Дата: 19.02.04 10:16
Оценка:
А>Гм... А в два statement'а кто-нибудь напишет?

Ага, сообразил уже...

#include <set>
#include <string>
#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
    std::multiset<std::string> set(
        (std::istream_iterator<std::string>(std::cin)),
        (std::istream_iterator<std::string>()));
    std::copy(set.begin(), set.end(),
        std::ostream_iterator<std::string> (std::cout, "\n"));
}
Re[7]: Вопрос к знатокам STL (VC++)
От: Bell Россия  
Дата: 19.02.04 11:44
Оценка: 14 (1)
Здравствуйте, LaptevVV, Вы писали:


B>>В STLport опримизированная swap для basic_string есть, но VC6 использовать ее все равно не может.

LVV>Почему?

Потому что для использования этой функции требуется, чтобы компилятор поддерживал частичное упорядочение шаблонов функций. VC6 к сожалению такой возможеостью не обладает, поэтому макрос _STLP_FUNCTION_TMPL_PARTIAL_ORDER для VC6 не определен, и супер быстрый вариант swap для std::string просто не импользуется, т.к. он как раз стоит в блоке условной компиляции с этим макросом.

LVV> STLport же элементарно прикручивается к VC6

Это не значит, что при этом используются все возможности STLport
Любите книгу — источник знаний (с) М.Горький
Re[8]: Вопрос к знатокам STL (VC++)
От: Lorenzo_LAMAS  
Дата: 19.02.04 11:51
Оценка:
Че-то я не догоняю, похоже. Проблема c partial-reordering в VC 6.0-7.0 (и ранее) есть. Потому свап для вектора хитро определен как

template<class T, class Allocator = allocator<T> >
class vector
{
////
    friend void swap(.......
////
};


Что мешает также поступить со строкой?
Of course, the code must be complete enough to compile and link.
Re[9]: Вопрос к знатокам STL (VC++)
От: Bell Россия  
Дата: 19.02.04 13:04
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Че-то я не догоняю, похоже. Проблема c partial-reordering в VC 6.0-7.0 (и ранее) есть. Потому свап для вектора хитро определен как


L_L>
L_L>template<class T, class Allocator = allocator<T> >
L_L>class vector
L_L>{
L_L>////
L_L>    friend void swap(.......
L_L>////
L_L>};
L_L>


L_L>Что мешает также поступить со строкой?


Да ИМХО ничего не мешает. Но такой функции для строк нет.
Любите книгу — источник знаний (с) М.Горький
Re[3]: :) std:: глаз мозолит
От: trop Россия  
Дата: 20.02.04 03:02
Оценка:
-
Posted via RSDN NNTP Server 1.6
-
Re: Еще один способ
От: Dmi3evS Россия http://dmi3s.blogspot.com/
Дата: 20.02.04 03:12
Оценка:
Здравствуйте, crazy25, Вы писали:

C>Есть тривиальная задача: на cin подается текстовый файл, его нужно принять, отсортировать и выдать в cout.


Читаю сейчас книгу Мэтью Г. Остина "Обобщенное программировани и STL".
В первой же главе как раз рассматривался вопрос сортировки строк.
Мне понравился подход, позволяющий получить отсортированное представление текстового файла, не трогая организацию строк.
Альтернативный взгляд на данные.
Дальше я процетирую книгу и пример из нее.

Если в вашей прогарамме используется большое количество строк, лучше совсем не применять класс string.
Зачастую оказывается более эффективным собрать все строки в одну "таблицу строк" и, когда вам нужно обратиться к конкретной строке,
указывать на строки таблицы.
<slip>
Вместо одного вектора для хранения строк нам понадобятся два: один — для таблицы строк и другой — для указателей на строки в таблице.
<skip>
Принимая во внимание способы работы большинства алгоритмов STL, удобней представить каждую строчку в виде пары итераторов
в строковой таблице: один — указывающий на первый символ строчки и другой — указвыающий на ее конец (за последний символ).


Текст программы (комментарии, оформление и пр. я старался точно скопировать):

#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;


struct strtab_cmp
{
  typedef vector<char>::iterator strtab_iterator;
  
  bool operator()( const pair<strtab_iterator, strtab_iterator>& x,
                   const pair<strtab_iterator, strtab_iterator>& y) const {
    return lexicographical_compare(x.first, x.second, y.first, y.second );
  }
};

struct strtab_print
{
  ostream& out;
  strtab_print( ostream& os ) : out(os) {}
  
  typedef vector<char>::iterator strtab_iterator;
  void operator()( const pair<strtab_iterator, strtab_iterator>& s) const {
    copy(s.first, s.second, ostream_iterator<char>(out));
  }
};


int main()
{
  vector<char> strtab;    // создание строковой таблицы
  char c;
  while(cin.get(c)) {
    strtab.push_back(c);
  }
                          // разбиение строковой тааблицы на строчки (lines)
  typedef vector<char>::iterator strtab_iterator;
  vector<pair<strtab_iterator, strtab_iterator> > lines;
  strtab_iterator start= strtab.begin();
  while (start != strtab.end()) {
    strtab_iterator next= find( start, strtab.end(), '\n' );
    if ( next != strtab.end())
      ++next;
    lines.push_back(make_pair(start,next));
    start= next;
  }
                          // сортировка вектора строчек
  sort(lines.begin(), lines.end(), strtab_cmp());
  
                          // запись строчек в стандартный вывод
  for_each(lines.begin(), lines.end(), strtab_print(cout));
}
Re[2]: Вопрос к знатокам STL (VC++)
От: crazy25  
Дата: 20.02.04 11:48
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, crazy25, Вы писали:


B>
B>using namespace std;

B>int main()
B>{
B>   istream_iterator<string> b(cin), e;
B>   list<string> words;
B>   copy(b, e, back_inserter(words));

B>   words.sort();
B>   copy(words.begin(), words.end(), ostream_iterator<string>(cout, "\n"));

B>   return 0;
B>}
B>


B>Только не надо забывать о том, что входная строка, состоящая из нескольких слов, разделенных пробелами, будет воспринята как набор отделных слов.


А если нужно именно со строками такое проделывать, без разбора на слова, такое возможно ?
Есть для этого красивые решения ?
Re[2]: Еще один способ
От: crazy25  
Дата: 20.02.04 11:55
Оценка:
Здравствуйте, Dmi3evS, Вы писали:

DS>Здравствуйте, crazy25, Вы писали:


C>>Есть тривиальная задача: на cin подается текстовый файл, его нужно принять, отсортировать и выдать в cout.


DS>Читаю сейчас книгу Мэтью Г. Остина "Обобщенное программировани и STL".

DS>В первой же главе как раз рассматривался вопрос сортировки строк.
DS>Мне понравился подход, позволяющий получить отсортированное представление текстового файла, не трогая организацию строк.
DS>Альтернативный взгляд на данные.
DS>Дальше я процетирую книгу и пример из нее.

Спасибо за интересный метод, но... он слишком трудоемкий для такой вобщем-то простой задачи.
Хотелось бы применить наиболее простое, но в то же время эффективное решение.
Re[3]: Вопрос к знатокам STL (VC++)
От: Bell Россия  
Дата: 20.02.04 13:15
Оценка:
Здравствуйте, crazy25, Вы писали:

C>А если нужно именно со строками такое проделывать, без разбора на слова, такое возможно ?

C>Есть для этого красивые решения ?

Чуть менее красивое решение:


int main(int argc, char** argv)
{
   list<string> strings;
   char buf[128] = {0};
   while(cin.getline(buf, sizeof(buf)))
      strings.push_back(buf);

   strings.sort();
   copy(strings.begin(), strings.end(), ostream_iterator<string>(cout, "\n"));

    return 0;
}
Любите книгу — источник знаний (с) М.Горький
Re[4]: Вопрос к знатокам STL (VC++)
От: WolfHound  
Дата: 20.02.04 14:33
Оценка:
Здравствуйте, Bell, Вы писали:

Тогда уж так
B>
B>int main(int argc, char** argv)
B>{
B>   list<string> strings;
B>   std::string str;
B>   while(std::getline(cin, str))
B>      strings.push_back(str);

B>   strings.sort();
B>   copy(strings.begin(), strings.end(), ostream_iterator<string>(cout, "\n"));

B>    return 0;
B>}
B>
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.