7. 01. void h(int i)
02. {
03. cout << "the value of i is ";
04. cout << i;
05. cout << 'n';
06. }
the value of i is 10
01. void h2(int i)
02. {
03. cout << "the value of i is " << i << 'n';
04. }
8. 01. void f()
02. {
03. int i;
04. cin >> i; // read an integer into i
05. double d;
06. // read a double-precision floating-point number into d
07. cin >> d;
08. }
01. void hello()
02. {
03. cout << "Please enter your namen";
04. string str;
05. cin >> str;
06. cout << "Hello, " << str << "!n";
07. }
11. 01. // read { "name" , number } pair. Note: formatted with { " " , and }
02. istream& operator>>(istream& is, Entry& e)
03. {
04. char c, c2;
05. if (is>>c && c=='{' && is>>c2 && c2=="") { // start with a { "
06. // the default value of a string is the empty string: ""
07. string name;
08. while (is.get(c) && c!='"') // anything before a " is part of the name
09. name+=c;
10. if (is>>c && c==',') {
11. int number = 0;
12. if (is>>number>>c && c=='}') { // read the number and a }
13. e = {name,number}; // assign to the entry
14. return is;
15. }
16. }
17. }
18. is.setf(ios_base::failbit); // register the failure in the stream
19. return is;
20. }
12. { "John Marwood Cleese" , 123456 }
{"Michael Edward Palin",987654}
01. for (Entry ee; cin>>ee; ) // read from cin into ee
02. cout << ee << 'n'; // write ee to cout
{"John Marwood Cleese", 123456}
{"Michael Edward Palin", 987654}
Editor's Notes
در این ویدیو ادامه ی بحث کتابخونه استاتدارد رو پی می گیریم و در مورد string و stream ها صحبت می کنم.
کتابخونه استاندارد برای کار با رشته ها یه type به نام string رو فراهم کرده. String یه سری عملیات پرکاربرد و مفید برای کار با رشته ها داره.
مثلا برای concat کردن رشته ها خیلی راحت می شه از + استفاده کرد. بعد از فراخوانی تابع compose مقدار Addr برابر dmr@bell-labs.com خواهد شد. اپراتور + برای انواع مختلفی از ورودی ها تعریف شده مثلا می تونید 2 تا string رو با هم جمع کرد یا یه string با یه c-style string و یا کاراکتر با string رو جمع کرد و بهم concat کرد. همین طور دارای move constructor هم هست و اجازه می ده که حتی stringهای بزرگ رو by-value از تابع return کرد بدون اینکه کپی صورت بگیره.
در بیشتر برنامه ها ما نیاز داریم که به انتهای یه string یه چیزی رو concat کنیم. برای این کار اپراتور += برای string نوشته شده و به راحتی می تونیم ازش استفاده کنیم. خط 3 و خط 4 باهم معادل هستند یعنی هم می تونید از + برای concat کردن استفاده کنید و هم از += استفاده کنید. اما دومی بهتره چون صرحتر داره مفهوم اضافه شدن یه کاراکتر رو به انتهای رشته نشون میده و efficient تره.
Stringها mutable هستند یعنی اینکه میتونیم مقدار اون رو تغییر بدیم. همینطور علاوه بر اپراتور های =، +=؛ اپراتور های subscript و توابع مفیدی برای کار با زیر رشته ها و substringها داره و قابلیت کار با زیر رشته ها و دستکاری کردن اونا رو بما میده.
تابع substr یه کپی از زیر رشته ای که می خوایم رو بر می گردونه. اولین آرگمان indexیی هست که می خوایم از اونجا زیر رشته شروع بشه. و دومین آرگمان طول زیر رشته هست و Index هم از صفر شروع میشه پس زیر رشته ای که توسط این خط برگردونده میشه stroustrup خواهد بود.
تابع replace یه زیر رشته رو با یه زیر رشته ی دیگه جایگزین می کنه. و مشابه substr اولین آرگمان index شروع زیر رشته، آرگمان دوم طول زیر رشته و سومین آرگمان رشته ای که می خوایم جایگزین کنیم هست. با اجرای این خط niels با nicholas جایگزین میشه. نکته ای که هست اینه که برای replace کردن یه زیر رشته با یه زیر رشته ی دیگه لازم نیست که size اونا با هم برابر باشه و string برای ما عملیات جا باز کردن و یا کوچیک کردن رو انجام میده.
در آخر هم اولین کاراکتر رشته رو با استفاده از تابع toupper به حرف بزرگ تبدیل کردیم.
ما میتونیم stringها رو با هم مقایسه کنیم. همین طور یه string رو با یه رشته ی ثابت یا Literal هم می تونیم مقایسه کنیم.
می تونیم 2 تا string رو با هم مقایسه کنیم که آیا با هم برابر هستند یا نه؟
و اینجا هم string رو با یه literal مقایسه کردیم. توی C++ به رشته ی Yes میگیم لیترال. در مورد Literalها در فصل 36 کتاب کامل بحث شده.
کتابخونه استاندارد ورودی و خروجی های فرمت بندی شده رو با iostream برای ما فراهم کرده. قبلا کارکردن با اون رو دیده بودیم و از cout و cin استفاده کرده بودیم. اما بقیه ورودی خروجی ها مثل کار با کارت گرافیک و یا GUI جزء استاندارد ISO نیستند و باید از کتابخونه های دیگه استفاده کرد.
در کتابخونه Iostream با استفاده از Cout ما می تونسم تمام built-in typeها رو روی خروجی چاپ کنیم. اپراتور << که اولین ورودیش ostream باشه به عنوان put to شناخته میشه و برای خروجی دادن استفاده میشه. مثلا برای اینکه عدد 10 رو خروجی بدیم به این صورت عمل می کنیم. عدد 10 تبدیل میشه به 2تا کاراکتر 1 و 0 و روی صفحه چاپ میشن.
مثال بالا با مثال پایین برابر هستند در هر 2 مثال یه عدد integer رو به خروجی فرستادیم. در اولی یه عدد ثابت و در دومی یه متغییر رو روی خروجی چاپ کردیم.
قبلا دیده بودیم که می تونستیم typeهای مختلفی رو با هم ترکیب کنیم و به خروجی بفرستیم مثلا می تونیم یه string رو به خروجی بفرستیم. بعد یه integer رو و بعد یه کاراکتر رو به خروجی بفرستیم.
خروجی این کد به این صورت خواهد شد.
ولی خیلی زود از اینکه همش cout رو تکرار کنیم خسته میشیم پس می یایم کل تابع h رو توی یک خط می نویسیم و خروجی هایی که به هم مرتبط هستند رو در کنار هم قرار میدیم. تابع h2 دقیقا همون خروجیی رو میسازه که تابع h میسازه.
کتابخونه استاندارد برای ورودی istream رو پیشنهاد میده. مشابه ostream، istream هم روی built-in typeها تعریف شده و میتونه اونا رو بخونه و مقدار اونا رو برگردونه.
اپراتور >> شیفت به راست برای خوندن از ورودی تعریف شده که به عنوان get from استفاده میشه. ما از Cin استفاده کرده بودیم و از ورودی مقادیر رو خونده بودیم.
عملوند سمت راست >> مشخص میکنه که از ورودی چه چیزی رو می خوایم بخونیم.
این خط یه عدد صحیح رو از ورودی می خونه مثلا 1234 و توی i ذخیره می کنه.
و بعد یه عدد ممیز شناور رو می خونه و در d ذخیره می کنه.
بعضی وقتا ما می خوایی یه سری از کاراکتر ها رو بخونیم و اونا رو بریزیم توی string .
برای اینکار کافیه چیزی که جلوی cin منویسیم typeش stringباشه. Cin از ورودی یه string رو میخونه و بر می گردونه. به صورت پیش فرض withespace مثل space یا tab باعث میشن که خوندن کاراکتر ها تموم بشه و به عنوان string برگردونده بشه.
برای اینکه بتونیم رشته هایی رو از ورودی بخونیم که وسطشون space داشته باشن باید از getline() استفاده کنیم. تابع getline یک خط از ورودی رو میخونه و برمیگردونه و اگه وسط خط space باشه اونا رو هم میخونه تا اینکه به کاراکتر new line یا enter برسه. آخرین کاراکتر که \n هست توسط cin حذف میشه و بقیه خط از ابتدا تا کاراکتر قبل از \n برگردونده میشه. String این ویژگی رو داره که ورودی شما هر چقدر باشه به همون اندازه حافظه میگیره و ورودی رو در خودش ذخیره میکنه و نیازی نیست که محاسبه ای برای ماکزیموم size ورودی انجام بدیم.
تا اینجا ما برای خوندن و چاپ کردن از built-in typeها استفاده کردیم. علاوه بر built-in typeها می تونیم typeهای تعریف شده توسط خودمون رو هم از ورودی بخونیم و یا در خروجی چاپ کنیم.
یه مثال ساده برای این کار با هم خواهیم دید. فرض کنید که می خوایم یه دفترچه تلفن ساده بسازیم .یه struct به نام entry می نویسیم که نام و شماره رو ذخیره کنه.
برای اینکه بتونیم entry رو در خروجی چاپ کنیم باید یه اپراتور شیفت به چپ یا put to بنویسیم و داخل اون هر فرمتی که تمایل داریم خروجی بر اساس اون باشه رو تولید کنیم.
این اپراتور ورودی اولش یه reference به یه ostream هست
و ورودی دومش یه const reference به Entry هست و در بدنش هم میاد name و number رو چاپ میکنه و اول و آخر اون هم یه آکولاد باز و یه آکولاد بسته می ذاره.
اما نوشتن اپراتور ورودی برای entry یکم پیچیده تره چون باید چک کنیم که وردی کاربر با فرمتی که انتظار داریم یکسان باشه و خطاهایی که ممکنه در هنگام ورود اطلاعات رخداده باشه رو هم در نظر بگیریم.
خروجی اپراتور باید همون refence از istream که در ورودی دریافت میکنه باشه. از همین is میتوینم برای چک کردن اینکه خطایی رخ داده یا نه استفاده کنیم. اگه خطایی رخ نداده باشه فقط اونو بر می گردونیم.
در غیر این صورت می تونیم flag یی رو set کنیم که بگیم یه خطا اتفاق افتاده.
وقتی توی شرط if از is >> c استفاده می کنیم به این معنیه که آیا موفق شدیم که یه کاراکتر رو بخونیم و مقدار اونو در c ذخیره کنیم یا نه؟ این دستور یه کاراکتر رو می خونه و به صورت پیش فرض از روی کاراکتر های whitespace میپره.
تابع is.get(c) هم یه کاراکتر از ورودی می خونه و مقدار اون رو در c ذخیره می کنه اما بر خلاف get from به صورت پیش فرض از روی whitespaceها نمیپره و اونا رو هم بر میگردونه. ما در این حلقه نیاز داریم که whitespaceها رو هم ذخیره کنیم چون ممکنه داخل اسمی که می خوایم از ورودی دریافت کنیم space وجود داشته باشه. ما با get from می تونیم از روی spaceهایی که خارج از اسم هستند بپریم ولی با تابع get؛ spaceهایی که داخل اسم هستند رو ذخیره کنیم.
حالا می تونیم از اون اپراتور های put to و get from که نوشتیم استفاده کنیم.
فرض کنید که ورودی ما به این صورت باشه. خط اول ورودی یه space بعد از آکولاد باز هست و یه tab هم قبل از آکولاد بسته هست و حظ دوم ورودی هم هیچ spaceیی نداریم.
می تونیم توی main از for برای خوندن هر تعداد ورودی از نوع entry استفاده کنیم و ورودی رو که می خونیم دوباره روی خروجی چاپ کنیم. از cin میخونیم و با cout در خروجی چاپ می کنیم.
خروجی این حلقه به این صورت خواهد شد.
در این ویدیو string و io streamها رو معرفی کردم. و پر کار برد ترین امکانات هر کدوم رو توضیح دادم.