PDA

View Full Version : سوال: مشکل این کد که خیلی آسونه چیه؟



quiet_programmer
شنبه 06 فروردین 1390, 12:54 عصر
با سلام.

program Pointers;

type
Student=record
Name:string;
Family:string;
end;
var
Stack: Array[1..20] of pointer;
Std:^student;
TStd:^Student;
st:string;
const
Top:integer=0;

procedure Push(Data:pointer);
begin
Stack[Top]:=Data;
Top:=Top+1;
end;

function Pop:pointer;
begin
Top:=Top-1;
Pop:=Stack[Top];
end;

begin
new(std);
Std^.Name:='javad';
Std^.Family:='rasouli';
push(Std);

new(TStd);
TStd:=Pop;
st:=Tstd^.Name;

writeln;
writeln(st);
dispose(TStd);
{writeln(TStd^.Family);}
readln;

end.

تو خط writeln به جای اینکه یه new line بنویسه دوتا کاراکتر چاپ میکنه. تو خط writeln(st);l هم بعد چاپ رشته دوتا کاراکتر به جای new line چاپ میکنه.

البته خودم زیاد وارد نیستم ولی تا قبل از اجرای رویه push دستور writeln درست کار میکنه و لی بعد از فراخوانی اون رویه این اتفاق میفته.

راستی اگه در مورد اینکه از اشاره گرها درست استفاده کردم یا نه هم راهنماییم کنین ممنونتون میشم

راستی کامپایلری که من استفاده میکنم اینه
Turbo Pascal 7.0 Full

اگه راهنمایی کننین ممنون میشم.

SAASTN
یک شنبه 07 فروردین 1390, 09:36 صبح
من اون کامپایلر رو ندارم، اما اون کامپایلر از خطهای 19 و 24 خطا نمی گیره؟؟؟!
شما Top رو بصورت ثابت تعریف کردی، مقداردهی به ثابتها در زمان اجرا هم امکان پذیر نیست (البته تو delphi یجورایی میشه امکانپذیرش کرد). شما باید Top رو بصورت یه متغیر Integer تعریف کنی و در ابتدای تابع main با صفر مقدار دهیش کنی. فکر کنم تعیین مقدار اولیه برای متغیرها در c شما رو به این اشتباه انداخته.

quiet_programmer
یک شنبه 07 فروردین 1390, 10:55 صبح
با سلام.


من اون کامپایلر رو ندارم، اما اون کامپایلر از خطهای 19 و 24 خطا نمی گیره؟؟؟!نه خطا نمیگیره چون ...


شما Top رو بصورت ثابت تعریف کردی، مقداردهی به ثابتها در زمان اجرا هم امکان پذیر نیستاگه نوع ثابت تعیین نشده باشه فرمایش شما درسته ولی در این حالت که نوع متغییر Top مشخص شده مشکلی نداره و بدرستی اجرا میشه.
تنها مشکلی که هست اینه: بعد از اجرای تابع push دستور writeln به درستی کار نمیکنه. مثلا اگه بعد از اجرای تابع Push دستور writeln('SAASTN');l رو داشته باشیم عبارت SAASTN رو چاپ میکنه و بعد به جای NewLine دوتا کاراکتر که تو اجراهای مختلف فرق میکنه به جای کاراکتر 10#+13# چاپ میکنه.

به هر حال اگه در مورد دستور writeln که new line رو نمیتونه به درستی چاپ کنه توضیح بدین ممنونتون میشم.

راستی به جای دستور writeln('SAASTN');l میشه از دو دستور write('SAASTN');L و دستور write(#13+#10);l استفاده کرد.ولی من خود دستور writeln رو میخوام:افسرده:

SAASTN
یک شنبه 07 فروردین 1390, 14:05 عصر
اگه نوع ثابت تعیین نشده باشه فرمایش شما درسته ولی در این حالت که نوع متغییر Top مشخص شده مشکلی نداره و بدرستی اجرا میشه.
واا! ثابت ثابته، متغیر هم متغیره. اینا تعاریفشون معلومه. مقدار ثابت قراره در طول اجرای برنامه ثابت باشه و مقدار متغیر در طول اجرای برنامه ممکنه تغییر کنه.
حالا من نظرم اینه که وقتی یه تحصیل کرده رشته نرم افزار می خواد از این تعریف مشخص عبور بکنه حتما باید دلائل کافی ارائه کنه، حالا یه مهندس عمران یا مکانیک میخواد یه تیکه برنامه برا خودش بنویسه کاری نداریم، ولی شما که داری Stack پیاده می کنی.
حالا کامپایلرشما اگه خطا نمیده پس پیشفرضش اینه. توی دلفی هم که عرض کردم میشه کاری کرد که مقدار ثابت رو در حین اجرا تغییر بدیم، باید حتما با یه Compiler Directive به کامپایلر دستور بدی که با ثابتهای دارای نوع مثل متغیر رفتار کنه. ولی این حالت پیشفرض نیست.

حالا دوتا پیشنهاد دارم:
اول اینکه کلا اونو ولش کن بیا با دلفی کار کن. البته می تونی Console بنویسی. من پروژه شما رو عینا Copy/Paste کردم تو دلفی به همون خطی که عرض کردم گیر داد. یه {$J+} اضافه کردم بدون مشکل اجرا شد و خروجی مدنظر رو نمایش داد. شما اگه با خود دلفی کار کنی بقیه هم راحتتر می تونن کمکت کنن.
دوم اینکه اگه می خوای با همون کار کنی یه تستی بکن با متغیر بنویس ببین چی میشه، از نگاه ناقص من تنها چیز نا متعارفی که توی کد شما وجود داره که ممکنه اجرای برنامه رو با مشکل روبرو کنه همین نکته است. قبلا هم گفتم، تصور نمی کنم دلیل قانع کننده ای داشته باشید که از تعاریف مشخص رشتتون عبور کنید. من که تا حالا با موردی برخورد نکردم که به همچین چیزی نیاز داشته باشه، و واقعا توی ذهنم جای سواله که کامپایلر برای چی باید همچین امکانی رو بده؟:متفکر:

MSK
یک شنبه 07 فروردین 1390, 17:33 عصر
دوست عزیز من کدتون رو توی fpc اجرا کردم و مشکلی نداشت.
http://freepascal.org/
fp7 قدیمیه و توش باگ زیاد داره؛ من خودم زیاد به همچین مسایلی(اگه این یکی هم باگ باشه) توش برخورد کردم.
البته من کد رو با fpc 2.4.2 توی لینوکس امتحان کردم نه توی ویندوز. در هر صورت writeln ها درست کار می کردند

quiet_programmer
یک شنبه 07 فروردین 1390, 20:37 عصر
واا! ثابت ثابته، متغیر هم متغیره. اینا تعاریفشون معلومه. مقدار ثابت قراره در طول اجرای برنامه ثابت باشه و مقدار متغیر در طول اجرای برنامه ممکنه تغییر کنه. ببخشید جسارت بنده رو. من تو این کامپایلر گفتم که همچین اتفاقی میوفته. توی این ورژن از کامپایلر اگه نوع ثابت تعیین نشه خطا میگیره ولی اگه نوع تعریف بشه میشه اونو تغییر داد.

لینک زیر رو مشاهده کنین (تائید فرمایش شماست).

http://www.gnu-pascal.de/gpc/Constant-Declaration.html

درسته منم میگم بره یه کامپایلر ایراد محسوب میشه که ثابت رو بشه دوباره مقدار دهی کرد ولی از طرفی برای زبانی که هنگام تعریف متغییر نمیشه مقدار اولیه داد خوب کمک بزرگی محسوب میشه.

باور کننین اولین بارمه دارم پاسکال کد میکنم و در مورد کامپایلرهای پاسکال و مزیت و معایب اونا اطلاعی ندارم.


اول اینکه کلا اونو ولش کن بیا با دلفی کار کن. البته می تونی Console بنویسی. من پروژه شما رو عینا Copy/Paste کردم تو دلفی به همون خطی که عرض کردم گیر داد.ممنونم از پیشنهادتون ولی نمیشه. موضوع پروژه بنده تبدیل الگوریتهای بازگشتی به غیر بازگشتی معادله. منم زبانی که انتخاب کردم پاسکال بود یعنی اینکه برنامه پاسکال رو بخونه فراخوانی بازگشتی رو تشخیص بده و کد مناسب رو جایگزین کنه.

همه ی اینا رو با Bcc32 کد کردم رسیدم به جایی که باید تو زبان مبدا(پاسکال) یه استک تعریف میکردم که بتونه با انواع دیتا تایپها کار کنه. با هزارو یک مکافات (تاپیکش هم هنوز هست) بلاخره موفق شدم ولی یه مشکل دیگه که ایجاد کرد این بود.

حالا زیاد جدی نیست مجبورم تو کدم بگم که writeln ها رو هم تشخیص بده و با دوستور write جایگذین کنه.


دوم اینکه اگه می خوای با همون کار کنی یه تستی بکن با متغیر بنویس ببین چی میشه،همون اول که شما گفتین امتحان کردم ولی درست نشد.

به هرحال ممنون از اینکه راهنمایی کردین.

vcldeveloper
دوشنبه 08 فروردین 1390, 05:08 صبح
واا! ثابت ثابته، متغیر هم متغیره. اینا تعاریفشون معلومه. مقدار ثابت قراره در طول اجرای برنامه ثابت باشه و مقدار متغیر در طول اجرای برنامه ممکنه تغییر کنه.
توی Turbo Pascal اون حالت وجود داشته، به همین دلیل هم رهنمود کامپایلر J+ در دلفی ارائه شده، تا اگر به همچین چیزی نیاز داشتید، یا خواستید یک کد قدیمی را کامپایل کنید، بتونید این حالت را فعال کنید. البته به طور پیش فرض این حالت در کامپایلر دلفی غیرفعال هست.

quiet_programmer
دوشنبه 08 فروردین 1390, 10:39 صبح
با سلام.

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

UNIT MyStack;

INTERFACE

TYPE
NodePtr=^Node;
Node=record
Item:Pointer;
Next:NodePtr;
end;
TYPE
Stack=OBJECT
PRIVATE
TopPtr: NodePtr;
NewPtr: NodePtr;
StackSize: Word;
PUBLIC
CONSTRUCTOR Init;
DESTRUCTOR EndLife;
FUNCTION Empty:Boolean;
FUNCTION Size:Word;
FUNCTION Top: pointer;
FUNCTION Push(Data:Pointer):Boolean;
PROCEDURE Pop;
END;

IMPLEMENTATION

CONSTRUCTOR Stack.Init;
BEGIN
StackSize:=0;
TopPtr:=NIL;
END;

DESTRUCTOR Stack.EndLife;
BEGIN
WHILE Top<>NIL DO
Pop;
END;

FUNCTION Stack.Empty:Boolean;
BEGIN
IF TopPtr=NIL THEN
Empty:=True
ELSE
Empty:=False;
END;

FUNCTION Stack.Size:Word;
BEGIN
Size:=StackSize
END;

FUNCTION Stack.Push(Data:pointer):Boolean;
BEGIN
New(NewPtr);
IF NewPtr<>NIL THEN
BEGIN
NewPtr^.item:=Data;
NewPtr^.Next:=TopPtr;
TopPtr:=NewPtr;
StackSize:=StackSize+1;
Push:=True;
END;
Push:=False;
END;

FUNCTION Stack.Top:pointer;
BEGIN
IF TopPtr=NIL THEN
Top:=NIL
ELSE
Top:=TopPtr^.Item;
END;

PROCEDURE Stack.Pop;
VAR
PrevNode: NodePtr;
BEGIN
IF TopPtr<>NIL THEN
BEGIN
PrevNode:=TopPtr;
TopPtr:=TopPtr^.Next;
StackSize:=StackSize-1;
Dispose(PrevNode);
END;
END;
end.

نحوه استفاه از یونیت رو هم به این صورت نوشتم. (البته کد زیر یکم درهم برهمه نوشتم فقط خواستم ببینم Mystack درست کار میکنه یانه.)

PROGRAM TEST;
USES
MySTACK;
VAR
St:Stack;
a:^integer;
b:^integer;
i:integer;
begin
{clrscr;}
if st.empty then
writeln('empty')
else
writeln('full');

writeln(st.size) ;
for i:=0 to 19 do
begin
new(a);
a^:=i;
St.Push(a);
end;
writeln(st.size);
if st.empty then
writeln('empty')
else
writeln('full');
for i:=0 to 10 do
begin
b:=St.Top;
St.Pop;
writeln(b^);
end;

for i:=1 to 5 do
begin
new(a);
a^:=i;
St.Push(a);
end;

for i:=0 to 10 do
begin
b:=St.Top;
St.Pop;
writeln(b^);
end;
if st.empty then
writeln('empty')
else
writeln('full');
readln;
end.

بازم خواهش دارم اگه کد خطای منطقی داره حتما بگین.