ورود

View Full Version : مبتدی: استفاده از شی get برای وارد کردن رشته



hossein2kk
دوشنبه 19 بهمن 1388, 22:34 عصر
سلام دوستان
چرا تو c++ قتی از این شی دو بار استفاده می کنیم مثلا :

int main () {
char str1[40] , str2 [40] ;
cin.get (str1,39);
cout << "Please enter the second one ..." ;
cin.get(str2,39);
cout << str1 << " " << str2;
getch();
return 0;
}
ساختار دوم get اسکیپ میشه ؟ ولی اگه اینطوری بنویسیم :

int main () {
char str1[40] , str2 [40] ;
cin.get (str1,39);
cout << "Please enter the second one ..." ;
cin.get();
cin.get(str2,39);
cout << str1 << " " << str2;
getch();
return 0;
}
درست میشه ؟ ون ساختار خالی چیکار می کنه ؟ تو یه کتابی کامنت داده بود جلوش :for discard end of line char ولی نفهمیدم منظورش چی بود .
پیشاپیش ممنون:چشمک:

hossein2kk
سه شنبه 20 بهمن 1388, 01:11 صبح
با اجازه مدیریت محترم تالار برای اینکه تالار شلوغ نشه همین جا سوال هام رو مطرح می کنم.
دوستان تو تابع زیر که برای تبدیل رشته به عدد هست چند تا نکته گنگ تو ذهن من مونده :

void ascii_to_int(int *value , char *str){
int sign = 1;
*value = 0;
while (*str == '-') str++;
if(*str=='-' || *str=='+')
sign = (*str ++ == '-') ? -1 : 1 ;
while (*str){
if((*str >= '0') && (*str <= '9'))
* value = (*value * 10) + (*str ++ -48);
else{
cout << "Warning : the <"<<*str<<"> is invalid charecter.\n";
break;
}
}
*value *= sign;
}
اول sign = (*str ++ == '-') ? -1 : 1 . این قسمت داره مقدار sign رو یا به عبارتی مثبت یا منفی بودن عبارت رو مشخص می کنه اما مشکل من تو شرط این ساختار هست .روی این شرط اگر دوستان توضیحی بدن سپاسگزار می شم.
دوم *value = (*value * 10) + (*str ++ -48) حقیقتش رو بخواید من از این قسمت چیز خاصی نفهمیدم :ناراحت: اگر یکی از دوستان لطف کنن توضیح کاملی بی نهایت ممنون میشم.
ضمنا من با توجه به طرح سوال این نمونه کد رو خودم نوشتم که جواب هم داد :

int ascii_to_int(char str []){
int len = strlen(str);
int result = 0 ;
int count = len-1;
for (int i = 0; i < len ;i++)
result += ((str[i]-'0') * pow(10 , count--));
return result;
}
ضمنا اگر کسی ایده ای برای بهتر شدن و کارایی بیشتر کد میشناسه ذکر کنه باز هم ممنون میشم.

sh4mid
سه شنبه 20 بهمن 1388, 03:38 صبح
خوشحالم که به C علاقمند شدی .:تشویق: خوب بریم سر سوالات
تو اولی گفتی

تو یه کتابی کامنت داده بود جلوش :for discard end of line char ولی نفهمیدم منظورش چی بودببین وقتی با تابع Get اولی یه رشته رو دریافت می کنی وقتی رشته رو کامل کردی Enter رو می زنی و رشته ای از از طریق صفحه کلید وارد کردی میره تو متغیر اولی ولی اون Enter نمیره یا همون نشانه CR-LF ... اون تو Buffer صفحه کلید می مونه اینجا وقتی اون تابع
cin.get() رو می نویسی در واقع اون Enter رو که تو Buffer مونده می خونی تا Buffer خالی بشه بعد میری سراغ دریافت رشته بعدی و اگه این کارو نکنی وقتی می خوای رشته بعدی رو بخونی بجای رشته اون Enter می ره تو متغیر str2
بریم سراغ دومی

اول sign = (*str ++ == '-') ? -1 : 1ببین این تابع قراره یه رشته بگیره و معادل عددی اش رو پس بده اگرم رشته مشکل داشت یه پیغام بده . str یه اشاره گر به char یا در واقع همون رشته است "آرایه ای از char"
با استفاده از عملگر * به محتویات یه اشاره گر می شه دسترسی پیدا کرد یعنی میشه فهمید تو اون چی ریخته شده ، با استفاده از عملگر ++ اشاره گر به خونه بعدی حافظه اشاره می کنه یعنی یه خونه میره جلو ، خوب چی داریم اینجا می گه اگه محتویات str برابر '-' بود بیا مقدار sing رو بگذار 1- وگرنه بگذار 1 بعدشم str رو یکی زیاد کن یعنی برو خونه بعدی "اگه دقت کرده باشی این تابع اول علامت موجود در رشته رو بررسی می کنه ".

