Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.03.06;
Скачать: [xml.tar.bz2];

Вниз

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

 
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.


 
Palladin ©   (2005-02-23 18:07) [41]

обойдешься всего лишь одним оператором IN


 
olookin ©   (2005-02-23 18:11) [42]

[40] begin...end ©   (23.02.05 18:07)

Может я и ошибаюсь, но GetTickCount не является точным методом определения времени выполнения КОНКРЕТНОЙ задачи. Может, лучше использовать QueryPerformanceFrequency/QueryPerformanceCounter?


 
begin...end ©   (2005-02-23 18:13) [43]

> olookin ©   (23.02.05 18:11) [42]

Не думаю, что GetTickCount может в данном случае дать ошибку в 100 раз и более. Но если сомневаетесь - используйте QueryPerformanceCounter и сообщите, пожалуйста, о результатах.


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

> olookin ©   (23.02.05 18:04) [39]

Все не так.


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

[43] begin...end ©   (23.02.05 18:13)

Да я не сомневаюсь. Насчет теста QueryPerformanceCounter - я тест этой функции делал с секундомером в руках. Что уж совсем по идиотски звучит...

А насколько различно по времени выполнение Ваших двух тестов (множество vs Pos)? Ну чтоб мне не пробовать....


 
olookin ©   (2005-02-23 18:19) [46]

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

Good а как?


 
begin...end ©   (2005-02-23 18:24) [47]

> olookin ©   (23.02.05 18:18) [45]

Pentium 3, 533 МГц (только не смейтесь).

1. SymbolsCount = 100000: Count1 = 3953, Count2 = 3953, множество: 10 мс; Pos: 110 мс.

2. SymbolsCount = 1000000: Count1 = 39218, Count2 = 39218, множество: 10 мс; Pos: 1031 мс.


 
olookin ©   (2005-02-23 18:25) [48]

[47] begin...end ©   (23.02.05 18:24)

Внушительное различие. Складаю оружие и признаю Вашу правоту...


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

> olookin ©   (23.02.05 18:19) [46]

Для простоты возьмем множество, состоящее не более, чем из 32 элементов. Поскольку элементы множества всегда упорядочены, то каждому из них можно сопоставить двоичный разряд 32-битного числа. Тогда вхождение элемента во множество можно отмечать единицей в соответствующем ему разряде, а отсутствие - нулем. И проверка вхождения элемента сведется к одноразому AND, без всяких циклов.

Почти то же самое происходит и в реальности. Никаких циклов.


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

> olookin ©   (23.02.05 18:19) [46]

Для простоты возьмем множество, состоящее не более, чем из 32 элементов. Поскольку элементы множества всегда упорядочены, то каждому из них можно сопоставить двоичный разряд 32-битного числа. Тогда вхождение элемента во множество можно отмечать единицей в соответствующем ему разряде, а отсутствие - нулем. И проверка вхождения элемента сведется к одноразому AND, без всяких циклов.

Почти то же самое происходит и в реальности. Никаких циклов.


 
olookin ©   (2005-02-23 18:30) [51]

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

Да, это убедительно...



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

Форум: "Основная";
Текущий архив: 2005.03.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.034 c
14-1108337563
neXOR
2005-02-14 02:32
2005.03.06
Какую профессию выбрать ?


3-1107786496
andrey__
2005-02-07 17:28
2005.03.06
Изменение цвета фона в TDBGrid


6-1104171339
KarpUha
2004-12-27 21:15
2005.03.06
Ответ от модема


1-1109056820
Hadroran
2005-02-22 10:20
2005.03.06
Чтение генератора из InterBase


4-1106224117
Дмитрий Ботвин
2005-01-20 15:28
2005.03.06
Изменение свойств файлов





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский