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

پرش به محتوای اصلی
>_
درس ۱۹متوسط

رشته‌ها (string) در ⁦C++⁩

std::string، cin در برابر getline، شمارش کلمات، تبدیل حروف، یافتن زیررشته و استخراج اعداد

معمولی
آرایه‌ها و رشته‌ها•صفحات ۳۱-۳۲•۴۵ دقیقه•۱٬۶۹۸ کلمهزمان مطالعه: ۰ دقیقه
فهرست این درس
// اهداف۵
  • آشنایی با کلاس std::string و تفاوت آن با آرایه کاراکتری
  • درک تفاوت `cin >>` و `getline` برای خواندن رشته
  • پیاده‌سازی الگوریتم شمارش کلمات با دو روش ساده و دقیق
  • تبدیل حروف کوچک به بزرگ و برعکس با استفاده از کدهای اسکی
  • یافتن تعداد تکرار یک زیررشته در رشته اصلی و استخراج اعداد از رشته

کلاس std::string چیست؟

کلاس std::string (یا به اختصار string با using namespace std;) یک نوع داده‌ی مدرن در ⁦C++⁩ برای کار با متن است که در کتابخانه‌ی <string> قرار دارد. این کلاس برخلاف آرایه‌ی کاراکتری C-style، خودش طول رشته را مدیریت می‌کند و نیازی به کاراکتر \0 دستی ندارد.

ویژگی‌های مهم std::string:

  • تغییرپذیر: می‌توان کاراکتر‌های آن را با اندیس تغییر داد (s[2] = 'X')
  • پویا: طول آن می‌تواند در زمان اجرا تغییر کند
  • امن: خطر Buffer Overflow ندارد
  • عملگر‌های ساده: با =, +, ==, <, > کار می‌کند

تعریف و مقداردهی string

برای استفاده از string باید <string> را include کنید. در عصر جدید ⁦C++⁩ این هدر معمولاً به‌صورت ضمنی توسط <iostream> هم include می‌شود، اما برای اطمینان همیشه صریح بنویسید.

روش‌های مختلف تعریفcpp
خروجی برنامه
Hello World
*****
Hello World
در حال باز کردن ویرایشگر…

تفاوت char و string

در جزوه اصلی یک خطای مفهومی وجود دارد: نوشته شده char ch = "z" که با خط قرمز مشخص شده. در ⁦C++⁩ نوع char فقط برای ذخیره‌ی یک کاراکتر با کوتیشن تکی 'z' مناسب است. برای ذخیره‌ی رشته‌ی چندکاراکتری (حتی یک حرف مثل "z") باید از string استفاده کنید.

نسخه اشتباه جزوه
کد دارای باگcpp
نسخه اصلاح‌شده و استاندارد
کد صحیحcpp

تفاوت cin و getline

دو راه اصلی برای خواندن ورودی رشته‌ای وجود دارد:

  • cin >> s: تا رسیدن به اولین فاصله (یا Tab یا Enter) می‌خواند. بنابراین فقط یک کلمه را می‌گیرد.
  • getline(cin, s): کل خط (شامل فاصله‌ها) را تا رسیدن به Enter می‌خواند.

مثلاً اگر ورودی "Salam Donya" باشد:

  • cin >> s فقط "Salam" را می‌گیرد.
  • getline(cin, s) کل "Salam Donya" را می‌گیرد.
ویژگیcin >> sgetline(cin, s)
خواندن فاصله✗✓
خواندن Enter✗✓ (پایان رشته)
مناسب برایکلمهجمله/خط کامل

خواندن جمله با getline

برای خواندن جمله‌ای که شامل فاصله است، حتماً از getline استفاده کنید.

خواندن کل خط به‌جای یک کلمهcpp
خروجی برنامه
Enter a sentence: Hello C++ World
You typed: Hello C++ World

نکته مهم: پاکسازی بافر با cin.ignore

اگر قبل از getline از cin >> استفاده کرده باشید، کاراکتر Enter در بافر باقی می‌ماند و getline آن را به‌عنوان ورودی خالی می‌خواند! راه‌حل: بین cin >> و getline یک دستور cin.ignore() قرار دهید تا Enter اضافی پاک شود.

main.cppcpp

طول رشته با .length()

متد length() (یا size()) تعداد کاراکتر‌های رشته را برمی‌گرداند. این متد نوع size_t (بدون علامت) برمی‌گرداند، پس در مقایسه با int مراقب باشید.

بدست آوردن تعداد کاراکتر‌های رشتهcpp
خروجی برنامه
Length = 3
First char = A
Last char = i
در حال باز کردن ویرایشگر…

دسترسی و تغییر کاراکتر‌ها

می‌توان با عملگر [] به هر کاراکتر دسترسی پیدا کرد یا آن را تغییر داد. این یکی از مزایای string نسبت به ثابت بودن برخی رشته‌ها در زبان‌های دیگر است.

string مانند آرایه اندیس‌دهی می‌شودcpp
خروجی برنامه
Abi
در حال باز کردن ویرایشگر…

مثال ۱: شمارش کلمات (روش ساده)

ایده‌ی ساده: تعداد کلمات برابر تعداد فاصله‌ها + ۱ است. این روش فرض می‌کند بین کلمات دقیقاً یک فاصله است و جمله با فاصله شروع یا تمام نمی‌شود.

تعداد فاصله‌ها + ۱cpp
خروجی برنامه
Enter a sentence: I love C++
Word count = 3

مثال ۲: شمارش کلمات (روش دقیق)

اگر جمله دارای فاصله‌های متوالی باشد (مثلاً "Hello World" با دو فاصله)، روش ساده اشتباه جواب می‌دهد. روش دقیق: یک کلمه را زمانی می‌شماریم که یک فاصله با کاراکتر غیرفاصله‌ی بعد از آن همراه شود (یعنی شروع یک کلمه‌ی جدید). اگر رشته با فاصله شروع نشده باشد، کلمه‌ی اول را هم اضافه می‌کنیم.

نادیده گرفتن فاصله‌های متوالیcpp
خروجی برنامه
Enter a sentence:  Hello   beautiful   world
Word count = 3

فلوچارت شمارش کلمات دقیق

گام‌های شمارش کلمات با نادیده گرفتن فاصله‌های متوالی:

flow.svg

مثال ۳: تبدیل حروف کوچک به بزرگ

در جدول اسکی، کد هر حرف کوچک انگلیسی دقیقاً ۳۲ واحد بیشتر از حرف بزرگ آن است. مثلاً 'a' = 97 و 'A' = 65. پس برای تبدیل کوچک به بزرگ، کافی است ۳۲ از کد اسکی کم کنیم. همچنین می‌توان از تابع آماده toupper در <cctype> استفاده کرد.

تفاوت کد اسکی حروف ۳۲ استcpp
خروجی برنامه
Enter text: Hello World 123
HELLO WORLD 123

مثال ۴: شمارش تعداد تکرار یک زیررشته

می‌خواهیم تعداد دفعاتی که رشته‌ی S2 در S1 ظاهر شده را بشماریم. روش: در هر موقعیت ممکن i، چک می‌کنیم آیا زیررشته‌ی شروع‌شده از i با طول S2.length() برابر با S2 است یا نه. برای جلوگیری از خطای unsigned، حتماً نوع‌ها را به int تبدیل کنید.

جستجوی s2 در s1cpp
خروجی برنامه
Enter S1: aabcdcabd
Enter S2: ab
2
در حال باز کردن ویرایشگر…

فلوچارت جستجوی زیررشته

گام‌های شمارش تعداد تکرار S2 در S1:

flow.svg

مثال ۵: استخراج و جمع دو عدد از رشته

می‌خواهیم رشته‌ای مثل "123+456" را بخوانیم و مجموع دو عدد ۱۲۳ و ۴۵۶ یعنی ۵۷۹ را چاپ کنیم. روش: ابتدا اندیس علامت + را پیدا می‌کنیم، سپس ارقام قبل و بعد از آن را به عدد تبدیل می‌کنیم. فرمول تبدیل کاراکتر به رقم: s[i] - '0' (یا s[i] - 48).

نکته: عنوان این مسئله در جزوه «مجموع ارقام» نوشته شده، اما کد واقعاً مجموع دو عدد را محاسبه می‌کند، یک تناقض در جزوه اصلی که ما آن را اصلاح کردیم.

رشته‌ی "123+456" → عدد ۵۷۹cpp
خروجی برنامه
Enter expression (e.g. 123+456): 123+456
Sum = 579
در حال باز کردن ویرایشگر…

