PDA

View Full Version : مبتدی: نکته ای در باب چاپ string با cout



khafan_bat
جمعه 05 شهریور 1389, 11:05 صبح
با سلام

یک سوال مبتدیانه . کنجکاو بودم اما نتونستم خودم پیداش کنم.

ببینید وقتی یک string رو توسط دستور cout به خروجی میبریم این دستور کاراکتر های آرایه ی رشته ای مورد نظر رو تا رسیدن به کاراکتر پوپ چاپ میکنه. حالا اگه کاراکتر پوچ رو از خونه ی آخر آرایه به وسط منتقل کنیم مطمئنا با رسیدن به اون متوقف خواهد شد و کارراکتر های بعد از اون رو چاپ نمیکنه. حالا من در کد زیر کلا کاراکتر پوچ رو حذف کردم و اون رو به خروجی بردم. سوال اینجاست عملکرد cout در این صورت چگونه است ؟ من با خروجی ای که در تصویر زیر میبینید مواجه شدم. با تشکر



#include <iostream>
#include <conio.h>

using namespace std;

int main()
{
char str[5]={'A','B','C','U','R'};
cout<<str<<endl;
cout<<sizeof(str)<<" Byte";
getch();
return 0;
}



http://up.iranblog.com/Files3/6f0232bb44374eda807a.PNG

Salar Ashgi
جمعه 05 شهریور 1389, 11:21 صبح
این خطا زیاد هم غیر طبیعی نیست ! چون معمولا range اندیس آرایه ها رو
خود کامپایلر کنترل نمیکنه و معمولا جهت چاپ آرایه ها به غیر از آرایه کاراکتری
با مقدار دهی خاص باید از حلقه ها استفاده کنیم، خروجی برنامه زیر رو ببینید :



#include <iostream>
#include <conio>
int main(){
int a[]={1,2,3};
cout<<&(a[0])<<endl;
cout<<a<<endl;
//=============
char b[]={"salar"};
cout<<b<<endl;
getch();
}
http://www.barnamenevis.org/forum/attachment.php?attachmentid=54836&stc=1&d=1282893634
تو حالت اول بجای چاپ آرایه ، آدرس آرایه که میشه همون آدرس خونه اول ، رو چاپ میکنه ، ولی همانطور
که میبینید تو مورد دوم مشکلی نیست !

