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

Вниз

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

 
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;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.025 c
8-1077368857
able
2004-02-21 16:07
2004.05.16
сравнение картинок


9-1052473423
Gandalf
2003-05-09 13:43
2004.05.16
Игра AutoWar


6-1080127550
rimd
2004-03-24 14:25
2004.05.16
idSMTP and idAntifreez


1-1083227723
senya
2004-04-29 12:35
2004.05.16
PDF не понимает русский язык, выдает "иероглифы"


1-1083052559
MicroWorld
2004-04-27 11:55
2004.05.16
Структурированый масив, и выборка из него