Модераторы: Snowy, MetalFan, bems, Poseidon

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как прочитать текстовый файл целиком, Чтение текстового файла 
:(
    Опции темы
Bugmaker
Дата 31.5.2009, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 161
Регистрация: 27.6.2008

Репутация: нет
Всего: нет



Добрый день.
Задача следующая:
Написать программу, которая считывает текст из файла и выводит предложения, которые не содержат запятых.

Разобрался как работать с ReadLn, но загвоздка в том, что предложение может начиниться на одной строке, а заканчиватьяс на другой.

Как прочитать весь файл целиком в массив, или, возможно есть другйо способ разделить файл на предложения...

Код

var
  Form1: TForm1;
   var f : TextFile; // îáúÿâëåíà ôàéëîâàÿ ïåðåìåííàÿ f òèïà TextFile
   myChar  : Char;
   i: integer;
   charArray  : Array of Char;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin

memo1.lines.loadfromfile('C:/2.txt');
AssignFile( f , 'C:/2.txt');
Reset(f);

While not(eof(f)) do // ïîêà ôàéë íå êîí÷èòñÿ âûïîëíÿòü öèêë
begin



Read ( f, myChar); // ïîñèìâîëüíîå ÷òåíèå
i:=i+1;
charArray[i]:= myChar;

end;


end;



end.



Пытаюсь сделать так, но получаю ошибку. Насколько я понимаю ошибука обращения к памяти  smile 

Это сообщение отредактировал(а) Bugmaker - 31.5.2009, 18:23
PM MAIL   Вверх
kami
Дата 31.5.2009, 19:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Код

function FileOfferCounter:integer;
var
  f:TFileStream;
  s, offer:string;
  StartPos, EndPos:integer; // начальная и конечная позиции предложения
  Counter:integer;
begin
  // в этом коде есть ряд недостатков.
  // например, не проверяется, есть ли такой файл вообще.
  // и так же - не является ли он пустым.

  f:=TFileStream.Create('c:\setup.log', fmOpenRead);
  SetLength(s, f.Size);
  f.Read(s[1], Length(s));

  EndPos:=0;
  Result:=0;
  While EndPos<Length(s) do
    begin
      StartPos:=EndPos+1;
      EndPos:=PosEx('.', s, StartPos);
      if EndPos=0 then
        break;
      offer:=Copy(s, StartPos, EndPos-StartPos+1);
      //Здесь offer - это предложение, от первого его символа до последнего, включая точку.
      // с ним (предложением) можно сделать все, что угодно - например, подсчитать количество слов, запятых и т.д.    
      // просто наличие/отсутствие запятых определяется функцией pos.
      inc(Result); // ну а я в своем примере просто подсчитаю количество предложений.
    end;
  f.Free;
end;


Это сообщение отредактировал(а) kami - 31.5.2009, 19:04
PM MAIL WWW   Вверх
Bugmaker
Дата 31.5.2009, 19:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 161
Регистрация: 27.6.2008

Репутация: нет
Всего: нет



Не определены Result и PosEx....
Они должны быть integer?

Извиняюсь.. вижу что объявлены.. компилятор выдает
"Undeclared identifier: 'Result'"
"Undeclared identifier: 'PosEx"



Это сообщение отредактировал(а) Bugmaker - 31.5.2009, 19:22
PM MAIL   Вверх
Данкинг
Дата 31.5.2009, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Yersinia pestis
****


Профиль
Группа: Завсегдатай
Сообщений: 8302
Регистрация: 7.11.2006
Где: მოსკოვი

Репутация: 11
Всего: 130



Цитата(Bugmaker @  31.5.2009,  20:16 Найти цитируемый пост)
"Undeclared identifier: 'Result'"

Ну так объяви его.


--------------------
There's nothing left but silent epitaphs.
PM MAIL WWW   Вверх
Bugmaker
Дата 31.5.2009, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 161
Регистрация: 27.6.2008

Репутация: нет
Всего: нет



Пишу на делфи билдере 7

вот весь код
Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  f:TFileStream;
  s, offer:string;
  StartPos, EndPos:integer; // íà÷àëüíàÿ è êîíå÷íàÿ ïîçèöèè ïðåäëîæåíèÿ
  Counter:integer;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin

  f:=TFileStream.Create('c:\2.txt', fmOpenRead);
  SetLength(s, f.Size);
  f.Read(s[1], Length(s));

  EndPos:=0;
  Result:=0;
  While EndPos<Length(s) do
    begin
      StartPos:=EndPos+1;
      EndPos:=PosEx('.', s, StartPos);
      if EndPos=0 then
        break;
      offer:=Copy(s, StartPos, EndPos-StartPos+1);
      //Çäåñü offer - ýòî ïðåäëîæåíèå, îò ïåðâîãî åãî ñèìâîëà äî ïîñëåäíåãî, âêëþ÷àÿ òî÷êó.
      // ñ íèì (ïðåäëîæåíèåì) ìîæíî ñäåëàòü âñå, ÷òî óãîäíî - íàïðèìåð, ïîäñ÷èòàòü êîëè÷åñòâî ñëîâ, çàïÿòûõ è ò.ä.    
      // ïðîñòî íàëè÷èå/îòñóòñòâèå çàïÿòûõ îïðåäåëÿåòñÿ ôóíêöèåé pos.
      inc(Result); // íó à ÿ â ñâîåì ïðèìåðå ïðîñòî ïîäñ÷èòàþ êîëè÷åñòâî ïðåäëîæåíèé.
    end;
  f.Free;
end;

end.



Сорри комментарии будут крокозябами %) НО они есть в посте kami.

