Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 15.12.2011, 17:28
Reedberg Reedberg вне форума
Прохожий
 
Регистрация: 29.05.2011
Сообщения: 8
Репутация: 10
По умолчанию Считывание координат

Здравствуйте! Нужно считать из .dat файла данные (координаты точек). Данные в файле представлены в следующем виде:

2 5 3 3 3 3 7 3
1 10 10
2 95 95
3 10 80
4 10 70
5 40 70
6 40 90
7 35 90
8 35 80
9 15 20

Первую строчку не трогаем, первую строчку считываем в отдельный массив [inf]. Все что ниже первой строчки записываем в массив целых чисел [cities].

Код:
procedure ReadNodes(); 
begin
  list:= TStringlist.Create;
  list.LoadFromFile('c:\nodes.dat');
  i:=0;
  str:= List.Strings[i]; //нулевая строка - информация о препятствиях
  j:=1;
  Inf[j]:=Strtoint(Copy(str,j,1));
  for i:=1 to NK-1 do
  begin
    j:=j+2;
    inf[i+1]:=Strtoint(Copy(str,j,1));
  end;

  for i := 1 to List.Count - 1 do
  begin
    if i>9 then
    begin
      str:= List.Strings[i];
      from:= Strtoint(Copy(str,1,2));
      cities[from].x:=Strtoint(Copy(str,4,2));
      cities[from].y:=Strtoint(Copy(str,7,2));
    end
    else
      begin
        str:= List.Strings[i];
        from:= Strtoint(Copy(str,1,1));
        cities[from].x:=Strtoint(Copy(str,3,2));
        cities[from].y:=Strtoint(Copy(str,6,2));
      end;
  end;
end;

Функция не работает, если координаты точки больше 99, то есть координата содержит три цифры. Как это исправить?
Ответить с цитированием
  #2  
Старый 15.12.2011, 17:43
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

Не работает потому, что в функции Copy(str,3,2) ты задаешь 2 символа для копирования, и соответственно следующее число начинаешь читать не с той позиции (с 4й например, а не с 5й)
Вот у меня есть ф-ция, которой я превращал строку в вектор, там как разделитель используются запятые, можешь переделать на пробелы
Код:
Function ConsoleCommand.texttopoint(var text:string;var Point:Tvector):Boolean;
var str1,xstr,ystr,zstr:string;err:integer;len,zap1:integer;
temp:Single;
begin
  str1:=text;
  len:=length(str1);
    if len>=5 then begin
     zap1:=pos(',',str1);
     xstr:=copy(str1,1,zap1-1);
     val(xstr,temp,err);
     if err=0 then begin
        delete(str1,1,zap1);
        zap1:=pos(',',str1);
        ystr:=copy(str1,1,zap1-1);
        val(ystr,temp,err);
        if err=0 then begin
         delete(str1,1,zap1);
         zstr:=str1;
         val(zstr,temp,err);
        end;
       end;
      if err=0 then begin
       Point.X:=strtofloat(xstr);
       Point.Y:=strtofloat(ystr);
       Point.Z:=strtofloat(zstr);
      result:=true;
     end else begin
   text:=format('_Error:"%s" не является координатами 3D точки',[text]);
   Result:=false;
  end;
 end else begin
text:=format('_Error:"%s" не является координатами 3D точки',[text]);
Result:=false;
end;

end;
Ответить с цитированием
  #3  
Старый 15.12.2011, 18:15
Аватар для Страдалецъ
Страдалецъ Страдалецъ вне форума
Гуру
 
Регистрация: 09.03.2009
Адрес: На курорте, из окна вижу теплое Баренцево море. Бррр.
Сообщения: 4,723
Репутация: 52347
По умолчанию

Ну а вот такой вариант устроит?
Код:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils, Classes;

Var
  Data, Row: TStringList;
  R,C: Integer;
  Matrix: Array of Array of Integer;
