ورود

View Full Version : ساخت آرایه داینامیک دو بعدی



emad_67
شنبه 19 خرداد 1386, 22:50 عصر
من تو یه سایت دیدم که برای ساخت آرایه داینامیک دو بعدی یه کدی رو به این شکل گذاشته بود


void main()
{
int n;
cout<<"enter your rows:";
cin>>n;
int **a=new int *[n];
for(int i=1;i<=n;i++)
a[i-1]=new int[i];
}

ولی من درست نفهمیدم که این چه جوری یه ارایه دو بعدی می سازه در واقع مشکل من سر این حلقه for هست که چه جوری بعد دوم رو به وجود میاره


for(int i=1;i<=n;i++)
a[i-1]=new int[i];

مثلا اگه من بخوام یه آرایه 3*3 به وجود بیارم تو این حلقه for برای i=1 به خونه a[0] یه خونه حافظه اختصاص میده ولی نمیدونم چه جوری مثل 3*3 آرایه به وجود میاد اگه کسی میدونه لطف کنه بگه

someCoder
شنبه 19 خرداد 1386, 23:04 عصر
مثلا اگه من بخوام یه آرایه 3*3 به وجود بیارم تو این حلقه for برای i=1 به خونه a[0] یه خونه حافظه اختصاص میده ولی نمیدونم چه جوری مثل 3*3 آرایه به وجود میاد اگه کسی میدونه لطف کنه بگه

int **a=new int *[3];
for(int i=0;i<3;i++)
a[i]=new int[3];

emad_67
شنبه 19 خرداد 1386, 23:21 عصر
به ضاهر باید همین جوری که شما مگین باشه ولی جواب نمیده اون کدی که نوشتین میاد یه ارایه 9*3 میسازه نه 3*3

someCoder
شنبه 19 خرداد 1386, 23:40 عصر
به ضاهر باید همین جوری که شما مگین باشه ولی جواب نمیده اون کدی که نوشتین میاد یه ارایه 9*3 میسازه نه 3*3

نه، کد آرایه 3*3 میسازه. برای 3 سطر و 9 ستون اینجوری میشه:

int **a=new int *[3];
for(int i=0;i<3;i++)
a[i]=new int[9];
حالا چیش جواب نمیده؟! با هر خونه که کار داشتی، مثل آرایه معمولی فراخونی کن:

a[x][y]

فقط حواست باشه که وقتی خودت new میکنی، delete هم یادت نره!

saeid5977
شنبه 19 خرداد 1386, 23:51 عصر
من تو یه سایت دیدم که برای ساخت آرایه داینامیک دو بعدی یه کدی رو به این شکل گذاشته بود


void main()
{
int n;
cout<<"enter your rows:";
cin>>n;
int **a=new int *[n];
for(int i=1;i<=n;i++)
a[i-1]=new int[i];
}

ولی من درست نفهمیدم که این چه جوری یه ارایه دو بعدی می سازه در واقع مشکل من سر این حلقه for هست که چه جوری بعد دوم رو به وجود میاره


for(int i=1;i<=n;i++)
a[i-1]=new int[i];

مثلا اگه من بخوام یه آرایه 3*3 به وجود بیارم تو این حلقه for برای i=1 به خونه a[0] یه خونه حافظه اختصاص میده ولی نمیدونم چه جوری مثل 3*3 آرایه به وجود میاد اگه کسی میدونه لطف کنه بگه
سلام
این کد میاد یه آرایه 2 بعدی درست میکنه اما نه بصورت منظم یعنی تعداد به صورت n*m نیست. سطر اول (صفرم) 1 ستون داره. سطر دوم 2 ستون الی آخر.
به نظر من کد آقای someCoder درست بود.

emad_67
شنبه 19 خرداد 1386, 23:55 عصر
بازم میگم اون کدی که گفتیم 9*3 میده شما ای کد رو اجرا کنید متوجه میشید


#include<iostream.h>
#include<stdlib.h>
#include<conio.h>
void main()
{
int i;
int **a=new int *[3];
for(i=0;i<3;i++)
a[i]=new int[3];
for(i=0;i<3;i++)
for(int j=0;j<9;j++)
a[i][j]=rand()%10;
for(i=0;i<3;i++)
for(int j=0;j<9;j++)
{
cout<<a[i][j]<<" ";
if(j==8)
cout<<endl;
}
getch();
}

emad_67
یک شنبه 20 خرداد 1386, 00:03 صبح
سلام
این کد میاد یه آرایه 2 بعدی درست میکنه اما نه بصورت منظم یعنی تعداد به صورت n*m نیست. سطر اول (صفرم) 1 ستون داره. سطر دوم 2 ستون الی آخر.
به نظر من کد آقای someCoder درست بود.

منم برام جای تعجب داره ولی کاملا مرتب ستون ها رو میچینه

someCoder
یک شنبه 20 خرداد 1386, 00:12 صبح
بازم میگم اون کدی که گفتیم 9*3 میده شما ای کد رو اجرا کنید متوجه میشید
الان این کد که نوشتی، نشون میده که یک آرایه 3*3 تعریف شده و از حد آرایه بیشتر استفاده کردی و عملا یک کد اشتباه (از نظر منطقی) نوشتی و داری با آدرسهایی که تخصیص داده نشده کار میکنی. اینو فراموش نکن که حد آرایه ها در c چک نمیشه و خود برنامه نویس باید مراقب حدود آرایه باشه.
این مثال رو اجرا کن تا بفهمی قضیه چیه.

int a[3][3], i, j;
for(i=0;i<9;i++){
a[0][i]=i;
}

for(i=0;i<3;i++){
for(j=0;j<3;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}

ضمنا، اینجا رو بخون: http://en.wikipedia.org/wiki/Array#Multi-dimensional_arrays

emad_67
یک شنبه 20 خرداد 1386, 00:34 صبح
الان این کد که نوشتی، نشون میده که یک آرایه 3*3 تعریف شده و از حد آرایه بیشتر استفاده کردی و عملا یک کد اشتباه (از نظر منطقی) نوشتی و داری با آدرسهایی که تخصیص داده نشده کار میکنی. اینو فراموش نکن که حد آرایه ها در c چک نمیشه و خود برنامه نویس باید مراقب حدود آرایه باشه.
این مثال رو اجرا کن تا بفهمی قضیه چیه.

خوب اینو من میدونم ولی اگه تخصیص حافظه نشده بود که ارور زمان اجرا پیش میومد و اصلا اون خونه ها مقذار نمی گرفتن چون مثلا اگه تو حلقه for مقدار j رو به 10 تغییر بدیم اون وقت ارور میده در زمان اجرا
در مورد این مثالتون هم خوب کامپایلر میاد با یه ارایه دو بعدی مثل یه بعدی رفتار میکنه ولی تو این مثال من قضیه فرق میکنه
ضمنا اگه اون مثالی که من در اولین پست گذاشتم غلطه پس چرا دقیقا درست جواب میده

someCoder
یک شنبه 20 خرداد 1386, 01:32 صبح
اگه تخصیص حافظه نشده بود که ارور زمان اجرا پیش میومدنه الزاما

اصلا اون خونه ها مقذار نمی گرفتن چرا میگیرن. یه جایی مقدار میگیره که مال تو نیست!

مثلا اگه تو حلقه for مقدار j رو به 10 تغییر بدیم اون وقت ارور میده در زمان اجراهمین الان هم اگر کدت رو تو NET 2005. اجرا کنی، با همین 9 بهت خطا میده.

ضمنا اگه اون مثالی که من در اولین پست گذاشتم غلطه پس چرا دقیقا درست جواب میدهاون مثال یه چیز دیگه است، اینی که تو میپرسی یه چیز دیگه و من نگفتم اون غلطه.


در مورد این مثالتون هم خوب کامپایلر میاد با یه ارایه دو بعدی مثل یه بعدی رفتار میکنه ولی تو این مثال من قضیه فرق میکنهبذار برات یه مثال دیگه بزنم تا مشکلت حل بشه:

int a[10], b[10], i;
for(i=0;i<20;i++){
a[i]=i;
}

for(i=0;i<20;i++){
cout<<a[i]<<" ";
}

emad_67
یک شنبه 20 خرداد 1386, 01:48 صبح
بذار برات یه مثال دیگه بزنم تا مشکلت حل بشه:

من مثالتونو کامپایل کردم ولیاجرا نشد طبیعی هم هست چون وقتی یه ارایه رو به صورت staticبهش حافظه میدیم مشکلی پیش نمیاد مشکل برا زمانی هست که صورت dynamic حافظه میگیره
مثلا وقتی این جوری نوشتم


void main()
{
int i;
int *a=new int[2];
for(i=0;i<5;i++){
a[i]=i;
}
for(i=0;i<5;i++)
{
cout<<a[i]<<" ";
}
}

باز هم همون مشکل پبش میاد می خوام بدونم کامپایلر با ارایه های dynamic چه حوری رفتار میکنه که این مشکل پیش میادش مثلا تو این مثال من اشاره گر رو با دو تا خونه تخصیص حافظه کردم ولی تا 5 تا عدد هم قبول میکنه

someCoder
یک شنبه 20 خرداد 1386, 02:00 صبح
خوب، خدا رو شکر که بالاخره فهمیدی ارور ندادن کامپایلر دلیل درست بودن کد نیست :چشمک: ضمن اینکه همین الان کدی که برای تو درست کار میکنه، تو کامپایلر من runtime error میده.
کامپایلر عملا چیزی به نام آرایه داینامیک نمیشناسه! تو وقتی مینویسی:

a[i]عملا کامپایلر فرض میکنه آرایه ای داریم که از آدرس a شروع شده و خونه شماره i رو تو لازم داری. پس کد تو تبدیل به این میشه:

a[i] ==> *(a+i) و کامپایلر هیچ کنترل دیگه ای روی کد تو نداره. حالا ممکنه این آدرس وقتی غلط هست، خطای زمان اجرا بگیری و ممکنه نگیری! در هر صورت مسوولیت کنترل آدرس ها با خودته.
برای اینکه ماجرای تبدیل کد کامپایلر رو ببینی، یه کار جالب میشه کرد، کدت رو اینجوری بنویس و ببین چی میشه: :چشمک:

void main()
{
int i;
int *a=new int[2];
for(i=0;i<2;i++){
i[a]=i;
}
for(i=0;i<2;i++)
{
cout<<i[a]<<" ";
}
}

emad_67
یک شنبه 20 خرداد 1386, 02:21 صبح
خیلی ممنون از جوابتون
حالا یه سوال در مورد همین runtime error در واقع وقتی کامپایلر میاد با ارایه به این صورت رفتار میکنه


a[i] ==> *(a+i)

پس عملا نباید هیچ وقت به run time error بر خورد کنیم مثلا تو همین برنامه ای که گذاشتم من وقتی اونو به این صورت مینویسم


void main()
{
int i;
int *a=new int[2];
for(i=0;i<10;i++)
a[i]=i;
for(i=0;i<10;i++)
cout<<a[i]<<" ";
}

این دفعه عدد ها رو چاپ میکنه و بعد یه error میده فقط تو این مثال من 5 رو به 10 تبدیل کردم که منطقا نباید اروری پیش بیاد ایا برای این هم میشه دلیلی اوورد یا مشکل کامپایلره؟
ضمنا در مورد اون کدتونم ممنون جالب بود

saeid5977
یک شنبه 20 خرداد 1386, 03:09 صبح
علت ارور اینکه جایی رو دستکاری کردی که برای کاری در نظر گرفته شده مثلا قسمتی از استک که ادرس برگشت تو اون push شده، که این قسمت تو حالت قبل دستکاری نمیشد.
به جرات میتونم بگم بالای 50 درصد باگ ها و ارور های برنامه هایی که تو سی نوشته میشه مربوط به همین بیرون زدن از محدوده آرایه هاست.