Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Строковые переменные

Автор: Очередная 30.01.2004 20:39

??? Привет! Чайник просит помощи у умных людей!!!
Помогите решить задачу на строковые переменные. Задача: Сколько одинаковых слов в предложении, введенном с клавиатуры? Вывести на экран слова и их количество. Заранее большое спасибо

Автор: trminator 30.01.2004 20:51

Давай начнем с начала.
Первым делом нужно уметь разделять строку на слова. Эти слова можно запихивать, допустим, в массив. Это получается? Если нет, поищи на форуме - такое тут обсуждалось... раз 20-30 +)

Автор: Очередная 1.02.2004 23:25

Слова я разделяю с помощью copy. Только у меня программа получается с целой кучей циклов. Вопрос: нельзя ли ее сделать по-проще?

Автор: P@sh@ 2.02.2004 8:26

А как узнаешь координаты слова? с помощью Pos? тогда для разделения нужен один цикл - while pos('<пробел>',s)<>0 do - или лучше аналогичный repeat ... until. Только этот метод неудобен, если слова могут разделяться не только пробелами, но и запятыми и т.д. Если учитывать все знаки препинания, понадобится еще цикл. Лучше сделать один цикл for по длине строки и каждый символ сравнивать с множеством знаков препинаний, и добавлять к слову, если это буква... затем полученное слово сравнить с массивом и либо увеличить счетчик во втором числовом массиве, либо дополнить массив слов. т.е. получается еще вложенный for, плюс цикл на вывод результатов - 3(три) цикла на программу. А у тебя сколько ?

Автор: trminator 2.02.2004 17:49

Попробуй изменить такую программу, чтобы в массив А не вставлялись повторяющиеся слова

Код

program strngs;
const razdel: set of char = [' ',',','.']; {разделители слов - пробел, точка, запятая. Больше не придумал +)}
var a: array[1..10] of string[20];
   i, j, n : integer;
   s, part: string;
begin
   ReadLn(s);
   i:=1; j:=1; n:=length(s);
   while i<=n do
   begin
       while s[i] in razdel do inc(i); {пропускаем  разделители слов}
       while (i<=n) and not (s[i] in razdel) do
       begin
         part:=part+s[i]; inc(i); {накапливаем строку}
       end;
       a[j]:=part; {<== тут изменить +)}
       inc(j) {ищем следующее слово}
   end;
{Ну тут их вывести. В переменной j должно получиться количество слов}
end.

Слово накапливается в строке part, перед тем, как добавлять его в массив, нужно проверить, нет ли его уже там.

Все-таки такое уже было на форуме... что-то искать лень.

Можно сделать, как говорит P@sh@, будет короче, но можно запутаться (наверное... я как-то писАл так, долго глючил. С тех пор так вот делаю +) ). А эта программа, по-моему, проще для понимания.

Автор: P@sh@ 3.02.2004 8:38

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

Автор: Очередная 3.02.2004 22:42

А можно это сделать без массивов, используя только функции для строковых переменных, циклы и т.д.?

Автор: trminator 4.02.2004 0:29

По-моему, нет... надо же где-то запоминать,какое слово сколько раз встречалось.
А вообще, возможно, пригодится примерно такая структура:

Код

type TWordInfo = record
 s: string; {Само слово}
 count: byte; {Сколько раз оно встречалось}
end;
var a: array[1..10] of TWordInfo;

То есть если слово не встречалось, добавляем в массив A запись, поле s - это слово, поле count = 1. А если встречалось (перед добавлением пройтись по массиву и проверить, нет ли записи, поле s в которой совпадает с новым словом), то просто увеличить значение count там.

Автор: Очередная 9.02.2004 23:42

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

Код
Program strings;
Var
j,n:integer;
s,sl,s1:string;
I,k:byte;
Begin
Writeln (‘Введите строку:’);
Readln (s);
k:=1;
j:=1;
For I:=1 to length(s) do
If s[I]=’ ‘ then
Begin
Sl:=copy(s,j+1,k);
j:=I;
k:=0;
s1:=copy (s,j,length(s));
If pos(sl,s1)=0 then
Begin
Writeln (sl);
k:=k+1;
s1:=copy(s,I+1,n);
End;
k:=k+1;
End;
End.

Автор: P@sh@ 10.02.2004 9:06

хм, столько ошибок... зачем нужны j и k? n вообще неизвестно чему равна
задумка в общем-то понятна, реализуется гораздо легче:

Код

program superstrings;
var s,s1: string;
   i: integer;
begin
 writeln('Enter the String:');
 readln(s);
 while s<>'' do begin
   i:=pos(' ',s); // в кавычках пробел
   if i=0 then i:=length(s)+1;
   s1:=copy(s,1,i-1);
   s:=copy(s,i+1,length(s));
   if pos(s1,s)>0 then writeln(s1);
 end;
end.

если б я знал, что pos может искать не только символ, но и строку! я бы сразу это написал. блин. почему-то у меня в памяти сохранилось такое описание функции - pos(c: char; s: string): integer; - откуда, интересно? может со времен Express Pascal'я на советских машинах ПК8010"Корвет" ?

Автор: Очередная 10.02.2004 11:18

Мне сказали, что к - это счетчик повторяющихся слов. n - это обозначение length(s)
smile.gifP@sh@! Спасибо за программу! Оказывается все намного проще чем мне объясняли!
:)trminator! Тоже большое спасибо за участие!

Автор: trminator 11.02.2004 0:32

м-да? кто-то тут программировать явно разучился... причем это не P@sh@ и не ты +) P@sh@, респект +) прога супер.

Хотя разделители не только пробелы. Еще запятые, точки, ... (хотя тут как в задании сказано). А это ИМХО pos'ом уже запарнее будет.

Автор: P@sh@ 11.02.2004 8:38

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

Автор: trminator 11.02.2004 17:30

Нет, все-таки бага:
Ввожу hello hellow
Ответ: hello

Цитата
if pos(s1,s)>0 then writeln(s1);

Корректно будет добавить к s1 спереди и сзади по пробелу, и в строчку тоже по пробелу в начале и в конце. Тогда должно работать

Автор: P@sh@ 12.02.2004 8:08

ага, а также по запятой, по точке и т.д.smile.gif

и правда, у функции pos к сожалению нету опции "слово целиком":)