Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.03.06;
Скачать: CL | DM;

Вниз

копирование нестандартной длины строки   Найти похожие ветки 

 
Yurij-7   (2005-02-23 16:44) [0]

Господа прошу помочь в следующей ситуации:
есть строка вида : "обороты 2180."
как из нее вытянуть только числовую векличину, в данном случае 2180, но может быть и 3 числа в конце строки.
Спасибо.


 
Sandman25 ©   (2005-02-23 16:45) [1]

Сканировать строку с конца и смотреть, когда закончатся цифры?


 
Antonn ©   (2005-02-23 16:47) [2]

Yurij-7   (23.02.05 16:44)
перебрать строку посимвольно, копировать в переменную только цифры и делиметр.


 
olookin ©   (2005-02-23 16:53) [3]

[2] Antonn ©   (23.02.05 16:47)

При строке типа "обороты на 20.03.2005 составили 1.452.000 млн руб." и делимитере "." получится "20.03.20051.452.000.". И чем это поможет?


 
Antonn ©   (2005-02-23 16:55) [4]

Antonn ©   (23.02.05 16:47) [2]

function str2num(s:string):string;
var i:integer; s_tmp:string;
begin
 result:="";
 for i:=0 to length(s) do
  if (ord(s[i])>47)and(ord(s[i])<58) then
   result:=result+s[i];
end;


 
Antonn ©   (2005-02-23 16:57) [5]

olookin ©   (23.02.05 16:53) [3]
какое условие, такое и решение:)


 
olookin ©   (2005-02-23 16:57) [6]

Тогда уж кусать строку на части по пробелам. А потом уже применять StrToNum


 
olookin ©   (2005-02-23 16:58) [7]

[5] Antonn ©   (23.02.05 16:57)

Здрасьте, а разве решение не должно подразумевать многозначность входной величины?


 
Yurij-7   (2005-02-23 16:58) [8]

а какую функцию использовать неподскажите?


 
Sandman25 ©   (2005-02-23 16:59) [9]

for
if
:=
IntToStr


 
Sandman25 ©   (2005-02-23 17:01) [10]

StrToInt


 
Antonn ©   (2005-02-23 17:04) [11]

Yurij-7
в обрабатываемой строке сколько численых значений? а то может там даты, проценты...


 
Yurij-7   (2005-02-23 17:07) [12]

нет там только число типа количество


 
olookin ©   (2005-02-23 17:11) [13]

[12] Yurij-7   (23.02.05 17:07)

А разделитель между строчной и числовой частями строки есть?


 
Yurij-7   (2005-02-23 17:19) [14]

да пробел, а в конце числа точка


 
olookin ©   (2005-02-23 17:21) [15]

Тогда удалем из строки все до последнего встречающегося пробела (включая его самого). Оставшуюся часть проверяем на соответствие числу. Кажется, все...


 
Antonn ©   (2005-02-23 17:27) [16]


> Оставшуюся часть проверяем на соответствие числу.

самое интересное:))

Ну тогда еще учтем делимитер для полного счастья:)

function str2num(s:string):real;
var i:integer; s_tmp:string;
begin
 s_tmp:="";
if length
 for i:=0 to length(s) do
 case ord(s[i]) of
  48..57: s_tmp:=s_tmp+s[i];
  44:     s_tmp:=s_tmp+",";
  46:     s_tmp:=s_tmp+",";
 end;
 result:= strtofloat(s_tmp);
end;


 
Yurij-7   (2005-02-23 17:28) [17]

а неподскажите как именно это сделать или может где прочитать ну в справке ничего немогу найти :(


 
Antonn ©   (2005-02-23 17:29) [18]

Yurij-7   (23.02.05 17:28) [17]
сделать inttostr или floattostr в блоке try..except, если прокатит, значит число:)


 
Antonn ©   (2005-02-23 17:30) [19]

Antonn ©   (23.02.05 17:29) [18]
т.е. strtoint или strtofloat


 
begin...end ©   (2005-02-23 17:31) [20]

TryStrToInt, TryStrToFloat


 
olookin ©   (2005-02-23 17:33) [21]

[16] Antonn ©   (23.02.05 17:27)
А я бы сделал не так...

function str2num(s:string):real;
var i:integer; s_tmp:string;
begin
s_tmp:="";
//if length вот этого я вообще не понял - это что такое?
for i:=1{элемент, т.е. символ строки начинается с 1, а не с 0} to length(s) do
if Pos("0123456789.(или ,)",s[i])<>0 then s_tmp:=s_tmp+s[i];
result:= strtofloat(s_tmp);
end;


 
olookin ©   (2005-02-23 17:36) [22]

Для полного счастья видимо так...

function str2num(s:string):real;
var i:integer; s_tmp:string;
z: string;
begin
z:="0123456789"+DecimalSeparator;
s_tmp:="";
for i:=1 to length(s) do
if Pos(z,s[i])<>0 then s_tmp:=s_tmp+s[i];
try
result:= strtofloat(s_tmp);
except НЕ_ПОМНЮ_ЧЕГО end;
//или просто использовать функцию Val
end;


 
Antonn ©   (2005-02-23 17:36) [23]

olookin ©   (23.02.05 17:33) [21]
яж "на коленке писал". {if length} - это не стертый кусок проверки длины начальной строки:)


> result:= strtofloat(s_tmp);

еще try..except вроде ставить надо для приличия. Или не стоит?


 
olookin ©   (2005-02-23 17:37) [24]

Нет, счастье не придет. Если не поменять z и s[i] местами... Хе-хе


 
Antonn ©   (2005-02-23 17:41) [25]

olookin ©   (23.02.05 17:36) [22]
DecimalSeparator;

