کدلپر - مرجع جامع آموزش برنامه‌نویسی

All Right Reserved © 2025 Codoloper

background codoloper

عملگرهای افزایش و کاهش Increment and Decrement Operators

خانه

زبان C دو تا عملگر خاص برای زیاد کردن یا کم کردن مقدار متغیرها داره. عملگر ++ یه واحد به متغیرش اضافه می‌کنه، و عملگر -- یه واحد ازش کم می‌کنه.
ما تا حالا چند بار از ++ استفاده کردیم، مثلاً:

 
if (c == '\n')
    ++nl;

نکته‌ی جالب اینه که ++ و -- می‌تونن به‌صورت پیشوند (قبل از متغیر مثل ++n) یا پسوند (بعد از متغیر مثل n++) استفاده بشن. توی هر دو حالت، متغیر n یکی زیاد می‌شه،
ولی فرقشون توی ترتیب انجام کاره:

  • ++n یعنی اول n زیاد می‌شه، بعد مقدارش استفاده می‌شه.

  • n++ یعنی اول مقدار فعلی استفاده می‌شه، بعد n زیاد می‌شه.

مثلاً اگه n برابر ۵ باشه:

 
x = n++;

باعث می‌شه x برابر ۵ بشه، ولی

 
x = ++n;

باعث می‌شه x برابر ۶ بشه.
در هر دو حالت در آخر n برابر ۶ می‌شه.

نکته‌ی مهم اینه که ++ و -- فقط روی متغیرها قابل استفاده‌ان. مثلاً (i + j)++ غیرقانونیه.

اگه جایی فقط خودِ عمل افزایش مهم باشه و مقدار نهایی استفاده نشه، مثل:

 
if (c == '\n')
    nl++;

فرقی نداره که پیشوند بنویسی یا پسوند، نتیجه یکیه.
ولی بعضی وقتا یکی از این دو شکل خاص لازم می‌شه.

مثلاً تابع squeeze(s, c) که همه‌ی کاراکترهای c رو از رشته‌ی s حذف می‌کنه:

 
/* squeeze: delete all c from s */
void squeeze(char s[], int c)
{
    int i, j;
    for (i = j = 0; s[i] != '\0'; i++)
        if (s[i] != c)
            s[j++] = s[i];
    s[j] = '\0';
}

اینجا هر بار که یه کاراکتر غیر از c پیدا می‌شه، اون کاراکتر در موقعیت فعلی j کپی می‌شه، و بعد j یکی زیاد می‌شه تا برای کاراکتر بعدی آماده باشه.
یعنی این دو بخش دقیقاً یکی هستن:

 
if (s[i] != c)
    s[j++] = s[i];

و

 
if (s[i] != c) {
    s[j] = s[i];
    j++;
}

یه مثال دیگه از همین نوع در تابع getline از فصل ۱ بود. اونجا می‌شد این کد:

 
if (c == '\n') {
    s[i] = c;
    ++i;
}

رو به شکل کوتاه‌تر نوشت:

 
if (c == '\n')
    s[i++] = c;

یه مثال سوم از کاربرد ++ در تابع استاندارد strcat(s, t) هست، که رشته‌ی t رو به آخر رشته‌ی s اضافه می‌کنه. فرض بر اینه که رشته‌ی s به اندازه‌ی کافی جا داره.
نسخه‌ی کتابخونه‌ای این تابع یه مقدار برمی‌گردونه (اشاره‌گر به رشته‌ی نتیجه)، ولی نسخه‌ی ما برنمی‌گردونه.

 
/* strcat: concatenate t to end of s; s must be big enough */
void strcat(char s[], char t[])
{
    int i, j;
    i = j = 0;
    while (s[i] != '\0')   /* find end of s */
        i++;
    while ((s[i++] = t[j++]) != '\0')   /* copy t */
        ;
}

اینجا بعد از هر بار کپی کردن یه کاراکتر از t به s، عملگر ++ بعد از i و j باعث می‌شه هر دو به موقعیت بعدی برن تا آماده‌ی حلقه‌ی بعدی بشن.

تمرین ۴-۲: یه نسخه‌ی جایگزین از تابع squeeze(s1, s2) بنویس که همه‌ی کاراکترهایی از s1 رو حذف کنه که توی رشته‌ی s2 هم وجود دارن.

تمرین ۵-۲: تابعی بنویس به نام any(s1, s2) که موقعیت اولین کاراکتری از s1 رو برگردونه که توی s2 هم وجود داره، یا اگه هیچ‌کدوم از کاراکترهای s2 توی s1 نیستن، مقدار -1 برگردونه.
(تابع استاندارد strpbrk همین کار رو انجام می‌ده ولی به‌جای شماره‌ی موقعیت، یه اشاره‌گر به اون مکان برمی‌گردونه.)