(value = (*value * 10) + (*str ++ -48*این تابع دو تا ورودی داره اولی یه اشاره گر به int و دومی یه رشته ، اینجا برای اینکه بتونیم مقدار عددی رشته رو بیرون بدیم از این اشاره گر به int استفاده می کنیم " Call By Reference" در واقع متغیر اول خروجی تابع در صورت کارکرد درست اون هست 'اینجا با آرایه ای از int سروکار نداریم'
(str ++ -48*) اینجا مقدار موجود در متغیر str رو از '0' کم می کنیم نتیجه معادل عددی char می شه مثلا اگه str برابر '8' باشه وقتی اونو از '0' کم کنیم مقدار عددی 8 رو به ما میده وقتی مقدار عددی اونو داد بعدش اونو یکی زیاد می کنه تا به خانه بعدی تو حافظه اشاره کنه اون مقدار عددی رو هم میریزه تو value دفعه بعد هم اول value رو در 10 ضرب میکنه و با عدد جدید جمع می کنه.
در مورد عملگر ? هم که دوستمون توضیح دادن

ضمنا اگر کسی ایده ای برای بهتر شدن و کارایی بیشتر کد میشناسه ذکر کنه باز هم ممنون میشم1- استفاده از تابع atoi
2- هیچ وقت اینجوری برنامه ننویس این مدل برنامه نویسی بدترین نوعشه پر از خطاهایی که فکرشو نمی کنی مثلا معلوم نیست برای متغیر str چقدر فضا اختصاص داده شده ، متغیر value به کجای حافظه اشاره می کنه ما نمی دونیم ولی اول فراخوانی تابع محتویاتشو صفر می کنیم همچنین نمونه کدهایی مثل (str ++ -48*) درسته که تو C Std گفته این تکه کد چطور باید باهاش برخورد بشه ولی Compiler های مختلف ممکنه نتیجه های مختلف بهمون بدن بعضی از compiler ها ممکنه برنامه بالا رو بدون دردسر Compile کنند ولی بعضی ها هم ممکنه که warning ها و خطاهای زیادی رو به ما اعلام کنند.
3- با دقت از مفهوم اشاره گر استفاده کن
اوه عجب پستی شد:کف:

hossein2kk
سه شنبه 20 بهمن 1388, 13:19 عصر
فوق العاده عالی !:تشویق:
بسیار ممنون از دو دوست عزیز Negative_Se7en (http://barnamenevis.org/forum/member.php?u=134418) و sh4mid (http://barnamenevis.org/forum/member.php?u=35307) !:قلب:
ضمنا Negative_Se7en (http://barnamenevis.org/forum/member.php?u=134418) جان انگار بچه محل ه در اومدیم ! من هم ساکن اسلامشهر - واوان هستم !:چشمک:
خوب با اینکه توضیحات دوستان واقعا کامل بود ولی من باز هم کمی بحث دارم !

سلام دوست عزیز.اول در مورد سوال اولت بگم 1 : sign = (*str ++ == '-') ? -1این یه ساختار شرطی که مقدار str رو ++ میکنه یعنی (str +=1) ، و بعد چک میکنه اگر این مقدار بشه با '-' sign رو مساوی با -1 میکنه و در غیر این صورت sign رو برابر با 1 میکنه.
خوب رو این موضوع میشه یکم فکر کرد !
اول خط قبل رو ببینیم :


while (*str == '-') str++;
خوب با این کد ما تا زمانی که فضای خالی داشته باشیم 1 خونه 1 خونه جلو میایم و وقتی که آخرین فضای خالی رو رد کردیم اشاره گر ما داره به همون sign یا علامت + یا - اشاره میکنه .
حالابه این ساختار رسیدیم :

(*str ++ == '-')
همون طور که استاد عزیز sh4mid (http://barnamenevis.org/forum/member.php?u=35307) فرمودن به محتوای خونه داریم اشاره می کنیم با عملیات ++ ما محتوای خونه رو یه واحد اضافه کنیم اگه می خواستیم یک خونه جلوتر بریم که با ساختار while بالا دیدیم که نیاز به استفاده از * نیست . یعنی کد اسکی رو برای - یه واحد اضافه می کنیم که حالا معلوم نیست چیه ! بعد اون موقع می گیم که - هست یا نه که با این برداشت های من نقیض است . همین الان من برنامه رو هم برای یک ورودی فرضی -225 تست کردم و دیدم که اگه به مقدار خروجی یک واحد اضافه کنیم علامت منفی رو در نظر نمی گیره و خروجی 226 میده .

این تابع دو تا ورودی داره اولی یه اشاره گر به int و دومی یه رشته ، اینجا برای اینکه بتونیم مقدار عددی رشته رو بیرون بدیم از این اشاره گر به int استفاده می کنیم " Call By Reference" در واقع متغیر اول خروجی تابع در صورت کارکرد درست اون هست 'اینجا با آرایه ای از int سروکار نداریم'
(str ++ -48*) اینجا مقدار موجود در متغیر str رو از '0' کم می کنیم نتیجه معادل عددی char می شه مثلا اگه str برابر '8' باشه وقتی اونو از '0' کم کنیم مقدار عددی 8 رو به ما میده وقتی مقدار عددی اونو داد بعدش اونو یکی زیاد می کنه تا به خانه بعدی تو حافظه اشاره کنه اون مقدار عددی رو هم میریزه تو value دفعه بعد هم اول value رو در 10 ضرب میکنه و با عدد جدید جمع می کنه.
در مورد عملگر ? هم که دوستمون توضیح دادن
خوب شما فرمودید که با * ما به محتوا دسترسی پیدا می کنیم در صورتی که آموخته های کم من میگه برای یک خونه جلو بردن اشاره گر ذکر اسم اشاره گر یعنی همون str نیازه . عملا برداشت من از این قطعه کد :

*value = (*value * 10) + (*str ++ -48);
یک واحد به محتوای جایی که str به آن اشاره می کند اضافه کن و سپس 48 واحد از این مقدار کم کن و با 10 برابر شده مقدار قبلی جمع کن . البته این قسمت برداشت من با توجه به خروجی برنامه فکر کنم اشتباه هست ولی اگه دوستان توضیحاتی تکمیلی ارائه کنن ممنون میشم.

1- استفاده از تابع atoi
2- هیچ وقت اینجوری برنامه ننویس این مدل برنامه نویسی بدترین نوعشه پر از خطاهایی که فکرشو نمی کنی مثلا معلوم نیست برای متغیر str چقدر فضا اختصاص داده شده ، متغیر value به کجای حافظه اشاره می کنه ما نمی دونیم ولی اول فراخوانی تابع محتویاتشو صفر می کنیم همچنین نمونه کدهایی مثل (str ++ -48*) درسته که تو C Std گفته این تکه کد چطور باید باهاش برخورد بشه ولی Compiler های مختلف ممکنه نتیجه های مختلف بهمون بدن بعضی از compiler ها ممکنه برنامه بالا رو بدون دردسر Compile کنند ولی بعضی ها هم ممکنه که warning ها و خطاهای زیادی رو به ما اعلام کنند.
3- با دقت از مفهوم اشاره گر استفاده کن
ممنون خیلی این تابع atoi (http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/)کاربردی بود ! نکاتی هم که گفتید رو هم کاملا باهاش موافقم ولی خوب شخصا لذت می برم از زیر و زبر c++ و روش ها و ایده های دیگران سر در بیارم به خاطر همین این سوالات رو مطرح کردم .
در مورد اشاره گر ها کاملا درست فرمودید . من هنوز نکات مبهم زیادی تو ذهنم دارم اگر منبع خاصی رو در نظر دارید ممنون میشم معرفی کنید چون واقعا نیاز مبرمی به اون دارم.
از وقتی که گذاشتید سپاسگزارم:چشمک:

sh4mid
چهارشنبه 21 بهمن 1388, 17:42 عصر
while (*str == '-') str++;خوب با این کد ما تا زمانی که فضای خالی داشته باشیم 1 خونه 1 خونه جلو میایم و وقتی که آخرین فضای خالی رو رد کردیم اشاره گر ما داره به همون sign یا علامت + یا - اشاره میکنه .نه تا وقتی مقدار متغیر str برابر '-' است میره روی خونه بعدی (در واقع برنامه اینجا اشتباه کرده کلا هرچی - هست رو می پرونه باید یکی نگه میداشت نه از رو همش می پرید)



(*str ++ == '-')
اگه می خواستیم یک خونه جلوتر بریم که با ساختار while بالا دیدیم که نیاز به استفاده از * نیست . یعنی کد اسکی رو برای - یه واحد اضافه می کنیم که حالا معلوم نیست چیه ! بعد اون موقع می گیم که - هست یا نه که با این برداشت های من نقیض است
ببین ما یک مفهومی داریم تو C به اسم اولویت عملگرها اینجا اولویت عملگر * (Dereference) با عملگر ++ یکی هست و از چپ به راست تعیین می شه کلا یعنی چی؟ یعنی اینکه اینجا اول عملگر * روی str اعمال می شه یعنی محتوی str رو با '-' مقایسه می کنه صرف نظر از جواب بعدش عملگر ++ روی آن اعمال می شه یعنی داریم

*str++ <==> *(str++)اون چیزی که مد نظر شماست اینه

(*str)++بین این دو تا بالایی فرق هست اولی اول مقدار متغیر رو میده بعد یکی میره جلو دومی مقدار متغیر رو یکی زیاد می کند


با * ما به محتوا دسترسی پیدا می کنیم در صورتی که آموخته های کم من میگه برای یک خونه جلو بردن اشاره گر ذکر اسم اشاره گر یعنی همون str نیازه
اینم مثل همون بالایی است که گفتم



*value = (*value * 10) + (*str ++ -48);یک واحد به محتوای جایی که str به آن اشاره می کند اضافه کن و سپس 48 واحد از این مقدار کم کن
نه ببین اول محتوی str رو از 48 کم می کنه بعد اونو یکی می بره جلو (به مفهوم بعد توجه کن)

البته این تکه Code که گذاشته بودی مشکل داشت یکم درست تر اینه


long long ascii_to_int_ex(const char *str) throw(char*)
{
int sign=1;
int minus=0,plus=0;
int value=0;
while(*str=='-' || *str=='+')
{
(*str=='-')?minus++:plus++;
str++;
}

while(*str)
{
if(isdigit(*str))
{
value=(value*10)+(*str-'0');
str++;
}else
{
throw "Invalid String";
break;
}
}

(minus%2==0) ?sign=1:sign=-1;
value*=sign;
return value;
}



long long ascii_to_int_ex(const char *str,bool& success)
{
int sign=1;
int minus=0;
long long val=0;
success=true;
while(*str=='-' || *str=='+')
{
if(*str=='-')minus++;
str++;
}

while(*str || success)
{
if(isdigit(*str))
{
val=(val*10)+(*str-'0');
str++;

}
else
{
success=false;
break;
}
}

(minus%2==0) ?sign=1:sign=-1;
val*=sign;
return val;
}


البته اینم مشکل داره مثلا اگه عدد زیادی بزرگ باشه Overflow میده و جواب برگشتی درست نیست

در پایان به اینم یه نگاه بنداز


#include <iostream>
using namespace std;

int main()
{
char* s1=new char[10];

strcpy(s1,"ABCDEFGHI0");

cout<<"*s1"<<'\t'<<*s1<<endl;
cout<<"*++s1"<<'\t'<<*++s1<<endl;
cout<<"*s1"<<'\t'<<*s1<<endl;
cout<<"*s1++"<<'\t'<<*s1++<<endl;
cout<<"*s1"<<'\t'<<*s1<<endl;
cout<<"*(s1++)"<<'\t'<<*(s1++)<<endl;
cout<<"*s1"<<'\t'<<*s1<<endl;
cout<<"(*s1)++"<<'\t'<<(*s1)++<<endl;
cout<<"*s1"<<'\t'<<*s1<<endl;
cout<<"*++s1"<<'\t'<<*++s1<<endl;
cout<<"*s1"<<'\t'<<*s1<<endl;
cout<<"*(++s1)"<<'\t'<<*(++s1)<<endl;
cout<<"*s1"<<'\t'<<*s1<<endl;
cout<<"++(*s1)"<<'\t'<<++(*s1)<<endl;
cout<<"*s1"<<'\t'<<*s1<<endl;

delete [] s1;

return 0;
}:کف::کف::کف::کف::کف::کف::کف::کف:: کف::کف::کف::کف::کف::کف::کف::کف::ک ف::کف::کف:
:کف::کف::کف::کف::کف::کف::کف::کف:: ف::کف::کف::کف::کف::کف::کف::کف::ک ::کف: