PDA

View Full Version : من کدی می خوام که بتونه یک فایل از ورودی بگیره



shining_eye
چهارشنبه 26 خرداد 1389, 10:33 صبح
من کدی می خوام که بتونه یک فایل از ورودی بگیره(مثلا یک فایل notepad)
خط به خط اطلاعات درون فایل را بخواند
اگر خطی از فایل تکرار شده باشد اعلام کند.(باdelphi )

vcldeveloper
چهارشنبه 26 خرداد 1389, 10:47 صبح
این که شد صورت مسئله یک تمرین ظاهرا دانشجویی!

majidbestgame
چهارشنبه 26 خرداد 1389, 11:15 صبح
من کدی می خوام که بتونه یک فایل از ورودی بگیره(مثلا یک فایل notepad)
خط به خط اطلاعات درون فایل را بخواند
اگر خطی از فایل تکرار شده باشد اعلام کند.(باdelphi )
----------------------------------------------------------------------------------
سلام...به قول آقاي كشاورز سوالتون دانشجويي بود:گیج:
من يك كد نوشتم كه ميتونه اطلاعات رو از يك فايل متني بخونه ( خط به خط ) و اونو داخل يك Memo بريزه...و چك ميكنه اگر دو خط كه پشت سر هم قرار ميگيرن تكراري بودن خطا بده...اگه مناسب بود كه خدا رو شكر وگر نه بعدا سر ميزنم كهببينم مشگلت حل شده يا نه...


procedure TForm1.Button1Click(Sender: TObject);
var
f:textfile;
s1,s2:string;
begin
s1:='';
s2:='';
assignfile(f,extractfilepath(application.ExeName)+ '\text.txt');
reset(f);
while not eof (f) do begin
readln(f,s1);
if s1<>s2 then begin
memo1.lines.add(s1);
end else begin
showmessage('Error');
end;
s2:=s1;
end;
closefile(f);
end;


اين كد رو تو notepad نوشتم و دسترسي به محيط دلفي نداشتم تست كنم...ولي ظاهرا كدش سالمه:لبخند:

majidbestgame
چهارشنبه 26 خرداد 1389, 23:10 عصر
شما میتونید ابتدا فایل متنی خودتونو داخل یک ممو Memo باز کنید سپس چک منید که آیا از خط های نوشته شده در آن کدام خط تکراری است حذفش کنید...جدی یا واسه ما سخت بود یا در کل سخته...:گیج:
یک کد براتون آماده کردم..که از یک آرایه استفاده میکنه...این آرایه در کدی که من نوشتم 100000 خط تکست را میتونه چک کنه..شما میتونید به اندازه دلخواه تنظیمش کنید...
و در صورتی که هر یک از خط ها در هر کجای(در هر خطی)دیگر وجو داشته باشد حذف میشود و فقط یکی از آنها باقی میماند و خط تکراری به صورت یک مسیج باکس نشان داده میشود....


procedure TForm1.Button1Click(Sender: TObject);
var a:array of string;
s:string;
i,j,k:integer;
begin
memo1.Text:='';
if opendialog1.Execute then
begin
if opendialog1.FileName<>'' then
begin
memo1.Lines.LoadFromFile(opendialog1.FileName);
setlength(a,form1.Memo1.Lines.Count);
// set str to arrays
for k:= 1 to memo1.lines.count - 1 do
begin
a[k]:=memo1.Lines.Strings[k];
end; { END OF FOR }
// set lines strings to s and test
for i:= 0 to memo1.Lines.Count-1 do
begin
s:=memo1.Lines.Strings[i];
for j:=i+1 to memo1.Lines.Count-1 do
begin //test of s
if a[j]=s then
begin
showmessage('error : '+a[j]); // if found repeat in lines show this error
s:='NotGoodByMbg'; // set s to 'NotGoodByMbg'
end; { END IF }
end; { END FOR J }
if uppercase(s)<>uppercase('NotGoodByMbg') then
begin // check if s<> 'NotGoodByMbg' then send line ext to
memo2.Lines.Add(s); // another memo
end; { END IF }
end; { END FOR }
end; { END IF }
end; { END IF }
end;


