Уважаемый, rraassttaa, прошу прощения за резкость, 
НОНачнём с того, что в русском языке существуют знаки препинания, скажу больше — некоторые ретрограды их даже используют на письме, наивно считая, что предложения вида
вот что я наделал посмотрите скажите как сделать так чтобы он не выводил повторяющиеся символы по нескольку раз а 1 раз пример
 читать как минимум неприятно, а как максимум — невозможно, ибо не ясно, где кончается одна мысль и начинается другая (пресловутое "казнить нельзя помиловать").
Теперь о программе:Простите, но Вы в цикле используете одну и ту же переменную в качестве счётчика ВСЕХ символов. Более того, Вы её постоянно обнуляете внутри цикла при встрече каждого допустимого символа. Подобный (конечно, весьмаааа отдалённо, но всё-таки...) подход имеет право на существование (если Вы не_хотите/не_можете (по условию задания) использовать массив), но в этом случае алгоритм должен был бы выглядеть примерно следующим образом:
1. Создаётся набор допустимых символов: "abc...xyzABC...XYZ0...9"
2. Для КАЖДОГО символа из набора осуществляется подсчёт его вхождений в обрабатываемую строку. Если количество вхождений больше нуля, в выходную строку добавляем соответствующее сообщение.
Приблизительный код:
- Код: Выделить всё
- var 
 i, j, k:integer;
 Nabor:string; // Символы, количество которых необходимо подсчитать
 InStr:string; // входная строка
 OutStr:string; // выходная строка
 begin
 OutStr:='';
 for i:=1 to Length(Nabor) do begin
 k:=0;
 for j:=1 to Length(InStr) do
 if InStr[j]=Nabor[i] then inc(k);
 if k>0 then OutStr:=OutStr+Nabor[i]+' - '+IntToStr(k)+'; '
 end;
 end.
 
Набор уникальных символов формируется программистом (если Вы желаете исключить из учёта какие-то символы (пробел, знаки пунктуации и арифметических операций, прочие специальные символы) или программно из введенной строки приблизительно так:
- Код: Выделить всё
- var 
 i, j, k:integer;
 nabor:string; // набор уникальных символов
 InStr:string; // входная строка
 begin
 Nabor:='';
 for i:=1 to Length(InStr) do begin
 k:=-1;
 for j:=1 to Length(Nabor) do
 if InStr[i]=Nabor[j] then begin
 k:=j;
 Break
 end;
 if k=-1 then Nabor:=Nabor+InStr[i]
 end;
 end.
 
Очевидно, что если использовать динамический массив для хранения счётчиков вхождения символов в строку, то скорость выполнения программы можно повысить:
- Код: Выделить всё
- var 
 i, j, k:integer;
 Counters:array of integer;
 nabor:string; // набор уникальных символов
 InStr:string; // входная строка
 OutStr:string; // выходная строка
 begin
 Nabor:='';
 SetLength(Counters, 1);
 for i:=1 to Length(InStr) do begin
 k:=-1;
 for j:=1 to Length(Nabor) do
 if InStr[i]=Nabor[j] then begin
 k:=j;
 Break
 end;
 if k=-1 then begin
 Nabor:=Nabor+InStr[i];
 k:=Length(Counters);
 SetLength(Counters, k+1);
 Counters[k]:=0
 end;
 inc(Counters[k])
 end;
 OutStr:='';
 for i:=1 to Length(Nabor) do
 OutStr:=OutStr+Nabor[i]+' - '+IntTostr(Counters[i])+'; '
 end.
 
P.S.В случае конкретно FreePascal, лучше использовать 
UTF8Length(s) вместо 
Length(s) и 
UTF8Copy(s,i,1) вместо 
s[i]. 
Если Вы не хотите различать строчные и прописные буквы, то сравнивать нужно не собственно символы, а символы, преобразованные к верхнему (
AnsiUpperCase(s) / 
UTF8UpperCase(s)) или нижнему 
(AnsiLowerCase(s) / 
UTF8LowerCase(s)) регистру. 
Для использования UTF8-функций, Вы должны подключить к своей программе модуль 
LCLProc.
С уважением, Алексей.