Module ১ · C থেকে যতটুকু C++ দরকার
std::, namespace আর যে header-গুলো সত্যিই include করবে
এই lesson-এ যা শিখবে
- Namespace কী, সেটা বলতে পারবে, নিজের দুইটা namespace লিখতে পারবে, আর
::দিয়ে তার ভিতরের কোনো নামে পৌঁছাতে পারবে। std::, একটা using-declaration আরusing namespace std;-এর মধ্যে বেছে নিতে পারবে, আর শেষেরটা কেন কখনো header-এ যায় না, সেটা বলতে পারবে।- এই track যত standard নাম ব্যবহার করে, প্রতিটার header বলতে পারবে, আর
<bits/stdc++.h>কেন শুধু GCC-তে চলে, সেটা বুঝিয়ে বলতে পারবে।
Bob-এর contest program শুরু হয় #include <bits/stdc++.h> দিয়ে, আর Playground-এ সেটা দিব্যি compile হয়, pass-ও করে। Maria program-টা নিজের Mac-এ নিয়ে যায়, যেখানে compiler হলো clang, তার নিজের library সহ, আর প্রথম লাইনেই আটকে যায়: fatal error: 'bits/stdc++.h' file not found। Program-এ কোনো ভুল নেই, তবু এক compiler নেয়, আরেকটা নেয় না। কেন, সেটা বুঝতে দুইটা জিনিস জানা লাগবে: একটা standard নাম থাকে কোথায়, আর কোন file সেটা তোমার program-এ নিয়ে আসে। এই lesson দুইটাই দেবে, সাথে হাতের কাছে রাখার মতো একটা table।
Namespace: নামের একটা বাক্স, যার নিজেরও নাম আছে
C-তে প্রতিটা function-এর নাম global, তাই দুইটা library-র দুজনেরই sort থাকতে পারে না। C library-গুলো এটা এড়ায় প্রতিটা নামের আগে একটা prefix বসিয়ে, যেমন sqlite3_open। C++-এর হাতে এর চেয়ে ভালো উপায় আছে। Namespace হলো নামের একটা বাক্স, যার নিজেরও একটা নাম আছে: দুইটা বাক্সে আলাদা আলাদা sort থাকতে পারে, আর তাদের মধ্যে কখনো ধাক্কা লাগে না।
Namespace বানানো, আর তার ভিতরে পৌঁছানো
namespace box_name {
declarations: functions, variables, constants
}
box_name::name
namespaceএকটা বাক্স খোলে;box_nameহলো বাক্সটার নিজের নাম।- দুই brace-এর মাঝে যা কিছু declare করা হয়, সবই থাকে বাক্সের ভিতরে।
::, যার নাম scope operator, বাক্সের ভিতরে তাকায়:box_name::nameমানে "ওই বাক্সেরname"।
নিচের program-এ sort নামের দুইটা function, একটা দোকানের বাক্সে, আরেকটা স্কুলের বাক্সে।
#include <iostream>
namespace shop {
void sort()
{
std::cout << "shop::sort puts prices cheapest first\n";
}
}
namespace school {
void sort()
{
std::cout << "school::sort puts marks highest first\n";
}
}
int main()
{
shop::sort();
school::sort();
return 0;
}
shop::sort puts prices cheapest first
school::sort puts marks highest first
Compiler কখনো জিজ্ঞেস করে না কোন sort-এর কথা বলছ, কারণ প্রতিটা call তার বাক্সের নাম বলে দেয়। main নিজে তোমার বানানো কোনো বাক্সে নেই। ও থাকে global namespace-এ, প্রতিটা program-এর সবচেয়ে বাইরের বাক্স, যেখানে C-র সব নামও থাকে।
মানে namespace থাকলে দুই টুকরা code একই নাম ব্যবহার করতে পারে, আর box::name বলে দেয় তুমি কোনটা চাইছ।
std:: আর সেটা না লেখার তিনটা উপায়
C++-এর standard library তার প্রতিটা নাম রাখে একটাই namespace-এ, std। এজন্যই lesson 01 লিখেছিল std::cout: std বাক্সের cout। একটা program-এ পঞ্চাশবার std:: লেখা ক্লান্তিকর, তাই C++ এটা বাদ দেওয়ার তিনটা উপায় দেয়।
Using-declaration একটা নাম ভিতরে আনে: using std::cout;। Using-directive পুরো বাক্সটাই ভিতরে আনে: using namespace std;। দুইটাই কাজ করে যে লাইনে লেখা হয়েছে সেখান থেকে, যে block-এর ভিতরে আছে তার শেষ পর্যন্ত। File-এর একদম ওপরে লিখলে সেটা বাকি পুরো file; function-এর ভিতরে লিখলে শুধু ওই function।
#include <iostream>
#include <string>
using std::cout;
int main()
{
using std::cin;
std::string title;
int pages = 0;
cin >> title >> pages;
cout << title << " has " << pages << " pages\n";
return 0;
}
Matilda has 240 pages
এই output input Matilda 240-এর জন্য। Using-declaration-এর নিচে কোথাও cout-এর আগে std:: লাগে না, আর main-এর ভিতরে cin-এরও লাগে না। std::string-কে কখনো ভিতরে আনা হয়নি, তাই ওর std:: থেকে যায়।
| তুমি লেখো | কোথায় | এরপর যা std:: ছাড়া লেখা যায় |
|---|---|---|
std::cout | প্রতিটা ব্যবহারে | কিছুই না; প্রতিবার বাক্সের নাম বলো |
using std::cout; | file-এর ওপরে | cout, বাকি পুরো file-এ |
using std::cin; | একটা function-এর ভিতরে | cin, শুধু ওই function-এর ভিতরে |
using namespace std; | file-এর ওপরে | std-এর সব নাম, বাকি পুরো file-এ |
মানে এগুলোর যেকোনোটার পরে cout আসলে std::cout-ই। বদলায় শুধু এটুকু: বাক্স থেকে কয়টা নাম বের করে দিচ্ছ, আর কত দূর পর্যন্ত।
using namespace std-এর দাম, আর একটাই নিয়ম
Lesson 01 বলেছিল, using namespace std; তোমার program-এ শত শত নাম ঢেলে দেয়, আর তোমার কোনো একটা নামের সাথে ওদের কোনোটার ধাক্কা লাগতে পারে। এই হলো সেই ধাক্কা। Kenji-র আর কয়টা lap বাকি, সেটা ও রাখে left নামের একটা global variable-এ।
#include <iostream>
using namespace std;
int left = 3;
int main()
{
cout << left << " laps left\n";
return 0;
}
GCC 12 Playground-এর command line-এ আর -Wall -Wextra-এ একইভাবে এটা ফিরিয়ে দেয়: error: reference to 'left' is ambiguous। Note-গুলো দুই candidate-এর নাম বলে: Kenji-র 'int left' আর 'std::ios_base& std::left(ios_base&)'। std::left হলো <iostream>-এর একটা আসল নাম, এমন একটা setting যেটা output বাঁ দিক ঘেঁষে সাজায়। Kenji এটা কখনো চায়নি; using-directive এটাকে বাক্স থেকে বের করে দিয়েছে, আর এখন global left দুইটা।
Variable-টা main-এর ভিতরে সরিয়ে নাও, একই program compile হয়ে print করবে 3 laps left। Function-এর ভিতরে declare করা নাম বাইরের নামগুলোকে ঢেকে দেয়, বাক্স থেকে আসা নামও। তাই ধাক্কাটা লাগে file-এর একদম ওপরের নামগুলোতে, আর contest program ঠিক ওখানেই তার বড় array আর counter রাখে।
এই গেল এক file-এর দাম। Header-এ, মানে যে file অন্য file include করে, দামটা ছড়িয়ে পড়ে। #include header-এর লেখাটা হুবহু বসিয়ে দেয় যে file include করছে তার ভিতরে, C-র মতোই। তাই header-এর ভিতরের using-directive গিয়ে পড়ে ওই প্রতিটা file-এ। ওই file-গুলোর লেখক এই লাইন কখনো লেখেনি, তবু তাদের নামে ধাক্কা লাগা শুরু হয়।
তাই এই track-এর একটা নিয়ম আছে, আর একটা অভ্যাস। নিয়ম: using namespace std; কখনো header-এ যায় না। অভ্যাস: ছোট, এক file-এর contest program-এ এটা চলতে পারে, কিন্তু এই module, আর track-এর প্রতিটা project lesson, প্রতিটা standard নামের আগে std:: লেখে।
Header table: কোন file কোন নাম আনে
Namespace বলে একটা নাম কী নামে ডাকা হয়। Header বলে নামটা কোথায় declare করা, আর নামটা তোমার program-এ আসার আগে সেটা #include করতেই হবে। এই track-এর প্রতিটা নাম আসে নিচের কোনো একটা header থেকে। প্রথম কয়েকটা STL program লেখার সময় table-টা পাশে খুলে রাখার মতো।
| Header | যা দেয় | কোথায় শেখানো হয় |
|---|---|---|
<iostream> | std::cin, std::cout, std::cerr | lesson 01 আর 02 |
<string> | std::string, std::getline, std::to_string | Module 3 |
<sstream> | std::istringstream, string-এর ভিতর থেকে সংখ্যা পড়া | lesson 02-এ ইশারা, Module 3 |
<utility> | std::pair, std::swap, std::move | lesson 05 আর 06 |
<tuple> | std::tuple, std::get, std::tie | lesson 06 |
<vector> | std::vector | Module 2 |
<array> | std::array | Module 4 |
<deque> | std::deque | Module 4 |
<list> | std::list | Module 5 |
<forward_list> | std::forward_list | Module 5 |
<stack> | std::stack | Module 6 |
<queue> | std::queue, আর std::priority_queue-ও | Module 6, Module 7 |
<set> | std::set, std::multiset | Module 8 |
<map> | std::map, std::multimap | Module 9 |
<unordered_set> | std::unordered_set | Module 10 |
<unordered_map> | std::unordered_map | Module 10 |
<iterator> | std::next, std::prev, std::distance | Module 11 |
<functional> | std::greater, বড়টা আগে রাখার ক্রম | Module 7, Module 12 |
<algorithm> | std::sort, std::max, std::min, std::reverse, std::count, std::lower_bound | lesson 05, Module 12, Module 13 |
<numeric> | std::accumulate, std::iota, std::gcd | Module 14 |
<bitset> | std::bitset | Module 15 |
<chrono> | program-এর সময় মাপার ঘড়ি | lesson 02 থেকে 04-এ মাপার কাজে লেগেছে |
দুইটা row অনেককে অবাক করে। std::priority_queue-এর নিজের কোনো header নেই; ও থাকে <queue>-এ। আর std::swap আছে <utility>-এ, অথচ ওর পড়শি std::max আর std::min আছে <algorithm>-এ। তাই GCC যখন বলে কোনো নাম is not a member of 'std', আগে এখানে তার header খুঁজে দেখো।
যা ব্যবহার করো, ঠিক সেটাই include করো
Lesson 05 লেখার সময় একটা মজার জিনিস ধরা পড়েছিল। এই program-এ <algorithm> নেই, তবু GCC 12 এটা compile করে ফেলে।
#include <iostream>
int main()
{
std::cout << std::max(3, 7) << '\n';
return 0;
}
7
এটা চলছে কপাল জোরে। GCC-র library, libstdc++, <iostream> বানিয়েছে আরও কয়েকটা header জুড়ে জুড়ে। সেই শিকলের কয়েক file নিচে এটা <string> include করে, আর <string> include করে bits/stl_algobase.h, যে file-এ std::max define করা। Compiler Explorer-এর include list (GCC-র -H option) প্রতিটা ধাপ দেখায়।
অন্য compiler আসে অন্য library নিয়ে, আর সেগুলো অন্যভাবে বানানো। Compiler Explorer-এ আমরা তিনটা ছোট program compile করেছি, প্রতিটায় শুধু <iostream>, তিনটা toolchain-এ।
শুধু <iostream> রেখে call করা হলো | GCC 12, libstdc++ | clang 15, libc++ | MSVC, Microsoft-এর library |
|---|---|---|---|
std::max | compile হয় | compile হয় | compile হয় |
std::getline | compile হয় | compile হয় | error C2039: 'getline': is not a member of 'std' |
std::sort | error: 'sort' is not a member of 'std'; did you mean 'qsort'? | compile হয় | error C2039: 'sort': is not a member of 'std' |
GCC column-টা Playground-এর command line, -O2 -std=c++17। Clang column হলো clang 15, -stdlib=libc++ দিয়ে, মানে clang-এর নিজের library, আর MSVC column হলো "x64 msvc v19.latest", /std:c++17 দিয়ে। প্রতিটা library সাথে আলাদা আলাদা বাড়তি জিনিস টেনে আনে, আর কেউই কথা দেয় না যে সামনেও আনবে। তাই যে program কোনো বাড়তির ওপর ভর দেয়, সেটা এক machine-এ ঠিক, পরেরটায় ভাঙা।
সমাধানের খরচ প্রতি header-এ এক লাইন। যে header-এর নাম ব্যবহার করছ, প্রতিটা include করো, program সেটা ছাড়া compile হলেও। তাহলে যেকোনো standard library-তে compile হবে, আজও, পরের library update-এর পরেও। তাই নিরাপদ উত্তর কখনো "আমার এখানে তো compile হলো" না, বরং "যে নামই ব্যবহার করি, তার header ওপরে আছে"।
bits/stdc++.h: সব header একসাথে, শুধু GCC-তে
<bits/stdc++.h> হলো GCC-র library-র ভিতরের একটা file, যেটা একবারে সব standard header include করে। File-টার নিজের comment একে বলে "an implementation file for a precompiled header", মানে GCC-র build দ্রুত করার একটা সহায়ক। এটা C++ standard-এর অংশ না। Contest programmer-রা এটা খুব পছন্দ করে, কারণ এক লাইনে এক ডজন লাইনের কাজ হয়, আর Playground সহ অনেক contest judge compile করে GCC দিয়ে।
#include <bits/stdc++.h>
int main()
{
std::cout << "hello\n";
return 0;
}
hello
এটা GCC 12-এর output। অন্য toolchain-এ file-টাই নেই। Compiler Explorer-এ clang 15, libc++ দিয়ে, মানে যে library একটা Mac নিজে থেকেই ব্যবহার করে, লাইন 1-এই থেমে যায়: fatal error: 'bits/stdc++.h' file not found। MSVC-ও ওখানেই থামে: fatal error C1083: Cannot open include file: 'bits/stdc++.h': No such file or directory। এটাই এই lesson-এর শুরুর Bob আর Maria-র গল্প।
Compile-এর সময়েও এর খরচ আছে, কারণ compiler প্রতিটা header পড়ে, লাগুক বা না লাগুক। আমরা hello program-টা দুইবার build করেছি, একবার <iostream> দিয়ে, একবার <bits/stdc++.h> দিয়ে, প্রতিটা একবার করে run।
| কোথায়, আর কোন command | <iostream> দিয়ে | <bits/stdc++.h> দিয়ে |
|---|---|---|
এই lesson-এর machine, GCC 14.2 (MinGW), g++ -std=c++17, ঘড়ি ধরে সময় | 1.39 s | 4.76 s |
Compiler Explorer, GCC 12.2, -O2 -std=c++17, ওর দেখানো build time | 376 ms | 1130 ms |
Compiler Explorer, GCC 12.2, preprocessor-এর পরে কয় লাইন (-E -P) | 22,382 | 92,295 |
দুই machine-এই এই এক লাইন পাঁচ লাইনের একটা program-এর build অন্তত তিন গুণ ধীর করেছে। পরে Compiler Explorer-এ আরও তিনবার চালিয়ে এসেছে 289 থেকে 378 ms, বনাম 1,863 থেকে 2,888 ms। Local run-গুলো হয়েছে প্রতিটার একবার warm-up build-এর পরে, তাই তফাতটা disk-এর কারণে না। Contest-এ এই খরচ সহ্য করা যায়; শত শত file-এর project-এ প্রতিটা file এই দাম দেয়।
তাই track-এর নিয়ম সোজা। Contest program-এ <bits/stdc++.h> চলবে, আর যতবার আসবে, ততবার আমরা বলে দেব এটা শুধু GCC-র। Project lesson-এ এটা কখনো আসবে না, কারণ project-কে build হতে হয় team-এর ব্যবহার করা প্রতিটা compiler-এ।
Namespace-এ variable-ও রাখা যায়। Alice একটা বইয়ের দোকান আর একটা library-র stock-এর হিসাব রাখে, আর দুইটা হিসাবের নামই stock।
#include <iostream>
namespace bookshop {
int stock = 0;
}
namespace library {
int stock = 0;
}
int main()
{
bookshop::stock = 12;
library::stock = 340;
bookshop::stock = bookshop::stock - 2;
std::cout << "bookshop " << bookshop::stock << ", library " << library::stock << '\n';
return 0;
}
bookshop 10, library 340
দুইটা বই বিক্রি হওয়ায় বদলেছে শুধু দোকানের হিসাব। C-তে দুইটার আলাদা নাম লাগত, যেমন bookshop_stock আর library_stock; এখানে সেই কাজটা করে বাক্স।
এবার দোকানের আর স্কুলের sort সত্যিকারের কাজ করে, আর দুইটাই দাঁড়িয়ে আছে তৃতীয় একটার ওপর, std::sort। এটা array-র একটা range ছোট থেকে বড় ক্রমে সাজায়, Module 12-এ শেখানো হবে। std::reverse একটা range উল্টে দেয়।
#include <algorithm>
#include <iostream>
namespace shop {
// Prices go cheapest first.
void sort(int prices[], int n)
{
std::sort(prices, prices + n);
}
}
namespace school {
// Marks go highest first.
void sort(int marks[], int n)
{
std::sort(marks, marks + n);
std::reverse(marks, marks + n);
}
}
void print(const int a[], int n)
{
for (int i = 0; i < n; i++) {
if (i > 0) {
std::cout << ' ';
}
std::cout << a[i];
}
std::cout << '\n';
}
int main()
{
int prices[4] = {300, 120, 450, 200};
int marks[4] = {72, 91, 65, 85};
shop::sort(prices, 4);
school::sort(marks, 4);
print(prices, 4);
print(marks, 4);
return 0;
}
120 200 300 450
91 85 72 65
shop::sort-এর ভিতরে তাকাও। ওখানে সাধারণ sort(prices, prices + n) লিখলে সেটা খুঁজে পায় shop::sort-কেই, সবচেয়ে কাছের বাক্স। তখন GCC 12 বলে error: invalid conversion from 'int*' to 'int' [-fpermissive], সাথে একটা note, যেটা void shop::sort(int*, int)-এর নাম বলে। Call-টাকে standard library-তে পাঠায় std::।
Amara পড়ে তার দোকানের নাম আর n-টা দাম, তারপর print করে কয়টা জিনিস, মোট দাম, আর সবচেয়ে সস্তা ও সবচেয়ে দামি দামটা। একজন beginner আসলে এই program-টাই লেখে, ঠিক যে header-গুলো লাগে সেগুলো নিয়ে।
#include <algorithm>
#include <iostream>
#include <numeric>
#include <string>
const int MAX_N = 100;
int main()
{
std::string shop;
int n = 0;
std::cin >> shop >> n;
if (n == 0) {
std::cout << shop << ": no items\n";
return 0;
}
int prices[MAX_N] = {0};
for (int i = 0; i < n; i++) {
std::cin >> prices[i];
}
std::sort(prices, prices + n);
long long total = std::accumulate(prices, prices + n, 0LL);
std::cout << shop << ": " << n << " items, total " << total << '\n';
std::cout << "cheapest " << prices[0] << ", dearest " << prices[n - 1] << '\n';
return 0;
}
Bookworm: 4 items, total 1070
cheapest 120, dearest 450
এই output input Bookworm 4, তারপর 300 120 450 200-এর জন্য। প্রতিটা header নিজের দাম মেটায়: <algorithm> std::sort-এর জন্য, <iostream> std::cin আর std::cout-এর জন্য, <numeric> std::accumulate-এর জন্য, আর <string> std::string-এর জন্য। std::accumulate একটা range-এর যোগফল বের করে 0LL থেকে শুরু করে, তাই মোটটা হয় long long (Module 14)।
Zara প্রথমেই দিয়ে দেখেছে Bookworm 0। n == 0 check ছাড়া prices[n - 1] পড়ত prices[-1], array-র বাইরে; check থাকায় program print করে Bookworm: no items।
এটা কোথায় কাজে লাগে
- SQLite। এর C interface-এর হাতে কোনো namespace নেই, তাই প্রতিটা public নাম শুরু হয়
sqlite3_দিয়ে, যেমনsqlite3_openআরsqlite3_exec। বাক্সের বদলে prefix, এটাই C-র উপায়। - LLVM। LLVM Coding Standards-এ একটা নিয়মের শিরোনামই "Do Not Use 'using namespace std'"। ওরা স্পষ্ট করে
std::লেখা পছন্দ করে, আর বলে header-এ using-directive থাকলে যে file সেটা include করে, তার প্রতিটা নোংরা হয়। - Chromium। Google-এর এই browser মেনে চলে Google C++ Style Guide, যেটা বলে
using namespace foo-এর মতো using-directive ব্যবহার না করতে। - GCC-র নিজের library।
bits/stdc++.hআসে libstdc++-এর সাথে, আর এর comment নিজেকে বলে precompiled header-এর একটা implementation file। এজন্যই এটা আছে GCC-তে আর GCC ব্যবহার করা judge-গুলোতে, আর কোথাও না।
যে ভুলগুলো সবাই করে
১. Using লাইন ছাড়াই std:: বাদ দেওয়া।
cout << "hello\n";
প্রতিটা command line-এ error: error: 'cout' was not declared in this scope; did you mean 'std::cout'?। GCC বাক্সের নামটাও বলে দেয়। লেখো std::cout। এই ভুলটা তুমি করবে, কারণ online-এ পাওয়া বেশিরভাগ code শুরু হয় using namespace std; দিয়ে, আর তুমি ওই লাইন বাদ দিয়ে শুধু ভিতরের অংশটা copy করো।
২. দুইটা colon-এর জায়গায় একটা।
std:cout << "hello\n";
Playground-এর command line ভুল 1-এর বার্তাটাই দেয়। -Wall -Wextra-এ GCC 12 সূত্রটা যোগ করে: warning: label 'std' defined but not used [-Wunused-label]। এক colon-এর std: হলো C-র label, goto-র একটা গন্তব্য, তাই cout খালি পড়ে থাকে। তাড়াহুড়োয় টাইপ করলে এটা হবে, কারণ দুই colon মানে একই key দুইবার চাপা।
৩. Header ছাড়া নাম ব্যবহার করা।
#include <iostream>
int main()
{
std::vector<int> v(3);
return 0;
}
প্রতিটা command line-এ error: error: 'vector' is not a member of 'std', সাথে কাজের একটা note, 'std::vector' is defined in header '<vector>'; did you forget to '#include <vector>'?। তবে GCC সবসময় header চেনে না: std::sort-এর বেলায় ও প্রস্তাব দেয় 'qsort', আর std::accumulate-এর বেলায় কিছুই না। তাই "is not a member of 'std'" পড়ো "একটা header নেই" হিসেবে, আর নামটা table-এ খুঁজে দেখো।
৪. নিজের function-কে তার বাক্স ছাড়া call করা।
namespace shop {
void sort()
{
}
}
sort();
প্রতিটা command line-এ error: error: 'sort' was not declared in this scope; did you mean 'shop::sort'?। বাক্সের বাইরে থেকে এর নামগুলোর আগে বাক্সের নাম লাগে। লেখো shop::sort();। এটা ভুলে যাবে, কারণ shop-এর ভিতরে সাধারণ নামেই কাজ হচ্ছিল।
Zara ক্লাসের জন্য বানানের একটা list বানায়, আর শব্দগুলো চায় অভিধানের ক্রমে। Program-টা লেখো ঠিক যে header-গুলো লাগে সেগুলো দিয়ে: অদরকারি কোনো header না, কোনোটা বাদও না, আর <bits/stdc++.h> তো একদমই না।
Input. একটা লাইনে n, তারপর n-টা শব্দ।
Output. n-টা শব্দ অভিধানের ক্রমে, প্রতি লাইনে একটা।
Constraints. 1 <= n <= 100। প্রতিটা শব্দ 1 থেকে 20টা ছোট হাতের অক্ষরের।
Sample. Input 4, তারপর pear apple zebra mango দিলে চার লাইনে আসে apple, mango, pear আর zebra।
#include <iostream>
// Add the other headers this program uses here, one per line,
// in alphabetical order. Not <bits/stdc++.h>.
const int MAX_N = 100;
int main()
{
int n = 0;
std::cin >> n;
// Read n words into an array of std::string, sort it with
// std::sort, and print the words one per line.
return 0;
}
আলাদা করে গ্রেড হয় না। Playground-এ একটা header বাদ থাকলেও এটা compile হয়ে যেতে পারে, আর এই lesson-এর কথাটাই সেটা, তাই প্রতিটা std:: নাম table-এর সাথে মিলিয়ে নাও।
Zara-র আবহাওয়া station চায় দুইটা reading-এর মধ্যে জোরালোটা: যেটা শূন্য থেকে বেশি দূরে, তাই -7 হারিয়ে দেয় 5-কে। std::max এটা বোঝায় না, তাই ও নিজের একটা max লেখে, নিজের একটা বাক্সে, weather, আর তুলনার জন্য দুইটা উত্তরই print করে।
Input. দুইটা পূর্ণসংখ্যা a আর b।
Output. দুইটা লাইন: প্রথমে std::max, একটা space আর দুইটার বড়টা; তারপর weather::max, একটা space আর যেটা শূন্য থেকে বেশি দূরে। দুইটাই শূন্য থেকে সমান দূরে হলে weather::max দেয় a।
Constraints. প্রতিটা পূর্ণসংখ্যা -100 থেকে 100-এর মধ্যে।
Sample. Input -7 5 দিলে দুই লাইনে আসে std::max 5 আর weather::max -7।
#include <algorithm>
#include <iostream>
namespace weather {
// Return whichever of a and b is further from zero; on a tie, return a.
int max(int a, int b)
{
return a; // replace this line
}
}
int main()
{
int a = 0;
int b = 0;
std::cin >> a >> b;
// Print "std::max " and std::max(a, b) on one line,
// then "weather::max " and weather::max(a, b) on the next.
return 0;
}
আলাদা করে গ্রেড হয় না। Sample-এর আগে Zara দিয়ে দেখবে 5 -5 আর 0 0।
সচরাচর যে প্রশ্নগুলো আসে
using namespace std;কি আমার program বড় বা ধীর করে?না। এটা শুধু বদলায়, তোমার code পড়ার সময় compiler কোন নামগুলো খুঁজে পায়। যে program তৈরি হয়, সেটা সব জায়গায়
std::লিখলে যা হতো, হুবহু তাই।<bits/stdc++.h>কি program চলার সময় ধীর করে?না, শুধু compile ধীর করে। যে declaration কেউ ব্যবহার করে না, তা থেকে কোনো machine code তৈরি হয় না। এই lesson-এর machine-এ GCC 14.2 (MinGW) দিয়ে build করা দুইটা hello program-এর size এসেছে 65,052 আর 65,241 byte।
std::cout-এ দুইটা colon, অথচstd::cin.tie-তে একটা dot কেন?::তাকায় একটা namespace-এর ভিতরে, মানে নামের বাক্সে।.পৌঁছায় একটা object-এর member-এ, ঠিক C-রstruct-এর মতো।std::cinহলোstdবাক্সের একটা object, আরtieতার একটা member।আমি কি
std-এ নিজের function যোগ করতে পারি?না। C++ standard বলে, namespace
std-এ নিজের declaration যোগ করা undefined behaviour, হাতে গোনা কয়েকটা ক্ষেত্র ছাড়া। নিজের নাম রাখো নিজের বাক্সে, যেমনshopআরweatherরাখে।Bob জিজ্ঞেস করে:
scanfআরprintfকি এখনো ব্যবহার করা যায়?যায়। C++-এ এরা আসে
<cstdio>থেকে, যেটাstdio.h-এর C++ রূপ,std::scanfআরstd::printfনামে। Lesson 02-এর নিয়ম তবু খাটে: এক program-এ input আর output-এর একটাই পরিবার।
মূল কথা
- Namespace হলো নামের একটা বাক্স, যার নিজেরও নাম আছে;
box::nameতার ভিতরে পৌঁছায়, তাইshop::sortআরschool::sort-এ কখনো ধাক্কা লাগে না। - পুরো standard library থাকে
std-এ;using std::cout;একটা নাম বের করে দেয়,using namespace std;দেয় সবগুলো। using namespace std;ছোট contest file-এ চলে, header-এ কখনো না; এই module প্রতিটা standard নামের আগেstd::লেখে।- প্রতিটা standard নাম আসে table-এর কোনো একটা header থেকে; যেটাই ব্যবহার করো, include করো, কারণ কোন header কী টেনে আনে, সেটা library ভেদে আলাদা।
<bits/stdc++.h>GCC-র নিজের file: libc++ সহ clang আর MSVC এটা মানে না, আর এটা একটা hello program-এর build অন্তত তিন গুণ ধীর করেছে।
এটাই এই module-এর শেষ lesson। এরপর আসছে এর problem set, দশটা judged problem, যেগুলোতে লাগবে lesson 01 থেকে 07, আর তারপর Module 2 খুলবে std::vector।
lesson ৭ শেষ
শেষ হলে চিহ্ন দিন, অগ্রগতি আপনার সাথে থাকবে।
পরেরটা: Problem: যতটুকু C++ দরকার