khafan_bat
جمعه 05 شهریور 1389, 11:37 صبح
متوجه نشدم. بزار سوالم رو اینطوری مطرح کنم. cout یک شی از کلاس ostream است و این کلاس یک عملگر >> دارد. حال اگر آرگومان این عملگر یک آرایه ی کاراکتری باشد آنگاه کلا این کلاس به چه صورت اون رو به خروجی میبره ؟ یعنی یک متغیر کانتر میسازه ، آرایه رو با استفاده از حلقه ی f0r به خروجی میبره ؟؟ یا اینکه با استفاده از while(array[i]!='\0 کاراکتر به کارکتر چاپ میکنه ؟؟ قضیه ی اندیس که مطرح کری چی هستش ؟

Negative_Se7en
جمعه 05 شهریور 1389, 11:40 صبح
رشته ای که شما به cout میدید یه آدرس هست.
اگر بگیم که رشته ی شما 5 بایت هست ، و بایت اول از آدرس 0x12FF44 و بایت آخر در آدرس 0x12FF48 هست.
cout اصلا درباره ی آرایه ی شما هیچ اطلاعاتی نداره.
cout فقط میدونه که تا زمانی که به مقدار 0 برنخورد ، باید به چاپ کردن بایت ها ادامه بده.
و اینجا هم همین اتفاق افتاده . در واقع اینجا به آدرسی بعد از آخرین بایت آرایه ی شما رسیده و بایت هایی رو چاپ میکنه که شما اونها رو مقدار دهی نکردید.
دلیل دیدن این کاراکتر های عجیب هم اینه که قبلا مقدار های این قسمت از بایت های RAM قبلا توسط برنامه ای تغییر کرده و به همون مقدار مونده.
و تا چند بایت جلوتر به مقدار 0 در حافظه ی برخورد کرده.و چاپ کردن رو متوقف کرده.

برای همینه که باید متغییرهاتون رو Initialize یا مقداردهی اولیه کنید.


تو حالت اول بجای چاپ آرایه ، آدرس آرایه که میشه همون آدرس خونه اول ، رو چاپ میکنه ، ولی همانطور
که میبینید تو مورد دوم مشکلی نیست !
توی هیچ کدوم از حالت ها مشکلی نیست !

manij_mhm
جمعه 05 شهریور 1389, 11:41 صبح
با سلام

یک سوال مبتدیانه . کنجکاو بودم اما نتونستم خودم پیداش کنم.

ببینید وقتی یک string رو توسط دستور cout به خروجی میبریم این دستور کاراکتر های آرایه ی رشته ای مورد نظر رو تا رسیدن به کاراکتر پوپ چاپ میکنه. حالا اگه کاراکتر پوچ رو از خونه ی آخر آرایه به وسط منتقل کنیم مطمئنا با رسیدن به اون متوقف خواهد شد و کارراکتر های بعد از اون رو چاپ نمیکنه. حالا من در کد زیر کلا کاراکتر پوچ رو حذف کردم و اون رو به خروجی بردم. سوال اینجاست عملکرد cout در این صورت چگونه است ؟ من با خروجی ای که در تصویر زیر میبینید مواجه شدم. با تشکر



#include <iostream>
#include <conio.h>


using namespace std;


int main()
{
char str[5]={'A','B','C','U','R'};
cout<<str<<endl;
cout<<sizeof(str)<<" Byte";
getch();
return 0;
}



http://up.iranblog.com/Files3/6f0232bb44374eda807a.PNG

cout از ادرس ابتدا شروع به چاپ می کنه تا جایی که داخل حافظه به کاراکتر پوچ برسه. اینم دلیل چاپ کاراکتر های نامشخص.
موفق باشید.

khafan_bat
جمعه 05 شهریور 1389, 12:11 عصر
الان افتاد !! متوجه شدم.

وقتی که یک استرینگ رو به cout میفرستیم در واقع cout آدرس بایت اول استرینگ رو میگیره و مقدارش رو چک میکنه و در صورت غیر صفر بودن چاپ و سپس به آدرس بایت بعدی میره و . . .

ok. tanks

حالا اومدیم و تو حافظه ی ما مقدار صفر نبود . . . .. !!

Negative_Se7en
جمعه 05 شهریور 1389, 12:18 عصر
حالا اومدیم و تو حافظه ی ما مقدار صفر نبود . . . .. !!
برنامه شما یه حریمی داره.برنامه های دیگه هم حریم خودشون رو دارن.
برنامه شما انقدر ادامه میده که از مرز حافظه ی خودش تجاوز کنه.
اگر برنامه شما به حریم برنامه های دیگه وارد بشه ، برنامتون Crash میکنه ، و با خطای Access Violation مواجه میشید.

manij_mhm
جمعه 05 شهریور 1389, 12:28 عصر
حالا اومدیم و تو حافظه ی ما مقدار صفر نبود . . . .. !!

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

khafan_bat
جمعه 05 شهریور 1389, 12:45 عصر
آره میدونم. تازه اصلا یادم اومد( در راستای صحبت های آقای seven ) که :

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

چه میکنه این deitel and deitel . هر از چند گاهی باید این کتاب رو یه دوری زد

راستی این پست صدم من تو برنامه نویس بود.!!!

Salar Ashgi
جمعه 05 شهریور 1389, 15:51 عصر
توی هیچ کدوم از حالت ها مشکلی نیست !


مشکل که هست ، ولی نه اون مشکلی که شما فک میکنید ،
هدف ما چاپ کردن عناصر آرایه هست و نه آدرس آرایه ، پس وقتی
اینکار انجام میشه ، این یعنی مشکل !

Negative_Se7en
جمعه 05 شهریور 1389, 16:05 عصر
نه میشه گفت مشکله ، نه میشه گفت مشکل نیست.
این یه کمبوده که کلاسی که cout ازش ایجاد شده ، Operatorی رو نداره تا آرایه یا اشاره گری از نوع int رو هم چاپ کنه.
و دلیل این هم که تو مورد دوم مشکلی نیست اینه که cout اشاره گرهای نوع char رو Support میکنه.

Salar Ashgi
جمعه 05 شهریور 1389, 17:44 عصر
نه میشه گفت مشکله ، نه میشه گفت مشکل نیست.
این یه کمبوده که کلاسی که cout ازش ایجاد شده ، Operatorی رو نداره تا آرایه یا اشاره گری از نوع int رو هم چاپ کنه.
و دلیل این هم که تو مورد دوم مشکلی نیست اینه که cout اشاره گرهای نوع char رو Support میکنه.


منم تو توضیحاتم فک نکنم چیزی جز این گفته باشم !

khafan_bat
جمعه 05 شهریور 1389, 18:20 عصر
عجب اشتباهی کردیم این سوال رو پرسیدیم :عصبانی++:
بی خیال تموم کنید .
برای خودم تازه چند تا سوال دیگه ایجاد شد

اصلا به طور کلی این سوال من مربوط میشد به ارایه های در زبان برنامه نویسی C ، در C++ استاندارد که این مشکل برطرف شده و هر آرایه ای طول خودش رو میدونه و آرایه های غیر کاراکتری رو هم میشه با cout به خروجی برد

Negative_Se7en
جمعه 05 شهریور 1389, 21:22 عصر
عجب اشتباهی کردیم این سوال رو پرسیدیم :عصبانی++:
بی خیال تموم کنید .
دعوا نیستش که تمومش کنیم.:لبخند:
خواستم دقیق تر مشکل بررسی بشه.
چون اگه من یا کسی دیگه اطلاعات اشتباهی درباره ی چیزی داریم بهتره که معلوم بشه ، و صحیحش رو یادبگیریم.

Salar Ashgi
جمعه 05 شهریور 1389, 23:53 عصر
دوست عزیز khafan_bat (http://www.barnamenevis.org/forum/member.php?u=87870) ، اولا باید هر سوالتون رو تو تاپیک جداگانه مطرح کنید ، تو این تاپیک شما چند تا
سوال میپرسین ؟!



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

کدوم مشکل ؟!
چرا بیخودی از کاه ، کوه میسازید ؟!
ما گفتیم عملگر cout واسه بجز آرایه های کاراکتری Overload نشده ! حالا مشکل کجاست حل کنیم ؟!


چون اگه من یا کسی دیگه اطلاعات اشتباهی درباره ی چیزی داریم بهتره که معلوم بشه ، و صحیحش رو یادبگیریم.

هیچ کس نظریه نادرستی ارسال نکرده که شما این حرفو میزنید !