برنامهی بعدی، تعداد کاراکترهای ورودی رو میشماره. این برنامه تقریباً شبیه برنامهی کپیکردن ورودی هست، فقط به جای چاپ، شمارش انجام میدیم.
نسخه اول: شمارش با while
#include <stdio.h>
/* شمارش کاراکترهای ورودی - نسخه اول */
int main() {
long nc;
nc = 0; // شمارنده از صفر شروع میشه
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
return 0;
}
توضیحات:
-
عملگر ++ یعنی افزایش یک واحد. پس ++nc معادل nc = nc + 1 هست، اما کوتاهتر و اغلب سریعتر.
-
عملگر -- هم برای کم کردن یک واحد استفاده میشه.
-
اینجا از نوع دادهی long استفاده کردیم تا احتمال سرریز (overflow) کمتر بشه، چون int روی بعضی ماشینها فقط ۱۶ بیتی هست و زود پر میشه.
-
در printf، فرمت %ld نشوندهندهی یه عدد long هست.
نسخه دوم: شمارش با for
#include <stdio.h>
/* شمارش کاراکترهای ورودی - نسخه دوم */
int main() {
double nc;
for (nc = 0; getchar() != EOF; ++nc); // بدنهی حلقه خالیه
printf("%.0f\n", nc);
return 0;
}
توضیحات:
-
این بار از نوع double استفاده کردیم تا بتونیم اعداد خیلی بزرگتر رو هم نگه داریم.
-
در printf، فرمت %f برای float و double استفاده میشه.
-
%.0f یعنی عدد اعشاری بدون قسمت اعشار (فقط عدد صحیح چاپ میشه).
-
چون کل کار توی شرط و بخش افزایش (++nc) انجام میشه، بدنهی for خالیه. برای همین یه ; (null statement) گذاشتیم تا دستور کامل بشه.
نکته مهم:
اگر ورودی هیچ کاراکتری نداشته باشه، حلقه حتی یک بار هم اجرا نمیشه و خروجی برابر صفر خواهد بود، که نتیجهی درستیه.
شمارش خطوط (Line Counting)
برنامهی بعدی، تعداد خطوط ورودی رو میشماره. همونطور که گفتیم، هر خط با کاراکتر newline (\n) تموم میشه.
#include <stdio.h>
/* شمارش خطوط ورودی */
int main() {
int c, nl;
nl = 0;
while ((c = getchar()) != EOF)
if (c == '\n')
++nl;
printf("%d\n", nl);
return 0;
}
توضیحات:
-
بدنهی while اینجا یه if هست. اگر کاراکتر ورودی \n باشه، شمارندهی خطوط (nl) یکی زیاد میشه.
-
در C از == برای مقایسه استفاده میشه (برابر بودن). نباید با = (انتساب) اشتباه بشه.
-
'A' یه ثابت کاراکتر هست (در ASCII مقدارش 65 میشه). پس 'A' بهتر از نوشتن 65 هست چون هم واضحتره و هم وابسته به سیستم خاصی نیست.
-
'\n' هم یه ثابت کاراکتره (نه رشته). مقدارش در ASCII عدد 10 هست.
تمرینها
تمرین 1-8: برنامهای بنویسید که تعداد فاصلهها (blanks)، تبها (tabs)، و خطهای جدید (newlines) رو بشماره.
تمرین 1-9: برنامهای بنویسید که ورودی رو کپی کنه، ولی هر چند فاصلهی متوالی رو با یک فاصله جایگزین کنه.
تمرین 1-10: برنامهای بنویسید که ورودی رو کپی کنه، ولی هر تب رو با \t، هر بکاسپیس رو با \b و هر بکاسلش رو با \\ جایگزین کنه. (این باعث میشه این کاراکترها بهصورت واضح دیده بشن.)
شمارش کلمات (Word Counting)
این برنامه تعداد خطوط، کلمات و کاراکترها رو با هم میشماره. (یه نسخهی ساده از دستور معروف wc در یونیکس.)
#include <stdio.h>
#define IN 1 /* داخل یک کلمه */
#define OUT 0 /* خارج از کلمه */
/* شمارش خطوط، کلمات و کاراکترها در ورودی */
int main() {
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc; // هر بار یه کاراکتر جدید
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
return 0;
}
توضیحات:
-
متغیر state مشخص میکنه الان داخل یک کلمه هستیم یا بیرون اون.
-
هر وقت اولین کاراکتر یه کلمه دیده میشه، شمارندهی کلمات (nw) یکی زیاد میشه.
-
خط nl = nw = nc = 0; همهی متغیرها رو صفر میکنه (از راست به چپ انجام میشه).
-
عملگر || یعنی OR. پس شرط if (c == ' ' || c == '\n' || c == '\t') بررسی میکنه آیا کاراکتر فاصله، خط جدید یا تب هست.
-
به محض اینکه یکی از شرطها درست باشه، بقیه بررسی نمیشن (بهینهسازی داخلی C).
ساختار if-else
فرم کلی:
if (expression)
statement1;
else
statement2;
-
اگر شرط درست باشه، statement1 اجرا میشه.
-
اگر درست نباشه، statement2 اجرا میشه.
-
هر کدوم میتونن یه دستور یا چندین دستور داخل {} باشن.
تمرینها
تمرین 1-11: چطور برنامهی شمارش کلمات رو تست میکنید؟ چه ورودیهایی میتونه اشکالات احتمالی رو آشکار کنه؟
تمرین 1-12: برنامهای بنویسید که ورودی رو بهصورت "هر کلمه در یک خط" چاپ کنه.