1. Заголовок темы должен быть информативным. В противном случае тема удаляется ... 2. Все тексты программ должны помещаться в теги [code=pas] ... [/code], либо быть опубликованы на нашем PasteBin в режиме вечного хранения. 3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали! 4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора). 5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM! 6. Одна тема - один вопрос (задача) 7.Проверяйте программы перед тем, как разместить их на форуме!!! 8.Спрашивайте и отвечайте четко и по существу!!!
Прошу помочь с исправлением ошибок в программе, Для каждого символа заданного текста указать его относительную частоту
Здравствуйте. Дана задача : Для каждого символа заданного текста указать его относительную частоту появления в тексте. Построить соответствующую диаграмму. Сообщение об одном символе должно печататься не более одного раза. Вот мой черновик. программа читает текст из файла, который может состоять из любого количества символов(английские , русские буквы, всевозможные знаки препинания и все это в несколько строк), выводить нужно только символы-буквы. всё шло прекрасно до того момента как текст состоял из двух-трёх строк, но если читать ,к примеру, полноценное стихотворение, то начинаются ошибки(выводит несколько раз сообщение об одинаковых символах, некоторые буквы не выводит вовсе, неправильно считает) и как мне уже подсказали формула по которой считается относительная частота не верна(.до диаграммы дело не доходит так понимаю, что смысла нет за неё браться пока происходят вот такие косяки.. Прошу посмотреть программу и помочь с выявлением ошибок
Program chast; uses crt; var t: text; s: string; a: array [0..255] of integer; k, b, i, max:integer; BEGIN clrscr; k:=0; assign(t,'int.pas'); reset(t); while not (eof(t)) do begin
readln(t,s); for i:=1 to length(s) do begin inc(k); case ord(s[i]) of 97..122,224..255:inc(a[ord(s[i])]); 65..90,128..159:begin s[i]:=chr(ord(s[i])+32); inc(a[ord(s[i])]); end; end; end;
writeln('Относительная частота повторений символов в тексте'); writeln; max:=0; for i:=32 to 255 do if a[i]<>0 then begin writeln(chr(i),'-','частота',(a[i]/100*k): 3 :2,'',' % ', ' встречается в тексте ',a[i],' раз(а)'); if a[i]>max then begin max:=a[i] ; b:=i end; end; end; writeln; writeln; writeln('всего символов - ',k, ' больше всего встречается-',chr(b),' ', max,' раз(а)'); close(t); readln; end.
Я так понимаю, что на каком-то форуме ты уже побывал.
Если выполняешь самостоятельно, то разберёшься.
1. Отформатируй текст программы. Станет видна основная ошибка - результат выводится после обработки каждой строки, а не по окончанию файла.
2. Действительно, странно как-то ты считаешь относительную частоту. Посчитай появление каждого символа из требуемого диапазона в тексте. Потом и выводи результат.
Код
if s[i] in ['a'..'z', 'A'..'Z', 'а'..'я', 'А'..'Я'] then {здесь не вполне корректно задан русский алфавит - подправишь сам} inc(a[ord(s[i])]);
[quote name='Федосеев Павел' date='14.04.2013 18:52' post='161990'] Я так понимаю, что на каком-то форуме ты уже побывал.
Если выполняешь самостоятельно, то разберёшься.
1. Отформатируй текст программы. Станет видна основная ошибка - результат выводится после обработки каждой строки, а не по окончанию файла.
2. Действительно, странно как-то ты считаешь относительную частоту. Посчитай появление каждого символа из требуемого диапазона в тексте. Потом и выводи результат.
Код
if s[i] in ['a'..'z', 'A'..'Z', 'а'..'я', 'А'..'Я'] then {здесь не вполне корректно задан русский алфавит - подправишь сам} inc(a[ord(s[i])]);
[/quote]
интересная штука получилось, читая Ваш совет, а именно
Код
if s[i] in ['a'..'z', 'A'..'Z', 'а'..'я', 'А'..'Я'] then inc(a[ord(s[i])]);
[/quote] думала сначала сделать так
Код
if s[i] in ['a'..'z'] then inc(a[ord(s[i])]); else {разделила потому что большие буквы нужно преобразовать в маленькие} if s[i] in ['A'..'Z'] then begin s[i]:=chr(ord(s[i])+32); inc(a[ord(s[i])]); end;
либо я чего то не допонимаю либо я все-таки чего то недопонимаю, так как если разбивать , то у меня не считает "а", так же как и в моем изначальном варианте а малую программа не считала вообще. НО если пишу
Код
if s[i] in ['a'..'z'] then inc(a[ord(s[i])]);
, то мало того что все считает, она даже большие считает и на экран выдает все в виде малых букв.( это по поводу латинских букв, с русскими пока не делаю) это конечно великолепно что так получается,НО я не понимаю почему она считает и большие и малые, если я большие даже не пишу в список?
Да-а-а, что-то я запамятовал о различии кодов прописных и строчных букв. Тогда, наверное нужно сделать
Код
MyABC:=['a'..'z', 'A'..'Z', 'а'..'я', 'А'..'Я']; ................... if s[i] in MyABC then inc(a[ord( MyLoCase(s[i]) )]);
А ранее определить процедуру MyLoCase(c: char): char, которая будет переводить символы в "нижний" регистр. Для латинских символов она уже есть стандартная, а для русских придётся самостоятельно добавить
Код
function MyLoCase(c: char): char; begin case c of 'a'..'z', 'A'..'Z': MyLoCase:=locase(c); 'а'..'я', 'А'..'Я': MyLoCase:=........ что-то своё else MyLoCase:=c; end;
И ещё, я не совсем понял что там считается не так. Если можно покажи код, тестовый файл и ожидаемый результат. Смею предположить, что перед использованием массива a его нужно обнулять.
такой вопрос. Чтобы подсчитать относительную частоту появления какого-то символа, нужно посчитать кол-во символов (в моем случае исключая пробелы и знаки препинания) и разделить кол-во появлений данного символа на общее число символов. так? но вот вопрос на общее число символов вообще или на общее кол-во встречающихся символов?(т.е. считать что буквы повторяются или раздилить на кол-во используемых символов?)
не могу понять как это реализовать. все символу подсчитать могу, а как исключить пробелы и знаки препинания? прокручиваю вариант использования pos и delete...хотя это совсем не лучший вариант
Добавлено через 2 мин. или if s[i] in ['a'..'z'] then inc(h){в итоге h покажет сколько всего?}?
Добавлено через 3 мин. вроде работает . как на Ваш взгляд есть лучше вариант?
Добавлено через 15 мин. вот на данный момент так, проверте пожалуйста
Код
uses CRT; var t: text; s: string; a: array [0..255] of integer; h, k, i:integer; BEGIN clrscr; assign (t, 'int.pas'); reset (t); while not (eof (t)) do BEGIN readln (t, s); inc(k); {строки} for i := 1 to length (s) do begin inc(k);{сколько в строке} s[i] := lowercase(s[i]); inc (a[ord (s[i])]); if s[i] in ['a'..'z'] then inc(h);{общее кол-во букв} END; end; for i := 65 to 255 do if (a[i] <> 0) then writeln (chr(i), ' - ','частота*-',( a[i]/h):3:3,', встречается раз -',a[i],' ','всего символов(букв)',h); close (t); readln; END.
Добавлено через 1 мин. правильно ли подсчитана частота?
Добавь в начале программы обнуление элементов массива a - это ОБЯЗАТЕЛЬНО. Инкремент inc (a[ord (s[i])]) выполняй после проверки вхождения символа в ['a'..'z']
Улучшить код, конечно, можно. Но на данном этапе обучения, я боюсь тебя запутать. Например, - интересующие символы в if использовать в виде константы if s[i] in MyABC then - убрать неиспользуемые модуль CRT, переменную k - закрывать файл сразу после использования - после цикла while - добавить обработку кириллицы применительно к конкретной кодовой странице (CP866 или CP1251)
и на счет MyABC. первый раз вижу, не разу этого не встречала, понятия не имею что это и преподаватели такого не объясняли поэтому думаю лучше обойтись без этого , дабы избежать лишних объяснений
Добавлено через 4 мин. спасибо, Вы мне очень помогли. но хотелось бы попросить помощи в вопросе про диаграмму. необходимо вывести соответствующую диаграмму. с графом то работала, но вот опять таки как это реализовать основываясь на моих данных. предполагаю придется делать процедуру. подскажите хотябы с алгоритмом, как быть?
Добавлено через 19 мин. и перед этим. зачем закрывать файл сразу после использования - после цикла while? какая разница?
Файл закрывается потому, что завершился кусок кода обработки данных. Далее идёт кусок визуализации результатов обработки.
MyABC и условие в if s[i] in ['a'..'z'] - это работа с типом МНОЖЕСТВО - set of char.
Я почти не работал с graph, только предполагаю. Визуализация в графическом режиме. 1. Масштабирование по X и по Y 2. Рисование прямоугольников с заполнением.
Масштабирование. 1. По X Пусть обрабатывались N=26 символов от 'a' до 'z'. Тогда ширина каждого прямоугольника будет равна dX:=(GetMaxX+1) div N Но лучше рисовать диаграмму немного отступив от края экрана, например 5% слева и 5% справа. Таким образом, остаётся всего лишь 90% ширины и получим dXshift:=( (GetMaxX+1)*5 ) div 100 {отступ от края экрана 5%} dX:=( (GetMaxX+1) - dXshift - dXshift) div N {ширина каждого прямоугольника} 2. По Y Среди значений массива (в нужном диапазоне символов от 'a' до 'z') ищется максимальный - Amax. Аналогично находим высоту максимального прямоугольника dYshift:=( (GetMaxY+1)*5 ) div 100 {отступ от края экрана 5%} dYmax:=(GetMaxX+1) - dYshift - dYshift А высоты каждого рисуемого прямоугольника будут находиться dY:=(a[i]*dYmax) div Amax
Рисование прямоугольников (псевдокод) с учётом что X возрастает слева направо, а Y сверху вниз
Код
for i:=ord('a') to ord('z') do begin dY:=(a[i]*dYmax) div Amax Xstart:=dXshift+dX*( i-ord('a') ) Ystart:=(GetMaxY+1)-dYshift Xstop:=Xstart+dX Ystop:=Ystart-dY прямоугольник(Xstart, Ystart, Xstop, Ystop) {кажется, bar или rectangle} end;
Может быть, при вызове bar нужно будет поменять местами Ystart и Ystop, нужно установить цвета, стили заполнения. Я просто не знаю. Нужно пробовать.
Наверняка, в интернете вообще и на форуме в частности есть примеры построения диаграмм.
P.S. Препод от нас требовал не графическую диаграмму, а горизонтальную в текстовом режиме символами '*'.
Код
dYmax:=80 for i:=ord('a') to ord('z') do begin dY:=(a[i]*dYmax) div Amax for Y:=1 to dY do write('*'); writeln; end;