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

Вниз

Чтение данных из текстового файла   Найти похожие ветки 

 
Andrew_Rostov   (2004-04-28 18:52) [0]

Есть тесктовый файл, содержащий строки с числами (вида 23.34335). Числа разделены пробелами. Задача - занести содержимое файла в массив.
Т.е. прочитать одну строку до символа перевода каретки #10#13 и разместить элементы в массив (предварительно провернув StrToFloat).

Основная неприятность в данный момент - разбиение строки на отдельные числа - может есть встроенная функция (или прийдется возиться с анализом каждого символа поученной строки?).

Пока докопался до:
var
File_2D:TextFile;

procedure LoadFrom_2D(FileName: string);
var
File_String:string;
begin
AssignFile(File_2D,FileName);
Reset(File_2D);
readln(File_2D,File_String);
//а вот тут нужно File_String порезать на кусочки :)
CloseFile(File_2D);
end;


 
Vit@ly ©   (2004-04-28 20:55) [1]

Требуется уточнение, известно ли количество чисел в строке, одинаково ли оно? В чем собсно смысл строки?


 
Andrew_Rostov   (2004-04-28 21:22) [2]

Можно считать, что кол-во чисел в строке задано пользователем.
Смысл строки - "матрица, растянутая в строку", т.е. из этой строки нужно выделить числа и восстановить матрицу.

Основной вопрос - как наименьшими затратами "распотрошить строку". Вручную можно в цикле анализировать каждый символ до появления конца строки, а по ходу дела заносить символы в буфер и при появлении пробела делать StrToFloat("буфер"), но что-то сдается мне должно быть стандартное решение...


 
Jack128 ©   (2004-04-28 21:39) [3]

Примерно так, я думаю

type
 TDoubleArray = array of Double;

procedure ParseDoubleList(const DoubleString: string; out DoubleArray: TDoubleArray);
var
 StartChar: PChar;
 EndChar: PChar;
begin
 if (DoubleString = "") then Exit;
 StartChar := @DoubleString[1];
 while (ord(StartChar^) <= 32) and (StartChar^ <> #0) do
   inc(StartChar);
 while StartChar^ <> #0 do
 begin
   EndChar := StartChar;
   while (ord(EndChar^) > 32) and (EndChar^ <> #0) do
     inc(EndChar);
   dec(EndChar);
   SetLength(DoubleArray, Length(DoubleArray) + 1);
   DoubleArray[High(DoubleArray)] := StrToFloat(copy(StartChar, 1, Integer(EndChar - StartChar + 1)));
   StartChar := PChar(EndChar + 1);
   while (ord(StartChar^) <= 32) and (StartChar^ <> #0) do
     inc(StartChar);
 end;
end;


 
Vit@ly ©   (2004-04-28 21:44) [4]

Если строки не волнуют, то
procedure ReadFromFile;
Var f: text;
   a: real; //или массив Array []
begin
Assign(f, "1111.txt");
Reset(F);
While Not EOF(F) do
 begin
  Read(f, a);
//здесь разберись со строками и столбцаи, никакого парсинга не потребуется
//
end;


 
TButton ©   (2004-04-28 22:25) [5]

ну такая есть мысль
делаешь стринглист - буфер.
заменяешь пробелы в строке с чилами запятыми. присваиваешь результат буфер.Commatext и получаешь строку рабитую на... на как надо вобщем =)


 
Miwa ©   (2004-04-28 22:29) [6]

Прикольно... Александр Панов схожий вопросс задавал в "Потрепаться" пару дней назад. Правда, для него была критична скорость. Вообщем, если уж надо ооооочень крутой алгоритм - поищи в "Потрепаться".


 
Anatoly Podgoretsky ©   (2004-04-28 22:37) [7]

TButton ©   (28.04.04 22:25) [5]
Заменять не надо, пробелы являются стандартными разделителями, но проще читать построчно с помощью ReadLn и в Commatext, далее дело техники. Даже количество элементов матрицы знать необязательно в этом случае. Массив для данных динамический двухмерны. Уложиться можно в десяток строк


 
TButton ©   (2004-04-28 22:46) [8]

>Заменять не надо...
честно - не знал


 
Юрий Зотов ©   (2004-04-28 23:15) [9]

Господа прогораммисты Delphi! Всякие там классы, парсинг строк и прочие навороты - все это, конечно, замечательно. Но было бы очень неплохо помнить, что старый добрый Паскаль пока еще никто не отменял, и что в первую очередь именно программисту на Delphi следовало бы его знать. И не стрелять из пушки по воробьям.

Поскольку "кол-во чисел в строке задано пользователем" (см. [2]), то никакой проблемы на самом деле не существует, и не надо ее выдумывать. Все делается с помощью самых обыкновенных Read и ReadLn. Нужно всего лишь написать простейший цикл for внутри простейшего цикла while, а это - упражнение для школьников. Подсказку см. в [4].


 
Германн ©   (2004-04-29 03:09) [10]

Имхо, даже Юрий Зотов ©   (28.04.04 23:15) [9] - слишком наворочен. (Хотя этот ответ - самый полный!).
Скорее всего достаточно Readln(F,v1,v2...vn), где n - кол-во "чисел в строке заданное пользователем". А вместо v1...vn можно подставить нужные элементы массива.


 
Fay ©   (2004-04-29 04:02) [11]

2Юрий Зотов ©   (28.04.04 23:15) [9]
>> старый добрый Паскаль пока еще никто не отменял
Звучит как "стакан старого доброго молока".


 
TButton ©   (2004-04-29 04:27) [12]

>Звучит как "стакан старого доброго молока".

знаете... я как-то хлебнул старого молока из  пакета... после этого случая я осознал, что "не все старое - доброе"


 
Fay ©   (2004-04-29 04:53) [13]

Я о том же ....


 
TUser ©   (2004-04-29 07:36) [14]

Вот у меня есть такой модуль. Функция GetDouble взвратит число независимо от DecimalSeparator. Остальное тоже может пригодиться.

unit uNumChecker;

interface

uses
 SysUtils, Strutils, math;

type
 EWrongRule = class(Exception)
    public
    constructor Create(Rule:string);
    end;

function IsValueRight(Rule:string; Value:double):boolean;
procedure MyVal(Value:string; var V:integer; var Code:integer);
function GetDouble(Value:string; var Code:integer):double;

implementation

procedure MyVal(Value:string; var V:integer; var Code:integer);
var i:integer; f:boolean;
begin
  i:=1; f:=true;
  while f and (i<=length(Value)) do
     if Value[i]="0" then inc (i)
        else f:=false;
  if f then begin Code:=0; V:=0; end else
     val(copy(Value,i,length(Value)-i+1),V,Code);
end;

function GetDouble(Value:string; var Code:integer):double;
var i,j,k,c:integer;
begin
  Code:=0;
  k:=pos(".",Value);
  if k=0 then Val(Value,result,Code) else begin
     if posex(".",Value,k+1)<>0 then
        raise EWrongRule.Create("Wrong double value: """+Value+"""");
     MyVal(copy(Value,1,k-1),i,c);
     if c<>0 then raise EWrongRule.Create("Wrong double value: """+Value+"""");
     Val(copy(Value,k+1,length(Value)-k),j,c);
     if c<>0 then raise EWrongRule.Create("Wrong double value: """+Value+"""");
     c:=length(Value); // while Value[c]="0" do dec(c);
     k:=c-k;
     if j = 0 then result:=i else
        result:=i+j/power(10,k);
     end;
end;

function IsValueRight(Rule:string; Value:double):boolean;
var s:string; i,j:integer;

  function IsIn(SubRule:string; Value:double):boolean;
  var i:integer; d:double;
  begin
     result:=false;
     i:=pos("-",SubRule);
     if i = 0 then begin
        Val(SubRule,d,i);
        if (i=0) and (abs(d-Value)<0.01) then
           result:=true
           else result:=false;
        end else if posex("-",SubRule,i+1)<>0 then
           raise EWrongRule.Create("Wrong SubRule: """+SubRule+"""")
           else if i=1 then begin
           val(copy(SubRule,2,length(SubRule)-1),d,i);
           if (i=0) and (d>=Value) then
              result:=true
              else result:=false;
           end else if i=length(SubRule) then begin
              val(copy(SubRule,1,length(SubRule)-1),d,i);
              if (i=0) and (d<=Value) then
                 result:=true
                 else result:=false;
              end else begin
              d:=GetDouble(copy(SubRule,1,i-1),j);
              if (j=0) and (d<=Value) then begin
                 d:=GetDouble(copy(SubRule,i+1,length(SubRule)-i),j);
                 if (j=0) and (d>=Value) then
                    result:=true
                    else result:=false;
                 end else result:=false;
              end;
  end;

begin
  s:="";
  for i:=1 to length(Rule) do
     if Rule[i] in ["0".."9",",","-","."] then s:=s+Rule[i]
        else if Rule[i]<>" " then
           raise EWrongRule.Create(Rule);
  result:=false;
  i:=pos(",",s); j:=1;
  if i=0 then i:=length(s)+1;
  repeat begin
     result:=result or IsIn(copy(s,j,i-j),Value);
     j:=i+1; i:=posex(",",s,j);
     end
  until (i=0) or result;
  result:=result or IsIn(copy(s,j,length(s)-j+1),Value);
end;

constructor EWrongRule.Create(Rule:string);
begin
  inherited Create("Wrond Rule: """+Rule+"""");
end;

end.


 
Piople ©   (2004-04-29 07:40) [15]

Блин а мож просто взять pos??? И после каждого нахождения пробуде копировать слова в массив???


 
Anatoly Podgoretsky ©   (2004-04-29 07:41) [16]

Германн ©   (29.04.04 03:09) [10]
Это если количество фиксированое, а при переменном придется делать в цикле

for i := 0 to n-1 do
 read(F, ar[j,i]);
readLn(f);


 
Юрий Зотов ©   (2004-04-29 08:40) [17]

> Fay ©   (29.04.04 04:02) [11]
> TButton ©   (29.04.04 04:27) [12]
> Fay ©   (29.04.04 04:53) [13]

Возражение по существу, что и говорить.


 
Vit@ly ©   (2004-04-29 10:06) [18]

Поддерживаю Anatoly Podgoretsky ©   (29.04.04 07:41) [16]
Хотя мне показалось, что я это уложил в посте [4] в строке

//здесь разберись со строками и столбцами, никакого парсинга не потребуется



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

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

Наверх




Память: 0.51 MB
Время: 0.032 c
3-1082374501
Maxim Volobuev
2004-04-19 15:35
2004.05.16
TADOCommand.Execute и возвращаемый им RecordSet


8-1074102210
miek
2004-01-14 20:43
2004.05.16
Демка "Граффити"


8-1077368857
able
2004-02-21 16:07
2004.05.16
сравнение картинок


3-1082283525
Viktor
2004-04-18 14:18
2004.05.16
ограничение кол-ва записей


1-1083004080
Nvart
2004-04-26 22:28
2004.05.16
Ошибка при чтении потока





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