LINUX.ORG.RU

подсчёт букв


0

0

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

anonymous

хм.. очень надо, млин..
Делаешь массив на 255 элементов, потом
getc(), и увеличиваешь значение элемента
с индексом, который возвратила getc
(getc вроде возвращает int), на еденичку.
в итоге в один проход мы получаем 
колличество определённых букв в этом массиве.
вроде так. Пробуй.

pisun
()

Ага, пасиб, конечно, но как это на С будет?..
Если не в лом кому-нидь, то пожалуйста
напишите сюда :)

anonymous
()
Ответ на: комментарий от pisun

> Делаешь массив на 255 элементов

Не всё так просто :) В нынешнее время в Linux обычно символ!=байт. Надо конвертить в Unicode, и уже на его основе считать. Чтобы не отжирать сразу много памяти под массив - использовать hash table.

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от watashiwa_daredeska

подозреваю что эту программу будут сдавать на компьютере с дос )))

anonymous
()
Ответ на: комментарий от anonymous

>Ага, пасиб, конечно, но как это на С будет?..
>Если не в лом кому-нидь, то пожалуйста
>напишите сюда :)

C++ устроит?

#include <iostream>
#include <iterator> 
#include <ext/numeric> 
#include <complex> 
#include <vector> 

using namespace std;

typedef std::complex<unsigned int> Pair;
typedef vector< Pair > PVector;

PVector vG(255, 0);

inline void add(const char& valueL )
{
  vG[valueL]+=Pair(0,valueL);
}

struct bigger
{
  inline bool operator() (const Pair& oneA, const Pair& two) const
  {
    return oneA.imag() > two.imag();
  }
};

int main (int argc, char * argv[])
{
  const unsigned char amountOfCharG= 10;
  __gnu_cxx::iota(vG.begin(), vG.end(), 0);
    
  for_each (istream_iterator<char>(cin), istream_iterator<char>(), add);
  partial_sort(vG.begin(), vG.begin()+ amountOfCharG, vG.end(), bigger());
    
  copy (vG.begin(), vG.begin()+ amountOfCharG, ostream_iterator<Pair>(cout,"\n")); cout<<endl; 
  return 0;
};

anonymous
()
Ответ на: комментарий от watashiwa_daredeska

>Не всё так просто :) В нынешнее время в Linux обычно символ!=байт.
а у нас пусть будет идеальная ситуация).

pisun
()
Ответ на: комментарий от watashiwa_daredeska

> Не всё так просто :) В нынешнее время в Linux обычно символ!=байт.
> Надо конвертить в Unicode, и уже на его основе считать. Чтобы не
> отжирать сразу много памяти под массив - использовать hash table.

Во-первых, тогда уж надо и читать не char'ы, а именно символы, согласно
локали (кстати, как?). Во-вторых, даже если это будет юникод или еще
какая мультибайтная кодировка, вряд ли там будет больше нескольких
десятков тысяч символов, а при таком раскладе массив все равно быстрей.
Имхо имеет смысл делать изначально массив под однобайтную кодировку
(т.е. CHAR_MAX), в случае его заполнения fallback на массив INT16_MAX,
а потом уже хэш-таблица.

Или можно просто "подкорректировать" условие задачи, заменив символы на
байты =)

int19h ★★★★
()
Ответ на: комментарий от anonymous

> typedef std::complex<unsigned int> Pair;
> typedef vector< Pair > PVector;

Кошмар... а что, std::pair уже отменили?

> struct bigger
> {
> inline bool operator() (const Pair& oneA, const Pair& two) const
> {
> return oneA.imag() > two.imag();
> }
> };

std::greater

> int main (int argc, char * argv[])
> {
> const unsigned char amountOfCharG= 10;
> __gnu_cxx::iota(vG.begin(), vG.end(), 0);

Это уже не C++ - нестандарт, батенька...

int19h ★★★★
()
Ответ на: комментарий от int19h

>Кошмар... а что, std::pair уже отменили?
Нет конечно. Просто для него придется определить 
operator<< для вывода с помощью copy:
copy (vG.begin(), vG.begin()+ amountOfCharG, ostream_iterator<Pair>(cout,"\n")); cout<<endl; 
Или ручками писать цикл.
а для complex все уже определено.

>> __gnu_cxx::iota(vG.begin(), vG.end(), 0);
>Это уже не C++ - нестандарт, батенька...
Да. Это было в SGI варианте STL, но в стандарт не попало.
При желании можно естественно заменить на цикл.

>std::greater
стандартным образом ни комплексные числа ни пары сравнивать нельзя.
так что получим что то типа:
/usr/include/c++/3.3/bits/stl_function.h:190: error: no match for 'operator>' 
   in '__x > __y'

В общем програмка написана, чтобы STL в моей памяти освежить.

anonymous
()
Ответ на: комментарий от anonymous

> operator<< для вывода с помощью copy:
> copy (vG.begin(), vG.begin()+ amountOfCharG, ostream_iterator<Pair>
> (cout,"\n")); cout<<endl; Или ручками писать цикл.
> а для complex все уже определено.

И все равно, нехорошо как-то... имхо лучше уж тогда свою структуру
нарисовать.

> >std::greater
> стандартным образом ни комплексные числа ни пары сравнивать нельзя.
> так что получим что то типа:
> /usr/include/c++/3.3/bits/stl_function.h:190: error: no match for
> 'operator>' in '__x > __y'

Вообще-то, для std::pair определен operator<

int19h ★★★★
()
Ответ на: комментарий от int19h

> тогда уж надо и читать не char'ы, а именно символы, согласно локали (кстати, как?).

Если чтоб эффективно - кастомные функции под каждую локаль. Самих-то функций, на самом деле, будет немного - просто данные разные.

> даже если это будет юникод или еще какая мультибайтная кодировка, вряд ли там будет больше нескольких десятков тысяч символов

Кхм. Я бы предположил, что даже на китайском вряд ли средненький текст до 10 тыс. различных иероглифов дотянет.

> при таком раскладе массив все равно быстрей.

Массив всегда быстрей :) Фишка в том, что есть, допустим 1000 различных символов с кодами разбросанными по всему диапазону Unicode. Вопрос на засыпку - сколько памяти надо под такой массив и сколько надо памяти на hash под 1000 символов.

> имеет смысл делать изначально массив под однобайтную кодировку

Под KOI8? Или Latin-1?

> в случае его заполнения

А в случае попадания символа не из этой кодировки?

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от watashiwa_daredeska

> > тогда уж надо и читать не char'ы, а именно символы, согласнолокали
> > (кстати, как?).
>
> Если чтоб эффективно - кастомные функции под каждую локаль. Самих-то
> функций, на самом деле, будет немного - просто данные разные.

Это как? В смысле, а если попадется неизвестная локаль?

> Кхм. Я бы предположил, что даже на китайском вряд ли средненький
> текст до 10 тыс. различных иероглифов дотянет.

Я бы предположил, что считать китайские иероглифы доведется нечасто =)

> Массив всегда быстрей :) Фишка в том, что есть, допустим 1000
> различных символов с кодами разбросанными по всему диапазону Unicode.
> Вопрос на засыпку - сколько памяти надо под такой массив и сколько
> надо памяти на hash под 1000 символов.

На данный момент диапазон, AFAIR, чуть больше 2^16. Если счетчик делать
int'ом, то, стало быть, получим 256Кб. Это многовато, но терпимо, с
учетом преимущества в скорости.

> > имеет смысл делать изначально массив под однобайтную кодировку
>
> Под KOI8? Или Latin-1?

Если она однобайтная, то нам все равно, какая она. Нас интересуют
только коды символов, а не их значение.

> > в случае его заполнения
>
> А в случае попадания символа не из этой кодировки?

Имеется в виду - в случае попадания символа с кодом >2^8? Это и есть
"заполнение", я просто не очень удачно выразился =)

int19h ★★★★
()
Ответ на: комментарий от int19h

> На данный момент диапазон, AFAIR, чуть больше 2^16.

В последнем UnicodeData-4.0.1 15100 строк, хотя там иероглифы не развёрнуты, а заданы диапазонами. При этом, есть символы с кодами E0xxx. А если ещё и Private Use учесть, то до 10FFFD дотягивает. Великоват массивчик выходит, хотя при нонешних объёмах памяти и наплевательском к ней отношении со стороны разработчиков, можно и массивом - всего чуть больше 4MB получится :)

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от watashiwa_daredeska

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

а вообще что кому то задание домашнее делается ?

alphex_kaanoken ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.