مجاري التدفق (Streams) ومعالجتها في لغة C++
تعد مجاري التدفق (Streams) أحد المفاهيم الأساسية في لغة C++ والتي تتيح للمبرمجين التفاعل مع البيانات التي يتم إدخالها أو إخراجها من أو إلى الكمبيوتر. تمثل مجاري التدفق وسيلة للتعامل مع البيانات بشكل تسلسلي، بحيث يُمكن قراءة البيانات من مجاري الإدخال أو إرسال البيانات إلى مجاري الإخراج. في هذا المقال، سنتناول مفهوم مجاري التدفق في C++ بشكل مفصل، ونشرح كيفية التعامل معها، بالإضافة إلى الأنواع المختلفة من المعالجات الخاصة بها في سياقات متعددة.
1. تعريف مجاري التدفق في C++
في C++، تشير مجاري التدفق إلى الكيانات التي تمثل تدفق البيانات أثناء عمليات الإدخال والإخراج. من خلال مجاري التدفق، يمكن للمبرمج أن يتفاعل مع البيانات التي يتعامل معها البرنامج بشكلٍ مباشر. تُعتبر مجاري التدفق واجهات تُستخدم لقراءة البيانات من مصادر مثل الملفات أو لوحة المفاتيح، أو لكتابة البيانات إلى ملفات أو شاشة العرض.
تتمثل الأنواع الرئيسية لمجاري التدفق في:
-
مجاري الإدخال (Input Streams): تستخدم لقراءة البيانات من مصادر الإدخال مثل الملفات أو لوحة المفاتيح.
-
مجاري الإخراج (Output Streams): تستخدم لكتابة البيانات إلى وجهات الإخراج مثل الملفات أو الشاشة.
-
مجاري الإدخال والإخراج (Input/Output Streams): يمكن استخدامها في نفس الوقت للقراءة والكتابة.
2. أنواع مجاري التدفق في C++
توفر C++ عدة أنواع من الكائنات لتمثيل مجاري التدفق، وهذه الكائنات هي:
-
istream: وهو الكائن المسؤول عن عمليات الإدخال.
-
ostream: وهو الكائن المسؤول عن عمليات الإخراج.
-
ifstream: خاص بالقراءة من الملفات.
-
ofstream: خاص بالكتابة إلى الملفات.
-
fstream: يدعم عمليات القراءة والكتابة على نفس الكائن.
هذه الكائنات تُعتبر فئات موجودة في المكتبة القياسية في C++ (STL)، ويمكن استخدامها بسهولة من خلال تضمين المكتبة أو المكتبات الخاصة بالملفات مثل .
3. استخدام مجاري التدفق لإدخال البيانات (Input Streams)
الوظيفة الأساسية لمجاري الإدخال هي قراءة البيانات من المستخدم أو من مصادر أخرى مثل الملفات. في C++، يتم استخدام الوسائط القياسية مثل cin لقراءة البيانات من لوحة المفاتيح.
على سبيل المثال، لقراءة عدد صحيح من المستخدم، يتم استخدام الكود التالي:
cpp#include
using namespace std;
int main() {
int number;
cout << "أدخل رقمًا: ";
cin >> number;
cout << "الرقم الذي أدخلته هو: " << number << endl;
return 0;
}
في هذا المثال، نستخدم cin لقراءة العدد الصحيح المدخل من المستخدم وتخزينه في المتغير number.
4. استخدام مجاري التدفق لإخراج البيانات (Output Streams)
في الجهة الأخرى، تُستخدم مجاري الإخراج لكتابة البيانات إلى وجهات مختلفة، مثل الشاشة أو ملفات. في C++، cout هو الكائن القياسي الذي يُستخدم لإخراج البيانات إلى الشاشة.
على سبيل المثال، لطباعة رسالة على الشاشة:
cpp#include
using namespace std;
int main() {
cout << "مرحبًا بالعالم!" << endl;
return 0;
}
هنا، نستخدم cout لإخراج النص “مرحبًا بالعالم!” على الشاشة.
5. التعامل مع الملفات باستخدام مجاري التدفق
بالإضافة إلى التعامل مع المدخلات والمخرجات من الشاشة، يمكن لـ C++ أيضًا التعامل مع الملفات باستخدام مجاري التدفق. تُستخدم الفئات ifstream و ofstream للوصول إلى الملفات من أجل القراءة والكتابة على التوالي.
5.1. قراءة البيانات من ملف باستخدام ifstream
cpp#include
#include
using namespace std;
int main() {
ifstream inputFile("input.txt"); // فتح الملف "input.txt" للقراءة
string line;
if (inputFile.is_open()) {
while (getline(inputFile, line)) {
cout << line << endl; // طباعة كل سطر في الملف
}
inputFile.close(); // إغلاق الملف بعد القراءة
} else {
cout << "لم يتمكن من فتح الملف!" << endl;
}
return 0;
}
في المثال السابق، ifstream يُستخدم لقراءة البيانات من ملف نصي. يتم استخدام getline() لقراءة كل سطر من الملف، ثم طباعته باستخدام cout.
5.2. كتابة البيانات إلى ملف باستخدام ofstream
cpp#include
#include
using namespace std;
int main() {
ofstream outputFile("output.txt"); // فتح الملف "output.txt" للكتابة
if (outputFile.is_open()) {
outputFile << "مرحبًا بالعالم!" << endl; // كتابة نص في الملف
outputFile.close(); // إغلاق الملف بعد الكتابة
} else {
cout << "لم يتمكن من فتح الملف!" << endl;
}
return 0;
}
هنا، ofstream يُستخدم لكتابة النص إلى ملف. إذا كان الملف مفتوحًا بنجاح، يتم كتابة النص باستخدام <<.
6. العمليات المركبة على الملفات باستخدام fstream
أحيانًا، قد يحتاج المبرمج إلى إجراء عمليات قراءة وكتابة على نفس الملف. في هذه الحالات، تُستخدم الفئة fstream التي تجمع بين خصائص ifstream و ofstream.
cpp#include
#include
using namespace std;
int main() {
fstream file("data.txt", ios::in | ios::out | ios::app); // فتح الملف للقراءة والكتابة والإضافة
if (file.is_open()) {
string line;
// قراءة البيانات من الملف
while (getline(file, line)) {
cout << line << endl;
}
// إضافة بيانات جديدة
file << "السطر الجديد" << endl;
file.close(); // إغلاق الملف بعد العمليات
} else {
cout << "لم يتمكن من فتح الملف!" << endl;
}
return 0;
}
في هذا المثال، fstream يُستخدم لفتح الملف للقراءة والكتابة والإضافة في الوقت نفسه.
7. معالِجات الأخطاء في مجاري التدفق
أثناء العمل مع مجاري التدفق في C++، من المهم التعامل مع الأخطاء التي قد تحدث، مثل عدم وجود الملف أو فشل القراءة/الكتابة. تُوفر C++ العديد من الأساليب لاكتشاف الأخطاء:
-
fail(): تُستخدم للتحقق من فشل العمليات. -
eof(): تُستخدم للتحقق من نهاية الملف. -
bad(): تُستخدم لاكتشاف الأخطاء في تدفق البيانات.
على سبيل المثال:
cpp#include
#include
using namespace std;
int main() {
ifstream file("data.txt");
if (file.fail()) {
cout << "فشل فتح الملف!" << endl;
} else {
string line;
while (getline(file, line)) {
cout << line << endl;
}
file.close();
}
return 0;
}
8. التنسيق مع مجاري التدفق
يمكن أيضًا تنسيق البيانات داخل مجاري التدفق. على سبيل المثال، يمكن تحديد كيفية طباعة الأعداد باستخدام الدوال التنسيقية:
-
setw(): لتحديد عرض الأعمدة. -
setprecision(): لتحديد عدد الأرقام بعد الفاصلة العشرية. -
fixedوscientific: للتحويل بين الكتابة العادية والعلمية للأرقام.
cpp#include
#include // لإدراج دوال التنسيق
using namespace std;
int main() {
double pi = 3.14159265358979;
cout << fixed << setprecision(2) << pi << endl; // طباعة pi مع دقة تصل إلى منزلتين عشريتين
return 0;
}
9. الاستنتاج
تُعتبر مجاري التدفق في C++ من الأدوات القوية التي تُساعد المبرمجين على التعامل مع بيانات الإدخال والإخراج بطرق مرنة وفعالة. باستخدام cin و cout و fstream وغيرها من الأدوات، يُمكن لمبرمجي C++ تصميم برامج قادرة على معالجة البيانات في مجموعة واسعة من السياقات، بما في ذلك الملفات والشاشات. وبفضل نظام التعامل مع الأخطاء المتطور، تُعتبر مجاري التدفق في C++ وسيلة آمنة وفعالة للوصول إلى البيانات وتنسيقها.

