Телефонный справичник

Дамьян

Есть программа, реализующая телефонный справочник, но работает неккоректно. После первой компиляции, когда ввожу данные в таблицу, он все записывает правильно и сохраняет в txt-файл. при последующей компиляции он выдает некорректные записи в таблице, и я не могу понять в чем именно дело. я думаю дело в загрузке из файла (процедура TForm1.LoadRecords), что она прописана неправильно. запись вроде написана корректно, по крайней мере я думаю так. Вот исходник:
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls;
 
const
csFileName = 'phones.txt';
 
type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    StringGrid1: TStringGrid;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure StringGrid1SetEditText(Sender: TObject; ACol, ARow: Integer;
      const Value: String);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
   public
    { Public declarations }
    // процедуры для чтения/записи данных
    procedure LoadRecords;
    procedure SaveRecords;
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  with StringGrid1 do begin
    FixedCols := 1; // заголовочные колонки с названиями полей
    FixedRows := 1; // заголовочный столбец с номерами записей
    ColCount := 5; // колонок - 5: номер, фамилия, имя, отчество, телефон
    RowCount := 2; //  пока хватит (кол-во строк в таблице)
    // прописываем заголовки
    Cells [0, 0] := '№';
    Cells [1, 0] := 'Фамилия';
    Cells [2, 0] := 'Имя';
    Cells [3, 0] := 'Отчество';
    Cells [4, 0] := 'Телефон';
    // выставляем ширину колонок
    ColWidths [0] := 40;
    ColWidths [1] := 150;
    ColWidths [2] := 150;
    ColWidths [3] := 150;
    ColWidths [4] := 120;
    // выставляем высоту строки
    DefaultRowHeight := 18;
    // разрешаем редактирование и выделение цветом
    Options := Options + [goDrawFocusSelected, goEditing];
  end;
  // наша процедура, которая грузит записи.
  LoadRecords;
end;
procedure TForm1.LoadRecords;
var
  s: TStrings; //класс для хранения набора строк
  i: integer;
begin
  s := TStringList.Create;
  try
    // если файла нет (первый запуск), ничего не делаем
    if FileExists (csFileName) then begin
      s.LoadFromFile (csFileName);
      // для всех записей в файле
      for i := 0 to s.Count - 1 do
        with StringGrid1 do begin
          // при необходимости - добавляем строки в грид
          if (i = RowCount - 1) then
            RowCount := RowCount + 1;
          // заполняем грид
          Cells [0, i + 1] := IntToStr (i + 1);
          Cells [1, i + 1] := s.Names [i];
          Cells [2, i + 1] := s.Names [i];
          Cells [3, i + 1] := s.Names [i];
          Cells [4, i + 1] := s.Values [s.Names [i]];
        end;
    end;
  finally
    s.Free;
  end;
end;
procedure TForm1.SaveRecords;
var
  s: TStrings;
  i: integer;
begin
  s := TStringList.Create;
  try
    with StringGrid1 do
      // для всех записей
      for i := 1 to RowCount - 1 do
        // формируем строку вида <фамилия>=<телефон> и добавляем в список
        s.Add (Cells [1, i] + '=' + Cells [2, i] + '=' + Cells [3, i] + '=' + Cells [4, i]);
    // сохраняем всё на диск
    s.SaveToFile (csFileName);
  finally
    s.Free;
  end;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  lastname, firstname, fathersname,
  number: string;
begin
  // запрашиваем у юзера фамилию, имя, отчество и телефон предполагаемой жертвы
  if InputQuery ('Ввод', 'Фамилия', lastname) and
     InputQuery ('Ввод', 'Имя', firstname) and
     InputQuery ('Ввод', 'Отчество', fathersname) and
    InputQuery ('Ввод', 'Телефон', number) then begin
    with StringGrid1 do begin
      // если первая строка пустая - пишем в неё, если нет - добавляем строку
      if Cells [0, RowCount - 1] <> '' then
        RowCount := RowCount + 1;
      // заполняем поля
      Cells [0, RowCount - 1] := IntToStr (RowCount - 1);
      Cells [1, RowCount - 1] := lastname;
      Cells [2, RowCount - 1] := firstname;
      Cells [3, RowCount - 1] := fathersname;
      Cells [4, RowCount - 1] := number;
    end;
    // записываем данные на диск
    SaveRecords;
  end;
end;
 
procedure TForm1.StringGrid1SetEditText(Sender: TObject; ACol,
  ARow: Integer; const Value: String);
begin
  SaveRecords;
end;
 
procedure TForm1.Button2Click(Sender: TObject);
var
  i: integer;
begin
  with StringGrid1 do
    // если таблица пустая - то и не фиг там удалять
    if Cells [Col, Row] <> '' then begin
      // первая строчка не удаляется, а просто очищается
      if RowCount = 2 then
        for i := 0 to 3 do
          Cells [i, 1] := ''
      // для всех остальных
      else begin
        // от текущей строки до конца
        for i := Row to RowCount - 2 do
          // смещаем все записи вверх
          Rows [i] := Rows [i + 1];
        // уменьшаем кол-во строк.
        RowCount := RowCount - 1;
      end;
      // пересчитываем нумерацию.
      for i := 1 to RowCount - 1 do
        Cells [0, i] := IntToStr (i);
      SaveRecords;
    end;
