C++: الإدخال والإخراج بعمق
آخر تحديث: 2026-08-26
في الدرس 03 استخدمنا
cinوcoutباختصار، لكن هذا كان مجرد قمة الجبل الجليدي.في السيناريوهات الواقعية، تحتاج للتعامل مع سلاسل نصية تحتوي مسافات، والتحكم في المنازل العشرية، وجعل الإخراج أكثر جمالًا...
في هذا الدرس، سنتعمق في جميع إمكانيات
cinوcout.
1. الاستخدام المتقدم لـ cout
(1) 1.1 أحرف الهروب
بعض الأحرف لا يمكن كتابتها مباشرة (مثل سطر جديد، Tab)، لذا يجب تمثيلها باستخدام أحرف الهروب.
| حرف الهروب | المعنى | المثال |
|---|---|---|
\n |
سطر جديد | std::cout << "Hello\nWorld"; |
\t |
Tab | std::cout << "Name:\tMOTO"; |
\\ |
شرطة مائلة خلفية | std::cout << "C:\\Users\\MOTO"; |
\" |
علامة اقتباس مزدوجة | std::cout << "He said \"Hi\""; |
\0 |
حرف فارغ (منهي السلسلة) | (ستُغطى لاحقًا) |
مثال: إخراج منسق بأحرف الهروب (صعوبة ⭐)
▶ مثال 2: تطبيق برمجي أساسي (صعوبة ⭐)
#include <iostream>
int main() {
std::cout << "========== Report Card ==========\n";
std::cout << "Name: \tMOTO\n";
std::cout << "Age: \t35\n";
std::cout << "Score: \t92.5\n";
std::cout << "===================\n";
return 0;
}
الخرج:
========== Report Card ==========
Name: MOTO
Age: 35
Score: 92.5
===================
(2) 1.2 endl مقابل \n
| التدوين | التأثير | الأداء |
|---|---|---|
std::endl |
يُخرج سطر جديد + يفرغ المخزن | بطيء (يفرغ في كل مرة) |
"\n" |
يُخرج سطر جديد فقط | سريع (موصى به) |
💡 توصية: ما لم تكن بحاجة صريحة لتفريغ المخزن، استخدم "\n" بدلًا من std::endl.
std::cout << "Hello" << std::endl; // Newline + flush (slow)
std::cout << "Hello\n"; // Newline only (fast, recommended)
2. الإخراج المنسق بـ cout
(1) 2.1 التحكم في المنازل العشرية
بشكل افتراضي، يختار cout التنسيق تلقائيًا لإخراج أعداد الفاصلة العائمة (مثل 3.14159 أو 3.14). لكن أحيانًا تحتاج عددًا ثابتًا من المنازل العشرية (مثل عرض سعر مثل $19.99).
يتطلب #include <iomanip>
#include <iostream>
#include <iomanip> // Must include this header
int main() {
double pi = 3.141592653589793;
std::cout << "Default: " << pi << std::endl;
// Fixed decimal places (2 digits)
std::cout << std::fixed << std::setprecision(2);
std::cout << "2 decimal places: " << pi << std::endl;
// Restore default
std::cout.unsetf(std::ios::fixed);
std::cout << std::setprecision(6); // Restore default precision
std::cout << "Restored default: " << pi << std::endl;
return 0;
}
💡 نقاط مهمة:
std::fixed— استخدام تنسيق الفاصلة العائمة الثابت (بدون التدوين العلمي)std::setprecision(n)— تعيين الدقة (عند دمجها معfixed، هذا يعني n منازل عشرية)
(2) 2.2 التحكم في عرض الإخراج (المحاذاة)
#include <iostream>
#include <iomanip>
int main() {
std::cout << std::left; // Left-align
std::cout << std::setw(10) << "Name" << std::setw(5) << "Age" << std::endl;
std::cout << std::setw(10) << "MOTO" << std::setw(5) << 35 << std::endl;
std::cout << std::setw(10) << "Alice" << std::setw(5) << 20 << std::endl;
return 0;
}
| المعالج | التأثير |
|---|---|
std::setw(n) |
تعيين عرض الإخراج التالي إلى n حرفًا |
std::left |
محاذاة لليسار |
std::right |
محاذاة لليمين (افتراضي) |
std::setfill(c) |
تعيين حرف الملء (الافتراضي مسافة) |
3. الاستخدام المتقدم لـ cin
(1) 3.1 فخ cin: يتوقف عند المسافات
cin >> يتوقف عن قراءة سلسلة نصية عندما يصادف مسافة!
#include <iostream>
#include <string>
int main() {
std::string name;
std::cout << "Please enter your full name (e.g., John Smith): ";
std::cin >> name;
std::cout << "Hello," << name << "!" << std::endl;
return 0;
}
نتيجة التشغيل:
Please enter your full name (e.g., John Smith): John Smith
Hello,John! ← Only read "John", "Smith" was discarded
(2) 3.2 استخدام getline لقراءة سطر كامل
لقراءة سطر كامل بما فيه المسافات، استخدم std::getline().
#include <iostream>
#include <string>
int main() {
std::string fullName;
std::cout << "Please enter your full name: ";
std::getline(std::cin, fullName); // Read entire line (including spaces)
std::cout << "Hello," << fullName << "!" << std::endl;
return 0;
}
نتيجة التشغيل:
Please enter your full name: John Smith
Hello,John Smith! ← Complete read
(3) 3.3 فخ المزج بين cin وgetline
المشكلة:
#include <iostream>
#include <string>
int main() {
int age;
std::string name;
std::cout << "Please enter your age: ";
std::cin >> age;
std::cout << "Please enter your name: ";
std::getline(std::cin, name); // ❌ This line gets skipped!
std::cout << "Age: " << age << ",Name: " << name << std::endl;
return 0;
}
السبب: بعد أن يقرأ cin >> age العدد الصحيح، يتبقى حرف سطر جديد \n في مخزن الإدخال. عندما يرى getline الحرف \n، يظن أن المستخدم أدخل سطرًا فارغًا ويعود فورًا.
الحل: استخدم cin.ignore() لتجاهل حرف السطر الجديد
#include <iostream>
#include <string>
int main() {
int age;
std::string name;
std::cout << "Please enter your age: ";
std::cin >> age;
std::cin.ignore(); // Discard the newline character
std::cout << "Please enter your name: ";
std::getline(std::cin, name); // ✅ Now it reads correctly
std::cout << "Age: " << age << ",Name: " << name << std::endl;
return 0;
}
💡 القاعدة الذهبية: إذا استخدمت cin >> أولًا ثم getline، تذكر إضافة cin.ignore().
4. تطبيق: نموذج تسجيل معلومات المستخدم
▶ مثال 1: تسجيل معلومات المستخدم (صعوبة ⭐⭐)
#include <iostream>
#include <string>
#include <iomanip>
int main() {
std::string name, address;
int age;
double salary;
std::cout << "========== User Information Registration ==========\n";
std::cout << "Please enter your name: ";
std::getline(std::cin, name);
std::cout << "Please enter your age: ";
std::cin >> age;
std::cin.ignore(); // Discard newline character
std::cout << "Please enter your address: ";
std::getline(std::cin, address);
std::cout << "Please enter your monthly salary: ";
std::cin >> salary;
// Output registration form
std::cout << "\n========== Registration Result ==========\n";
std::cout << "Name: " << name << std::endl;
std::cout << "Age: " << age << " years old" << std::endl;
std::cout << "Address: " << address << std::endl;
std::cout << std::fixed << std::setprecision(2);
std::cout << "Monthly salary: " << salary << " yuan" << std::endl;
std::cout << "==============================\n";
return 0;
}
الخرج:
========== User Information Registration ==========
Please enter your name:
Please enter your age:
Please enter your address:
Please enter your monthly salary:
========== Registration Result ==========
Name:
Age: years old
Address:
Monthly salary: yuan
=============================
نتيجة التشغيل:
========== User Information Registration ==========
Please enter your name: MOTO
Please enter your age: 35
Please enter your address: Meijia Vocational College, Xiaogan, Hubei
Please enter your monthly salary: 15000
========== Registration Result ==========
Name: MOTO
Age: 35 years old
Address: Meijia Vocational College, Xiaogan, Hubei
Monthly salary: 15000.00 yuan
==============================
5. مقدمة في إدخال/إخراج الملفات (اختياري)
بخلاف القراءة من لوحة المفاتيح والكتابة على الشاشة، يمكن لـ C++ أيضًا قراءة البيانات من ملفات وكتابة البيانات إلى ملفات.
(1) 5.1 الكتابة إلى ملف
#include <iostream>
#include <fstream> // File stream header
int main() {
std::ofstream outFile("output.txt"); // Create output file stream
if (!outFile) {
std::cout << "Cannot open file!" << std::endl;
return 1;
}
outFile << "Hello, File!" << std::endl;
outFile << "This is the content written to the file." << std::endl;
outFile.close(); // Close the file
std::cout << "Write successful!" << std::endl;
return 0;
}
بعد التشغيل، سيُولَّد ملف output.txt في دليل البرنامج.
(2) 5.2 القراءة من ملف
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ifstream inFile("output.txt"); // Create input file stream
if (!inFile) {
std::cout << "Cannot open file!" << std::endl;
return 1;
}
std::string line;
while (std::getline(inFile, line)) {
std::cout << "Read: " << line << std::endl;
}
inFile.close();
return 0;
}
💡 نصيحة: إدخال/إخراج الملفات موضوع كبير — هذه مجرد مقدمة مختصرة. سيكون هناك درس مخصص يغطيه بعمق لاحقًا.
❓ أسئلة شائعة
system("chcp 65001"); في بداية برنامجك للتحويل إلى ترميز UTF-8، أو تغيير خط وحدة التحكم إلى "NSimSun". macOS/Linux عادةً لا تواجه هذه المشكلة.cin/cout مُعرَّفان في فضاء الأسماء std. يمكنك استخدام using namespace std; لتجنب كتابة std::، لكن هذا غير موصى به — يمكن أن يسبب تعارضات في الأسماء. يُنصح دائمًا بكتابة std::cin، std::cout.system("cls");، macOS/Linux: system("clear");. لكن هذا الأسلوب غير قابل للنقل وغير موصى به في الإنتاج — للاستخدام المؤقت فقط أثناء التعلم.getline يمكنها فقط قراءة السلاسل النصية. لقراءة الأعداد الصحيحة، استخدم cin >>. إذا كنت تريد قراءة سطر كامل ثم تحليله كعدد صحيح، استخدم std::stoi(line) لتحويل سلسلة نصية إلى عدد صحيح.▶ مثال 3: إخراج منسق (صعوبة ⭐)
#include <iostream>
#include <iomanip>
int main() {
double price = 19.99;
int quantity = 5;
std::cout << "Unit price: " << std::fixed << std::setprecision(2) << price << std::endl;
std::cout << "Quantity: " << std::setw(5) << quantity << std::endl;
std::cout << "Total: " << price * quantity << std::endl;
return 0;
}
الخرج:
Unit price: 19.99
Quantity: 5
Total: 99.95
std::fixed + std::setprecision(2) يحافظ على منزلتين عشريتين؛ std::setw(5) يضبط العرض.
coutيستخدم أحرف الهروب (\n،\t) للتحكم في التنسيق- استخدم
std::fixed+std::setprecision(n)للتحكم في المنازل العشرية - استخدم
std::setw(n)للتحكم في عرض الإخراج (المحاذاة) cin >>يتوقف عن قراءة السلاسل النصية عند المسافات؛ استخدمgetlineلقراءة أسطر كاملة- عند المزج بين
cin >>وgetline، تذكر إضافةcin.ignore()لتجاهل حرف السطر الجديد - إدخال/إخراج الملفات يتطلب
#include <fstream>
📖 ملخص
- std::cin: تيار الإدخال القياسي
- std::cout: تيار الإخراج القياسي
- std::cerr: تيار الخطأ القياسي (غير مخزَّن)
- التنسيق:
std::setw،std::setprecision، إلخ.
📝 تمارين
- أساسي (صعوبة ⭐): اكتب برنامجًا يُخرج جدول ضرب (1-9) بالتنسيق التالي:
1 x 1 = 1
1 x 2 = 2 2 x 2 = 4
1 x 3 = 3 2 x 3 = 6 3 x 3 = 9
...
(تلميح: استخدم \t للمحاذاة وحلقات متداخلة)
- متوسط (صعوبة ⭐⭐): اكتب برنامجًا يتيح للمستخدم إدخال:
- اسم المنتج (قد يحتوي مسافات، مثل "iPhone 15 Pro")
- سعر الوحدة
- الكمية
يحسب البرنامج الإجمالي ويُخرج بتنسيق:
========== Shopping Receipt ==========
Product name: iPhone 15 Pro
Unit price: 6999.00 yuan
Quantity: 2
Total: 13998.00 yuan
==============================
- تحدي (صعوبة ⭐⭐⭐): اكتب برنامجًا ينفذ "إدخال دفتر عناوين":
- دع المستخدم يدخل معلومات 3 جهات اتصال (الاسم، الهاتف، الصلة)
- اكتب المعلومات إلى ملف
contacts.txt - ثم اقرأ من الملف واعرضه
(تلميح: استخدم ofstream للكتابة، ifstream للقراءة)
- cout يستخدم << للإخراج، يدعم أحرف الهروب (\n، \t)
- الإخراج المنسق: fixed/setprecision للمنازل العشرية، setw للعرض
- cin يستخدم >> للإدخال، يتوقف عند المسافات
- getline يقرأ سطرًا كاملًا من السلسلة النصية؛ أضف cin.ignore() عند المزج مع cin
- إدخال/إخراج الملفات: ofstream للكتابة، ifstream للقراءة
6. 🚀 الخطوة التالية
الآن بعد أن تعلمت الإدخال والإخراج، سنتعلم بعد ذلك الجمل الشرطية (if-else) (الدرس 06) — تمكين البرامج من اتخاذ القرارات وتنفيذ كود مختلف بناءً على شروط مختلفة.