IPB
ЛогинПароль:

> Прочтите прежде чем задавать вопрос!

1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!

> Задача на сортировку стрингов., Мое решение некорректно работает с кириллицей :(
forscripts
сообщение 15.12.2007 17:05
Сообщение #1





Группа: Пользователи
Сообщений: 8
Пол: Мужской

Репутация: -  0  +


Итак, суть задачи: дан файл input.txt, содержащий в первой строке число - количество строк, а затем строку в каждой строке. Необходимо отсортировать эти строки в порядке убывания, при этом создав файл config.txt вида
Код
1 1 1

//Первое число показывает, стоит урезать пробелы или нет.
Если надо обрезать пробелы, ставим 1. Если не надо, 0.
Пример:
При сравнении строк "А Б В" и " АБВ" со значением опции 1 в выходной файл будут выведены
строки "АБВ" и "АБВ", со значением опции 0 - " АБВ" и "А Б В" соответственно.

//Второе число показывает, считать большие буквы равные маленьким, или нет.
Если считать большие буквы равные маленьким, ставим 1. Если считать их разными, 0.
Пример:
При сравнении строк "абв" и "АБВ" со значением опции 1 в выходной файл будут выведены "АБВ"
и "АБВ". При значении опции 0 - "АБВ" и "абв" соответственно.

//Третье число показывает, транслитерировать русские названия или нет.
Если надо транслитерировать русские названия, все кириллические символы будут переведены в
символы латиницы. Если нет, то русские символы останутся на месте, а все русские строки
в выходном файле будут расположены после латинских.
Пример:
При сравнении строк "zak" и "абв" при значении опции 1 в выходной файл будут выведены "abv"
и "zak", при значении опции 0 - "zak" и "абв" соответственно.


Результат должен быть выведен в файл output.txt

Моя программа (все текстовые файлы и исходник программы) добавлена в прикрепления.

Вот код основной программы:


program strsort;
 var f1,f2,conf:text; 
	 n:integer;
	 a:array[1..1000] of string; 
	 i,k,e,q:integer; 
	 r:integer; 
	 s,s1,s2,t:string;
	 opt1,opt2,opt3:integer; 
 function trlit(a:string):string;
 var s:string;
	 q:string;
	 t,k:integer;
 begin
  q:='';
  s:='';
  k:=1;
  t:=length(a);
  while k<=t do begin
  case a[k] of
			... (тут все буквы большого и малого регистра кириллицы и их аналоги в транслите)
			else s:=a[k];
			end;
 if length(s)>=2 then begin t:=t+length(s); k:=k+length(s); end;
 q:=q+s;
 k:=k+1;
 end;
 trlit:=q;
 end;
 function up(s:string):string;
  var stmp:string;
	  z:byte;
	  c:char;
  begin
   stmp:='';
	for z:=1 to length(s) do
	begin
	 c:=s[z];
	 case c of
	  'а'..'п':stmp:=stmp+chr(ord(c)-32);
	  'р'..'я':stmp:=stmp+chr(ord(c)-80);
	  else stmp:=stmp+upcase(c);
	 end;
	end;
  up:=stmp;
 end;
 function sravn(s1,s2:char):integer;
 begin
  if s1<s2 then sravn:=1;
  if s1=s2 then sravn:=0;
  if s1>s2 then sravn:=2;
 end;
 function probel(s:string):string;
  var i,l:integer;
 begin
  l:=length(s); 
  for k:=1 to l do for i:=1 to l do if s[i]=' ' then begin delete(s,i,1); l:=l-1; end;
  probel:=s;
 end;
begin
 assign(f1,'input.txt');
 assign(f2,'output.txt');
 assign(conf,'config.txt');
 reset(conf);
 read(conf,opt1,opt2,opt3);
 close(conf);
 if ((opt1<>0) and (opt1<>1)) or ((opt2<>0) and (opt2<>1)) or ((opt3<>0) and (opt3<>1)) then
 begin
  writeln('Ошибка при чтении конфигурационных данных.');
  writeln('Поломался файл config.txt ');
  readln;
  halt;
 end;
 reset(f1);
 readln(f1,n);
 for i:=1 to n do readln(f1,a[i]); 
 close(f1);
 if opt1=1 then for i:=1 to n do a[i]:=probel(a[i]);
 if opt2=1 then for i:=1 to n do a[i]:=up(a[i]); 
 if opt3=1 then for i:=1 to n do a[i]:=trlit(a[i]); 
 k:=1; 
 while k<n do begin
 for i:=1 to n-1 do begin
  r:=0; q:=1;
  while r=0 do begin 
   s1:=a[i]; 
   s2:=a[i+1];
   r:=sravn(s1[q],s2[q]);
   if (q>length(s1)) or (q>length(s2)) then r:=1;
   q:=q+1;
  end;
  if r=2 then begin s:=a[i]; a[i]:=a[i+1]; a[i+1]:=s; end;
 end;
 k:=k+1;
 end;
 rewrite(f2);
 for i:=1 to n do writeln(f2,a[i]);
 close(f2);
end.



Программа компилируется и абсолютно корректно работает со строками в латинице и кириллице с отключенными опциями 2 (перевод с верхний регистр) и 3 (транслитерация). С включенными опциями 2 и 3 программа с кириллицей работает некорректно. Если я правильно понимаю, скомпиленная ФриПаскалем прога не может корректно работать с виндовскими текстовыми файлами, и поэтому считывает кириллицу некорректно. Подскажите, пожалуйста, что делать, и как научить прогу полностью корректно обращаться с кириллицей.
Спасибо.

Сообщение отредактировано: forscripts - 17.12.2007 16:49


Прикрепленные файлы
Прикрепленный файл  StringSort.rar ( 2.49 килобайт ) Кол-во скачиваний: 149
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов(1 - 7)
andriano
сообщение 15.12.2007 17:33
Сообщение #2


Гуру
*****

Группа: Пользователи
Сообщений: 1 168
Пол: Мужской
Реальное имя: Сергей Андрианов

Репутация: -  28  +


Судя по функции up - приведение к верхнему регистру - она ориентирована на 866 кодовую страницу (используемую в DOS), и даже для нее неверно обрабатывает букву "ё". В виндах обычно испольуется 1251 кодовая страница (в GUI, и 866 - в консоли). Неплохо бы предусмотреть в программе переключение между кодировками - в Виндах может понадобиться и та, и другая.

По поводу работы с кодировками.
Рекомендую воспользоваться чем-то вроде:
var
  i,j,k : integer;
  f : file;
begin
  assign(f,'ascii.cod');
  rewrite(f,1);
  for j := 0 to 15 do begin
    for i := 0 to 15 do begin
      k := i + j*16;
      blockwrite(f,k,1);
    end;
    k := 13;
    blockwrite(f,k,1);
    k := 10;
    blockwrite(f,k,1);
  end;
  close(f);
end.

Полученный таким образом файл можно прсматривать в различных кодирвках встроенными во вьюеры Total Commander'а или FAR'а для выявления закономерностей перекодирования.
Могу сразу сказать, что для ВСЕХ символов нижнего регистра (включая "ё") в 1251 от их кода надо отнимать 32. Только диапазоны будут несколько другими.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
volvo
сообщение 15.12.2007 17:43
Сообщение #3


Гость






forscripts, для начала разберись с компилятором. Если ты используешь FPC (а то, что ты не пользуешься TP - это однозначно, у меня нет дефектов зрения, присущих другим), то используй и AnsiUpperCase/AnsiLowerCase для перевода в нужный регистр. При правильном использовании они работают с любой кодовой страницей.

А вообще вопрос надо бы передвинуть... В 32-бита...
 К началу страницы 
+ Ответить 
andriano
сообщение 15.12.2007 18:17
Сообщение #4


Гуру
*****

Группа: Пользователи
Сообщений: 1 168
Пол: Мужской
Реальное имя: Сергей Андрианов

Репутация: -  28  +


Цитата(volvo @ 15.12.2007 17:43) *
А вообще вопрос надо бы передвинуть... В 32-бита...
А зачем?
Неужели 1000 строк следует обрабатывать другим алгоритмом, нежели 200?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
forscripts
сообщение 17.12.2007 16:48
Сообщение #5





Группа: Пользователи
Сообщений: 8
Пол: Мужской

Репутация: -  0  +


andriano, спасибо за помощь, попробую так...
Я пробовал и тупо отнимать 32 от численного значения символа в кириллице (методом проб и ошибок определил, под какими номерами стоят буквы кириллицы), но все равно не работало корректно(((
volvo апкейс не работает корректно, к сожалению, тоже. Юзаю ФПК, да.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
andriano
сообщение 17.12.2007 18:57
Сообщение #6


Гуру
*****

Группа: Пользователи
Сообщений: 1 168
Пол: Мужской
Реальное имя: Сергей Андрианов

Репутация: -  28  +


Так надо отнимать не от ЛЮБОГО символа кириллицы, а только от СТРОЧНОГО.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
forscripts
сообщение 17.12.2007 19:04
Сообщение #7





Группа: Пользователи
Сообщений: 8
Пол: Мужской

Репутация: -  0  +


я понял, просто неправильно выразился))
все равно корректно не работало.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
andriano
сообщение 17.12.2007 19:29
Сообщение #8


Гуру
*****

Группа: Пользователи
Сообщений: 1 168
Пол: Мужской
Реальное имя: Сергей Андрианов

Репутация: -  28  +


Да, для ё и некоторых букв украинского/белорусского алфавита отнимать надо 16.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 

- Текстовая версия 31.07.2025 3:27
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"