begin
 Data := TStringList.Create;
 Data.LoadFromFile('C:\11\nodes.txt');
 Data.Delete(0);
 SetLength(Matrix, Data.Count);
 for R := 0 to Data.Count - 1
 do begin
    Row := TStringList.Create;
    Row.Text := StringReplace(Data.Strings[R],#32,#13,[rfReplaceAll]);
    SetLength(Matrix[R], Row.Count);
    for C := 0 to Row.Count - 1
    do Matrix[R,C] := StrToIntDef(Row[C], 0);
    Row.Free;
    end;
 Data.Free;
 for R := 0 to High(Matrix)
 do begin
    for C := 0 to High(Matrix[R])
    do Write(Matrix[R,C]:3);
    WriteLn;
    end;
 ReadLn;
end.
__________________
Жизнь такова какова она есть и больше никакова.
Помогаю за спасибо.
Ответить с цитированием
  #4  
Старый 16.12.2011, 15:33
Reedberg Reedberg вне форума
Прохожий
 
Регистрация: 29.05.2011
Сообщения: 8
Репутация: 10
По умолчанию

Большое спасибо за ответы!

YVitaliy, вы все верно написали, я понимаю, почему не работает, если в координате больше трех цифр, именно это я и хочу преодолеть.

Страдалецъ, к сожалению ваш код не запустился.
Появляется ошибка в следующей строке:

Код:
do Write(Matrix[R,C]:3);

Debugger Exception Notification
Project Progect1.exe raised an exception class EInOutError with message 'I/O error 105'. Process stopped. Use Step or Run to continue.
Ответить с цитированием
  #5  
Старый 16.12.2011, 16:15
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

У вас в качестве разделителя используются пробелы, значит нужно искать его (пробел) в строке с помощью ф-ции Pos, считывать первую координату, задав количеством символов значение етой функции-1, потом удалять из строки символы с 1 до Pos, и повторять так 2 раза для 3х координат, как у меня в примере.
ЗЫ. В данном случае как первая координата идет параметр from, а X и Y как вторая и третья координата

так пойдет:
Код:
function getcoord(var str:string):string;//функция считывает первую
//координату со строки(до первого пробела) а потом удаляет ее вместе с
//пробелом
var i,j,r:integer;
begin
result:=str;
r:=pos(' ',str);// в кавычках пробел 
if r=0 then exit;
result:=copy(str,1,r-1);//копируем строку до пробела
delete(str,1,r);//удаляем символы строки до пробела включительно
end;

procedure ReadNodes(); 
begin
  list:= TStringlist.Create;
  list.LoadFromFile('c:\nodes.dat');
  i:=0;
  str:= List.Strings[i]; //нулевая строка - информация о препятствиях
  j:=1;
  Inf[j]:=Strtoint(Copy(str,j,1));
  for i:=1 to NK-1 do
  begin
    j:=j+2;
    inf[i+1]:=Strtoint(Copy(str,j,1));
  end;

  for i := 1 to List.Count - 1 do
  begin
    if i>9 then
    begin
      str:= List.Strings[i];
      from:= Strtoint(getcoord(str));
      cities[from].x:=Strtoint(getcoord(str));
      cities[from].y:=Strtoint(getcoord(str));
    end
    else
      begin
        str:= List.Strings[i];
        from:= Strtoint(getcoord(str));
        cities[from].x:=Strtoint(getcoord(str));
        cities[from].y:=Strtoint(getcoord(str));
      end;
  end;
end;

Последний раз редактировалось YVitaliy, 16.12.2011 в 16:28.
Ответить с цитированием
  #6  
Старый 16.12.2011, 17:19
AlexSku AlexSku вне форума
Специалист
 
Регистрация: 07.05.2007
Адрес: Москва
Сообщения: 884
Репутация: 21699
По умолчанию

Почему вы считываете символы, а не числа? Можно вот так:
Код:
type
  TCity = record
    x, y : Integer;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    StringGrid1: TStringGrid;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    c: array[1..10] of TCity;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  F: TextFile;
  I, J: Integer;
begin
  if not OpenDialog1.Execute then Exit;

  AssignFile(F, OpenDialog1.FileName);
  Reset(F);
  ReadLn(F);    // пропускаем первую строку
  for I:= 1 to 5 do
  begin
    Read(F, J, c[J].x, c[J].y);    // считываем числа
    // просмотр
    StringGrid1.Cells[1,J]:= IntToStr(c[J].x);
    StringGrid1.Cells[2,J]:= IntToStr(c[J].y);
  end;
  CloseFile(F);
end;
Ответить с цитированием
  #7  
Старый 16.12.2011, 17:48
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

Тоже неплохой вариант
Ответить с цитированием
  #8  
Старый 16.12.2011, 17:52
Аватар для Страдалецъ
Страдалецъ Страдалецъ вне форума
Гуру
 
Регистрация: 09.03.2009
Адрес: На курорте, из окна вижу теплое Баренцево море. Бррр.
Сообщения: 4,723
Репутация: 52347
По умолчанию

Не понял, какая нафик ошибка ввода/вывода может быть при выводе на консоль. Бред какой-то. Код абсолютно рабочий для приведенного выше примера данных.
AlexSku если вы будете читать из текстового файла как число, то вы получите бред. В текстовом виде у вас будет 5. А если прочитать этот текст как число, то будет уже 53
__________________
Жизнь такова какова она есть и больше никакова.
Помогаю за спасибо.
Ответить с цитированием
  #9  
Старый 16.12.2011, 18:04
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

Страдалецъ, вы неправы, данная функция рабочая, позволяет считать последовательно записанные значения из строки в файле, единственный ее недостаток - доступна только при работе с файлом, а если есть отдельная строка?
Ответить с цитированием
  #10  
Старый 16.12.2011, 19:33
AlexSku AlexSku вне форума
Специалист
 
Регистрация: 07.05.2007
Адрес: Москва
Сообщения: 884
Репутация: 21699
По умолчанию

Цитата:
Сообщение от Страдалецъ
AlexSku если вы будете читать из текстового файла как число, то вы получите бред. В текстовом виде у вас будет 5. А если прочитать этот текст как число, то будет уже 53
Какой же бред? Процедура Read прочитает число 5. А вот примеры для работы с символами вынуждают вас искать пробелы.
Ответить с цитированием
  #11  
Старый 16.12.2011, 19:34
AlexSku AlexSku вне форума
Специалист
 
Регистрация: 07.05.2007
Адрес: Москва
Сообщения: 884
Репутация: 21699
По умолчанию

Цитата:
Сообщение от YVitaliy
Страдалецъ, вы неправы, данная функция рабочая, позволяет считать последовательно записанные значения из строки в файле, единственный ее недостаток - доступна только при работе с файлом, а если есть отдельная строка?
А где эта строка, разве не в файле? Есть две операции чтения: Read и ReadLn.

Пример, естественно, приблизительный (напр., чтение надо вести до конца файла - Eof).
Ответить с цитированием
  #12  
Старый 16.12.2011, 19:43
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

Да, но есть же класс String, и я думаю, он к файлу отношения не имеет. А данная функция в конечном итоге имхо тоже ищет пробелы для считывания нужных данных
Ответить с цитированием
  #13  
Старый 16.12.2011, 22:20
Reedberg Reedberg вне форума
Прохожий
 
Регистрация: 29.05.2011
Сообщения: 8
Репутация: 10
По умолчанию

Всем большое спасибо за помощь, особенно YVitaliy! Все заработало, буду теперь разбираться как!
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 12:27.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025