روش مدرن‌تر: استفاده از s.find

به‌جای حلقه‌ی دستی برای پیدا کردن علامت +، می‌توانید از متد آماده s.find('+') استفاده کنید. این متد اندیس اولین وقوع را برمی‌گرداند یا اگر پیدا نشد، مقدار string::npos را برمی‌گرداند:

main.cppcpp

این روش خواناتر و کم‌خطاتر از حلقه‌ی دستی است.

هشدار: نوع size_t بدون علامت است

تابع s.length() نوع size_t (بدون علامت) برمی‌گرداند. اگر بنویسید s.length() - 2 و طول رشته کمتر از ۲ باشد، نتیجه یک عدد بسیار بزرگ و مثبت می‌شود (نه منفی!). برای جلوگیری از این خطای خاموش، همیشه به int تبدیل کنید: (int)s.length() - 2.

این یکی از رایج‌ترین منابع باگ در برنامه‌های ⁦C++⁩ مبتنی بر رشته است.

مرور سریع مطالب

۱۷ بخش در این درس

تمرین‌ها

01
تمرین•حل کامل دارد

برنامه‌ای بنویسید که یک جمله از کاربر بگیرد و تعداد حروف صدادار (a, e, i, o, u — بزرگ یا کوچک) را بشمارد.

نمایش راهنما
از `getline` استفاده کنید و با یک حلقه روی هر کاراکتر، آن را با هر یک از حروف صدادار مقایسه کنید.
02
تمرین•حل کامل دارد

برنامه‌ای بنویسید که یک رشته بگیرد و معکوس آن را چاپ کند (مثلاً "Hello" → "olleH").

نمایش راهنما
از دو اندیس i (از ۰) و j (از length-1) استفاده کنید و کاراکتر‌ها را با `swap` جابجا کنید.
03
تمرین•حل کامل دارد

برنامه‌ای بنویسید که یک رشته و یک کاراکتر بگیرد و تعداد تکرار آن کاراکتر در رشته را چاپ کند.

نمایش راهنما
با یک حلقه روی رشته و شرط `s[i] == c` شمارش کنید.
04
تمرین•حل کامل دارد

برنامه‌ای بنویسید که یک رشته بگیرد و بررسی کند آیا این رشته **پالیندروم** است یا خیر (مثل «level» یا «radar» که از دو طرف یکی خوانده می‌شود).

نمایش راهنما
کاراکتر‌های `i` ام از ابتدا و `i` ام از انتها را با هم مقایسه کنید.
05
تمرین•حل کامل دارد

برنامه‌ای بنویسید که یک رشته شامل دو عدد اعشاری جدا شده با علامت `/` بگیرد و خارج‌قسمت آن‌ها را چاپ کند (مثلاً "12/3" → 4).

نمایش راهنما
ابتدا موقعیت `/` را پیدا کنید، سپس هر بخش را به عدد تبدیل کرده و تقسیم کنید.
// نکات-کلیدی۶
  • 01کلاس `std::string` جایگزین مدرن و امن آرایه‌ی کاراکتری C-style است و حافظه را خودش مدیریت می‌کند.
  • 02`cin >> s` فقط یک کلمه (تا فاصله) می‌خواند، در حالی که `getline(cin, s)` کل خط شامل فاصله‌ها را می‌خواند.
  • 03اگر قبل از `getline` از `cin >>` استفاده کرده‌اید، حتماً `cin.ignore()` قرار دهید تا Enter اضافی پاک شود.
  • 04متد `length()` تعداد کاراکتر‌ها را برمی‌گرداند؛ در عملیات حسابی همیشه آن را به `int` تبدیل کنید.
  • 05برای تبدیل حروف کوچک به بزرگ، ۳۲ از کد اسکی کم کنید (یا از تابع `toupper` استفاده کنید).
  • 06برای جستجوی یک کاراکتر یا زیررشته می‌توانید از متد `s.find()` و بررسی `string::npos` استفاده کنید.
گام بعدی پیشنهادی

آرایه‌های دو‌بعدی

ماتریس، قطر اصلی و فرعی، پیمایش و الگوهای مثلثی

۴۰ دقیقهمتوسط۱۶ بخش

شروع درس

جستجوی سریع در درس‌ها

نام درس، موضوع یا کلمه کلیدی را بنویسید و با Enter به آن بروید