PDA

View Full Version : آرايه اي از struct ها



اوبالیت به بو
یک شنبه 18 مرداد 1388, 15:14 عصر
سلام
مي خواستم بدونم كه آيا ميشه آرايه اي از ساختارها داشت؟من مي خوام تو پروژم اين كار رو بكنم كه اسامي كارمندان رو بگيرم و در يك struct تو حافظه ذخيره كنم. تعداد كارمندان هم 100 تا بيشتر نيست. آيا بايد آرايه اي از struct داشته باشم يا نه قضيه فرق داره؟

tdkhakpur
یک شنبه 18 مرداد 1388, 15:23 عصر
سلام
اگر از نظر فنی بخواهید نه خیر خوب نیست بهتره داده ها را یک به یک از فایل یا منبع بخوانید و بروزش کنید.
ولی اگر موضوع چیز دیگریست میتوانید مثل هر نوع تعریف دیگری آن را هم تعریف کنید.


typedef struct myst
{
char name[32];
.
.
.
.

}MyStruct;
MyStruct starray[100];

afi_program
یک شنبه 18 مرداد 1388, 18:59 عصر
بله همون طور که دوستمون نوشتن میتونی آرایه ای از ساختارها داشت.به نظر منم همین کار با توجه به تعداد کم داده ها خوب باشه

اوبالیت به بو
یک شنبه 18 مرداد 1388, 19:31 عصر
اگر از نظر فنی بخواهید نه خیر خوب نیست بهتره داده ها را یک به یک از فایل یا منبع بخوانید و بروزش کنید
نبايد از فايل استفاده كنم.
حالا اگر بخوام عناصر رو مقدار دهي كنم يا چاپ كنم چه دستوري رو بايد بنويسم؟
فرض كنيد مي خوام به كارمندم اسم بدم چي جوري از فيلد Name استفاده كنم؟

tdkhakpur
یک شنبه 18 مرداد 1388, 20:05 عصر
سلام
داخل تاپیک مجموعه برنامه های نوشته شده به زبان C و ++C (http://barnamenevis.org/forum/showthread.php?t=150444) ‏ فکر کنم صفحه 2 یک برنامه مثل کاری که شما میخوایید را قرار دادم میتوانید اسفاده کنید.

Nima_NF
یک شنبه 18 مرداد 1388, 22:07 عصر
نبايد از فايل استفاده كنم.
فرض كنيد مي خوام به كارمندم اسم بدم چي جوري از فيلد Name استفاده كنم؟

برای کپی رشته ها از strcpy یا معادل یونیکد آن و برای اعداد با علامت مساوی، مثلا:



typedef struct myst
{
char name[32];
int num;

}MyStruct;

MyStruct starray[100];

starray[5].num = 1;
strcpy(starray[5].name , "my name");

// ...

اوبالیت به بو
یک شنبه 18 مرداد 1388, 23:51 عصر
سلام به اين شبه كد نگاه كنيد:


typedef struct MyStudent
{
int StudentNumber;
char Name[30];
}Student;
Student st[100];
int cnt=0; //counter for array
int Search(int n);
void main()
{
cout << "Enter Student Number:" << "\t";
cin >> st[cnt].StudentNumber;
if (Search (st[cnt].StudentNumber)==1)
cout << "can notadd Student";
else
{
cout << "\n" << "Enter Name:" << "\t";
cin >> st[cnt].Name;
}
cnt++;
}
int Search(int n)
{
for (int i=0;i<100;i++)
if (n=st[i].StudentNumber)
return 1;
return -1;
}

من وقتي براي اولين بار بعد از اينكه شماره دانش آموز رو وارد كردم برنامه بايد به متد Search بره. اما پاسخي كه متد Search به من مي ده اشتباه هستش. يعني اون چيزي كه return مي كنه اشتباه هستش. چه روش خطي چه دودويي پاسخ رو اشتباه بر مي گردونه.
1) مشكلش به نظر شما چيه؟
2) اصلاً اين روش كد زدن درست هست؟ نمي خوام از pointer ها استفاده كنم!

tdkhakpur
دوشنبه 19 مرداد 1388, 00:25 صبح
اصلاح شده


for (int i=0;i<100;i++)
if (n=st[i].StudentNumber)
return i; // اصلاح کنید

اوبالیت به بو
دوشنبه 19 مرداد 1388, 11:19 صبح
ممنون جنابtdkhakpur (http://barnamenevis.org/forum/member.php?u=99732)
ولي علت تغييرخروجي return چيه؟ return قبلي چرا جواب نمي داد؟

afi_program
دوشنبه 19 مرداد 1388, 11:29 صبح
شرمنده کدی که نوشتین یه ایراد بد داره!!

if (n=st[i].StudentNumber)باید
if (n==st[i].StudentNumber)باشه

afi_program
دوشنبه 19 مرداد 1388, 11:38 صبح
برای تشکر از دکمه تشکر استفاده کن.
چون همیشه وارد if میشه و 1 برمیگردونه.ولی تو برنامه باید میزاشتی 1- تا درست باشه

اوبالیت به بو
دوشنبه 19 مرداد 1388, 11:38 صبح
شرمنده کدی که نوشتین یه ایراد بد داره!!

if (n=st[i].StudentNumber)باید
if (n==st[i].StudentNumber)باشه

ممنون كدم همين شكلي هست. اينجا دستي مي نوشتم ديگه يادم رفته بود. ولي همين شكليه.
در ضمن مشكل هنوز پا برجاست.
مشكل اينجاست:


if (Search (st[cnt].StudentNumber)==1)
cout << "can notadd Student";
else
{
cout << "\n" << "Enter Name:" << "\t";
cin >> st[cnt].Name;
}

اين if اصلاً درست كار نمي كنه. Step Over كردم كه ببينم چرا اينجوري ميشه دليلش اينه كه اصلاً شرط به درستي چك نميشه. يعني اولين دستور بعد از if اجرا ميشه.

كاري كه من مي خوام بكنم اين هست:
شماره دانشجويي رو تو آرايه اي كه از struct هست ذخيره مي كنم. بايد چك كنم ببينم كه در حافظه هست يا نه تا اجازه عمليات ديگه رو بدم. اعصاب مارو خورديده:لبخند::کف::لبخند:

afi_program
دوشنبه 19 مرداد 1388, 11:46 صبح
همون طور که گفتم به نظرم شرط باید 1- باشه.امتحان کن.
برای تشکر از دکمه تشکر استفاده کن.

اوبالیت به بو
دوشنبه 19 مرداد 1388, 11:49 صبح
همون طور که گفتم به نظرم شرط باید 1- باشه.امتحان کن.

قربون شكلت چه فرقي مي كنه اگه شرط false باشه نبايد دستورش اجرا بشه اما من چه -1 و چه i رو return مي كنم اولين دستور بعد if اجرا ميشه.
قاعده مي گه كه نبايد فرق بكنه چون شرط دو حالت داره پس شما چه اول بنويسي چه آخر نبايد فرقي بكنه.

اوبالیت به بو
دوشنبه 19 مرداد 1388, 12:32 عصر
خيلي باحال شد. اينجارو:


if (Search (st[cnt].StudentNumber)==-1)
cout << "is not register";
else
cout << "is register";

مقدار خروجي is register هست.
حالا كد رو اينجوري تغيير مي دم:


if (Search (st[cnt].StudentNumber)!=-1)
cout << "is not register";
else
cout << "is register";

مقدار خروجي is not register هست.

دليلش رو كسي مي دونه؟

Nima_NF
دوشنبه 19 مرداد 1388, 13:43 عصر
نوشتن برنامه به این شکل (کدی که تحت عنوان شبهه کد نوشتید) غلط هست.
این کد فقط تا زمانی درست هست که برنامه اجرا باشد و طبق کدی که شما نوشتید cnt همیشه صفر هست، پس همیشه با اولین دور حلقه for داخل تابع search اولین if درست خواهد بود و return هم همیشه 1 هست. چون برنامه را همیشه یک مرتبه اجرا می کنید پس مطمئنا وقتی چیزی قبلا داخل آرایه struct شما نیست باید همیشه در اولی وجود داشه باشد.

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

ضمنا، در آخرین پست شما از != استفاده کردید، یعنی مخالف، خوب مسلما وقتی تاحالا if درست بود این دفعه باید else درست باشد!

اوبالیت به بو
دوشنبه 19 مرداد 1388, 13:53 عصر
این کد فقط تا زمانی درست هست که برنامه اجرا باشد
پروژه همينه. يعني فقط زماني كه برنامه اجرا ميشه بايد متغيرها مقدار بگيرن.

طبق کدی که شما نوشتید cnt همیشه صفر هست،
cnt در ابتدا صفر هستش. اين cnt براي پيمايش آرايه st هستش كه در پايان مقدار دهي فيلد StudentNumber و Name يك واحد بهش اضافه ميشه. البته يه شرط قبلش گذاشتم كه اين روند تا 100 بار بيشتر اجرا نشه.

پس همیشه با اولین دور حلقه for داخل تابع search اولین if درست خواهد بود و return هم همیشه 1 هست.
احسنت. دقيقاً همين اتفاق مي افته.

چون برنامه را همیشه یک مرتبه اجرا می کنید پس مطمئنا وقتی چیزی قبلا داخل آرایه struct شما نیست باید همیشه در اولی وجود داشه باشد.

اين درست. ولي من قبل از اينكه متد Search رو صدا بزنم st[cnt].StudentNumber كه در ابتدا صفر هستش (يعني خانه اول) رو مقدار دهي مي كنم. پس با توجه به گفته شما اولين خانه نبايد مقدارش صفر باشه چون قبلاً مقدار دهي شده.
ممنون كه وقت مي ذاريد.

Saeed_m_Farid
دوشنبه 19 مرداد 1388, 15:41 عصر
خيلي باحال شد. اينجارو:


if (Search (st[cnt].StudentNumber)==-1)
cout << "is not register";
else
cout << "is register";
مقدار خروجي is register هست.
حالا كد رو اينجوري تغيير مي دم:


if (Search (st[cnt].StudentNumber)!=-1)
cout << "is not register";
else
cout << "is register";
مقدار خروجي is not register هست.

دليلش رو كسي مي دونه؟
جناب obalitjoOon، دقیقاً می خواهید چکار کنید؟ آخه تو یه آرایه خالی که احتمالاً پر مقادیر تصادفی است، چطوری دنبال یه رکورد خاص می گردید؟ در مورد سوال بالا هم خوب اگه درست نباشه، غلطه دیگه، تعجب نداره!
جسارتاً فکر کنم امروز خیلی به مغزتون فشار آوردین؛ اصولی اش اینه که اگه دنبال رکوردی می گردین، قبلاً لیست تون رو پر کنید و بعد دنبال عضوی از اون بگردید، برای نمونه از فایل لیست رو لود کنید، مثلاً اینطوری :

int loadStudentNames(char* TheFile)
{
FILE* pSearchFile = NULL;
char c[2] = "\0",
pCurStr[255];

cnt = 0;
strcpy(pCurStr, "");
if (pSearchFile = fopen(TheFile, "r"))
{
while ((c[0]=getc(pSearchFile) )!= EOF)
{
c[1] = '\0';
if((c[0] != 10 ) &&
(c[0] != ' ') &&
(c[0] != 13 ) )
{
strcat(pCurStr, c);
}else
{
strcpy(c, "\0");
strcpy(st[cnt++].Name, pCurStr);
strcpy(pCurStr, "");
}
}
fclose(pSearchFile);
return cnt;
}else
{
fclose(pSearchFile);
return false;
}
}
اینطوری اسامی از فایل خونده میشن، بعد برای نمونه بازاء cnt ای که از فایل مقداردهی شده، StudentNumber ها رو هم بدین، بعد مثلاً دنبال یه ایندکس خاص که از کاربر گرفتید، بگردین، یا عضوی رو تغییر بدین.
من یکمی کدتون رو برای نمونه، دستکاری کردم :

//---------------------------------------------------------------------------

#include <stdio>
#include <string>

//---------------------------------------------------------------------------

typedef struct MyStudent
{
int StudentNumber;
char Name[30];
}Student;

Student st[100];
int cnt=0; //counter for array

//---------------------------------------------------------------------------

int Search(int n)
{
for (int i=0; i<100; i++)
if (n == st[i].StudentNumber)
return i+1;
return false;
}

//---------------------------------------------------------------------------

int loadStudentNames(char* TheFile)
{
FILE* pSearchFile = NULL;
char c[2] = "\0",
pCurStr[255];

cnt = 0;
strcpy(pCurStr, "");
if (pSearchFile = fopen(TheFile, "r"))
{
while ((c[0]=getc(pSearchFile) )!= EOF)
{
c[1] = '\0';
if((c[0] != 10 ) &&
(c[0] != ' ') &&
(c[0] != 13 ) )
{
strcat(pCurStr, c);
}else
{
strcpy(c, "\0");
strcpy(st[cnt++].Name, pCurStr);
strcpy(pCurStr, "");
}
}
fclose(pSearchFile);
return cnt;
}else
{
fclose(pSearchFile);
return false;
}
}

//---------------------------------------------------------------------------

void main(void)
{
loadStudentNames("C:\\123.txt");

for (int idx=0; idx<cnt; idx++)
st[idx].StudentNumber = idx+1;

int iNum = 0,
iFnd = 0;
printf("%s\t", "Enter Student Number:");
scanf("%d", &iNum);
if (iFnd = Search (iNum))
{
printf("\n Student[%d] Old Name = %s\n", iFnd, st[iNum].Name);
printf("\n Enter New Name: \t");
scanf("%s", &st[cnt].Name);
}
else
printf("can not find Student");
}
//---------------------------------------------------------------------------
پ.ن. : فقط چون کامپایلر من cout و cin رو قبول نمی کرد - شایدم قبول میکرد ولی من عادت ندارم! - ، با printf و scanf جایگزین کردمشون، اون قسمتها رو توجه نکنید...

اوبالیت به بو
دوشنبه 19 مرداد 1388, 21:33 عصر
خيلي ممنون Saeed_m_Farid (http://barnamenevis.org/forum/member.php?u=41415) از اين كه وقت مي ذاريد.
ببينيد من نبايد از فايل استفاده كنم وگرنه خودم اين كار رو مي كردم.
سوال من اينه:

قبل از اينكه متد Search فراخواني بشه من خانه اول حافظه رو مقداردهي كردم. اما وقتي در متد Search مي خواد از خانه اول (يعني صفر) شروع به جستجو كنه با مقدار صفر روبه رو ميشه و در همون اولين if از متد خارج ميشه. چرا؟ مگه من قبلاً مقداردهي نكردم؟

Saeed_m_Farid
سه شنبه 20 مرداد 1388, 09:05 صبح
قبل از اينكه متد Search فراخواني بشه من خانه اول حافظه رو مقداردهي كردم. اما وقتي در متد Search مي خواد از خانه اول (يعني صفر) شروع به جستجو كنه با مقدار صفر روبه رو ميشه و در همون اولين if از متد خارج ميشه. چرا؟ مگه من قبلاً مقداردهي نكردم؟
نه با مقدار صفر روبرو نمیشه، مقداردهی شما درسته ولی شرط بررسی و دید شما غلطه.
اگه تو کد قبلی بنده، به تابع Search تغییر داده شده نگاه می کردین، متوجه یه تغییر کوچک می شدین، ضمناً موقع بررسی نتیجه Search به عدم درستی باید نگاه کنید، کاری که شما برعکسش رو انجام دادین؛ یعنی کد شما میشه به صورت زیر (بدون پر کردن آرایه از فایل) :


//---------------------------------------------------------------------------

typedef struct MyStudent
{
int StudentNumber;
char Name[30];
}Student;

Student st[100];
int cnt=0; //counter for array
int Search(int n);

void main( )
{
cout << "Enter Student Number:\t";
cin >> st[cnt].StudentNumber;
if (Search(st[cnt].StudentNumber))
{
cout << "\n Enter Name:\t";
cin >> st[cnt].Name;
}
else
cout << "can''t Find Student";

cout << "Number = " << st[cnt].StudentNumber
<< ", Name = " << st[cnt].Name;
getch();
}

int Search(int n)
{
for (int i=0;i<100;i++)
if (n==st[i].StudentNumber)
return i+1;
return false;
}
//---------------------------------------------------------------------------

به هر صورت حتی با اینکه این کد کار میکنه، به قول Nima_NF، بنظر من هم دقیقاً "نوشتن برنامه به این شکل (کدی که تحت عنوان شبهه کد نوشتید) غلط هست."؛ اصلاً cnt به چه کارتون میاد؟ یا منطق کد چیه؟

موفق باشید.

tdkhakpur
سه شنبه 20 مرداد 1388, 15:48 عصر
سوال من اينه:
قبل از اينكه متد Search فراخواني بشه من خانه اول حافظه رو مقداردهي كردم. اما وقتي در متد Search مي خواد از خانه اول (يعني صفر) شروع به جستجو كنه با مقدار صفر روبه رو ميشه و در همون اولين if از متد خارج ميشه. چرا؟ مگه من قبلاً مقداردهي نكردم؟
سلام

cin >> st[cnt].StudentNumber;
شما نباید محتوای ساختار را در معرض ورودی قرار بدید به جای متغییر موجود در داخل ساختار یک متغییر دیگر تعریف و استفاده کنید.
صورت اصلی برنامه را به شکل زیر تغییر بدید


void main( )
{
int StudentNumber, FindIndex;
cout << "Enter Student Number:\t";
cin >> StudentNumber;
FindIndex = Search(StudentNumber);
if (FindIndex!=-1)
{
cout << "\n Enter Name:\t";
cin >> st[index].Name;
}
else
cout << "can''t Find Student";

cout << "Number = " << st[index].StudentNumber << ", Name = " << st[index].Name;
getch();
}


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

اوبالیت به بو
سه شنبه 20 مرداد 1388, 15:56 عصر
از دوستاني كه وقت گذاشتن ممنون. ولي يه نكته بود كه هيچ كس بهش توجه نكرد و اكثراً مي گفتين كه با آرايه خالي مواجه ميشه. خوب ميشه كه ميشه چه ربطي داره؟ آرايه اگر خالي باشه با صفر مقداردهي ميشه و بالاخره بايد شرط اجرا بشه.
اين برنامه هم نبايد از فايل استفاده كنه اگر مي شد كه اين كار رو مي كردم.

دوستان اين كدي كه من نوشتم درست اجرا ميشه نكته اي كه هيچ كس به اون اشاره نكرد و به ذهن خودمم نرسيد اين بود كه در شرط st[i].StudentNumber==Num كه در متد Search وجود داره مقدار صحيح return ميشه چون در اولين اجراي حلقه داره خودش رو با خودش مقايسه مي كنه خوب معلومه كه اولين دفعه 1 رو return كنه. به اين خاطر كه st[0].StudentNumber در پارامتر Num ريخته ميشه و خوب چون اولين بار هستش كه مقدار ميگيره معلومه كه در اولين شرط مقدار 1 رو return مي كنه چون خودش، خودش رو پيدا مي كنه.
راه حل اينه كه در main برنامه يه متغير ديگه تعريف كنيم و اون رو به پارامتر Num ارسال كنيم و در متد Search بيام st[i].StudentNumber رو با Num مقايسه كنيم.
شكل صحيح برنامه:


void main()
{
long STDNum=0;
cout << "Enter Student Number:" << "\t";
cin >> STDNum;
if (Search (STDNum)==1)
cout << "can notadd Student";
else
{
st[cnt].StudentNumber = STDNum
cout << "\n" << "Enter Name:" << "\t";
cin >> st[cnt].Name;
}
cnt++;
}
int Search(int n)
{
for (int i=0;i<100;i++)
if (n==st[i].StudentNumber)
return 1;
return -1;
}

اوبالیت به بو
سه شنبه 20 مرداد 1388, 16:00 عصر
مرسي جناب tdkhakpur (http://barnamenevis.org/forum/member.php?u=99732) مثل اينكه همزمان پيام رو ارسال كرديم.
در پست آخرتون (http://barnamenevis.org/forum/showpost.php?p=778486&postcount=21) درست اشاره كرديد.

Saeed_m_Farid
سه شنبه 20 مرداد 1388, 16:40 عصر
آرايه اگر خالي باشه با صفر مقداردهي ميشه و بالاخره بايد شرط اجرا بشه. ...

نه خیر، اگر خالي باشه با یک مقدار تصادفی مقداردهی میشه که امکان داره برابر با مقدار شما باشه و همه چی بهم بریزه.

...
در شرط st[i].StudentNumber==Num كه در متد Search وجود داره مقدار صحيح return ميشه چون در اولين اجراي حلقه داره خودش رو با خودش مقايسه مي كنه ...

موردی هم که شما بهش توجه نکردین، صورت مساله است. شما باید می فرمودید که : "برنامه ای میخوام بنویسم که لیست دانش آموزان رو میگیره و اگه قبلاً شماره دانش آموز موردنظر وجود داشته باشه، نمی خواهید ویرایش کنیدش ... " - البته این لیست تو حافظه ذخیره میشه و بعد از پایان برنامه از بین میره (که لیست هم نیست یه عضوه!)

اگه حتی روی مساله همین هم باشه، شما بازم باید از while یا for استفاده کنید تا یه تعداد دانش آموز رو بگیرید و یه عملیاتی باهاشون انجام بدین، نه اینکه یه عضو رو پر کنید و برنامه رو ببندید! خوب برنامه که بسته میشه، همه چی از بین میره، صحبت من اینه که شما چه استفاده ای از عضو وارد شده کردین؟

به ما حق بدین که ندونیم منظور شما از برنامه چیه ...

اوبالیت به بو
سه شنبه 20 مرداد 1388, 17:15 عصر
نه خیر، اگر خالي باشه با یک مقدار تصادفی مقداردهی میشه که امکان داره برابر با مقدار شما باشه و همه چی بهم بریزه.

اگر اين كد رو run كنيد مقادير صفر رو ميبينيد:


for (int i=0;i<100;i++)
cout << st.StudentNumber << "\t";


موردی هم که شما بهش توجه نکردین، [I]صورت مساله است. شما باید می فرمودید که : "برنامه ای میخوام بنویسم که لیست دانش آموزان رو میگیره و اگه قبلاً شماره دانش آموز موردنظر وجود داشته باشه، نمی خواهید ویرایش کنیدش ... " - البته این لیست تو حافظه ذخیره میشه و بعد از پایان برنامه از بین میره (که لیست هم نیست یه عضوه!)
چون برنامه 1 بار اجرا ميشه و دفعه بعدي وجود نداره. نبايد عضوها رو از فايل بخونه يا بنويسه بلكه بايد در حافظه نگه داره و بعد پايان برنامه از بين بره. (سناريو اينه من كه كاره اي نيستم)

اگه حتی روی مساله همین هم باشه، شما بازم باید از while یا for استفاده کنید تا یه تعداد دانش آموز رو بگیرید و یه عملیاتی باهاشون انجام بدین، نه اینکه یه عضو رو پر کنید و برنامه رو ببندید! خوب برنامه که بسته میشه، همه چی از بین میره، صحبت من اینه که شما چه استفاده ای از عضو وارد شده کردین؟

من قسمتي از برنامه رو گذاشتم. تكميل كه شد اينجا ارائه مي دم.
با for يا while هم ميشه نوشت.

به ما حق بدین که ندونیم منظور شما از برنامه چیه ...
چشم. خوب بيان نكردم.