noa
Гость
|
|
« : 19-11-2003 17:28 » |
|
помогите мне нужно открыть файл и посчитать в нём сиволы и каждый поотдельности. шлите пожалуйста на noa@ua.fm Заранее благодарен!!!
|
|
|
Записан
|
|
|
|
Sommer
Молодой специалист
Offline
|
|
« Ответ #1 : 19-11-2003 17:31 » |
|
noa, а что значит "и каждый по отдельности?"
|
|
|
Записан
|
когда-нибудь, я верю, ты будешь ехать по этому городу и поймёшь, что хочешь увидеть меня за рулём мчащейся по соседней полосе машины. но тогда меня уже не будет в этом городе forever yours.
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #2 : 19-11-2003 18:32 » |
|
noa, мда - задчка однако, FILE *f; f = fopen(filename, "r"); // Fikle to read only while (fread(f,char)) { // Делать что либо с символами } fclose(f); все - это читает все символы с файла Причем все и каждый в отдельности. Могут быть проблемы - я его не компилировал, а формат функции чтения не помню, мож она там что не так возвращает...
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Thinker
Гость
|
|
« Ответ #3 : 19-11-2003 22:04 » |
|
открыть файл и посчитать в нём сиволы и каждый поотдельности
Если это означает подсчет сколько раз каждый символ присутствовал в файле и речь не идет о Unicode, то можно создать массив целых чисел размером в искомый алфавит (в худшем случае - 256), и использовать его как счетчик. С Unicode задачка становится гораздо интереснее К делу не относится: Для любителей структур данных - можно еще и построить частотный индех всех слов в документе, причем документ (в моем случае) был около 1 терабайта - snapshot куска интернета Причем кодировки там были смешанные и зачастую неправильно помеченные. Было интересно .... 8)
|
|
|
Записан
|
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #4 : 19-11-2003 22:38 » |
|
Thinker, все очень просто - завтра протрезвею и вывешу алгоритм на 10 строк больше того, который написан у меня, и сделаю вам подсчет - с условием уникода, или без него - без всяких проблем...
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Alf
Гость
|
|
« Ответ #5 : 20-11-2003 00:33 » |
|
Если это означает подсчет сколько раз каждый символ присутствовал в файле и речь не идет о Unicode, то можно создать массив целых чисел размером в искомый алфавит (в худшем случае - 256), и использовать его как счетчик. С Unicode задачка становится гораздо интереснее А вот ежели взять да и завести для хранения счетчиков ассоциативный массив, даже Unicode не внесет желаемого разнообразия. Задачка останется по-прежнему скучной...
|
|
|
Записан
|
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #6 : 20-11-2003 00:56 » |
|
Alf, а она и так скучна, и не в юникоде дело. Процесс: 1. берется файл - читается весь. 2. Определяется формат. 3. Создается связный список, в котором в зависимости от формата фалйа данное - 1 байт или 2. Можно и не связный спиок а массив в случае 1 байта символа из 256 позиций - но ломает так делать. 4. Затем банальный перебор позиций для каждого символа. Принцип подсчета - первый символ фала считается сколько раз втречается и в памяти забивается на соответствующую байду. В нашем случае когда 256 символов - обычно сначала сичтали 0 символы - потом все остальные заменяли на 0. Для юникода тоже можно взять первый символ - посчитать его содержимое, а потом заменять другие на него - не суть. И все. Остается прикол когда файл размером больше оперативки в разы, например 2 Гига. Тогда пробежку делаем в кусках фала, которые считываем, скажем по 20 мег, или по 100 мег - в зависимости от системы. Задача ВСЯ - включая работу по связному списку и оформлению в нормальный объект - порядка 100 строк кода максимум.... и то с запасом на всякие там заморочки по улучшению... Скучно. noa, ты можешь брать на вооружение эту схему - все будет работать как часики. ----------------------- (кстати если не нужна точность, а порядок, то можно использовать оценочные алгоритмы вот там интереснее...)
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Alf
Гость
|
|
« Ответ #7 : 20-11-2003 08:02 » |
|
Alf, а она и так скучна, и не в юникоде дело. Процесс: 1. берется файл - читается весь. 2. Определяется формат. 3. Создается связный список, в котором в зависимости от формата фалйа данное - 1 байт или 2. Можно и не связный спиок а массив в случае 1 байта символа из 256 позиций - но ломает так делать. 4. Затем банальный перебор позиций для каждого символа. Принцип подсчета - первый символ фала считается сколько раз втречается и в памяти забивается на соответствующую байду. В нашем случае когда 256 символов - обычно сначала сичтали 0 символы - потом все остальные заменяли на 0. Для юникода тоже можно взять первый символ - посчитать его содержимое, а потом заменять другие на него - не суть. И все. Если я правильно понял идею, делается как минимум несколько проходов файла, а именно - столько, сколько различных символов в нем встречается? Остается прикол когда файл размером больше оперативки в разы, например 2 Гига.
Тогда пробежку делаем в кусках фала, которые считываем, скажем по 20 мег, или по 100 мег - в зависимости от системы.
Сложно... Не в смысле - безумно сложно само по себе, а для решаемой задачи сложновато. А почему бы не так: берем ассоциативный массив счетчиков, изначально обнуленных. Читаем входной файл поэлементно и инкрементируем счетчик, ассоциированный с этим элементом. Работать должно с любыми кодировками, читать данные однократно и не зависеть от размера входного файла. И по памяти выгадаем: массив счетчиков в любом случае компактнее исходных данных. Если, конечно, не выдумают какую-нибудь всегалактическую кодировку подлиннее Unicode, скажем, 32-битную Тогда таблица счетчиков тоже распухнет изрядно... Правда, и перспектива сканировать файл до 4.000.000.000 раз тоже не очень...
|
|
|
Записан
|
|
|
|
Diletant
Помогающий
Offline
|
|
« Ответ #8 : 20-11-2003 10:27 » |
|
Не понял проблемы
FILE *f; TCHAR MyChar; int iCounts[sizeof(MyChar)*8]; int i;
for (i= 0; i < sizeof(MyChar)*8; i++) { iCounts = 0; }
f = fopen(filename, "rb"); // Fikle to read only
while (fread(f,MyChar)) { (iCounts[(int)MyChar])++ } fclose(f);
Вместо TCHAR может быть какой угодно char.
|
|
|
Записан
|
|
|
|
Alf
Гость
|
|
« Ответ #9 : 20-11-2003 11:54 » |
|
Не понял проблемы
... int iCounts[sizeof(MyChar)*8]; ...
Не понял эту конструкцию. Судя по всему, это массив счетчиков экземпляров символа? sizeof(MyChar) вернет размер, занимаемый переменной типа MyChar, в байтах. В случае символов ASCII это будет 1, для Unicode - 2. Соответственно и размерность таблицы будет 8 либо 16. Вроде маловато. Вот кабы 2 возвести в эту степень, было бы уже ближе к истине, по-моему.
|
|
|
Записан
|
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #10 : 20-11-2003 12:14 » |
|
Alf, нет - прозод один - при возможности можно сделать, просто вчера был пъян и фокус не удался При проходе в один раз - мы делаем проверку на существующий проверенный уже символ - если он был, то тогда увеличиваем его счетчик, если не был то добавляем его в массив и коунтер увеличиваем. примерно: #define size_of_file - тут не пишу просто - сичтаем определили размер в байтах filesize(). typedef struct { char a[size_of_file]; int count[size_of_file]; int active_num; } mystr; mystr str; str.active_num = 0; FILE *f; f = fopen(filename, "r"); // Fikle to read only bool flag=false; while (fread(f,char)) { for (int i=0; i<active_num; i++) { if (char == str.a ) { str.count++; flag = true; break; } } if (flag == false) { active_num++; str.a[active_num] = char; str.count[active_num] = 1; } else { flag = false; }
} fclose(f);
УСЕ
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #11 : 20-11-2003 12:30 » |
|
Ну... не понимаю как можно осбуждать на основе таких скудных данных, да и noa пропал. Ну да ладно - спонтанно продолжаем разговор, предположив что мы знаем, что ему нужно. в принципе согласен с Alf и Diletant думаю имеется ввиду одно и то же. Вопросы к коду Diletant: Я это место тоже не понял? Думаю так: int iCounts[sizeof(char)*256]; - число символов для таблицы ANSI. Обнулить счётчики: memset(iCounts,0,sizeof(int)*sizeof(char)*256); и главное: "(iCounts[(int)MyChar])++" ? Наверно всё-таки так: (iCounts[( unsigned char)MyChar])++ тк в С++ char вообщето со знаком, поэтому для символа с кодом > 127 всё вылетает в отрицательную область, да плюс ещё кастинг в 4х байтовый целый!!! Индекс получится сумасшедший.
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #12 : 20-11-2003 12:41 » |
|
Гром, а так разве проще? По-моему сложнее.
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
Diletant
Помогающий
Offline
|
|
« Ответ #13 : 20-11-2003 14:33 » |
|
Вопросы к коду Diletant:
Я это место тоже не понял? Думаю так: int iCounts[sizeof(char)*256]; - число символов для таблицы ANSI.
Поторопился я :oops: . Умножать надо, естественно, на 256. Хотя IMHO sizeof(MyChar) предпочтительнее во избежание путаницы со встроенным типом С. Обнулить счётчики: memset(iCounts,0,sizeof(int)*sizeof(char)*256);
Это уже на любителя, но я не люблю без особой необходимости использовать memset. и главное: "(iCounts[(int)MyChar])++" ? Наверно всё-таки так: (iCounts[( unsigned char)MyChar])++ тк в С++ char вообщето со знаком, поэтому для символа с кодом > 127 всё вылетает в отрицательную область, да плюс ещё кастинг в 4х байтовый целый!!! Индекс получится сумасшедший. Все-таки так: (iCounts[( unsigned int)MyChar])++ если мы хотим UNICODE поддерживать. В противном случае придется юникодный компилятор использовать.
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #14 : 20-11-2003 15:03 » |
|
Это уже на любителя, но я не люблю без особой необходимости использовать memset.
Согласен, я не люблю циклы закручивать. (iCounts[(unsigned int)MyChar])++
Сделай char ch = -65; (unsigned int)ch и посмотри, что получится.
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #16 : 20-11-2003 15:49 » |
|
Я не совсем уверен, что с UNICODE так же всё гладко получится. Например с началом файла мы уже пролетаем. Мне ща надо уже сваливать, а завтра меня не будет. Если что, на след неделе продолжим. Честно говоря про UNICODE я ещё хорошо не думал, да и нужно ли оно? noa- то вон, пропал.
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #17 : 20-11-2003 15:49 » |
|
Джон, чем сложнее. Идея проста до безобразия. Встречается символ - смотрим его в своем списке, находим, увеличиваем каунтер - не находим - создаем новый элемент. На обычных чар - заработает 100% и очень быстро. Процедура поиска в своем списке может быть ускорена Я ж писал это прямо тут даже не заставляя себя думать Может и неправильно так поступать, но.... Посик в массиве для поиска можно ускорять - если он будет не массивом а упорядоченным списком, по данным, тогда мы можем брать алгоритм разделения его. В любом случае два байта это FFFF максимум элементов и поиск будет бытрее чем в гиговом файле к примеру... Вот отчюда и вывод так быстрее в случае больших файлов.
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #18 : 20-11-2003 16:01 » |
|
Я пока с уверенностью говорю только про ANSI посмотри код Diletantа. Один проход без поиска char MyChar; int iCounts[256*sizeof)char:(; memset)iCounts,0,sizeof)int:*sizeof)char:*256:; FILE *f = fopen)"d{\\a.txt", "rb":; while )fread)&MyChar,sizeof)char:,1,f:: )iCounts[)unsigned char:MyChar(:++; fclose)f:;
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
|