توی این بخش میخوایم با یه سری برنامه آشنا بشیم که روی دادههای کاراکتری کار میکنن. جالبه بدونی خیلی از برنامهها، در اصل نسخههای بزرگتر و پیچیدهتر همین نمونههای سادهای هستن که الان یاد میگیری.
مدل ورودی و خروجی در C
کتابخونه استاندارد C یه مدل خیلی ساده برای کار با ورودی و خروجی متن ارائه میده:
-
ورودی و خروجی متن به صورت جریان (stream) کاراکترها در نظر گرفته میشه.
-
یه stream متنی شامل دنبالهای از کاراکترهاست که به خطها تقسیم شدن.
-
هر خط از تعدادی کاراکتر (حتی ممکنه صفر کاراکتر باشه) + در انتها یه کاراکتر newline (\n) تشکیل میشه.
وظیفهی کتابخونه استاندارد اینه که این مدل رو رعایت کنه. پس ما برنامهنویسها لازم نیست نگران باشیم که متن توی فایل یا روی صفحه چطوری نمایش داده میشه.
توابع ورودی و خروجی کاراکتر
کتابخونه استاندارد چندین تابع برای خوندن و نوشتن کاراکترها به صورت تکتک داره.
سادهترینهاش این دوتا هستن:
-
getchar
-
putchar
تابع getchar
هر بار که صدا زده میشه، کاراکتر بعدی رو از جریان ورودی (معمولاً کیبورد) میخونه و برمیگردونه.
مثال:
int c; c = getchar(); // خوندن یک کاراکتر
بعد از اجرای این خط، متغیر c مقدار کاراکتر خوندهشده رو در خودش داره.
(در فصل ۷ میبینیم که ورودی میتونه از فایل هم باشه، نه فقط کیبورد.)
تابع putchar
این تابع یک کاراکتر رو چاپ میکنه.
مثال:
putchar(c);
اینجا مقدار موجود در متغیر c به صورت یک کاراکتر روی خروجی (معمولاً صفحهنمایش) چاپ میشه.
نکته:
-
میتونیم از putchar و printf به صورت ترکیبی استفاده کنیم.
-
ترتیب چاپ خروجی دقیقاً همون ترتیبیه که توابع صدا زده میشن.
کپی کردن فایل یا File Copying
تا اینجا با توابع getchar و putchar آشنا شدیم. شاید برات جالب باشه که فقط با همین دو تا تابع میشه کلی برنامهی کاربردی نوشت!
یکی از سادهترین نمونهها، برنامهایه که ورودی رو میگیره و همون رو به خروجی چاپ میکنه. یعنی هر چیزی تایپ کنی، همون دوباره نشون داده میشه.
به صورت الگوریتم ساده اینطوریه:
-
یه کاراکتر بخون
-
تا وقتی که به علامت پایان فایل (EOF) نرسیدی:
-
همون کاراکتر رو چاپ کن
-
دوباره یه کاراکتر جدید بخون
-
نسخه اول برنامه (Copy Program – Version 1)
#include <stdio.h>
/* کپی کردن ورودی به خروجی؛ نسخه اول */
int main() {
int c;
c = getchar(); // گرفتن اولین کاراکتر
while (c != EOF) {
putchar(c); // چاپ کاراکتر
c = getchar(); // خوندن کاراکتر بعدی
}
return 0;
}
-
عملگر != یعنی «برابر نبودن». پس شرط c != EOF یعنی: "تا وقتی که ورودی برابر پایان فایل نباشه".
-
چیزی که به نظر میاد روی کیبورد یا صفحهنمایش یه کاراکتره، در واقع داخل حافظه به صورت الگوی بیتی ذخیره میشه.
-
نوع دادهی char برای ذخیرهی کاراکترها طراحی شده. اما اینجا ما از int استفاده کردیم. چرا؟
دلیلش اینه که باید بتونیم EOF رو هم ذخیره کنیم.
EOF یه مقدار خاصه (داخل <stdio.h> تعریف شده) که نشون میده ورودی تموم شده. این مقدار نمیتونه با هیچ کاراکتر واقعی اشتباه گرفته بشه. چون char کوچیکه و ممکنه نتونه این مقدار رو نگه داره، پس از int استفاده میکنیم.
نسخه دوم برنامه (Copy Program – Version 2)
برنامهنویسهای حرفهای C معمولاً کد رو جمعوجورتر مینویسن. توی C عمل انتساب (=) خودش یه عبارت (expression) حساب میشه و میتونه توی شرط هم بیاد.
پس میشه برنامه رو اینطوری نوشت:
#include <stdio.h>
/* کپی کردن ورودی به خروجی؛ نسخه دوم */
int main() {
int c;
while ((c = getchar()) != EOF)
putchar(c);
return 0;
}
توضیحات:
-
اینجا توی شرط while، همزمان هم کاراکتر خونده میشه، هم به c داده میشه، و هم بررسی میشه که EOF نباشه.
-
پرانتزها خیلی مهمن! چون اولویت عملگر != بیشتر از = هست. بدون پرانتز، کد این شکلی تفسیر میشه:
c = (getchar() != EOF);
یعنی c برابر میشه با ۰ یا ۱، بسته به اینکه getchar به EOF رسیده باشه یا نه. این دقیقاً همون چیزی نیست که ما میخوایم.
نکته: این روش (نوشتن شرط با انتساب داخلش) در C خیلی رایجه. کد رو جمعوجورتر و خواناتر میکنه، البته اگر زیادهروی نشه.
تمرینها
تمرین 1-6: بررسی کن که عبارت getchar() != EOF مقدارش ۰ یا ۱ میشه.
تمرین 1-7: یه برنامه بنویس که مقدار EOF رو چاپ کنه.