end;
 
procedure TForm1.Button3Click(Sender: TObject);
var
  i: integer;
  s: string;
begin 
  // запрашиваем что искать
  if InputQuery ('Ввод', 'Что искать?', s) then
    with StringGrid1 do
      // перебираем все строки, кроме заголовков
      for i := 1 to RowCount - 1 do
        // если ячейка начинается с введённого слова - переходим на неё и сваливаем
        if Pos (s, Cells [Col, i]) = 1 then begin
          Row := i;
          Break;
        end;
end;
 
end.
9 ответов

Дамьян

при последующей компиляции
Она зачем ? Чем первая не угодила ?


Дамьян

Она зачем ? Чем первая не угодила ?
понимаете, там данные записываются в текстовый файл, и когда эти данные становятся нужными при повторном открытии программы, получается бардак. вот, примерно поэтому


Дамьян

при повторном открытии
Причем здесь "открытие" ? Ты заявил именно про "компиляцию", успешным результатом которой является создание исполняемого кода. Скомпилировал - получил exe. Повторно скомпилировал - снова получил exe. Вопрос : чем тебя не устроил 1-й exe - результат именно компиляции ?


Дамьян

Причем здесь "открытие" ? Ты заявил именно про "компиляцию", успешным результатом которой является создание исполняемого кода. Скомпилировал - получил exe. Повторно скомпилировал - снова получил exe. Вопрос : чем тебя не устроил 1-й exe - результат именно компиляции ?
значит я неправильно выразился, извините. при повторном открытии


Дамьян

выдает некорректные записи
Никому кроме тебя не ведомо чем они "некорректны".


Дамьян

// формируем строку вида <фамилия>=<телефон> и добавляем в список s.Add (Cells [1, i] + '=' + Cells [2, i] + '=' + Cells [3, i] + '=' + Cells [4, i]);
Name/Value это пара. Одно имя , разделитель ( в данном случае знак равно) и одно значение. А у тебя получается сразу четыре слова.


Дамьян

Name/Value это пара. Одно имя , разделитель ( в данном случае знак равно) и одно значение. А у тебя получается сразу четыре слова.
ну это я понимаю, просто я не знаю как правильно все это прописать


Дамьян

Например, создать ещё один стринглист и с помощью функции ExtractStrings вытаскивать из каждой строчки в него значения.
procedure TForm1.LoadRecords;
var
  s,sTemp: TStrings; //класс для хранения набора строк
  i: integer;
begin
  s := TStringList.Create;
  sTemp := TStringList.Create;
  try
    // если файла нет (первый запуск), ничего не делаем
    if FileExists (csFileName) then begin
      s.LoadFromFile (csFileName);
      // для всех записей в файле
      for i := 0 to s.Count - 1 do
        with StringGrid1 do begin
          // при необходимости - добавляем строки в грид
          if (i = RowCount - 1) then
            RowCount := RowCount + 1;
          // заполняем грид
          sTemp.Clear;
          ExtractStrings(['='],[' '], PChar(s[i]),sTemp);
 
          Cells [0, i + 1] := IntToStr (i + 1);
          Cells [1, i + 1] := sTemp[0];
          Cells [2, i + 1] := sTemp[1];
          Cells [3, i + 1] := sTemp[2];
          Cells [4, i + 1] := sTemp[3];
        end;
    end;
  finally
    s.Free;
    sTemp.Free;
  end;
end;


Дамьян

Например, создать ещё один стринглист и с помощью функции ExtractStrings вытаскивать из каждой строчки в него значения.
procedure TForm1.LoadRecords;
var
  s,sTemp: TStrings; //класс для хранения набора строк
  i: integer;
begin
  s := TStringList.Create;
  sTemp := TStringList.Create;
  try
    // если файла нет (первый запуск), ничего не делаем
    if FileExists (csFileName) then begin
      s.LoadFromFile (csFileName);
      // для всех записей в файле
      for i := 0 to s.Count - 1 do
        with StringGrid1 do begin
          // при необходимости - добавляем строки в грид
          if (i = RowCount - 1) then
            RowCount := RowCount + 1;
          // заполняем грид
          sTemp.Clear;
          ExtractStrings(['='],[' '], PChar(s[i]),sTemp);
 
          Cells [0, i + 1] := IntToStr (i + 1);
          Cells [1, i + 1] := sTemp[0];
          Cells [2, i + 1] := sTemp[1];
          Cells [3, i + 1] := sTemp[2];
          Cells [4, i + 1] := sTemp[3];
        end;
    end;
  finally
    s.Free;
    sTemp.Free;
  end;
end;
спасибо большое! все отлично работает! что бы я без Вас делал