الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

ارجو مساعدة في فهم هذه الدالة

بدأه V0LCAN0 في 27 نوفمبر 2009 · 13 رد · 1,854 مشاهدة · في لغة Delphi
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله

عيدكم مبارك سعيد

جيت في وقت غير مناسب الناس مشغوله

اخواني الكرام لقد قطعت اشواط كثيرة نحو التعلم لغة دلفي والا هناك عقبة ستغير مستواي ...

والان احتاج من ينير دربي فما اقدر وحدي افهم الاكواد وانا ما عندي حد يساعدني لهذا جت عندكم

ما اطول عليكم يا اخوان


function explode(const separator, s: string; limit: Integer = 0): TDynStringArray;
var SepLen: Integer;
F, P: PChar;
begin
SetLength(Result, 0);
if (S = '') or (Limit < 0) then
Exit;
if Separator = '' then
begin
SetLength(Result, 1);
Result[0] := S;
Exit;
end;
SepLen := Length(Separator);

P := PChar(S);
while P^ <> #0 do
begin
F := P;
P := AnsiStrPos(P, PChar(Separator));
if (P = nil) or ((Limit > 0) and (Length(Result) = Limit - 1)) then
P := StrEnd(F);
SetLength(Result, Length(Result) + 1);
SetString(Result[High(Result)], F, P - F);
F := P;
while (P^ <> #0) and (P - F < SepLen) do
Inc(P);
end;
end;

ذه الدالة لتقسيم سلسلة نصية ووضعا في مصفوفة ويستم تقسيمها بواسطة seperator

(شرح للمبتدئين اذا اهمهم الامر )

مثلا seperator عن رمز | فاذا السلسلة هكذا " Proud| to| be| muslim "

سيتم تقسيمها الى

proud

to

be

muslim

========

SetLength تحدد حجم الاحرف صح ؟ هل result السلسلة النصية كامل بدون تقسيم ؟ وجعلنا حجمها 0 ؟

بعدها قلنا اذا s فارغ (لا يحتوي على اي شيئ) و limit (عدد عناصر المصفوفة) اصغر من 0

اخرج من الدالة .. (او من IF فقط ؟)

ثم قلنا اذا seperator لا يتحوي على شيئ

نجعل السلسلة النصية حجمها 1 يعني يكون فيها حرف واحد صح ؟

Result[0] := S; لم افهم اي شيئ

خروج .

SepLen := Length(Separator);

seplen يحتوي على حجم seperator يعني راح يكون 1

عندنا متغير P من نوع pchar

نقلنا محتوى s لى P لتحويله الى Null terminated string

وقلنا عندما P^ لا تكون فارغة

انقل محتوى P الى F

ثم P := AnsiStrPos(P, PChar(Separator));

P سيحتوي على ؟؟؟

AnsiStrPos ستحتوي على او حرف ومعه باقي السلسلة !!! لماذا هناك P نفسه ؟

الكود اعلاه هوا لتصحيح هل معلوماتي صح ام لا وذالط كله عرفته لوحدي وتعبت من البحث لهذا طلبت مساعدتك

ولم استطع فهم الباقي

هذا هوا

if (P = nil) or ((Limit > 0) and (Length(Result) = Limit - 1)) then

P := StrEnd(F);

SetLength(Result, Length(Result) + 1);

SetString(Result[High(Result)], F, P - F);

F := P;

while (P^ <> #0) and (P - F < SepLen) do

Inc(P);

end;

end;

ارجوا ان تفهموني

لا اطلب ان تضيع وقتك وتساعدني دفعة وحده يمكنك اخي الكريم ان ترد علي كل ما تكون فاضي وتفهمني جزئ بجزء

بارك الله فيكم

−1
#2

السلام عليكم...

انت هنا تحاول ان تفهم كود لتروجان -_-

للاسف اذا اردت ان تفهم سورس تدميري فلا تنتضر الاخرين ان يساعدوك

تم تعديل هذه المشاركة بواسطة fkugd2003 في 27 نوفمبر 2009 في 02:23

العمل كثير و الوقت قليل أعاننا الله

seo zen SEO Enlightment amazon danbo

#3

السلام عليكم...

بعد إذن الأخ fkugd2003 ... من أين استنتج أن الكود له علاقة بـ "تروجان" (Trojan) ؟

الأخ V0LCAN0 سنحاول في الليلة القادمة شرح الدالة بالتفصيل إن شاء الله. المعذرة الليلة الوقت متأخر.

و السلام عليكم.

وَ قُلِ اعْمَلُوا فَسَيَرَى اللهُ عَمَلَكُمْ وَ رَسُولُهُ وَ الْمُؤْمِنُونَ

صدق الله العظيم

#4

الرد على طالب العلم ادب قبل ان يكون دكاء و ارادة -_- ارجو من كل اخ في هدا المنتدى ان يحترم من يطلبون المعرفة حتى و لو في اشياء بسيطة

http://www.delphi3000.com/articles/article_3609.asp

ليس ذنبي اذا صنعت كامرا وتم تصوير نساء عاريات بها

ليس ذنبي اذا طلبت شرح دالة استعملها الهاكرز في برامجهم حتى وان اردت التعلم من برامج الهاكرز فما هي المشكلة ما دمت طالبا للعلم واذا عملت شيئ سيئ فانا من يتحمل المسؤولية

على العموم ساجتهد اكثر لوحدي او ياتي احد الاخوة الذي لا يكتم العلم

#5

المشرف الكريم najy_zl, ردك يثلج الصدر بعد التحطيم الذي رايته

هذه الدالة هي في الاصل لــلغة php وقد وضعت رابط فوق لاحد الاشخاص حولها الى delphi

بارك الله فيك

وخذ كل راحتك في الرد علي فانا دائما موجود بذن الله

#6

السلام عليكم...

لا أعتقد أن الأخ fkugd2003 يقصد أية إساءة. تلك وجهة نظره و قد عبر عنها بكلام ليس فيه أي تجريح أو إهانة.

على أية حال دعنا نتجاوز تلك النقطة.

نلتقي مساء الغد إن شاء الله.

و السلام.

وَ قُلِ اعْمَلُوا فَسَيَرَى اللهُ عَمَلَكُمْ وَ رَسُولُهُ وَ الْمُؤْمِنُونَ

صدق الله العظيم

#7

كنت في البداية قد كتبت ردا أخر قبل ان اكتشف ان الامر يتعلق بكود تروجان

@najy_zl

اقتباس
بعد إذن الأخ fkugd2003 ... من أين استنتج أن الكود له علاقة بـ "تروجان" (Trojan) ؟

راجع الرابط هدا

http://www.opensc.ws/source-code-help/5766-injected-dll-error.html

في نفس الوقت Volcano

لا اظن انني هاجمتك؟؟ رأيي في هذا النوع من المواضيع معروف ..

اقتباس
ليس ذنبي اذا طلبت شرح دالة استعملها الهاكرز في برامجهم حتى وان اردت التعلم من برامج الهاكرز فما هي المشكلة ما دمت طالبا للعلم واذا عملت شيئ سيئ فانا من يتحمل المسؤولية

و يتحمل من ساعدك المسؤولية ايضا

العمل كثير و الوقت قليل أعاننا الله

seo zen SEO Enlightment amazon danbo

#8

لا يوجد في ردك تهجم وانما تحطيم emoticons.png على العموم ما عندي مشكلة ونسيت هذا الجزء من الموضوع ...

بالنسبة للرابط الذي وضعته فهوا قام باخذ سورس كود موجود في موقع آخر واستعمله في برنامجه

هذا هوا السورس كود من المبرمج

http://www.coderprof...winsock-example

وهوا لتعلم كيفية عمل اتصال بين خادم وعميل بواسطة winsock ....

تم تعديل هذه المشاركة بواسطة V0LCAN0 في 27 نوفمبر 2009 في 04:11

#9

على العموم كي لا تزعل منا :D

تفضل و عيدك مبارك .. نفس الدالة بطريقة اسهل بدون المؤشرات

function ExplodeStr(S: string; const Delim: Char; const List: Classes.TStrings;
  const AllowEmpty: Boolean = True; const Trim: Boolean = False): Integer;
var
  Item: string;       // current delimted text
  Remainder: string;  // remaining unconsumed part of string

  // ---------------------------------------------------------------------------
  procedure AddItem;
  begin
    // Adds optionally trimmed item to list if required
    if (Trim) then
      Item := SysUtils.Trim(Item);
    if (Item <> '') or AllowEmpty then
      List.Add(Item);
  end;
  // ---------------------------------------------------------------------------

begin
  // Clear the list
  List.Clear;
  // Check we have some entries in the string
  if S <> '' then
  begin
    // Repeatedly split string until we have no more entries
    while SplitStr(S, Delim, Item, Remainder) do
    begin
      AddItem;
      S := Remainder;
    end;
    // Add any remaining item
    AddItem;
  end;
  Result := List.Count;
end;

function SplitStr(const S: string; Delim: Char; out S1, S2: string): Boolean;
var
  DelimPos: Integer;  // position of delimiter in source string
begin
  // Find position of first occurence of delimter in string
  DelimPos := SysUtils.AnsiPos(Delim, S);
  if DelimPos > 0 then
  begin
    // Delimiter found: do split and return True
    S1 := Copy(S, 1, DelimPos - 1);
    S2 := Copy(S, DelimPos + 1, MaxInt);
    Result := True;
  end
  else
  begin
    // Delimeter not found: return false and set S1 to whole string
    S1 := S;
    S2 := '';
    Result := False;
  end;
end;

تم تعديل هذه المشاركة بواسطة fkugd2003 في 27 نوفمبر 2009 في 04:50

العمل كثير و الوقت قليل أعاننا الله

seo zen SEO Enlightment amazon danbo

#10

بارك الله فيك هكذا يكون fkugd2003 والا فلا emoticons.png

معرفة طرقة عديدة او متعددة يعني توسيع خلايا مخ وافكار وهذا ما اريده biggrin.gif

رائع طريقة جميلة جدا .. ساحاول فهمها جيدا

لكني ما زلت مصر على فهم الكود الذي وضعته انا

فانا اريد التعلم

والطريقة التي اريد ان افهمها هي مثلا

if (P = nil) or ((Limit > 0) and (Length(Result) = Limit - 1)) then

اذا p ارجعت nil (لان AnsiStrPos ترجع Nil في حال لم تجد المطلوب) واذا عدد العناصر اكبر من 0 و حجم result (لا اعرف في هذه الحالة ماذا يحتوي result) يساوي حجم العناصر - 1 .... وهكذا ...

و

P := StrEnd(F);

SetLength(Result, Length(Result) + 1);

SetString(Result[High(Result)], F, P - F);

F := P;

while (P^ <> #0) and (P - F < SepLen) do

Inc(P);

end;

لم افهمها لان معقدة قليلا عن الباقي ...

وعذرا على هذا الكم من الاسئلة

فانا ليس عندي من يساعدني

فاذا لم يساعدني احد سابقى اتخبط بين صفحات google ولن اجد من يقول هذا خطا وهذا صح ....

عيدك مبارك

وشكرا للاهتمام

تم تعديل هذه المشاركة بواسطة V0LCAN0 في 27 نوفمبر 2009 في 05:08

#11

لا زلت في الانتظار بارك الله فيكم

وينك اخي اخي ناجي ...ان شاء الله خير ..

#12

السلام عليكم


P := AnsiStrPos(P, PChar(Separator));

قوم بنقل المؤشر لمكان وجود الفاصلة التي نبحث عنها وينسخ السلسلة منها إلى ما بعدهها

مثلا :

P:= "hello every one "

تصبح

p:= " every one"P

SetLength(Result, Length(Result) + 1);

بما أننا نريد إضافة كلمة جديدة للمصفوفة وكنا قد حدنا طولها سابقا يجب زيادة طول هذذه المصفوفة بمعدل 1

SetString(Result[High(Result)], F, P - F);

إضافة كلمة جديدة للمصفوفة وطبعا إلى أخر بند High وهذه الكلمة مأخوذة من السلسلة F والطول الذي نريد نسخه هو الفرق بين طول P وطول F ولهذا اليبب تم نسخ محتوى P إلى F في البداية لأن P سوف يتغير

إعادة نسخ محتوى P الجديد إلى F

while (P^ <> #0) and (P - F < SepLen) do
Inc(P);

هذا ضروري للخروج من التكرار كما قلنا سابقا فإن النسخ يكون من الفاصلة وما بعدها هذا يعني أن الفاصلة سوف تبقى سوف تبقى وعند إعادة البجث سوف يجدها ثانيتا وهذا سوف يكر عملية البحث في نفس المكان

حاول تجريب الكود مع هذه الرسائل ولاحظ محتواها

function explode(const separator, s: string; limit: Integer = 0): TDynStringArray;
var SepLen: Integer;
	F, P: PChar;
begin
  SetLength(Result, 0);
  if (S = '') or (Limit < 0) then
	Exit;
  if Separator = '' then
	begin
  	SetLength(Result, 1);
  	Result[0] := S;
  	Exit;
	end;
  SepLen := Length(Separator);

  P := PChar(S);
  while P^ <> #0 do  
	begin
  	ShowMessage(P);
  	F := P;
  	P := AnsiStrPos(P, PChar(Separator));
  	ShowMessage(P);
  	if (P = nil) or ((Limit > 0) and (Length(Result) = Limit - 1)) then
    	P := StrEnd(F);
  	SetLength(Result, Length(Result) + 1);
  	SetString(Result[High(Result)], F, P - F);
  	F := P;
  	ShowMessage(IntToStr(Length(P)));
  	while (P^ <> #0) and (P - F < SepLen) do
    	Inc(P);
  	ShowMessage(IntToStr(Length(P)));
  	ShowMessage(P);
	end;  
end;
1
#13

السلام عليكم...

بعد إذن أخينا الكريم "حسين طي" و مع الاعتذار لأخينا الكريم "V0LCAN0" عن التأخير... كنت أجهز الرد منذ الأمس بشيء من التفصيل لكنني توقفت بسبب بعض المشاغل، وها قد سبقني الأخ "حسين طي" مشكوراً، و لكن لا بأس من الإعادة، ففي الإعادة إفادة!

الدالة explode تأخذ نصاً (s) يحتوي على فاصل (separator) واحد أو أكثر حيث تقوم بتقسيم النص حسب الفواصل و تعيد النصوص المفصولة على هيئة مصفوفة نصوص. عدد عناصر المصفوفة يتحدد بعدد الفواصل ضمن النص و بقيمة البارامتر limit كالتالي:

1. إذا كانت قيمة البارامتر limit صفراً فإن عدد عناصر المصفوفة يتحدد بعدد الفواصل في النص.

2. إذا كانت قيمة البارامتر limit أكبر من الصفر و كان عدد الفواصل في النص أكبر من قيمة limit فإن عدد عناصر المصفوفة يتحدد بقينة limit اعتباراً من بداية النص. مثلاً إذا احتوى النص على 5 فواصل و كانت قيمة limit هي 3 فإن حجم المصفوفة المعادة سيكون 3 عناصر: العنصر الأول يحتوي على الجزء من النص الموجود قبل الفاصل الأول، العنصر الثاني يحتوي على الجزء من النص الواقع بين الفاصل الأول و الفاصل الثاني، و العنصر الثالث يحتوي على بقية النص (من بعد الفاصل الثاني) كما هو بفواصله.

و للتوضيح أكثر، إذا كان النص هو 'East|or|West|Home|is|best' حيث يحتوي على 5 فواصل (الفاصل هنا هو العلامة '|') و كانت قيمة limit هي 3 فإن المصفوفة المعادة ستكون كالتالي:

العنصر الأول = East

العنصر الثاني = or

العنصر الثالث = West|Home|is|best

أي أن العنصر الثالث يحتوي على بقية النص.

3. إذا كانت قيمة البارامتر limit أكبر من الصفر و كان عدد الفواصل في النص أقل من قيمة limit فإن عدد عناصر المصفوفة يتحدد بعدد الفاواصل في النص.

القيمة التي تعيدها الدالة هي من النوع TDynStringArray و هو يعني مصفوفة من النصوص (strings) و يجب أن يكون هذا النوع معرفاً في مكان ما في البرنامج:

type
TDynStringArray = array of string;

أو أنه هناك خطأ إملائي في كتابة اسم النوع لأنه يوجد نوع اسمه TStringDynArray معرف في الوحدة Types التابعة لدلفي (و يجب إضافة اسم هذه الوحدة إلى عبارة uses في البرنامج).

نأتي إلى شرح طريقة عمل الدالة:

* الكلمة Result تشير إلى متغير محلي تنشئه دلفي تلقائياً داخل كل دالة و يشير إلى القيمة التي ستعيدها الدالة، و لهذا فنوع المتغير Result يكون دائماً من نفس نوع الدالة. مثلاً إذا كنا نكتب دالة تعيد قيمة من النوع Integer فإن المتغير Result يكون تلقائياً من النوع Integer، و إذا كانت الدالة من النوع String فإن Result يكون تلقائياً من النوع String و هكذا. في مثالنا هذا فإن Result عبارة عن مصفوفة نصوص.

* في البداية السطر التالي:

  SetLength(Result, 0);

يعمل على ضبط حجم المصفوفة على صفر، أي مصفوفة دون عناصر، و هذا يجعلها = nil أي مصفوفة فارغة.

* السطران التاليان:

  if (S = '') or (Limit < 0) then
    Exit;

يعني أنه إذا كان النص المطلوب تقسيمه فارغاً (لا يوجد نص) أو إذا كان عدد العناصر المطلوبة أقل من الصفر فإنه يتم الخروج من الدالة. أي أن الدالة ستعيد مصفوفة فارغة.

* الأسطر التالية:

  if Separator = '' then
    begin
      SetLength(Result, 1);
      Result[0] := S;
      Exit;
    end;

تعني أنه إذا لم يتم تحديد فاصل (separator) فذلك يعني أن كامل النص ستتم إعادته في مصفوفة ذات عنصر واحد. لاحظ أن السطر:

      SetLength(Result, 1);

يعني ضبط حجم المصفوفة (التي يمثلها المتغير Result) بحيث يكون فيها عنصر واحد (من النوع string) و ليس كما أشرت أنت سابقاً أنها ستحتوي على حرف أو رمز واحد. عندما نستخدم الإجراء SetLength لتحديد حجم مصفوفة ديناميكية فإن ترقيم عناصر المصفوفة يبدأ بالصفر (أول عنصر رقمه 0، ثاني عنصر رقمه 1، ثالث عنصر رقمه 2... إلخ).

* السطر التالي:

  SepLen := Length(Separator);

يتحصل على طول الفاصل. ذلك يعني أنه يمكننا استعمال فاصل يتكون من أكثر من رمز أو حرف واحد، مثلاً هكذا: ## أو هكذا: %%% أو هكذا: SEPARATOR ... إلخ.

* السطر التالي:

  P := PChar(S);

يجعل المؤشر P يشير إلى عنوان أول حرف أو رمز في النص S. بما أن P من النوع PChar فذلك يعني أنه يشير إلى مصفوفة من الحروف أو الرموز المتتالية المنتهية برمز الفراغ (NULL = #0). و هي ما يسمى بـ Null-terminated string.

* السطر التالي:

  while P^ <> #0 do

يبدأ حلقة تستمر حتى نهاية السلسلة النصية. نهاية السلسلة النصية هي أول حرف فارغ (NULL) الذي قيمته #0.لاحظ أن التعبير ^P يعني في هذه الحالة الحرف أو الرمز الذي يشير إليه P أي أول حرف أو رمز في السلسلة التي تشير إليها P.

* السطر التالي:

      F := P;

تجعل المتغير F يشير إلى نفس السلسلة الحرفية التي يشير إليها المتغير P. يجب أن ننتبه هنا إلى P و F يحملان نفس القيمة و يشيران إلى نفس الموقع في الذاكرة.

* السطر التالي:

      P := AnsiStrPos(P, PChar(Separator));

يستعمل الدالة AnsiStrPos للحصول على النص الموجود ابتداءً من أول فاصل إلى نهاية السلسة النصية. إذا كان هناك فاصل في السلسلة النصية فإن قيمة P ستتغير لتشير إلى موقع ذلك الفاصل، و إذا لم يكن هناك فاصل فإن قيمة P ستكون nil.

لنفرض أنه يوجد فاصل: إذن أصبحت قيمة P تشير إليه بينما ما زالت قيمة F تشير إلى أول حرف أو رمز في السلسلة. و إذا نظرنا إليهما كعنوانين في الذاكرة فإن قيمة P أصبحت أكبر من قيمة F لأنها تقع بعدها.

* السطران التاليان:

      if (P = nil) or ((Limit > 0) and (Length(Result) = Limit - 1)) then
        P := StrEnd(F);

للتأكد من أننا وصلنا إلى الحد المطلوب: إما أن P تشير إلى لا شيء (nil) أو تحصلنا على العدد المطلوب حسب قيمة limit. في كلتا الحالتين نجعل P تشير إلى نهاية السلسلة F و هو الرمز #0

* السطر التالي:

      SetLength(Result, Length(Result) + 1);

يستعمل الإجراء SetLength مرة أخرى لزيادة حجم المصفوفة بمقدار عنصر واحد. لاحظ أن الدالة Length تعطينا الحجم الحالي للمصفوفة (أي عدد عناصرها الحالية).

* السطر التالي:

      SetString(Result[High(Result)], F, P - F);

ينسخ مجموعة من الحروف أو الرموز من السلسلة F إلى العنصر الأخير (الجديد) في المصفوفة. عدد الحروف أو الرموز المنسوخة يتحدد بالتعبير P - F . لا ننسى هنا أن كلاً من P و F يشيران إلى موقعين ضمن نفس السلسلة النصية، و أن قيمة P كمؤشر أكبر من قيمة F لأنها تشير إلى عنوان أكبر، و أن الفرق بينهما هو عدد الحروف أو الرموز بينهما لأنهما من النوع PChar الذي هو سلسلة من الحروف أو الرموز. الدالة High تعطي رقم آخر عنصر في المصفوفة.

* السطر التالي:

      F := P;

يعيد ضبط قيمة F بحيث تشير إلى حيث تشير P للبدء في دورة البحث عن الفاصل التالي...

* السطران التاليان:

      while (P^ <> #0) and (P - F < SepLen) do
        Inc(P);

حلقة داخلية لتقديم موقع P لأنها حالياً تشير إلى موقع الفاصل (إذا لم تكن nil) و بدون هذه الحلقة سيدور البحث في حلقة مفرغة.

--- انتهى ---

نرجو الاستفادة و السلام.

1

وَ قُلِ اعْمَلُوا فَسَيَرَى اللهُ عَمَلَكُمْ وَ رَسُولُهُ وَ الْمُؤْمِنُونَ

صدق الله العظيم

#14

حسين طي

بارك الله فيك على شرحك واعطائي شيئ من وقتك

جزاك الله كل خير ...وغفر لك

اضافة رائعة للكود

najy_zl

المشرف العزيز

لا اعرف كيف اشكرك على هذا الشرح الرائع

جزاك الله كل خير و ادخلك الجنة ورحم والديك

تم تعديل هذه المشاركة بواسطة V0LCAN0 في 29 نوفمبر 2009 في 20:48

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…