شناخت نوع داده `char` (۱ بایت) و نحوه تعریف و مقداردهی آن با کوتیشن تکی `'A'`
آشنایی با جدول ASCII و به خاطر سپردن کدهای کلیدی: `'A'=65`, `'a'=97`, `'0'=48`
تبدیل دوطرفه بین `char` و `int` (هم implicit و هم با cast صریح `int(ch)`)
یادگیری ترفند تبدیل حروف بزرگ به کوچک (کم کردن ۳۲ یا جمع `'a'-'A'`) و تبدیل رقم کاراکتری به عدد (`ch - '0'`)
آشنایی با تابع `getch()` از `<conio.h>` و درک اینکه چرا این تابع غیراستاندارد است و جایگزینهای آن
نوع داده char: حروف در حافظه کامپیوتر
تا اینجا با اعداد صحیح (int) و اعشاری (float/double) کار کردیم. اما برنامههای واقعی نیاز به ذخیره حروف هم دارند: نام کاربر، رمز عبور، متن پیام و...
در C++ نوع دادهی char برای ذخیره یک کاراکتر استفاده میشود. هر char دقیقاً ۱ بایت (۸ بیت) فضا اشغال میکند و میتواند ۲۵۶ مقدار متفاوت بگیرد. دامنه دقیق به پیادهسازی بستگی: signed char (پیشفرض در x86) از ۱۲۸- تا ۱۲۷، unsigned char از ۰ تا ۲۵۵. برای متن ASCII کلاسیک (کدهای ۳۲-۱۲۶) این فرق مهم نیست.
کامپیوتر در حافظه فقط اعداد ذخیره میکند، نه حروف. پس چطور حروف را نمایش میدهیم؟
پاسخ: با استفاده از یک جدول کدگذاری که به هر حرف یک عدد مشخص اختصاص میدهد. معروفترین این جدولها ASCII است.
تعریف و مقداردهی char:
main.cppcpp
توجه: در C++ کوتیشن تکی '...' برای یک کاراکتر و کوتیشن دوتایی "..." برای رشته (string) استفاده میشود. نوشتن char ch = "A" خطای کامپایل است!
جدول ASCII چیست؟
ASCII (American Standard Code for Information Interchange) یک جدول استاندارد است که به ۱۲۸ کاراکتر رایج، کدهای عددی ۰ تا ۱۲۷ را اختصاص داده است. هر char در حافظه، در واقع این عدد است.
بخشهای مهم جدول ASCII که باید حفظ کنید:
محدوده
کاراکترها
مثال
۰–۳۱
کاراکترهای کنترلی (مثل Enter، Tab)
غیرقابل چاپ
۳۲
فاصله (space)
' '
۴۸–۵۷
ارقام 0 تا 9
'0'=48، '9'=57
۶۵–۹۰
حروف بزرگ انگلیسی A تا Z
'A'=65، 'Z'=90
۹۷–۱۲۲
حروف کوچک انگلیسی a تا z
'a'=97، 'z'=122
دو نکته طلایی:
۱. فاصله بین حرف بزرگ و کوچک دقیقاً ۳۲ است. یعنی 97 - 65 = 32. این برای تبدیل بزرگ/کوچک حیاتی است.
۲. فاصله بین کاراکتر رقم '0' و عدد 0 دقیقاً ۴۸ است. یعنی '0' در حافظه بهصورت عدد ۴۸ ذخیره میشود، نه ۰!
برای کشیدن جدول کامل ASCII به بخش مرجع در انتهای درس نگاه کنید.
مثال ۱: تعریف char و چاپ آن
این برنامه نشان میدهد که چطور یک کاراکتر را تعریف و چاپ میکنیم. وقتی cout << ch را مینویسیم، C++ مقدار عددی حافظه را بهعنوان کاراکتر نمایش میدهد (یعنی حرف A).
اما اگر cout << (int)ch را بنویسیم، همان مقدار عددی بهصورت عدد چاپ میشود (یعنی ۶۵). این یکی از مهمترین ترفندهای C++ است که در ادامه عمیقتر بررسی میکنیم.
تعریف char ch = 'A' و چاپ حرف و کد اسکی آنcpp
$خروجی برنامه
Character: A
ASCII code: 65
Character: 5
ASCII code: 53
در حال باز کردن ویرایشگر…
تبدیل بین char و int
چون char در حافظه در واقع یک عدد صحیح (۸ بیتی) است، میتوانیم آن را به int و برعکس تبدیل کنیم. این تبدیل دوطرفه و خودکار (Implicit) است:
main.cppcpp
یا برعکس:
main.cppcpp
سه روش برای تبدیل صریح:
main.cppcpp
این تبدیلها آنقدر پرکاربردند که در بسیاری از الگوریتمهای کاراکتری (تبدیل حروف، شمارش حروف صدادار، رمزنگاری ساده) استفاده میشوند.
نکته: متغیر char میتواند مقدار منفی هم بگیرد (اگر signed char باشد)؛ اما برای کاراکترهای ASCII استاندارد، مقدار همیشه مثبت است. اگر میخواهید مطمئن شوید مقادیر منفی نمیگیرد، از unsigned char استفاده کنید (محدوده ۰ تا ۲۵۵).
مثال ۲: تبدیل char به int و برعکس
این برنامه دو مثال کلاسیک از صفحه ۱۳ جزوه را پوشش میدهد:
۱. عدد → کاراکتر: عدد ۹۷ در حافظهی یک char، حرف کوچک 'a' است.
۲. کاراکتر → عدد: حرف 'B' در حافظهی یک int، عدد ۶۶ است.
نکته: در نسخه اصلی جزوه، یک اشتباه تایپی وجود داشت: نوشته بودند کد 'B' اسکی برابر ۹۸ است، اما در واقع B بزرگ کد ۶۶ دارد و b کوچک کد ۹۸. این اشتباه را در بخش comparison انتهای درس به طور کامل بررسی میکنیم.
مثالهای صفحه ۱۳: چاپ کاراکتر معادل عدد و برعکسcpp
$خروجی برنامه
a
66
66 66 66
در حال باز کردن ویرایشگر…
تفاوت حروف بزرگ و کوچک: اختلاف ثابت ۳۲
فاصله بین 'A' (کد ۶۵) و 'a' (کد ۹۷) دقیقاً ۳۲ است. این اختلاف برای تمام حروف انگلیسی ثابت است:
حرف بزرگ
کد
حرف کوچک
کد
اختلاف
A
65
a
97
32
B
66
b
98
32
C
67
c
99
32
...
...
...
...
32
Z
90
z
122
32
دو روش برای محاسبه این اختلاف:
۱. مستقیماً عدد ۳۲ را کم یا زیاد کنیم:
main.cppcpp
۲. بهصورت قابلحمل با فرمول 'a' - 'A' (تمیزتر و قابلحملتر):
main.cppcpp
روش دوم بهتر است چون در کدهایی که ممکن است بعداً به Unicode یا سیستمهای دیگر منتقل شوند، انعطاف بیشتری دارد. همچنین خواننده کد متوجه میشود که «این عدد ۳۲ از کجا آمده».
مثال ۳: تبدیل حرف بزرگ به کوچک
این مثال از صفحه ۱۴ جزوه است. الگوریتم ساده است:
۱. یک متغیر d برای نگهداری اختلاف بین حروف بزرگ و کوچک تعریف میکنیم (d = 'a' - 'A' = 32).
۲. کاراکتر بزرگ را از ورودی میگیریم.
۳. با عملگر -= اختلاف را از کاراکتر کم میکنیم.
نکته: چون از getch() (غیراستاندارد) استفاده میکنیم، در محیطهای مدرن GCC/Clang ممکن است خطا بدهد. در ادامه با جایگزین استاندارد cin هم نسخه مینویسیم.
برنامهای که یک حرف بزرگ را میگیرد و معادل کوچک آن را چاپ میکندcpp
$خروجی برنامه
Enter an uppercase letter: G
Lowercase: g
در حال باز کردن ویرایشگر…
تبدیل رقم کاراکتری به عدد صحیح
یکی از تلههای کلاسیک: عدد 5 (بهعنوان int) با کاراکتر '5' (بهعنوان char) یکی نیستند!
عدد صحیح 5 در حافظه بهصورت 00000101 ذخیره میشود.
کاراکتر '5' در حافظه بهصورت عدد اسکی 53 (یعنی 00110101) ذخیره میشود.
وقتی کاربر عدد ۵ را وارد میکند، cin >> int_n مقدار 5 میگیرد، اما cin >> char_ch کاراکتر '5' (با کد اسکی ۵۳) را میگیرد.
تبدیل '5' (char) به 5 (int):
main.cppcpp
چرا این کار میکند؟ چون در جدول ASCII ارقام '0' تا '9' پشت سر هم آمدهاند (کدهای ۴۸ تا ۵۷). پس اگر '0' (کد ۴۸) را از '5' (کد ۵۳) کم کنیم، عدد ۵ به دست میآید.
تبدیل برعکس (int به char):
main.cppcpp
این ترفند در پردازش ورودی کاراکتری، استخراج ارقام از رشته، و ساخت اعداد از ارقام مجزا بسیار کاربرد دارد.
مثال ۴: سه برابر یک رقم کاراکتری
این مثال از صفحه ۱۴ جزوه است. هدف: ورودی '5' (بهعنوان کاراکتر) → خروجی 15 (یعنی ۳×۵).
الگوریتم:
۱. کاراکتر را با getch() یا cin بخوانیم.
۲. آن را به عدد صحیح تبدیل کنیم با کم کردن '0'.
۳. در عدد ۳ ضرب کنیم و چاپ کنیم.
نکته: اگر کاربر '5' را وارد کند، ch - '0' = 53 - 48 = 5 میشود و سپس 3 * 5 = 15.
کاراکتر رقم را میگیرد و سه برابر مقدار عددی آن را چاپ میکندcpp
$خروجی برنامه
Enter a digit: 5
3 * 5 = 15
در حال باز کردن ویرایشگر…
تفاوت `'0'` و `0`: یک تله کلاسیک
یکی از منابع رایج باگ در برنامههای مبتدی، اشتباه گرفتن '0' (کاراکتر صفر) با 0 (عدد صحیح صفر) است.
عبارت
نوع
مقدار در حافظه
'0'
char
48 (کد اسکی کاراکتر صفر)
0
int
0
'\0'
char
0 (کاراکتر پاینتهای رشته، Null Terminator)
مثال خطای رایج:
main.cppcpp
همچنین به '\0' دقت کنید که در رشتههای C-style (آرایه char) برای نشاندادن پایان رشته استفاده میشود. این کاراکتر مقدار عددی ۰ دارد اما بهصورت '\0' نوشته میشود.
قاعده طلایی: همیشه با کوتیشن تکی '…' یک کاراکتر، و با کوتیشن دوتایی "…" یک رشته بنویسید.
تابع getch(): خواندن کلید بدون Enter
وقتی با cin >> ch یک کاراکتر را میخوانیم، دو ویژگی آزاردهنده دارد:
۱. کاربر باید بعد از تایپ، Enter هم بزند.
۲. کاراکتر تایپشده روی صفحه نمایش دیده میشود (Echo).
در برنامههایی مثل منوها، بازیها، یا رمز عبور، این رفتار مطلوب نیست. میخواهیم با فشردن یک کلید، بلافاصله آن را بخوانیم بدون نیاز به Enter و بدون نمایش.
تابع getch() این کار را انجام میدهد:
main.cppcpp
این تابع جزو هدر <conio.h> (Console Input/Output) است.
کاربردهای رایج getch():
توقف برنامه تا فشردن یک کلید (در انتهای برنامه)
خواندن کلیدهای جهتنما (Arrow Keys) در منوها
گرفتن رمز عبور بدون نمایش کاراکترها
ساخت بازیهای تعاملی ساده
اما این تابع غیراستاندارد است. در ادامه میبینیم چه جایگزینهایی دارد.
مثال ۵: برنامه کامل نمایش کد ASCII
این مثال از صفحه ۱۳ جزوه است و یکی از کلاسیکترین برنامههای آموزشی C++ است. هدف: خواندن یک کاراکتر از کاربر و نمایش کد اسکی آن.
اگر کاربر کلید 'A' را فشار دهد، خروجی باید این باشد:
main.cppcpp
نکته: در محیطهای مدرن، <conio.h> ممکن است در دسترس نباشد. در آن صورت، نسخه با cin را بهکار ببرید (که Enter میخواهد اما در همهجا کار میکند).
یک کاراکتر را با getch() میخواند و کد اسکی آن را چاپ میکندcpp
$خروجی برنامه
Press any key...
The ASCII code of A is: 65
(اگر کلید A فشار داده شود)
getch() غیراستاندارد است
هدر <conio.h> و تابع getch() جزو استاندارد C++ نیستند. این هدر مربوط به کامپایلرهای قدیمی داس ویندوز (مثل Turbo C++ و Borland C++) است.
مشکلات:
در GCC (لینوکس، مک، ویندوز مدرن) بهصورت پیشفرض موجود نیست.
در Clang (مک) هم موجود نیست.
در MSVC (Visual Studio) نسخهای با نام _getch() (با زیرخط اول) موجود است.
در محیطهای آموزشی آنلاین (Online Judges) معمولاً در دسترس نیست.
جایگزینهای استاندارد:
۱. cin >> ch — سادهترین و قابلحملترین، اما نیاز به Enter دارد و space را رد میکند.
۲. cin.get(ch) — فضای خالی را هم میخواند اما هنوز Enter لازم است.
۳. کتابخانههای کراسپلتفرم مثل ncurses (POSIX) یا conioex — برای منوها و بازیهای واقعی.
۴. API سیستمعامل مثل termios در لینوکس/مک یا ReadConsole در ویندوز.
برای کدهای آموزشی ساده، بهترین انتخاب cin >> ch است. هرگز در پروژههای قابلحمل به getch() تکیه نکنید.
اصلاح اشتباه جزوه: ۹۸ به جای ۶۶ برای 'B'
در صفحه ۱۳ جزوه، یک اشتباه تایپی در توضیح مثال وجود داشت. در نمودار کناری، نوشته بودند «مقدار: ۹۸» برای کاراکتر 'B'، در حالی که کد اسکی 'B' (حرف بزرگ) برابر ۶۶ است. عدد ۹۸ مربوط به 'b' (حرف کوچک) است.
این خطا نشان میدهد چرا حفظ چند کد اسکی کلیدی مهم است:
'A' = 65 (حرف بزرگ اول)
'a' = 97 (حرف کوچک اول)
'0' = 48 (رقم صفر)
'B' = 66 (دومین حرف بزرگ)
'b' = 98 (دومین حرف کوچک)
توصیه: همیشه کد را اجرا کنید و خروجی را ببینید، نه فقط روی توضیحات دستنویس تکیه کنید.
نسخه اشتباه جزوه
کد دارای باگcpp
نسخه اصلاحشده و استاندارد
کد صحیحcpp
جدول مرجع ASCII (مهمترین کاراکترها)
این جدول مرجع سریع برای کاراکترهای پرکاربرد را به خاطر بسپارید:
03تبدیل `char` ↔ `int` خودکار است؛ میتوان از `int(ch)`, `(int)ch` یا `static_cast<int>(ch)` برای تبدیل صریح استفاده کرد.
04تبدیل حرف بزرگ به کوچک: `ch = ch + 32` یا تمیزتر: `ch = ch + ('a' - 'A')`. تبدیل رقم کاراکتری به عدد: `n = ch - '0'`.
05`'0'` (char با کد اسکی ۴۸) با `0` (int با مقدار ۰) فرق دارد. همیشه برای کاراکتر از کوتیشن تکی `'…'` و برای رشته از `"…"` استفاده کنید.
06تابع `getch()` از `<conio.h>` غیراستاندارد است و در کامپایلرهای مدرن (GCC/Clang) موجود نیست؛ در کدهای قابلحمل از `cin >> ch` یا `cin.get(ch)` استفاده کنید.
گام بعدی پیشنهادی
عملگرهای مقایسهای و دستور if
از == تا if/else: اولین گام در مسیر تصمیمگیری در برنامه
int i =int(ch);// روش تابعیint j =(int)ch;// روش سبک Cint k =static_cast<int>(ch);// روش مدرن C++
1#include<iostream>2usingnamespace std;34intmain(){5// مثال 1: عدد 97 → حرف 'a'6char x =97;7 cout << x << endl;// خروجی: a89// مثال 2: حرف 'B' → عدد 6610char ch ='B';11int i = ch;12 cout << i << endl;// خروجی: 661314// مثال 3: تبدیل صریح با int(ch)15char ch2 ='B';16 cout <<int(ch2)<<" "<<(int)ch2 <<" "<<static_cast<int>(ch2)<< endl;17// خروجی: 66 66 661819return0;20}
// تبدیل بزرگ → کوچکchar lower = ch +32;// تبدیل کوچک → بزرگchar upper = ch -32;
int diff ='a'-'A';// = 32char lower = ch + diff;
1#include<iostream>2usingnamespace std;34intmain(){5char ch;6int d ='a'-'A';// d = 3278 cout <<"Enter an uppercase letter: ";9 cin >> ch;1011// بررسی اینکه واقعاً حرف بزرگ است12if(ch >='A'&& ch <='Z'){13 ch = ch + d;// یا ch = ch + 32;14 cout <<"Lowercase: "<< ch << endl;15}else{16 cout <<"Not an uppercase letter!"<< endl;17}1819return0;20}
char ch ='5';int n = ch -'0';// n = 53 - 48 = 5
int n =7;char ch = n +'0';// ch = 7 + 48 = 55 = '7'
1#include<iostream>2usingnamespace std;34intmain(){5char ch;6 cout <<"Enter a digit: ";7 cin >> ch;89// بررسی اینکه واقعاً رقم است10if(ch >='0'&& ch <='9'){11int n = ch -'0';// تبدیل char به int (مثلاً 5)12 cout <<"3 * "<< n <<" = "<<3* n << endl;13}else{14 cout <<"Not a digit!"<< endl;15}1617return0;18}
#include<conio.h>char ch =getch();// بلافاصله پس از فشردن کلید، در ch ذخیره میشود
The ASCII code of A is:65
1#include<iostream>2#include<conio.h>3usingnamespace std;45intmain(){6char x;7 cout <<"Press any key...";8 x =getch();// بدون Enter و بدون نمایش9 cout << endl <<"The ASCII code of "<< x <<" is: "<<int(x)<< endl;10return0;11}
1#include<iostream>2usingnamespace std;34main()5{6char ch ='B';7int i = ch;8 cout << i;// خروجی واقعی: 669}10// توضیح اشتباه در جزوه نوشته بود: «مقدار: 98»11// اما 98 مربوط به 'b' کوچک است، نه 'B' بزرگ!