а если у него в тексте этот сепаратор другой?


 
begin...end ©   (2005-02-23 17:42) [26]

> Antonn ©   (23.02.05 17:27) [16]

Нагляднее использовать не коды символов, а сами символы:

case s[i] of
 "0".."9" : ...
 ...
end.

> olookin ©   (23.02.05 17:33) [21]
> olookin ©   (23.02.05 17:36) [22]

1. В Pos параметры перепутаны местами.
2. Каждый символ искать во всей строке - медленно.

> Antonn ©   (23.02.05 17:36) [23]

> еще try..except вроде ставить надо для приличия. Или
> не стоит?

Стоит. Или см. [20].

Я бы использовал множества: if s[i] in ["0".."9", DecimalSeparator] then ... ну и последнюю точку как-то учитывал.


 
olookin ©   (2005-02-23 17:49) [27]

[25] Antonn ©   (23.02.05 17:41)

А при конвертации строки сепаратором является тот, которрый указан в DecimalSeparator. Так что разделителем может быть хоть символ "%"... Лишь бы это было учтено...


 
olookin ©   (2005-02-23 17:50) [28]

[26] begin...end ©   (23.02.05 17:42)
>>Каждый символ искать во всей строке - медленно.

Варианты какие есть?


 
Yurij-7   (2005-02-23 17:50) [29]

Всем большое спасибо, разобрался.


 
begin...end ©   (2005-02-23 17:53) [30]

> olookin ©   (23.02.05 17:50) [28]

Множество или case.


 
Antonn ©   (2005-02-23 17:54) [31]

olookin ©   (23.02.05 17:49) [27]
А при конвертации строки сепаратором является тот, которрый указан в DecimalSeparator. Так что разделителем может быть хоть символ "%"... Лишь бы это было учтено...

значит нужно еще прогнать строку и назначить сепаратор? А не накладно-ли?


 
olookin ©   (2005-02-23 17:54) [32]

[30] begin...end ©   (23.02.05 17:53)

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


 
Юрий Зотов ©   (2005-02-23 17:56) [33]

> olookin ©   (23.02.05 17:54) [32]

В сотни раз. Если не в сотни тысяч раз.


 
olookin ©   (2005-02-23 17:56) [34]

[31] Antonn ©   (23.02.05 17:54)

Нет, DecimalSeparator задается перед вызовом функции. Просто при конвертации строки будет считаться валидным сепаратором именно тот, что задан DecimalSeparator. Например, если есть строка "0,1235", а DecimalSeparator равен ".", то при вызове StrToFloat возникнет ошибка. А если перед этим установить DEcimalSeparator:=",", то ошибки не будет.


 
olookin ©   (2005-02-23 17:57) [35]

[33] Юрий Зотов ©   (23.02.05 17:56)

Вот как? Почему? Есть множество из 10 элементов и строка из 10 символов. Неужели механизм сравнения для них отличается?


 
Antonn ©   (2005-02-23 17:58) [36]

olookin ©   (23.02.05 17:56) [34]
но мы же не знаем какой сепаратор в тексте. Или знаем?


 
olookin ©   (2005-02-23 18:01) [37]

[36] Antonn ©   (23.02.05 17:58)

Знаем. Инчае что мы вообще обрабатываем? Неизвестного формата данные?


 
Юрий Зотов ©   (2005-02-23 18:02) [38]

> olookin ©   (23.02.05 17:57) [35]

Отличается принципиально.

Проверка вхождения символа в строку - это цикл.
Проверка вхождения элемента во множество - близко к обыкновенному AND.


 
olookin ©   (2005-02-23 18:04) [39]

[38] Юрий Зотов ©   (23.02.05 18:02)

А реально? Согласитесь, что простым AND я не обойдусь, пытаясь выяснить вхождение элемента в множество. Надо так или иначе перебирать все эелемнты этого множества и проверять их на соответствие элементу. Тот же цикл.


 
begin...end ©   (2005-02-23 18:07) [40]

> olookin ©   (23.02.05 17:54) [32]

Убыстряет.

const
 SymbolsCount = 100000;
 DecimalSymbols = "0123456789";
var
 I: Integer;
 S: string;
 T1, T2, Count1, Count2: Cardinal;
begin
 // Заполнение строки
 SetLength(S, SymbolsCount);
 Randomize;
 for I := 1 to SymbolsCount do
   S[I] := Chr(Random(255));
 // Тест с множеством
 Count1 := 0;
 T1 := GetTickCount;
 for I := 1 to Length(S) do
   if S[I] in ["0".."9"] then
     Inc(Count1);
 T1 := GetTickCount - T1;
 // Тест с Pos
 Count2 := 0;
 T2 := GetTickCount;
 for I := 1 to Length(S) do
   if Pos(S[I], DecimalSymbols) > 0 then
     Inc(Count2);
 T2 := GetTickCount - T2;
 ShowMessageFmt("Count1 = %d, Count2 = %d, множество: %d мс; Pos: %d мс", [Count1, Count2, T1, T2])
end.



Страницы: 1 2 вся ветка

Текущий архив: 2005.03.06;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.099 c
14-1108144122
Мазут Береговой
2005-02-11 20:48
2005.03.06
Денежные переводы стали "нетрудовыми доходами"


14-1108204746
leonidus
2005-02-12 13:39
2005.03.06
Тестирование качалки сайтов


1-1108815635
TUser
2005-02-19 15:20
2005.03.06
Быстрая сортировка


8-1100738055
elected
2004-11-18 03:34
2005.03.06
Текстурный шрифт


1-1109155839
ТехникПТО
2005-02-23 13:50
2005.03.06
Загрузка картинок в TImage