Главная страница
    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.



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

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

Наверх




Память: 0.54 MB
Время: 0.039 c
11-1089554522
Андрей
2004-07-11 18:02
2005.03.06
ToolBar - Решение странной проблемы


14-1108402701
Ломброзо
2005-02-14 20:38
2005.03.06
"Как захочешь, так и было" (10 кБ)


3-1107422213
Term
2005-02-03 12:16
2005.03.06
Безопасность MS SQL


4-1106125280
Dionnis
2005-01-19 12:01
2005.03.06
Определение вида кодировки


1-1108808059
Kiriill
2005-02-19 13:14
2005.03.06
EXE





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский