Module ১ · C-র সঙ্গে পরিচয়: প্রথম program, চিহ্ন ধরে ধরে
তোমার প্রথম C program, লাইন ধরে ধরে
এই lesson-এ যা শিখবে
- Playground-এ নিজের প্রথম C program চালাতে পারবে আর তার output পড়তে পারবে।
- Skeleton-র প্রতিটা অংশের নাম বলতে পারবে: directive, function header, body, statement, return।
- দুইটা
printfএকটা newline ভাগ করে নিলে কী ছাপবে, সেটা আগেই বলতে পারবে।
Alice পাঁচ লাইন লিখল, Run চাপল, আর পর্দায় এল Hello, C. চার সেকেন্ড সে খুশি থাকল। তারপর return 0; লাইনটা মুছে আবার Run চাপল, আর তাতেও এল Hello, C.
তাহলে ওই লাইনটা কী কাজে ছিল? যে program চলে, আর যে program তুমি বোঝো, দুইটা এক জিনিস না। এই lesson সেই পাঁচ লাইনকে এক শব্দ ধরে ধরে খুলবে, আর Alice-র মুছে ফেলা লাইনটা কারণসহ ফিরিয়ে দেবে।
C-তে keyword আছে 32টা। তোমার প্রথম program তার দুইটা ব্যবহার করে, বাকি 30টা অপেক্ষা করতে পারে।
পাঁচটা লাইন, একবার দেখে নাও
পুরো program-টা নিচে। এখনই বোঝার চেষ্টা করো না। আগে শুধু এর চেহারাটা চোখে বসতে দাও।
#include <stdio.h>
int main(void)
{
printf("Hello, C.\n");
return 0;
}
Hello, C.
এখানে অর্থ বহন করছে চারটা জিনিস: # দিয়ে শুরু একটা লাইন, একটা function header, একজোড়া brace, আর তার ভেতরে দুইটা statement। এরপর সারা জীবন যত C program লিখবে, সবই এই চেহারাটার একটু লম্বা রূপ।
লাইন 1: include directive
শুরুর # চিহ্নটা একটা সংকেত। এটা বলে: এই লাইন compiler-র জন্য না। এটা preprocessor-র জন্য, যে tool সবার আগে চলে আর তোমার file গুছিয়ে দেয় (Module 0, lesson 4)।
include তার নির্দেশ, আর নির্দেশটা সোজাসাপটা: ওই file-র পুরোটা এখানে, এই মুহূর্তে, compile শুরুর আগেই বসিয়ে দাও।
stdio.h হলো standard input output header-র সংক্ষেপ। এটা সাদামাটা একটা text file, তোমার compiler-র সঙ্গেই এসেছে। এর ভেতরে printf, scanf আর আরও প্রায় চল্লিশটা function-র declaration আছে।
Declaration মানে প্রতিশ্রুতি, code না। Menu-র কথা ভাবো: কোন খাবার আছে আর কোনটার কী লাগে, সেটাই ওতে লেখা। রান্নাঘর, মানে printf-র আসল machine code, থাকে C standard library-তে, আর জোড়া লাগে linker-এ।
কোণাকৃতি bracket < > preprocessor-কে system-র নিজের folder-এ পাঠায়। Double quote, যেমন #include "myfile.h", তাকে আগে তোমার project folder-এ পাঠায়।
তাই directive কোনো statement না, আর ওতে semicolon বসে না। ওখানে একটা বসালে তুমি program-র ভেতরে একটা এলোমেলো ; বসিয়ে দিলে।
লাইন 3: function-র header
এখান থেকেই তোমার program চলতে শুরু করে। Operating system program চালু করার সময় main-কে call করে। File-র প্রথম লাইনকে না। তুমি প্রথমে যে function লিখেছ তাকেও না। সব সময় main।
বাম থেকে ডানে তিনটা টুকরো:
intহলো return type। এটা কথা দেয়,mainশেষ হলে সে operating system-কে একটা পূর্ণসংখ্যা ফেরত দেবে।mainহলো নাম, আর নামটা C standard বেঁধে দিয়েছে।Main,MAINআরmain2তিনটা আলাদা নাম, আর এর একটাও system যাকে call করে সেটা না।(void)হলো parameter-র তালিকা। Parameter মানে function যে মানগুলো নেয়, আর এখানেvoidবলছে "এটা কিছুই নেয় না"।
int main(int argc, char *argv[])-ও দেখবে, যেভাবে একটা program তার নামের পরে লেখা শব্দগুলো পড়ে। সেটা Module 15। তার আগে (void) লিখলেই তুমি যা বলতে চাও তা বলা হয়।
তাই int main(void) হলো একটা প্রতিশ্রুতি আর একটা নাম, আর মেশিন নিজের ভাগটা রাখে ওটাকে সবার আগে call করে।
লাইন 4 আর 7: দুইটা brace
Curly brace function-র body চিহ্নিত করে: কোথায় শুরু আর কোথায় শেষ। এই দুইটার মাঝের সবকিছুই main-র কাজ।
Brace সব সময় জোড়ায় আসে। সঙ্গীহীন একটা brace C-তে beginner-দের সবচেয়ে সাধারণ ভুল। এর message-টা অদ্ভুত লাগে, কারণ compiler ব্যাপারটা টের পায় file-র একদম শেষে।
তাই কোনো error যদি তোমার না ছোঁয়া শেষ লাইনটার নাম বলে, brace গুনে দেখো।
লাইন 5: statement, টুকরো ধরে ধরে
এই লাইনটা একটা function call। তুমি printf-কে তার কাজটা করতে বলছ, আর হাতে একটা জিনিস ধরিয়ে দিচ্ছ।
- Function-র হাতে যে মান তুমি ধরিয়ে দাও, তার নাম argument। এখানে argument হলো
"Hello, C.\n"লেখাটা। - Double quote বানায় একটা string literal, মানে নির্দিষ্ট একটুকরো লেখা।
\nএকটা escape sequence। এর মানে newline: পরের লাইনের শুরুতে যাও।- Semicolon statement-টা শেষ করে। C-তে statement শেষ হয় তুমি যেখানে শেষ বলো, লাইন যেখানে শেষ সেখানে না।
\n-টা আরেকবার দেখো, কারণ এটা সবাইকে অবাক করে। তুমি লিখেছ দুইটা character, একটা backslash আর একটা n। Output-এ থাকে একটা character, লাইন শেষ করা ওই অদৃশ্যটা। Backslash ছাপা হয় না; ওটা compiler-কে তার পরের character নিয়ে দেওয়া নির্দেশ।
তাই printf("A\nB\n") একটা call থেকেই দুই লাইন ছাপে, আর ওই string-র দৈর্ঘ্য 4টা character, 6টা না।
লাইন 6: return 0, আর Alice যেটা মুছেছিল
main একটা int ফেরত দেওয়ার কথা দিয়েছিল, তাই সে দেয়। প্রচলিত নিয়মে 0 মানে "শেষ, কোনো সমস্যা হয়নি", আর অন্য যেকোনো সংখ্যা মানে কিছু একটা গড়বড় হয়েছে।
ওই সংখ্যাটা program-র exit status, আর এটা সাজসজ্জা না। Operating system ওটা মনে রাখে। Linux বা macOS-এ একটা program চালিয়ে তারপর echo $? লিখলে ফেরত দেওয়া সংখ্যাটা দেখতে পাবে।
$ ./hello
Hello, C.
$ echo $?
0
এভাবেই একটা script ঠিক করে পরের ধাপ কী। CI pipeline-র প্রতিটা "build failed, stopping here" আসলে শূন্য ছাড়া অন্য কিছু ফেরত দেওয়া একটা program।
এবার Alice-র পরীক্ষাটা। C99 standard থেকে, main-র শেষ brace পর্যন্ত পৌঁছালে ফলটা return 0;-র সমান। ওর program ঠিক ছিল, কারণ standard লাইনটা ওর হয়ে বসিয়ে দিয়েছে।
তবুও লাইনটা লেখো। এক লাইনই তো, আর এটা তুমি যা বলতে চাও সেটাই বলে, আর এই ছাড়টা C-তে কেবল main পায়। মান ফেরত দেয় এমন অন্য কোনো function-এ এটা বাদ দিলে সেটা সত্যিকারের একটা bug।
তাই main-এ return 0; বাদ পড়লে কিছুই বদলায় না, আর আর কোথাও return বাদ পড়লে সবই বদলে যায়।
Skeleton, প্রতিটা অংশের নাম দিয়ে
#include <header> directive: for the preprocessor, no semicolon
int main(void) return type, name, parameter list
{ body starts
statement; one instruction, ended by a semicolon
return 0; the exit status handed to the system
} body ends
#includecompile শুরুর আগে declaration-ভরা একটা file বসিয়ে দেয়।intহলোmainযা ফেরত দেয়;(void)হলো সে যা নেয়, মানে কিছুই না।- Brace দুইটা body ধরে রাখে; compiler ওদের জোড়ায় জোড়ায় গোনে।
- ভেতরের প্রতিটা statement
;দিয়ে শেষ হয়, যত লাইন জুড়েই লেখা হোক।
হাতে লিখো। paste করো না। লিখতে গিয়ে যে ভুলগুলো করবে, ওগুলোই শেখার জায়গা।
#include <stdio.h>
int main(void)
{
printf("Hello, C.\n");
return 0;
}
Hello, C.
লেখাটা বদলে আবার Run চাপো, আর দেখো output তোমার পিছু নিচ্ছে। এই চক্রটাই, লেখা আর চালানো, পুরো কাজ।
Compiler-এ চালাওStatement উপর থেকে নিচে, ক্রম ধরে চলে। মাঝখানে চালাকির কিছু ঘটে না।
#include <stdio.h>
int main(void)
{
printf("Welcome to Progsity\n");
printf("Track: C, from zero\n");
printf("Part Zero: before you write a single line\n");
return 0;
}
Welcome to Progsity
Track: C, from zero
Part Zero: before you write a single line
এবার একটা \n মুছে আবার চালাও। দুই লাইন জুড়ে এক লাইন হয়ে যায়, আর তাতেই প্রমাণ হয় ভাঙাটা আসে escape sequence থেকে, আলাদা call থেকে না।
চারটা printf হাতে পেলে বেশিরভাগ মানুষ সঙ্গে সঙ্গে একটা বাক্স আঁকে। দাঁড়ি দুইটার ভেতরের character গুনে দেখো; না মিললে বাক্সটা কাত হয়ে যায়।
#include <stdio.h>
int main(void)
{
printf("+----------------+\n");
printf("| PROGSITY C |\n");
printf("| Part Zero |\n");
printf("+----------------+\n");
return 0;
}
+----------------+
| PROGSITY C |
| Part Zero |
+----------------+
এখানে প্রতিটা লাইন 18 character চওড়া। Judge তোমার output-কে প্রত্যাশিত output-র সঙ্গে মেলানোর সময় space-ও গোনে, তাই একটা বাড়তি space মানেই ভুল উত্তর। নিচের problem-গুলোতে ঠিক সেটার সামনেই পড়বে।
Compiler-এ চালাওএটা কোথায় কাজে লাগছে
- Git. Git-র source-র
git.cfile-এ আছেint main(int argc, const char **argv), parameter-র তালিকা সহ সেই একই header, আরgit push-র পর তোমার shell যে status পড়ে সেটা ওটাই ফেরত দেয়। - SQLite.
sqlite3command line tool-টা একটাই C file,shell.c, যারmainতোমার query পড়ে আর.quitলিখলে 0 ফেরত দেয়। - GNU coreutils.
ls.cশেষ হয় একটাreturnদিয়ে, যেটা exit status বহন করে, আর সেজন্যইls missing-file; echo $?শূন্য ছাড়া অন্য একটা সংখ্যা ছাপে। - Nginx.
nginx.c-তে একটাইmain, কয়েকশো লাইন লম্বা, যেটা configuration পড়ে আর worker process চালু করে। একই skeleton, শুধু আসবাব বেশি।
যে ভুলগুলো সবাই করে
১. Include লাইনটা ভুলে যাওয়া, আর তাতেও পার পেয়ে যাওয়া।
int main(void)
{
printf("Hello, C.\n");
return 0;
}
Playground-র GCC 12-তে এটা warning: implicit declaration of function 'printf', আর program build হয়ে ঠিকঠাক ছাপে। Compiler printf-র নামও শোনেনি, তার চেহারাটা অনুমান করেছে, আর এইবার অনুমান মিলে গেছে। GCC 14 একই লাইনকে error বানায়। Header-টা দাও; যে warning তুমি বোঝো, সেটাও সারানোর মতো warning।
২. Printf-র P বড় হাতের হয়ে যাওয়া।
#include <stdio.h>
int main(void)
{
Printf("Hello, C.\n");
return 0;
}
GCC 12 বলে warning: implicit declaration of function 'Printf', আর তারপর linker বলে undefined reference to 'Printf'। C ছোট আর বড় হাতের অক্ষর আলাদা গোনে, তাই Printf আলাদা একটা নাম, আর ওটা কোথাও লেখাই নেই। দুইটা message একসঙ্গে পড়লেই সূত্রটা পাবে: compiler তোমাকে বিশ্বাস করেছে, আর linker খুঁজতে গিয়েছে।
৩. Directive-র শেষে semicolon দেওয়া।
#include <stdio.h>;
int main(void)
{
printf("Hello, C.\n");
return 0;
}
GCC 12 বলে warning: extra tokens at end of #include directive, তারপর program build করে চালিয়েও দেয়। Preprocessor header-র নামটা পড়েছে, তারপর এমন একটা semicolon পেয়েছে যার তার কোনো দরকার নেই, আর নালিশ করে ওটা ফেলে দিয়েছে। Directive statement না, ওতে semicolon বসে না, আজ ভুলটা তোমার কিছু না কাড়লেও।
৪. Semicolon বাদ পড়ার error-এ লাইন নম্বরটাকে বিশ্বাস করা।
printf("Hello, C.\n")
return 0;
GCC বলে error: expected ';' before 'return', আর return লাইনটার নাম বলে। ওই লাইনে কোনো সমস্যাই নেই। Compiler পড়তে পড়তে এমন একটা শব্দে এসে থেমেছে, যেটা statement-টা আর চালিয়ে নিতে পারে না, আর নালিশ করেছে ওখানেই। যে লাইনের নাম বলছে, সব সময় তার উপরের লাইনটা দেখো।
Alice স্কুলের মেলায় বই বেচে, আর তার stall-র জন্য একটা সাইন লাগবে। সাইনটা দুই লাইনের: একটা বাঁধা banner, তারপর Stall শব্দটা আর তার stall নম্বর।
Input. এক লাইনে একটা integer n, stall নম্বর।
Output. ঠিক দুই লাইন:
=== PROGSITY ===
Stall n
Constraints. 1 <= n <= 999।
Sample. Input 7 দিলে আসবে === PROGSITY ===, তারপর Stall 7। Banner-র দুই পাশে ঠিক তিনটা সমান চিহ্ন, আর প্রতি জোড়ার ভেতরে একটা space।
#include <stdio.h>
int main(void)
{
int n;
scanf("%d", &n);
/* Your two printf calls go here. */
return 0;
}
Input পড়ার লাইনটা তোমার জন্য লেখা আছে; scanf ঠিকভাবে শেখানো হয় Module 3-এ। এটার hidden test সহ grading হয় এই module-র Problems lesson-এ, banner-two-lines নামে।
Maria চায় তার তিন বিষয়ের নম্বর ছোট একটা card-র মতো ছাপা হোক, প্রতি লাইনে এক বিষয়, তিনটা আলাদা printf call দিয়ে।
Input. এক লাইনে তিনটা integer a b c, মানে Maths, Physics আর Chemistry-র নম্বর।
Output. এই ক্রমে তিন লাইন:
Maths: a
Physics: b
Chemistry: c
Constraints. 0 <= a, b, c <= 100।
Sample. Input 90 85 77 দিলে আসবে Maths: 90, Physics: 85, Chemistry: 77, প্রতিটা নিজের লাইনে। প্রতিটা colon-র পরে একটা space।
#include <stdio.h>
int main(void)
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
/* Three printf calls, one per subject. */
return 0;
}
Grading হয় three-printf-lines নামে। একটা না, তিনটা call ব্যবহার করো; আসল কথাটা হলো statement ক্রম ধরে চলে।
Bob-র report লাইনটায় একটা tab আর একজোড়া উদ্ধৃতি চিহ্ন থাকতে হবে। String-র ভেতরে quote ছাপতে escape লাগে, কারণ খালি একটা quote string-টা আগেই শেষ করে দিত।
Input. এক লাইনে একটা integer s, Bob-র score।
Output. ঠিক দুই লাইন। Tab মানে একটা tab character, space না:
Bob wrote: "Hello, C."
Score: s
Constraints. 0 <= s <= 100।
Sample. Input 95 দিলে আসে Bob wrote:, একটা tab, তারপর "Hello, C."; দ্বিতীয় লাইনটা Score:, একটা tab, তারপর 95।
#include <stdio.h>
int main(void)
{
int s;
scanf("%d", &s);
/* Two printf calls. You need \t and \" here. */
return 0;
}
Grading হয় tab-and-quote নামে। Escape-র table আছে এই module-র lesson 3-এ, চেষ্টা করার আগে দেখে নিতে চাইলে।
যে প্রশ্নগুলো সবার মনে আসে
int main(void)-র বদলেint main()লেখা যায়?Compile হয়, আর C17-এ দুইটার মানে একটু আলাদা:
()parameter নিয়ে কিছুই বলে না,(void)বলে একটাও নেই।(void)লিখলে code review-তে এটা নিয়ে কেউ প্রশ্ন করবে না।\nএকটা character কেন, দুইটা না কেন?কারণ backslash ছাপা হয় না। ওটা compiler-কে বলে, লাইন শেষ করা ওই একটামাত্র অদৃশ্য character রাখো। তোমার file-এ দুইটা character, program-র output-এ একটা।
Indentation-এ কিছু আসে যায়?
Compiler-র কিছু আসে যায় না, সে token-র মাঝের space, tab আর ফাঁকা লাইন ধরেই না। পরের পাঠকের অনেক কিছু আসে যায়, আর এই module-র lesson 5 ঠিক সেটা নিয়েই।
0-র বদলে 1 ফেরত দিলে কী হয়?
Program একই জিনিস ছাপে, আর operating system-কে বলে সে ব্যর্থ হয়েছে। Status দেখে এমন একটা shell script ওখানেই থেমে যেত। "কিছু গড়বড় হয়েছে" বোঝাতে না চাইলে 0 ব্যবহার করো।
এগুলো চালাতে কিছু বসাতে হবে?
না। প্রতিটা example-র Run link Playground খুলে দেয়, program আগেই ভেতরে বসানো থাকে। নিজের মেশিনে compiler বসানো এই module-র lesson 6, আর ওটা ইচ্ছাধীন।
মূল কথা
- একটা C program মানে একটা directive, একটা function header, একজোড়া brace, আর ভেতরে statement।
#include <stdio.h>printf-র প্রতিশ্রুতিগুলো বসায়; আসল code জোড়া লাগে linker-এ।mainহলো বাঁধা নামটা, যাকে operating system call করে, আরintহলো সে যে status ফেরত দেয়।- Statement শেষ হয় তার semicolon-এ, লাইনের শেষে না।
\nএকটা character, লেখা হয় দুইটা দিয়ে, আর নতুন লাইনটা ওটাই বানায়।- C99 থেকে
main-র শেষে পৌঁছালে নিজেই 0 ফেরত যায়, তবুও লাইনটা তুমি লেখো।
পরের lesson-এ ভুল হওয়ার দুই রকমের সঙ্গে পরিচয় হবে। একটা compiler নিতেই রাজি হয় না, আরেকটা সে হাসিমুখে build করে ভুল উত্তর দেয়।
lesson ১ শেষ
শেষ হলে চিহ্ন দিন, অগ্রগতি আপনার সাথে থাকবে।
পরেরটা: Syntax আর semantics: ভুল হওয়ার দুই রকম