Насколько я вижу вот тут:
var
  Form1: TForm1;
  f:TFileStream;
  s, offer:string;
  StartPos, EndPos:integer; // íà÷àëüíàÿ è êîíå÷íàÿ ïîçèöèè ïðåäëîæåíèÿ
  Counter:integer;
implementation

Они уже объявлены, где еще это нужно сделать?

PM MAIL   Вверх
Данкинг
Дата 31.5.2009, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Yersinia pestis
****


Профиль
Группа: Завсегдатай
Сообщений: 8302
Регистрация: 7.11.2006
Где: მოსკოვი

Репутация: 11
Всего: 130



Цитата(Bugmaker @  31.5.2009,  20:32 Найти цитируемый пост)
Сорри комментарии будут крокозябами

Русскую раскладку включи перед копированием текста.

Цитата(Bugmaker @  31.5.2009,  20:32 Найти цитируемый пост)
Они уже объявлены,

Извиняюсь, ступил: result - это же к функции относится. А PosEx где объявлена? Это, видимо, функция какого-то модуля.


--------------------
There's nothing left but silent epitaphs.
PM MAIL WWW   Вверх
Bugmaker
Дата 31.5.2009, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 161
Регистрация: 27.6.2008

Репутация: нет
Всего: нет



Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    procedure Button1Click(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
   var f : TextFile;
   myChar  : Char;
   i,i1,s: integer;
   myString : array of string;
   z: Array of integer;


   charArray  : Array of Char;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  i:=0;
  i1:=0;
memo1.lines.loadfromfile('C:/2.txt');
AssignFile( f , 'C:/2.txt');
Reset(f);

 SetLength(charArray,100000);
 SetLength(z,100000);

    While not(eof(f)) do
    begin

    Read ( f, myChar);
    i:=i+1;
    charArray[i]:= myChar;
    Memo2.Lines.Add(myChar);
    i1:=i;
    end;

    for i:=0 to i1 do
    begin

    if charArray[i]='.' then
        begin
        ShowMessage('to4ka');
        s:=s+1;
        z[s]:=i;
        end;

    end;

end;


end.


Вобщем вот такой код  разбивающий весь файл на char'ы и запоминающий номер точек.. подскажите как теперь из этих char'ов собрать обратно нужные предложения)

Это сообщение отредактировал(а) Bugmaker - 31.5.2009, 21:20
PM MAIL   Вверх
kami
Дата 31.5.2009, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(Bugmaker @  31.5.2009,  19:16 Найти цитируемый пост)
"Undeclared identifier: 'Result'"

Я привел код функции.
И Result - это результат этой функции.
Но! это код для подсчета количества предложений. Всего-то нужно добавить в него одну строку (условный оператор), чтобы получить выполнение задачи
Цитата(Bugmaker @  31.5.2009,  14:52 Найти цитируемый пост)
выводит предложения, которые не содержат запятых.




Цитата(Bugmaker @  31.5.2009,  19:16 Найти цитируемый пост)
"Undeclared identifier: 'PosEx"

Кнопку F1 уже отменили?
uses StrUtils;
PM MAIL WWW   Вверх
Bugmaker
Дата 31.5.2009, 21:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 161
Регистрация: 27.6.2008

Репутация: нет
Всего: нет



kami огромнейшее спасибо, разобрался)
PM MAIL   Вверх
kami
Дата 31.5.2009, 21:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(kami @  31.5.2009,  21:26 Найти цитируемый пост)
 Всего-то нужно добавить в него одну строку (условный оператор)

Извините - 2 строки:
условный оператор и вывод предложения,  не содержащего запятых.
PM MAIL WWW   Вверх
Bugmaker
Дата 3.6.2009, 21:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 161
Регистрация: 27.6.2008

Репутация: нет
Всего: нет



Возникла еще пара вопросов... первый в том, что предложение может оканчиваться вопросительным и восклицательным знаком а не точкой...
Второй - запятая может быть в дробном числе.. как учесть эти моменты? 
Чешу репу, ковыряюсь но надежды на меня мало... Помогите пожалуйста)

У меня почему то такое ощущение что все придется переделывать ... не используя PosEx а перебирая каждый символ (

На данный момент код такой:

Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, StrUtils;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
    f:TFileStream;
  s, offer:string;
  StartPos, EndPos:integer; // íà÷àëüíàÿ è êîíå÷íàÿ ïîçèöèè ïðåäëîæåíèÿ
  Counter, Result:integer;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
        f:=TFileStream.Create('c:\2.txt', fmOpenRead);
  SetLength(s, f.Size);
  f.Read(s[1], Length(s));

  EndPos:=0;
  Result:=0;
  While EndPos<Length(s) do
    begin
      StartPos:=EndPos+1;
      EndPos:=PosEx('.', s, StartPos);
      if EndPos=0 then
        break;
      offer:=Copy(s, StartPos, EndPos-StartPos+1);
        if Pos(',',offer)=0 then Memo1.Lines.Add(offer);

      inc(Result);
    end;
  f.Free;

end;

end.




Думаю стоит перейти к такой вот форме..
Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, StrUtils;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  var f : TextFile;
  myChar : char;



implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
AssignFile( f , 'C:/2.txt');
Reset(f);

  while not eof(f) do
     begin
        Read ( f, myChar);
    if myChar='.' then          // тут действия если встречается точка
        begin


          ShowMessage('ss');
        end;
    if myChar='!' then          // тут действия если встречается восклицательный знак
        begin
          ShowMessage('ss');
        end;
    if myChar='?' then          // тут действия если встречается вопросительный знак
        begin
          ShowMessage('ss');
        end;
        Memo1.Lines.Add(myChar);
     end;

CloseFile(f);


end;

end.





Это сообщение отредактировал(а) Bugmaker - 3.6.2009, 22:20
PM MAIL   Вверх
kami
Дата 3.6.2009, 22:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Продолжаем.
Я не зря сказал, что когда найден offer, с ним можно сделать все, что угодно.

С учетом вышесказанного (предложение может заканчиваться вопросительным и восклицательным знаком) дополним код:

Код

While EndPos<Length(s) do
    begin
      StartPos:=EndPos+1;
      EndPos:=PosEx('.', s, StartPos);
      if EndPos=0 then
        break;
      offer:=Copy(s, StartPos, EndPos-StartPos+1);
        if Pos(',',offer)=0 then Memo1.Lines.Add(offer);

      inc(Result);
    end;


Это исходное положение.
Изменяем поиск EndPos.

Код

function FindEndOffer(StartPos:integer; Str:string):integer;
var
   TmpResult:integer;
begin
  TmpResult:=PosEx('.', str, StartPos);
  Result:=TmpResult;
  // изначальное положение. Найдена (а может и нет) точка
  if Result=0 then
    Result:=Length(str); // точка не найдена. Для дальнейшей нормальной работы функции
  // определяем, что "позиция точки" - в конце всего текста.

  TmpResult:=PosEx('?', str, StartPos);
  if (TmpResult<>0) and (TmpResult<Result) then // если найден вопросительный знак
    // и он расположен раньше точки, значит предложение заканчивается им.
    Result:=TmpResult;

  TmpResult:=PosEx('!', str, StartPos);
  if (TmpResult<>0) and (TmpResult<Result) then // если найден восклицательный знак
    // и он расположен раньше вопросительного, значит предложение заканчивается им.
    Result:=TmpResult;
end;


Теперь - заменяем строку исходного текста 
Код

EndPos:=PosEx('.', s, StartPos);

на
Код

EndPos:=FindEndOffer(StartPos, s);


Сейчас напишу и про расширенный поиск запятых.

Добавлено через 2 минуты и 6 секунд
Кстати - из-за новой введенной функции текст от последней точки(вопросительного/восклицательного знака) до конца текста (даже если последний символ в тексте не является точкой/знаком) будет считаться предложением.
PM MAIL WWW   Вверх
kami
Дата 3.6.2009, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Дополняем код после 
Цитата(kami @  3.6.2009,  22:22 Найти цитируемый пост)
offer:=Copy(s, StartPos, EndPos-StartPos+1);

Учитываем, что запятая может быть в дроби.
Определяем, что дробь - это последовательность символов, включающая запятую, слева и справа от которой расположены цифры.

Код

function IsValidComma(str:string; cPos:integer):boolean;
begin
  // в этой функции предполагается, что в позиции pos находится именно запятая и ничто иное.
  Result:=True;
  if cPos>1 then
    Result:=Result and not (str[cPos-1] in ['0'..'9']); // предыдущий символ -не цифра
  if cPos<Length(str) then
    Result:=Result and not (str[cPos+1] in ['0'..'9'); // следующий символ - не цифра
end;

function IsValidOffer(offer:string):boolean;
var
  tmpPos:integer;
begin
  Result:=True;
  TmpPos:=0;
  Repeat
    TmpPos:=PosEx(',',offer, TmpPos+1); // проходим по всем запятым в предложении
    if TmpPos<>0 then  // найдена очередная запятая
      if not isValidComma(offer, TmpPos) then // если запятая "неправильная"
        begin
          Result:=False; // то и предложение неправильное
          break;
        end;
  until TmpPos=0; 
end;


Теперь после offer:=Copy....... пишем
Код

if IsValidOffer(offer) then
  Memo1.Lines.Add(offer);


Писал прямо в браузере, мог с логикой немного напутать (в смысле, not не там, где нужно), но это уже оставляю на твоей совести - должен же быть какой-то творческий процесс smile Проходя отладчиком по этим функциям и просматривая значения переменных можно легко найти, где нарушена логика.
PM MAIL WWW   Вверх
Bugmaker
Дата 3.6.2009, 22:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 161
Регистрация: 27.6.2008

Репутация: нет
Всего: нет



Result:=Result and not (str[cPos+1] in ['0'..'9'); // следующий символ - не цифра  --- тут небольшая опечатка но это мелочи..


Вот эту часть не понял
begin
  // в этой функции предполагается, что в позиции pos находится именно запятая и ничто иное.
  Result:=True;
  if cPos>1 then
    Result:=Result and not (str[cPos-1] in ['0'..'9']); // предыдущий символ -не цифра
  if cPos<Length(str) then
    Result:=Result and not (str[cPos+1] in ['0'..'9'); // следующий символ - не цифра
end;

Пока что програамма наоборот не выводит предложения с дробными числами... Зато выводит с обычными запятыми чего делать не должна(

Помоему дело в функции IsValidComma ... 
Не вижу условия при котором она False... 

Это сообщение отредактировал(а) Bugmaker - 3.6.2009, 23:08
PM MAIL   Вверх
kami
Дата 3.6.2009, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(Bugmaker @  3.6.2009,  22:55 Найти цитируемый пост)
Result:=Result and not (str[cPos-1] in ['0'..'9']);

Рассмотрим отдельно.
1. str[cPos-1] in ['0'..'9']
Если символ, предшествующий запятой находится в рамках от "0" до "9" (то есть является цифрой), то результат выполнения этой части кода будет True. И False - в противном случае.
Рассматриваем полностью эту строку.
2. Берем предыдущий результат and  результат 1).


Цитата(Bugmaker @  3.6.2009,  22:55 Найти цитируемый пост)
Пока что програамма наоборот не выводит предложения с дробными числами

Ну и сделай в последней строке function IsValidComma:
Result:=not Result.
Получишь инвертированный результат работы кода внутри функции и будет выводить другие предложения smile
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0609 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.