PDA

View Full Version : سوال: ذخیره ی اطلاعات در فایل تصادفی



Muhammad-Ali
چهارشنبه 28 مرداد 1388, 11:31 صبح
سلام
من یک فایل تصادفی دارم که رکوردها را بر اساس کد اسکی "نام خانوادگی" این گونه ذخیره می کنم:
به این صورت که عدد حاصل از جمع کد اسکی حروف، رو تقسیم بر "1001" کرده و اینطوری مکان رکورد برای ذخیره بدست میاد و رکورد رو در اونجا ذخیره می کنم. اگر هم مکان مورد نظر اشغال بود، دستور دادم تا در مکان بعدی خالی ذخیره شود. (خلاصه از درهم سازی "تقسیم بر عدد اول" استفاده می کنم.)

حالا مشکلی که دارم اینه: مثلا چند تا "رکورد" که نام خانوادگی آنها "حسینی" است رو ذخیره میکنم و هیچ مشکلی نداره، هر چندتا که بخوام می تونم ذخیره کنم. ولی بعد از اینکه یک "نام خانوادگی" با کد اسکی بزرگتر وارد میشه مثل "سلیمانی"، اونوقت دیگه رکوردی با نام خانوادگی "حسینی"، ذخیره نمی شه!!!؟

اگر سوالم رو گنگ مطح کردم معذرت میخوام، هر جا که مبهم بود بگید توضیح بدم و یا اگر لازم بود کد رو بذارم.
با تشکر از همه ی دوستان

tdkhakpur
چهارشنبه 28 مرداد 1388, 15:14 عصر
نه سوالتان واضحه فقط کد بررسی شرط را ارسال کنید

Muhammad-Ali
چهارشنبه 28 مرداد 1388, 20:35 عصر
لازمه بگم که مراحل اجرای کد رو خط به خط با دیباگر VS دنبال می کنم، همه ی مراحل اجرای کد هم درست هستش، و حتی دستور fwrite هم رکورد رو، تو فایل مینویسه، ولی وقتی توی فایل نگاه میکنی، یا لیست میگیری، اثری از رکورد جدید نیست. البته بگم که این کد بارها تغییر داده شده پس اگر خنده دار به نظر می رسه ببخشید. توضیحات ناچیز زیر رو هم دادم، شاید کمکتون کنه:

t_contact که قبل از این کد مقدار گرفته، یک temp برای تست اینه که رکورد خوانده شده از فایل محتوایی داره یا نه، که این عمل با متغییر status مشخص میشه. محتوای رکوردی که باید نوشته بشه در contact هستش.
r_place مکان رکورد رو از روال درهم ساز تحویل میگیره.
ساختمان telephone هم که ساختمان اصلی هستش.
اين كه مي بینید if زیاد شده برای اطمینان هستش که ببینم مشکل از کجاست.



if (t_contact.status != 1) {
fseek(outfile,(sizeof(struct telephone)*r_place),SEEK_SET);
if (! fwrite (&contact,sizeof(struct telephone),1,outfile))
std::cout<<"--- Can't be write curently record into file ---"<<endl;
else {
fflush(outfile);
fclose(outfile);
}
}
از اینجا به بعد که اگر مکان فایل اشغال باشه next میکنه.
else if (t_contact.status == 1){

while(t_contact.status == 1) {

t_contact.status = 0;
fread(&t_contact,sizeof(struct telephone),1,outfile);
if (t_contact.status != 1) {
if (! fwrite (&contact,sizeof(struct telephone),1,outfile))
std::cout<<"--- Can't be write curently record into file ---"<<endl;
else {
fflush(outfile);
fclose(outfile);
break;
}
}//End if
}//End while

tdkhakpur
چهارشنبه 28 مرداد 1388, 20:47 عصر
سلام
به این شکلی نمیشه شما بهتر بود ساختار را هم ارسال میگردید.
به هر صورت با توجه به کد ارسالی شما میتواند دو دلیل برای این مشکل وجود داشته باشد.
1- اینکه طول نام خانوادگی را چک کنید که انازه اش کم نباشد.
2 - اینکه شما قبل از ریختن رکورد داخل فایل status را هم update کنید تا وضعیت اصلی وارد فایل بشود.
باز ارسال کنید بهتر میشود.

Muhammad-Ali
پنج شنبه 05 شهریور 1388, 15:41 عصر
سلام. با عرض معذرت خدمت آقا tdkhakpur که دیر اومدم(و همچنین سایر دوستان). چند روزی گرفتاری کاری بودم.
ادامه:


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

ساختار رو در زیر مشاهده می کنید:


struct telephone {
int status;
char family[25];
char name[20];
char h_tel[25];
char w_tel[25];
char mobile[25];
}contact;


به هر صورت با توجه به کد ارسالی شما میتواند دو دلیل برای این مشکل وجود داشته باشد.
1- اینکه طول نام خانوادگی را چک کنید که انازه اش کم نباشد.اين دليل رو خوب متوجه نشدم. به نظرم حتی اگر "نام خانوادگی" یک کاراکتر هم باشد، فکر نکنم مشکلی داشته باشد.(روی کاغذ که مشکلی نداشت)، باز اگر ایرادی داره بگین از کجا می تونه باشه.

2 - اینکه شما قبل از ریختن رکورد داخل فایل status را هم update کنید تا وضعیت اصلی وارد فایل بشود.
status یک فیلد هستش، فایل نیست، در ضمن هنگام خواندن رکورد مورد نظر وضعیت 1 رو بهش منتقل می کنم و سپس همراه رکورد مورد نظر، در فایل نوشته میشه(فکر کنم ساختار گویا هستش) که مشخص کننده ی وضعیت رکورد هستش.

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

Muhammad-Ali
پنج شنبه 05 شهریور 1388, 15:47 عصر
ببخشید، منظورتون رو بعد از ارسال متوجه شدم:

2 - اینکه شما قبل از ریختن رکورد داخل فایل، status را هم update کنید تا وضعیت اصلی وارد فایل بشود.
محتوای این فیلد رو Update می کنم.

tdkhakpur
پنج شنبه 05 شهریور 1388, 19:38 عصر
در ضمن هنگام خواندن رکورد مورد نظر وضعیت 1 رو بهش منتقل می کنم
ببینید نمیدانم برای چی این نوع الگوریتم را به کار برده اید ولی اصولا وقتی از یک منبعی مثل فایل داده ای استخراج میشود قرار دادن وضعیت یا تغییر خصوصیتی مثل status تاثیری به حال داده ها ندارد.
ولی در بررسی کد شما هیچ خطی وجود ندارد تا اسم فامیلی را بررسی کند شما بهتر هست برای هر action روی داده های فایل بررسی را با فیلدها مربوصه انجام بدید نه با فیلد وضعیت.

Muhammad-Ali
پنج شنبه 05 شهریور 1388, 23:50 عصر
ببینید نمیدانم برای چی این نوع الگوریتم را به کار برده ایداگر پیشنهادی دارین سراپا گوشم. شاید راه بهتری پیدا بشه. مثلا چه نوع الگوریتمی؟

ولی اصولا وقتی از یک منبعی مثل فایل داده ای استخراج میشود قرار دادن وضعیت یا تغییر خصوصیتی مثل status تاثیری به حال داده ها ندارد.درست میگی، این فیلد به نظر اضافه میاد. یعنی شما میگید که برای چک کردن وضعیت از همان نام خانوادگی استفاده کنم، و وجود فیلد status مشکل به وجود میاره؟؟؟در این مورد هم اگر راه حلی دارین بگین تا اعمال کنم.

ولی در بررسی کد شما هیچ خطی وجود ندارد تا اسم فامیلی را بررسی کند شما بهتر هست برای هر action روی داده های فایل بررسی را با فیلدها مربوصه انجام بدید نه با فیلد وضعیت.
با این تفاسیر فیلد status رو بردارم؟

tdkhakpur
جمعه 06 شهریور 1388, 00:00 صبح
بینید من یه چیز میگوییم و شما مطلب را به نوعی دیگر بیان میکنید.
شما اونجایی که وجود یا عدم وجود یک رکورد را بررسی میکنید بصورت شرط با نام خانوادگی قرار بدید مثلا


while(!feof(outfile)) {

t_contact.status = 0;
fread(&t_contact,sizeof(struct telephone),1,outfile);
if (strcmp(t_contactfamily, contact.family)==0){
fflush(outfile);
fclose(outfile);
std::cout<<"رکورد مشابه پیدا شد.";
break;
}else
if (feof(outfile)){
if (! fwrite (&contact,sizeof(struct telephone),1,outfile))
std::cout<<"--- Can't be write curently record into file ---"<<endl;
break;
}//End if
}//End while

البته این تغییرات با توجه به الگوریتم شماست

Muhammad-Ali
جمعه 06 شهریور 1388, 00:15 صبح
بینید من یه چیز میگوییم و شما مطلب را به نوعی دیگر بیان میکنید.
شما اونجایی که وجود یا عدم وجود یک رکورد را بررسی میکنید بصورت شرط با نام خانوادگی قرار بدید مثلا
ممنون از راهنماییتون:لبخندساده:، نظرهای شما رو اعمال می کنم، تا ببینم نتیجه چی میشه.

Muhammad-Ali
یک شنبه 08 شهریور 1388, 03:00 صبح
با سلام خدمت دوستان

آقای tdkhakpur اون الگوریتمی که واسم تصحیح کرده بودین، اصلا با کد من جور در نمیاد و من احساس می کنم، یجور دیگه برداشت شده. به هر حال اون کاری رو که شما گفتید رو من انجام دادم اما با تغییرات کلی در برنامه؛ چون که اساس تصمیم گیریها در برنامه به فیلد status متکی بود مجبور به تغییرات زیادی شدم، اما باز هم همون مشکل اول رو داشت (پست اول).
بنابراین تصمیم گرفتم تابع write برنامه رو (قدیمیه، قبل از تغییر) به طور کامل تشریح کنم:
باز هم اگر احساس کردین که چیز دیگه ای کم داره یا احتیاج داره که فایلی رو ضمیمه کنم بگید تا انجام بدم.

ساختمان رکورد رو دوباره میذارم:



struct telephone {
int status;
char family[25];
char name[20];
char h_tel[25];
char w_tel[25];
char mobile[25];
}contact;



int write_record()
{

struct telephone t_contact;
int len = 0;
int r_place = 0;


t_contact یک temp هستش که سر جاش توضیح میدم چه کار میکنه. متغییر len اندازه ی نام خانوادگی رو باید در خود نگه داره که این رو هم سر جاش توضیح میدم. r_place مکان نوشته شدن رکورد، در فایل را می گیرد، این رو هم سر جاش توضیح میدم.


//Read the contact data, Example -> family, name, . . .
contact.status=1; //"status" field Use for existing or no existing the record.

printf("Enter Family: ");
gets_s(contact.family);

printf("Enter Name: ");
gets_s(contact.name);

printf("Enter Home Telephone: ");
gets_s(contact.h_tel);

printf("Enter Work Telephone: ");
gets_s(contact.w_tel);

printf("Enter Mobile: ");
gets_s(contact.mobile);
همانطور که می بینید، کد بالا محتویات یک contact رو از صفحه کلید می خونه.
status فیلد وضعیت هستش. میدونم، شاید اضافه باشه ولی در سایر توابع و حتی همین تابع خیلی از کار ها رو آسان می کنه(چک کردن یک صفر و یک آسان تر هستش یا یک رشته!). بنابراین برای هر رکوردی که بخواد اضافه بشه یک فیلد status به طور خودکار بهش اضافه میشه.
بقیه کد هم که باید مشخص باشه. خواندن اسم و نام خانوادگی و . . .


len=strlen(contact.family);
left_right_trim(contact.family, len);

متغییر len اندازه ی فیلد "نام خانوادگی یا family" را می گیرد و سپس به تابع left_right_trim می دهد تا فضاهای خالی احتمالی چپ و راست فیلد "family" گرفته شود.



if(contact.family[0] == NULL || contact.family[0] == 32){
system("cls");
std::cout<<" No argument for write to file!\n Press eny key . . .\n ";
return -1;
}
چند خط بالا هم چک میکند که اگر فیلد "نام خانوادگی(family)" وارد نشده باشد، از تابع write خارج شود. چون این فیلد کلید است و الگوریتم Hashing باید بر روی کاراکترهای این فیلد عمل کند.


r_place=hash_file(contact.family);
متغییر r_place اینجاست که مقدار می گیرد. این متغییر مکان نوشته شدن رکورد در فایل را از تابع hash_file بدست می آورد. همانطور که می بینید، ورودی hash_file فیلد "family" می باشد.




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







FILE *outfile;
outfile=fopen("tel.dat","r+b");
if(!outfile) {
printf("Can not open file\nPress eny key");
return -1;
}
else {
rewind(outfile); //Come back to the file first.
fseek(outfile,(sizeof(struct telephone)*r_place),SEEK_SET);
fread(&t_contact,sizeof(contact),1,outfile);
}








چند خط کد بالا فایل مورد نظر را باز می کند. در شرط if اگر فایل باز نشد پیغام می دهد که نتوانسته فایل را باز کند و از تابع خارج می شود، در غیر این صورت اگر تابع باز شد، با دستور rewind به اول تابع می رود، سپس fseek به مکانی رجوع میکند که رکورد باید در آن مکان نوشته شود. اگر یادتان باشه گفتم که t_contact یک temp هستش، خوب کاراییش انجاست که رکورد جاری رو توسط تابع freed در خودش جا میده.(توضیح بیشتر: رکورد می تواند وجود داشته باشد یا می تواند وجود نداشته باشد. اگر وجود نداشته باشد که رکورد خوانده شده در همین مکان نوشته می شود در غیر این صورت، به مکان بعدی می رود. جلوتر توضیح می دهم).


if (t_contact.status != 1) {
fseek(outfile,(sizeof(struct telephone)*r_place),SEEK_SET);
if (! fwrite (&contact,sizeof(struct telephone),1,outfile))
std::cout<<"--- Can not write curently record into file ---"<<endl;
else {
fflush(outfile);
fclose(outfile);
}
}
همانطور که توضیح مختصری در بالا دادم t_contact حاوی رکوردیست؛ که موقعیت سنج فایل توسط تابع hashing به آن جا انتقال یافته است.

در خطوط بالا if بررسی می کند که t_contact حاوی رکورد با ارزشی است یا نه، یا اینکه مکان نوشتن، رکورد خوانده شده خالیست یا پر؟خوب اگر خالی باشد، fseek برای اطمینان بیشتر دوباره به مکان مورد نظر برای فایل می رود و بعد از آن ، یعنی در خط بعدی رکورد خوانده شده توسط fwrite نوشته می شود، در غیر این صورت به else if که جلوتر توضیح می دهم می رود.

(توضیح بیشتر:مثال: در توضیحات بالا مبین است که اگر نام خانوادگی ای مثل "حسینی" برای بار اول وارد فایل شده باشد، در اولین مکانی که توسط تابع hashing بدست آمده نوشته می شود.)


else if (t_contact.status == 1){

while(t_contact.status == 1) {

t_contact.status = 0;
fread(&t_contact,sizeof(struct telephone),1,outfile);
if (t_contact.status != 1) {
if (! fwrite (&contact,sizeof(struct telephone),1,outfile))
std::cout<<"--- Can not write curently record into file ---"<<endl;
else {
fflush(outfile);
fclose(outfile);
break;
}
}//End if
}//End while
}
در کدهای بالا else if چک می کند که آیا t_contact (که در بالا خوانده شد)، فیلد status اش 1 هست یا نه. خوب اگر 1 بود، (با توجه به مثالی که در بالا زدیم) مشخص می شود که مشخصات یک رکورد با نام خانوادگی "حسینی" در فایل موجود هست، و رکورد خوانده شده ی جاری باید بعد از رکورد موجود نوشته شود.
حلقه ی while نیز چک می کند که، به محض اینکه یک فضای خالی، بعد از رکورد موجود یا رکوردهای موجود در فایل پیدا کرد، رکورد خوانده شده را بنویسد. و سپس کار تابع تمام می شود.

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

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

tdkhakpur
یک شنبه 08 شهریور 1388, 12:50 عصر
سلام
خود شما گفتید که r_place مکانی هست که رکورد نوشته شده است ولی باز شما تابع hash را ارسال میکردید بهتر میشد. شما با این توضیحاتی که شما دادید باید بصورت زیر رکورد شما خوانده شود.


fseek(outfile,(sizeof(struct telephone)*r_place),SEEK_SET);
اصلاح
fseek(outfile,r_place,SEEK_SET);

اگر حل نشد برنامه تان را ضمیمه کنید

Muhammad-Ali
یک شنبه 08 شهریور 1388, 15:22 عصر
سلام
خود شما گفتید که r_place مکانی هست که رکورد نوشته شده است ولی باز شما تابع hash را ارسال میکردید بهتر میشد. شما با این توضیحاتی که شما دادید باید بصورت زیر رکورد شما خوانده شود.


fseek(outfile,(sizeof(struct telephone)*r_place),SEEK_SET);
اصلاح
fseek(outfile,r_place,SEEK_SET);
اگر حل نشد برنامه تان را ضمیمه کنید
r_plase یک متغیر هستش که برگشتی تابع hash رو در خود نگه می داره.
حالا این تابع hash کارش اینه:
به عنوان مثال نام خانوادگی "hoseiny" رو به عنوان پارامتر میگیره، بعدش میاد و کد اسکی تک تک حروف رو جمع می کنه و سپس تقسیم بر 1001 می کنه، سپس باقیمانده ی این تقسیم رو بر می گردونه. نتیجه این میشه که مقدار برگشتی تابع hash در r_place میشینه. یعنی مکانی که رکورد باید در فایل نوشته بشه.
در موقع نوشتن رکورد هم اگر این مکان (r_place) اشغال بود به یک خانه جلوتر میره، اگر باز هم اشغال بود جلوتر، تا جایی که یک مکان خالی پیدا کنه.


fseek(outfile,r_place,SEEK_SET);این کد شما هم به نظر درست نمیاد. چون که از اول فایل فقط به اندازه ی r_place جلو میره. مثلا اگر مقدار r_place 750 باشه، اونوقت فقط 750 بایت میره جلو در حالی که ما انتظار داریم به اندازه ی 750 ساختمان بره جلو.

به هر حال باز اگر مفهوم نبود، بگید برنامه رو ضمیمه کنم.

tdkhakpur
یک شنبه 08 شهریور 1388, 20:47 عصر
سلام
ببینید کدی را که من اصلاح کردم به این مطلب تکیه داشت که مقدار برگشتی شما از hashموقعیت فعلی فایل باشد.


به عنوان مثال نام خانوادگی "hoseiny" رو به عنوان پارامتر میگیره، بعدش میاد و کد اسکی تک تک حروف رو جمع می کنه و سپس تقسیم بر 1001 می کنه، سپس باقیمانده ی این تقسیم رو بر می گردونه. نتیجه این میشه که مقدار برگشتی تابع hash در r_place میشینه. یعنی مکانی که رکورد باید در فایل نوشته بشه.

ولی در مورد نکته بالا این طرز تحلیل اشتباهه چون امکان دارد عدد مشابهی بدست بیاد مثلا 2+3 یا 4+1 یا 5+0 همه شان 5 میشوند. نمشه که موقعیت فایل را براساس جمع کاراکتر ها در نظر گرفت .
برای این کار شما یک رکورد را که نوشتید با استفاده از تابع زیر موقعیت فعلی را بدست بیارید.

offset = ftell(outfile);

Muhammad-Ali
یک شنبه 08 شهریور 1388, 22:50 عصر
ولی در مورد نکته بالا این طرز تحلیل اشتباهه چون امکان دارد عدد مشابهی بدست بیاد مثلا 2+3 یا 4+1 یا 5+0 همه شان 5 میشوند. نمشه که موقعیت فایل را براساس جمع کاراکتر ها در نظر گرفت .من این الگوریتم رو بارها امتحان کردم، هم روی کاغذ و توی سیستم، 99 درصد وطمئنم مشکلی نداره.
اینی که شما میگین عدد مشابهی بدست میاد، اصلا اینطوری نیست، چون بارها تست کردم هر دفعه مکان متغییر میشه. توجه داشته باشید که من باقیمانده ی تقسیم رو ملاک قرار می دم نه جمع کاراکترها رو.
در ضمن اگر بتونین پست اول من رو بخونین خوب میشه، چون پست یه خورده طولانی شده و مشکل اصلی گم.
---

Muhammad-Ali
دوشنبه 09 شهریور 1388, 22:12 عصر
فایل مربوط به کد برنامه:

afsongarepars
چهارشنبه 18 شهریور 1388, 17:12 عصر
اگه میشه به سوالم جواب بدین شماره رکوردو چطوری پیدا کنم/؟مثلا دکمه addرو در نظر بگیر یه میزنم یه مقدارو تو فایل تصادفی ذخره میکن اگه این کارو دوباره بکنم مقدار جدید رو قبلی رونویسی میشه چیکار کنم که اضافه سه؟منتظرم حتما جواب بده:عصبانی++::افسرده:

Muhammad-Ali
چهارشنبه 18 شهریور 1388, 23:56 عصر
اگه میشه به سوالم جواب بدین شماره رکوردو چطوری پیدا کنم/؟مثلا دکمه addرو در نظر بگیر یه میزنم یه مقدارو تو فایل تصادفی ذخره میکن اگه این کارو دوباره بکنم مقدار جدید رو قبلی رونویسی میشه چیکار کنم که اضافه سه؟منتظرم حتما جواب بده:عصبانی++::افسرده:
سلام
سوالتان واضح نیست؟!

afsongarepars
شنبه 21 شهریور 1388, 16:34 عصر
یه سوال دارم چرا وقتی تو یه فایل تصادفی داده هارو به فارسی ذخیره میکنم بعد وقتی میخوام گت کنم یعنی از فایل بخونم یه چیزای عجق وجقه دیگه می یاد حا لا چیکار کنم این که واضحه؟کی جواب میدین؟:افسرده::ناراحت:

afsongarepars
شنبه 21 شهریور 1388, 16:42 عصر
سلام یادم رفت ببخشید یه سوال دیگه در کنترل flexgridفرق این دو تا چیه؟
flexgrid1.text
flexgrid1.additem
?:متفکر:

Muhammad-Ali
شنبه 21 شهریور 1388, 21:11 عصر
تایپیک تکراری لود شد.

Muhammad-Ali
شنبه 21 شهریور 1388, 21:20 عصر
اگه میشه به سوالم جواب بدین شماره رکوردو چطوری پیدا کنم/؟مثلا دکمه addرو در نظر بگیر یه میزنم یه مقدارو تو فایل تصادفی ذخره میکن اگه این کارو دوباره بکنم مقدار جدید رو قبلی رونویسی میشه چیکار کنم که اضافه سه؟منتظرم حتما جواب بده:عصبانی++::افسرده:
ببخشید الان متوجه شدم.
خوب، باید با یه الگوریتمی چک کنی؛ که اگر رکوردی در منطقه ای از فایل وجود داشت که شما قصد نوشتن رکورد جدید را دارید، اشاره گر فایل را به آدرس بعدی هدایت کنید تا رکورد جدید در آنجا نوشته بشه، اگر باز هم پر بود بعدی و همینطور ادامه بدبد تا یه جای خالی پیدا کنه. میتونید از فیلد کلید رکورد ساختمان اصلی اسفاده کنی. اولین پست صفحه 2 همین تایپیک رو اگر با دقت بخونین متوجه میشین، نمونه کدش هم هست. (البته بستگی به نوع الگوریتم درهم ساز شما هم داره)


سلام یادم رفت ببخشید یه سوال دیگه در کنترل flexgridفرق این دو تا چیه؟
flexgrid1.text
flexgrid1.additem
تجربه ای در این زمینه ندارم.

یه سوال دارم چرا وقتی تو یه فایل تصادفی داده هارو به فارسی ذخیره میکنم بعد وقتی میخوام گت کنم یعنی از فایل بخونم یه چیزای عجق وجقه دیگه می یاد حا لا چیکار کنم این که واضحه؟کی جواب میدین؟
جواب این رو هم نمیدوم، ولی اگر یک گشتی توی همین سایت بزنی، جواب سوالت رو حتما پیدا می کنی.

afsongarepars
شنبه 21 شهریور 1388, 23:00 عصر
ساعت 12:26 گذشته چرا نیومدین:افسرده:؟؟