C: المعاملات والتعبيرات
المعاملات أشبه بأدوات المطبخ - تستخدم السكين للتقطيع والمقلاة للقلي. مكونات مختلفة تحتاج أدوات مختلفة، وحسابات مختلفة تحتاج معاملات مختلفة.
1. المعاملات الحسابية
توفر C سبعة معاملات حسابية أساسية لأكثر الحسابات الرياضية شيوعا.
| المعامل | المعنى | مثال | النتيجة |
|---|---|---|---|
+ |
الجمع | 5 + 3 |
8 |
- |
الطرح | 5 - 3 |
2 |
* |
الضرب | 5 * 3 |
15 |
/ |
القسمة | 7 / 2 |
3 |
% |
باقي القسمة | 7 % 2 |
1 |
+ |
إيجابي أحادي | +5 |
5 |
- |
سلبي أحادي | -5 |
-5 |
(1) فخ القسمة الصحيحة
عند قسمة عددين صحيحين، النتيجة أيضا عدد صحيح - يُتجاهل الجزء الكسري ببساطة، بدون تقريب.
#include <stdio.h>
int main(void) {
int a = 7;
int b = 2;
printf("%d / %d = %d\n", a, b, a / b);
printf("%d %% %d = %d\n", a, b, a % b);
return 0;
}
7 / 2 = 3
7 % 2 = 1
7.0 / 2 تعطي 3.5.
(2) استخدامات معامل باقي القسمة
معامل باقي القسمة % يعمل فقط مع الأعداد الصحيحة. له عدة حالات استخدام عملية جدا:
- التحقق من الزوجية:
n % 2يساوي 0 يعني زوجي - الحصول على آخر رقم:
n % 10يعطي خانة الآحاد - الفهرسة الدائرية:
i % sizeيبقي الفهرس يدور بين 0 و size-1
#include <stdio.h>
int main(void) {
int n = 12345;
printf("آخر رقم: %d\n", n % 10);
printf("زوجي: %s\n", n % 2 == 0 ? "نعم" : "لا");
return 0;
}
آخر رقم: 5
زوجي: لا
2. معاملات الزيادة والنقصان
معامل الزيادة ++ يضيف 1 إلى متغير، و -- يطرح 1. لكل منهما شكلان: سابقي ولاحق، يختلفان فيما يُرجعه التعبير.
(1) السابقي مقابل اللاحق
| الشكل | الاسم | التأثير | قيمة التعبير |
|---|---|---|---|
++i |
زيادة سابقة | i تزداد بـ 1 | القيمة الجديدة (المزادة) |
i++ |
زيادة لاحقة | i تزداد بـ 1 | القيمة القديمة (الأصلية) |
--i |
نقصان سابقي | i تنقص بـ 1 | القيمة الجديدة (المنقصة) |
i-- |
نقصان لاحق | i تنقص بـ 1 | القيمة القديمة (الأصلية) |
#include <stdio.h>
int main(void) {
int a = 5;
int b = ++a;
printf("سابقي: a=%d, b=%d\n", a, b);
int c = 5;
int d = c++;
printf("لاحق: c=%d, d=%d\n", c, d);
return 0;
}
سابقي: a=6, b=6
لاحق: c=6, d=5
a = ++a + a++. السلوك غير معرف، والمترجمات المختلفة ستعطي نتائج مختلفة.
3. معاملات العلاقات
تقارن معاملات العلاقات بين قيمتين، وتُرجع "صحيح" (1) أو "خطأ" (0).
| المعامل | المعنى | مثال | النتيجة |
|---|---|---|---|
== |
يساوي | 5 == 5 |
1 |
!= |
لا يساوي | 5 != 3 |
1 |
< |
أصغر من | 3 < 5 |
1 |
> |
أكبر من | 3 > 5 |
0 |
<= |
أصغر من أو يساوي | 5 <= 5 |
1 |
>= |
أكبر من أو يساوي | 3 >= 5 |
0 |
#include <stdio.h>
int main(void) {
int a = 10;
int b = 20;
printf("a == b: %d\n", a == b);
printf("a != b: %d\n", a != b);
printf("a < b: %d\n", a < b);
return 0;
}
a == b: 0
a != b: 1
a < b: 1
== للمقارنة، = للإسناد. الخلط بينهما يحول المقارنة إلى إسناد لن يُنتج خطأ. عادة جيدة: ضع الثابت على اليسار: 5 == a - إذا كتبت بالخطأ 5 = a، سيكشف المترجم الخطأ.
4. المعاملات المنطقية
تجمع المعاملات المنطقية بين شروط متعددة، وتُرجع أيضا 1 (صحيح) أو 0 (خطأ).
| المعامل | المعنى | مثال | النتيجة |
|---|---|---|---|
&& |
و المنطقية | 1 && 0 |
0 |
| ` | ` | أو المنطقية | |
! |
نفي المنطقية | !0 |
1 |
(1) جدول الصواب
| A | B | A && B | A || B | !A | |---|---|--------|--------|----| | 0 | 0 | 0 | 0 | 1 | | 0 | 1 | 0 | 1 | 1 | | 1 | 0 | 0 | 1 | 0 | | 1 | 1 | 1 | 1 | 0 |
(2) التقييم قصير الدائرة
مع &&، إذا كان الطرف الأيسر خطأ، لا يُقيّم الطرف الأيمن أبدا. مع ||، إذا كان الطرف الأيسر صحيحا، يُتجاوز الطرف الأيمن. هذه الميزة يمكن استخدامها لتجنب العمليات غير القانونية:
#include <stdio.h>
int main(void) {
int divisor = 0;
int value = 10;
if (divisor != 0 && value / divisor > 5) {
printf("الشرط متحقق\n");
} else {
printf("الشرط غير متحقق، ولا قسمة على صفر\n");
}
return 0;
}
الشرط غير متحقق، ولا قسمة على صفر
-5 "صحيحة" في سياق منطقي.
5. معاملات الإسناد
معامل الإسناد الأساسي = يخزن القيمة في الطرف الأيمن في متغير الطرف الأيسر. توفر C أيضا معاملات إسناد مركبة تجمع بين عملية وإسناد.
| المركبة | المكافئة |
|---|---|
a += b |
a = a + b |
a -= b |
a = a - b |
a *= b |
a = a * b |
a /= b |
a = a / b |
a %= b |
a = a % b |
#include <stdio.h>
int main(void) {
int score = 80;
score += 10;
printf("بعد المكافأة: %d\n", score);
score -= 25;
printf("بعد العقوبة: %d\n", score);
score *= 2;
printf("بعد المضاعفة: %d\n", score);
return 0;
}
بعد المكافأة: 90
بعد العقوبة: 65
بعد المضاعفة: 130
6. المعامل الشرطي (المعامل الثلاثي)
المعامل الشرطي ?: هو المعامل الثلاثي الوحيد في C. صياغته:
condition ? expression1 : expression2
إذا كان الشرط صحيحا، يُقيّم expression1؛ وإلا يُقيّم expression2. هو اختصار لـ if-else.
#include <stdio.h>
int main(void) {
int age = 20;
char *status = age >= 18 ? "بالغ" : "قاصر";
printf("العمر %d، %s\n", age, status);
int a = 15, b = 28;
int max = a > b ? a : b;
printf("القيمة الأكبر: %d\n", max);
return 0;
}
العمر 20، بالغ
القيمة الأكبر: 28
7. معامل الفاصلة
معامل الفاصلة , يُقيّم كل تعبير من اليسار إلى اليمين، وقيمة تعبير الفاصلة بالكامل هي قيمة آخر تعبير.
#include <stdio.h>
int main(void) {
int a, b, c;
c = (a = 1, b = 2, a + b);
printf("a=%d, b=%d, c=%d\n", a, b, c);
return 0;
}
a=1, b=2, c=3
8. معامل sizeof
sizeof تُرجع عدد البايتات التي يشغلها نوع بيانات أو متغير في الذاكرة. يُقيّم وقت الترجمة، وليس وقت التشغيل.
#include <stdio.h>
int main(void) {
printf("char: %zu bytes\n", sizeof(char));
printf("int: %zu bytes\n", sizeof(int));
printf("float: %zu bytes\n", sizeof(float));
printf("double: %zu bytes\n", sizeof(double));
int arr[5] = {1, 2, 3, 4, 5};
printf("الحجم الكلي للمصفوفة: %zu bytes\n", sizeof(arr));
printf("عدد عناصر المصفوفة: %zu\n", sizeof(arr) / sizeof(arr[0]));
return 0;
}
char: 1 bytes
int: 4 bytes
float: 4 bytes
double: 8 bytes
الحجم الكلي للمصفوفة: 20 bytes
عدد عناصر المصفوفة: 5
sizeof تتطلب أقواسا لأسماء الأنواع (sizeof(int)) لكن ليس للمتغيرات (sizeof a). ومع ذلك، للاتساق، من الأفضل استخدام الأقواس دائما.
9. أسبقية المعاملات
عندما يحتوي تعبير على معاملات متعددة، يُقيّم ذو الأسبقية الأعلى أولا. الجدول أدناه يسردها من الأعلى إلى الأدنى:
| الأسبقية | المعاملات | التجميع |
|---|---|---|
| 1 (الأعلى) | () [] -> . |
من اليسار لليمين |
| 2 | ! ~ ++ -- +(أحادي) -(أحادي) *(تgunref) &(أخذ العنوان) sizeof |
من اليمين لليسار |
| 3 | * / % |
من اليسار لليمين |
| 4 | + - |
من اليسار لليمين |
| 5 | << >> |
من اليسار لليمين |
| 6 | < <= > >= |
من اليسار لليمين |
| 7 | == != |
من اليسار لليمين |
| 8 | & |
من اليسار لليمين |
| 9 | ^ |
من اليسار لليمين |
| 10 | ` | ` |
| 11 | && |
من اليسار لليمين |
| 12 | ` | |
| 13 | ?: |
من اليمين لليسار |
| 14 | = += -= *= /= %= إلخ |
من اليمين لليسار |
| 15 (الأدنى) | , |
من اليسار لليمين |
▶ مثال
اجمع معاملات متنوعة لحساب مجموع أرقام عدد مكون من ثلاثة أرقام:
#include <stdio.h>
int main(void) {
int num = 952;
int hundreds = num / 100;
int tens = (num / 10) % 10;
int ones = num % 10;
int sum = hundreds + tens + ones;
printf("العدد: %d\n", num);
printf("مئات: %d، عشرات: %d، آحاد: %d\n", hundreds, tens, ones);
printf("مجموع الأرقام: %d\n", sum);
return 0;
}
العدد: 952
مئات: 9، عشرات: 5، آحاد: 2
مجموع الأرقام: 16
▶ مثال
استخدم المعاملات المنطقية ومعاملات العلاقات لتحديد ما إذا كانت سنة كبيسة:
#include <stdio.h>
int main(void) {
int year = 2024;
int is_leap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
printf("%d %sسنة كبيسة\n", year, is_leap ? "" : "ليست ");
return 0;
}
2024 سنة كبيسة
10. تحويل الأنواع
(1) التحويل الضمني
عند خلط أنواع مختلفة في تعبير، يُحوّل المترجم تلقائيا النوع ذو الدقة الأدنى إلى النوع ذو الدقة الأعلى:
#include <stdio.h>
int main(void) {
int a = 5;
double b = 2.0;
double c = a / b;
printf("5 / 2.0 = %f\n", c);
char ch = 'A';
int code = ch + 1;
printf("'A' + 1 = %c (ASCII %d)\n", code, code);
return 0;
}
5 / 2.0 = 2.500000
'A' + 1 = B (ASCII 66)
اتجاه التحويل: char → int → long → double، int → unsigned → long → double.
(2) التحويل الصريح
استخدم (type_name) لإجبار قيمة على نوع محدد:
#include <stdio.h>
int main(void) {
int a = 7, b = 2;
double result = (double)a / b;
printf("مع التحويل: %f\n", result);
return 0;
}
مع التحويل: 3.500000
❓ أسئلة شائعة
a++ و ++a عند استخدامهما في سطر منفصل؟= و ==؟= للإسناد ("يصبح")، == للمقارنة ("هل يساوي؟"). كتابة if (a = 0) بالخطأ لن تسبب خطأ لكنها تغير المنطق تماما. عادة جيدة: ضع الثابت على اليسار - if (0 == a) - ليُكشف خطأ الكتابة مثل if (0 = a) من قبل المترجم.% مع أعداد الفاصلة العائمة؟% يعمل فقط مع الأنواع الصحيحة. لباقي قسمة الفاصلة العائمة، استخدم الدالة fmod() من #include <math.h>.📖 ملخص
- في الحسابات، القسمة الصحيحة تقطع الجزء الكسري؛ باقي القسمة يعمل فقط مع الأعداد الصحيحة
++/--السابقي يُرجع القيمة الجديدة، اللاحق يُرجع القيمة القديمة؛ تجنب استخدامهما عدة مرات على نفس المتغير في تعبير واحد- معاملات العلاقات تُرجع 0 أو 1؛ انتبه للخلط بين
=و== - المعاملات المنطقية
&&و||تُقيّم بقصر الدائرة، ما يمكنه حماية التعبير الأيمن - لا تحفظ الأسبقية - عند الشك، أضف أقواسا
📝 تمارين
- اكتب برنامجا يأخذ عددا من الثواني (مثلا 3661) ويستخدم
/و%لحساب الساعات والدقائق والثواني المقابلة، ثم يُخرج النتيجة. - اكتب برنامجا يأخذ عددين صحيحين ويستخدم المعامل الثلاثي لإيجاد وإخراج القيمتين الأكبر والأصغر.
- اكتب برنامجا يستخدم
sizeofلطباعة أحجامshortوintوlongوlong longعلى حاسوبك ولاحظ النتائج.