با این کد ابتدا شما فایل متنی خود را لود میکنید و سپس برنامه چک میکنه که آیا خطی در این فایل بیش از یک بار آمده است یا نه و اگر باشد معلوم میکند و آن خط را دباره درج نمی کند

یک برنامه که به این شکل کار میکنه رو گذاشتم...دانلود کنید و ببینید....
اینم یک عکس از شکل برنامه


51296


51297

SAASTN
چهارشنبه 26 خرداد 1389, 23:45 عصر
من درست متوجه نقش آرایه a نشدم.:متفکر:
در هر صورت اگه لازم هم باشه برای همچین منظوری بهتره از آرایه داینامیک استفاده کنید.

var
a: array of string;
...
Memo1.Lines.LoadFromFile(OpenDialog1.FileName);
SetLength(a, Memo1.Lines.Count;

Felony
پنج شنبه 27 خرداد 1389, 07:51 صبح
var
Str: TStringList;
Temp1: string;
LineNO, LineRepeat: Integer;
begin
Str:= TStringList.Create;
try
Str.LoadFromFile('FileName');
Temp1:= Str.Strings[0];
for LineNO:= 0 to Str.Count - 1 do
for LineRepeat:= LineNO+1 to Str.Count - 1 do
if Str.Strings[LineRepeat]= Temp1 then
ShowMessage('Line '+ IntToStr(LineRepeat)+' duplicated : '+ Temp1)
else
Temp1:= Str.Strings[LineNO];
finally
Str.Free;
end;

majidbestgame
یک شنبه 30 خرداد 1389, 03:02 صبح
بله................. کد همه ی دوستان درسته....

من درست متوجه نقش آرایه a نشدم.:متفکر:

از این آرایه برای ذخیره ی String های مربوط به فایل متنی استفاده کردم...ب جای استرینگ لیست :لبخند:
روش چک کردن برای پیدا کردن خط تکراری روش حبابی ( سرچ کردن در آرایه به صورت حبابی ) است ( اگه اشتباه نکرده باشم ) حالا ما اومدم و از یک open dialog هم استفاده کردیم ، یک memo افزودیم به فرم و یک دگمه برای لود و توضیحات همراه کد....اینا باعث شدن کد یک جورایی زیاد به نظر برسه...

Felony
یک شنبه 30 خرداد 1389, 06:46 صبح
بله................. کد همه ی دوستان درسته....

از این آرایه برای ذخیره ی String های مربوط به فایل متنی استفاده کردم...ب جای استرینگ لیست :لبخند:
روش چک کردن برای پیدا کردن خط تکراری روش حبابی (سرچ کردن در آرایه به صورت حبابی ) است ( اگه اشتباه نکرده باشم ) حالا ما اومدم و از یک open dialog هم استفاده کردیم ، یک memo افزودیم به فرم و یک دگمه برای لود و توضیحات همراه کد....اینا باعث شدن کد یک جورایی زیاد به نظر برسه...

چرا اتفاقا اشتباه کردید ، سرچ کردن حبابی دیگه چه صیغه ای هست ؟!
الگوریتم حبابی برای مرتب سازی هست نه جست و جو .

SAASTN
یک شنبه 30 خرداد 1389, 12:20 عصر
از این آرایه برای ذخیره ی String های مربوط به فایل متنی استفاده کردم...ب جای استرینگ لیست
شما روی سطور Memo1 میگردی و هر سطری که تکراری تشخیص دادی به Memo2 منتقل می کنی. حالا اینکه مقایسه رو بجای اینکه بین دوتا از سطر های Memo1 انجام بدی روی یه آرایه و یه سطر Memo انجام می دی، که من علت این رو نمی فهمم.

SAASTN
چهارشنبه 02 تیر 1389, 12:15 عصر
چرا a رو از نوع integer تعریف کردی؟؟؟ بعد توش هم که چیزی نریختی.
باز هم می گم توی این کار نیازی به تعریف a نیست.
خط

if a[i]=a[j] then
رو باید به

if memo1.Lines[I] = Memo1.Lines[J] then
تغییر بدی.

ListBox1.Items.Add(Inttostr(I));
رو هم به

ListBox1.Items.Add(Memo1.Lines[I]);


نم ی دونم چه طور ادامه سوالم و تو همون تاپیک میتونم بنویسم
همون پایین یه editor هست که می تونی توش جواب رو بنویسی و دکمه ارسال پاسخ رو بزنی.
مشخصا خیلی کم حوصله هستید و حتی یکبار هم کل صفحه رو نگاه نکردید.

shining_eye
چهارشنبه 02 تیر 1389, 12:31 عصر
از کمکی که کردین یک دنیا ممنون
نه این قسمت رو دیده بودم فقط فکر می کردم اینجا فقط مخصوص سوال جواب دادنه:لبخند:

shining_eye
چهارشنبه 02 تیر 1389, 14:06 عصر
ولی این کد فقط برای آ؛نهایی جواب می ده که فقط یک تکرار داشته باشه بیش از یک تکرار
که باشه اشتباه جواب میده:متفکر:

vcldeveloper
چهارشنبه 02 تیر 1389, 14:17 عصر
unit uRepeatCounter;

interface

uses
SysUtils, Classes;

type
TRepeatCounter = class
private
/// Internal input string list
FInList : TStringList;
/// Internal output string list
FRepeatedLines : TStringList;
/// Adds the sepcified line and its index from input list to output list.
procedure AddLineToRepeatedLinesList(LineIndex: Integer);
/// Prepares the input list, then sorts it.
procedure PrepareInList;
public
constructor Create;
destructor Destroy; override;
/// Finds repeated lines in the input list and saves them in FRepeatedLines
procedure FindRepetition;
procedure LoadFromFile(const FileName: TFileName);
procedure LoadFromStream(Stream: TStream);
procedure LoadFromStrings(Strings: TStrings);
/// Output string list
property RepeatedLines : TStringList read FRepeatedLines;
end;

implementation

{ TRepeatCounter }

constructor TRepeatCounter.Create;
begin
FInList := TStringList.Create;
FRepeatedLines := TStringList.Create;
end;

destructor TRepeatCounter.Destroy;
begin
FInList.Free;
FRepeatedLines.Free;
inherited;
end;

procedure TRepeatCounter.AddLineToRepeatedLinesList(LineInde x: Integer);
var
ActualLineNum : Integer;
LineContent : string;
OutStr : string;
begin
/// Get actual line number which we previously saved in PrepareInList method.
ActualLineNum := Integer(FInList.Objects[LineIndex]);
/// Get actual line content from input list.
LineContent := FInList[LineIndex];
/// Format result string as "LineNumber = LineContent"
/// Using this format gives us option to retrieve line numbers or line content
/// using Values or Names properties of TStringList.
OutStr := Format('%d=%s', [ActualLineNum, LineContent]);
FRepeatedLines.Add(OutStr);
end;

procedure TRepeatCounter.FindRepetition;
var
CurrentLine,
NextLine : Integer;
begin
/// A list with one line, has no repetition.
if FInList.Count < 2 then
Exit;

CurrentLine := 0;
/// Iterate over all lines to find repetitions.
while CurrentLine < FInList.Count do
begin
/// Since our list is sorted, repeated lines are presented sequentially, so
/// for each line, we check lines next to it, to find repeated lines.
for NextLine := CurrentLine + 1 to FInList.Count - 1 do
begin
/// If a repeated line is found, add it to the result list; otherwise
/// jump to the next line
if SameText(FInList[CurrentLine],FInList[NextLine]) then
AddLineToRepeatedLinesList(NextLine)
else
Break;
end;
/// Go to the next not-repeated line.
CurrentLine := NextLine;
end;
/// Sort result list.
FRepeatedLines.Sort;
end;

procedure TRepeatCounter.LoadFromFile(const FileName: TFileName);
begin
FInList.LoadFromFile(FileName);
PrepareInList;
end;

procedure TRepeatCounter.LoadFromStream(Stream: TStream);
begin
FInList.LoadFromStream(Stream);
PrepareInList;
end;

procedure TRepeatCounter.LoadFromStrings(Strings: TStrings);
begin
FInList.Assign(Strings);
PrepareInList;
end;

procedure TRepeatCounter.PrepareInList;
var
I : Integer;
begin
/// We want to sort the input list, so that we can find repeated lines faster,
/// but sorting the lines changes their line number.
/// To preserve line numbers, we save actual line number to FInList.Objects
/// list, by typecasting line number to TObject.
for I := 0 to FInList.Count - 1 do
FInList.Objects[i] := TObject(I);
/// Sort the input list using quick sort algorithm.
FInList.Sort;
FRepeatedLines.Clear;
end;

end.

برای متوجه شدن نحوه عملکرد کدهای فوق، Commentهای داخل سورس کد را مطالعه کنید.


نحوه استفاده:

var
RepeatCounter : TRepeatCounter;
begin
if OpenDialog1.Execute then
begin
RepeatCounter := TRepeatCounter.Create;
try
RepeatCounter.LoadFromFile(OpenDialog1.FileName);
RepeatCounter.FindRepetition;
ListBox1.Items.Assign(RepeatCounter.RepeatedLines) ;
finally
RepeatCounter.Free;
end;
end;
end;

در مثال بالا، یک دکمه با نام Button1 و یک لیست باکس با نام ListBox1 در یک فرم با نام Form1 استفاده شدند، و با زدن دکمه، فایل انتخاب شده در OpenDialg لود شده، و خطوط تکراری آن مشخص میشند. نتیجه در ListBox1 نمایش داده میشه. برای هر خط تکراری، شماره خط، و محتوای آن خط در ListBox1 درج میشه.

SAASTN
چهارشنبه 02 تیر 1389, 17:43 عصر
چه جور اشتباهی؟ لطفا شفاف مشخص کنید.
اگه منظورتون اینه که سطر هایی که مثلا 3 تکرار دارند دو بار توی ListBox اضافه میشن، خوب موقع درج سطر جدید توی Listbox هم بررسی کنید که سطری که الان می خواید توی Listbox اضافه کنید قبلا اضافه نشده باشه.
if Memo1.Lines[I] = Memo1.Lines[J] then
begin
AddedBefore := False;
for K := 0 to Listbox1.Items.Count - 1 do
if Memo1.Lines[I] = ListBox1.Items[K] then
begin
AddedBefore := True;
Break;
end;
if not AddedBefore then
ListBox1.Items.Add(Memo1.Lines[I]);
end;

SAASTN
پنج شنبه 03 تیر 1389, 10:46 صبح
شما احتمالا هر دوی حلقه های I و J رو از صفر شروع کردی (بجای اینکه J رو از I + 1 شروع کنی) که توی این وضعیت اگه تکرار یه سطر n باشه تعداد درج توی memo2 برابر n * n-1 میشه. برا دلیلش هم که دیگه باید trace کنی.
کاری که میشه کرد اینه که شما یه آرایه از boolean ایجاد کنی، هر کدوم از سطور اگه تا حالا تکراری نبودن به ازای تکرارش توی memo2 درج کنی و توی ارایه عنصر موازی رو فلگ بزنی که بعدا دیگه بررسیشون نکنی.

ضمنا این که درس شما پاسکاله یا شما علاقمندید که پروژه تون رو با دلفی انجام بدید دلیل نمی شه که تمام مسائلتون رو توی بخش دلفی و پاسکال مطرح کنید. این سوالایی که می پرسید مربوط به الگوریتم نویسی هست که جای دیگه باید مطرحشون کنید.
لطفا رعایت کنید.

در مورد حذف سطور تکراری از memo1 هم ساده ترین پیشنهادی که می تونم بدم اینه که شما موقعی که هر کدوم از سطور رو بررسی می کنی اگه تکراری بود به memo2 منتقلش کنی و اگه تکراری هم نبود به یه memo3. بعد که کار تموم شد محتویات memo3 رو به memo1 منتقل کنید

Memo1.Lines.Assign(Memo3.Lines);