Sunday, November 17, 2013

[ সি প্রোগ্রামিং: অধ্যায় এগারো ] আবারও অ্যারে [Array Again] ।

গণিত শিক্ষকের জন্য লেখা প্রোগ্রামটির কথা মনে আছে তো? সেই যে আমরা তিনটি অ্যারে ব্যবহার করে প্রোগ্রাম লিখেছিলাম ছাত্র-ছাত্রীদের গণিত পরীক্ষার মোট নম্বর বের করার জন্য। মনে না থাকলে প্রোগ্রামটি আবার দেখে নাও।

আমরা প্রথম সাময়িক পরীক্ষার নম্বর রেখেছিলাম একটি অ্যারেতে, দ্বিতীয় সাময়িক পরীক্ষার নম্বর আরেকটি অ্যারেতে, ফাইনাল পরীক্ষার নম্বর আরেকটি অ্যারেতে আর মোট নম্বর আরও একটি অ্যারেতে – মোট চারটি অ্যারে ব্যবহার করেছি। তো এখন যদি পুরো স্কুলের ফলাফল নির্ণয়ের জন্য প্রোগ্রাম লেখতে হয়, তবে সব ক্লাসের সব ছাত্র-ছাত্রীর সব বিষয়ের সব পরীক্ষার জন্য একটি করে অ্যারে ব্যবহার করা খুবই ঝামেলার কাজ হয়ে যাবে। তাই মোটামুটি সব প্রোগ্রামিং ল্যাঙ্গুয়েজেই মাল্টি-ডাইমেনশনাল অ্যারের ব্যবস্থা আছে। এতক্ষণ আমরা যেসব অ্যারে ব্যবহার করেছি, তার সবগুলোই ছিল এক ডাইমেনশনের অ্যারে।

এখন ওই প্রোগ্রামটি আমরা একটু অন্যভাবে লিখব, একটি মাত্র অ্যারে ব্যবহার করে। আপাতত কষ্ট কমানোর জন্য ধরি ক্লাসে মোট দশজন ছাত্র-ছাত্রী আছে। নিচের ছকে তাদের নম্বরগুলো লিখলাম:



Roll: 1
Roll: 2
Roll: 3
Roll: 4
Roll: 5
Roll: 6
Roll: 7
Roll: 8
Roll: 9
Roll: 10
First terminal exam
80
70
92
78
58
83
85
66
99
81
Second terminal exam
75
67
55
100
91
84
79
61
90
97
Final exam
98
67
75
89
81
83
80
90
88
77
Total marks











Total Marks সারির ঘরগুলো ফাঁকা, কারণ এগুলো এখনো হিসাব করিনি। প্রথম সাময়িক পরীক্ষার 25%, দ্বিতীয় সাময়িক পরীক্ষার 25% এবং ফাইনাল পরীক্ষার 50% নম্বর যোগ করে মোট নম্বর বের করতে হবে। এখন দেখো, আমাদের ছকে তাদের নম্বরগুলো রাখতে হয়েছে 4 টা সারি (row) এবং 10 টা কলামে। আমরা আগে যেই প্রোগ্রাম লিখেছিলাম, তাতে প্রথম রো-এর জন্য একটি অ্যারে, দ্বিতীয় রো-এর জন্য একটি, তৃতীয় রো-এর জন্য একটি এবং চতুর্থ রো-এর জন্য একটি অ্যারে ব্যবহার করেছিলাম। এখন ব্যবহার করব একটি 2-D অ্যারে (টু ডাইমেনশনাল অ্যারে)।

2-D অ্যারে ডিক্লেয়ার করার নিয়ম হচ্ছে: data_type array_name [number of rows][number of columns];
যেমন ওপরের ছকটা যদি marks নামের একটি 2-D অ্যারেতে রাখতে চাই, তবে লিখতে হবে: int marks[4][10];

এখন, অ্যারের প্রথম রো হচ্ছে marks[0], দ্বিতীয় রো হচ্ছে marks[1], তৃতীয় রো হচ্ছে marks[2] এবং চতুর্থ রো হচ্ছে marks[3]। আবার marks[0][0] হচ্ছে প্রথম রো-এর প্রথম কলাম, marks[0][1] হচ্ছে প্রথম রো-এর দ্বিতীয় কলাম, marks[0][5] হচ্ছে প্রথম রো-এর ষষ্ঠ কলাম, marks[1][0] হচ্ছে দ্বিতীয় রো-এর প্রথম কলাম, marks[2][3] হচ্ছে তৃতীয় রো-এর চতুর্থ কলাম। আশা করি, বুঝতে পেরেছ।

এখন বলো তো, যার রোল নম্বর 10 তার দ্বিতীয় সাময়িক পরীক্ষার নম্বর কোন ঘরে আছে? আর marks[0][0] ঘরে কার এবং কোন পরীক্ষার নম্বর আছে?

marks[0][0]-এ থাকবে রোল 1-এর প্রথম সাময়িক পরীক্ষার নম্বর আর marks[1][9]-এ থাকবে রোল 10-এর দ্বিতীয় সাময়িক পরীক্ষার নম্বর। অ্যারেতে সংখ্যাগুলো এভাবে রাখতে পারি:

 int marks[4][10] = {{80, 70, 92, 78, 58, 83, 85, 66, 99, 81}, {75, 67, 55, 100, 91, 84, 79, 61, 90, 97}, {98, 67, 75, 89, 81, 83, 80, 90, 88, 77}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};  

এখানে খেয়াল করেছ যে আমরা আসলে একটি অ্যারের ভেতর চারটি এক ডাইমেনশনের অ্যারে রেখেছি। marks[0]তে আছে প্রথম সাময়িক পরীক্ষায় সবার নম্বর, marks[1]-এ দ্বিতীয় সাময়িক পরীক্ষার নম্বর, marks[2]-এ ফাইনাল পরীক্ষার নম্বর এবং marks[3]তে মোট নম্বর (যেহেতু এখনো এটি হিসাব করিনি, তাই সব 0 লিখে দিলাম)।

এখন সম্পূর্ণ প্রোগ্রামটি তোমার কম্পিউটারে টাইপ করে কম্পাইল ও রান করো।

 #include <stdio.h>  
 int main()  
 {  
     int marks[4][10] = {{80, 70, 92, 78, 58, 83, 85, 66, 99, 81}, {75, 67, 55, 100, 91, 84, 79, 61, 90, 97}, {98, 67, 75, 89, 81, 83, 80, 90, 88, 77}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};  
     int col;  
     for(col = 0; col < 10; col++) {  
         marks[3][col] = marks[0][col] / 4.0 + marks[1][col] / 4.0 + marks[2][col] / 2.0;  
         printf("Roll NO: %d  Total Marks: %d\n", col + 1, marks[3][col]);  
     }  
     return 0;  
 }  
 প্রোগ্রাম: ১১.১  

নম্বরগুলো আগে না লিখে যদি আমরা ব্যবহারকারীর কাছ থেকে ইনপুট হিসেবে নিতে চাইতাম তাহলে কী করতে হতো?

 int marks[4][10];  
 int i, j;  
 for (i = 0; i < 4; i++) {  
     for (j = 0; j < 10; j++) {  
         scanf("%d", &ara[i][j]);  
     }  
 }  

এভাবে নেস্টেড লুপের সাহায্যে আমরা ইনপুট নিতে পারি। প্রথম লুপটি ব্যবহার করা হয়েছে রো-এর জন্য আর দ্বিতীয় লুপটি কলামের জন্য। যখন i = 0, অর্থাৎ প্রথম রো-এর জন্য আমরা j = 0 থেকে 9 পর্যন্ত সব ঘরের ইনপুট নিচ্ছি, তারপর আবার i = 1 (দ্বিতীয় রো)-এর জন্য j = 0 থেকে 9 (প্রতি কলাম) পর্যন্ত সব ঘরের মান ইনপুট নেওয়া হচ্ছে।

এখন আমরা 1 থেকে 10 পর্যন্ত সংখ্যাগুলোর নামতা বের করার জন্য 2-D অ্যারে ব্যবহার করে একটি প্রোগ্রাম লিখব। একের নামতা হবে প্রথম রো-তে, দুইয়ের নামতা দ্বিতীয় রো-তে … দশের নামতা দশম রো-তে থাকবে। তোমরা কি প্রোগ্রামটি নিজে নিজে লিখার চেষ্টা করবে? এক ঘণ্টার মধ্যেও যদি না হয়, তবে আমার কোডটি দেখো। প্রোগ্রামিং শেখার সময় অনেক সহজ প্রোগ্রাম লিখতেও প্রচুর সময় লাগে, তাতে হতাশ হবার কিছু নেই।

 #include <stdio.h>  
 int main()  
 {  
     int namta[10][10];  
     int row, col;  
     for (row = 0; row < 10; row++) {  
         for(col = 0; col < 10; col++) {  
             namta[row][col] = (row + 1) * (col + 1);  
         }  
     }  
     for (row = 0; row < 10; row++) {  
         for(col = 0; col < 10; col++) {  
             printf("%d x %d = %d\n", (row + 1), (col + 1), namta[row][col]);  
         }  
         printf("\n");  
     }  
     return 0;  
 }  
 প্রোগ্রাম: ১১.২  

সম্পূর্ণ আউটপুট স্ক্রিনে না-ও আটতে পারে, তাতে চিন্তার কিছু নেই।

এখন তোমাদের জন্য একটি সমস্যা। ওপরের প্রোগ্রামটি পরিবর্তন করো যাতে আউটপুট হিসেবে আমরা দেখতে পারি যে namta অ্যারেতে মোট কয়টি জোড় ও কয়টি বেজোড় সংখ্যা আছে। সেই সঙ্গে অ্যারেতে যতগুলো সংখ্যা আছে, তার যোগফলও বের করতে হবে। আশা করি, প্রোগ্রামটি ঠিকঠাক লিখতে পেরেছ। যদি কোনো সমস্যা হয়, তবে তুমি তোমার বন্ধুর সাহায্য নিতে পারো।

আচ্ছা, কেউ যদি বলে, সার্কভুক্ত সাতটি দেশের নাম একটি অ্যারেতে রাখতে, তাহলে কী করবে? একটি char type অ্যারেতে একটি দেশের নাম রাখা যায়। যেমন: char country[] = "Bangladesh";। তাহলে সাতটি দেশের নাম রাখার জন্য আমাদের একটি 2-D অ্যারে ব্যবহার করতে হবে। এই অ্যারেতে মোট কয়টি রো থাকবে? সাতটি। কলাম কয়টি থাকবে? জানি না। আসলে একেক দেশের নামের দৈর্ঘ্য তো একেক রকম। তাই আমরা একটি কাজ করতে পারি, কলামে 100টি ক্যারেক্টার রাখার ব্যবস্থা করতে পারি, কারণ সার্কের কোনো দেশের নামে তো 100টির বেশি ক্যারেক্টার নেই, কম আছে।

 #include <stdio.h>  
 int main()  
 {  
     char saarc[7][100] = {"Bangladesh", "India", "Pakistan", "Sri Lanka", "Nepal", "Bhutan", "Maldives"};  
     int row;  
     for (row = 0; row < 7; row++) {  
         printf("%s\n", saarc[row]);  
     }  
     return 0;  
 }  
 প্রোগ্রাম: ১১.৩  

প্রোগ্রামটি তোমার কম্পিউটারে লিখে রান করাও। এখন তোমরা বলো তো, saarc[3][3], saarc[0][5] ও saarc[5][0] – এই তিনটি ঘরে কী কী ক্যারেক্টার আছে? একটু পরে একটি প্রোগ্রাম লিখব, তার সঙ্গে তোমার উত্তর মিলিয়ে নেবে।

আমরা যদি ওই অ্যারের প্রতিটি ক্যারেক্টার আলাদাভাবে প্রিন্ট করতে চাই, তবে প্রোগ্রামটি এভাবে লিখতে পারি:

 #include <stdio.h>  
 #include <string.h>  
 int main()  
 {  
     char saarc[7][100] = {"Bangladesh", "India", "Pakistan", "Sri Lanka", "Nepal", "Bhutan", "Maldives"};  
     int row, col, name_length;  
     for (row = 0; row < 7; row++) {  
         name_length = strlen(saarc[row]);  
         for(col = 0; col < name_length; col++) {  
             printf("%c ", saarc[row][col]);  
         }  
         printf("\n");  
     }  
     return 0;  
 }  
 প্রোগ্রাম: ১১.৪  

আবার যদি দেখতে চাই কোন ঘরে কী আছে, তাহলে রো এবং কলাম নম্বরসহ প্রিন্ট করতে পারি।

 #include <stdio.h>  
 #include <string.h>  
 int main()  
 {  
     char saarc[7][100] = {"Bangladesh", "India", "Pakistan", "Sri Lanka", "Nepal", "Bhutan", "Maldives"};  
     int row, col, name_length;  
     for (row = 0; row < 7; row++) {  
         name_length = strlen(saarc[row]);  
         for(col = 0; col < name_length; col++) {  
             printf("(%d, %d) = %c, ", row, col, saarc[row][col]);  
         }  
         printf("\n");  
     }  
     return 0;  
 }  
 প্রোগ্রাম: ১১.৫  

এবারে নিচের ছকটি দেখো।

6
4
7
8
9
3
7
1
9
9
8
6
4
2
7
2
4
2
5
9
4
1
6
7
3

এখন 2-D অ্যারে ব্যবহার করে তোমাদের দুটি প্রোগ্রাম লিখতে হবে। প্রথম প্রোগ্রামটির কাজ হবে প্রতিটি রো-এর সংখ্যাগুলোর যোগফল বের করা আর দ্বিতীয় প্রোগ্রামের কাজ হবে প্রতিটি কলামের সংখ্যাগুলোর যোগফল বের করা।

প্রথম প্রোগ্রামের আউটপুট হবে এই রকম:
Sum of row 1: 34
Sum of row 2: 29
Sum of row 3: 27
Sum of row 4: 22
Sum of row 5: 21
দ্বিতীয় প্রোগ্রামের আউটপুট হবে এই রকম:
Sum of column 1: 23
Sum of column 2: 22
Sum of column 3: 20
Sum of column 4: 31
Sum of column 5: 37

তোমাদের অনেকেরই দ্বিতীয় প্রোগ্রামটি লিখতে একটু সময় লাগতে পারে, কিন্তু হতাশার কোন কারণ নেই। সময় লাগাই স্বাভাবিক। এখন নিচের ছকটি দেখো। আগের ছকটির সঙ্গে-এর কোথায় যেন একটু মিল রয়েছে!


6
3
8
2
4
4
7
6
4
1
7
1
4
2
6
8
9
2
5
7
9
9
7
9
3

আসলে আগের ছকের রোগুলো নতুন ছকের কলাম, আর আগের ছকের কলামগুলো নতুন ছকের রো। যেমন আগের ছকের প্রথম রো-টি ছিল: 6, 4, 7, 8, 9। আর এই ছকের প্রথম কলাম হচ্ছে: 6, 4, 7, 8, 9। একইভাবে আগের ছকের দ্বিতীয় রো নতুন ছকের দ্বিতীয় কলামের সঙ্গে মেলে। এখন আমরা একটি প্রোগ্রাম লিখব, যেটি একটি 5 x 5 অ্যারেকে (অর্থাৎ 5 রো এবং 5 কলামবিশিষ্ট অ্যারে), আরেকটি 5 x 5 অ্যারেতে এমনভাবে কপি করবে, যাতে প্রথম অ্যারের রোগুলো হয় দ্বিতীয় অ্যারের কলাম আর প্রথম অ্যারের কলামগুলো হয় দ্বিতীয় অ্যারের রো। মানে ওপরের ছক দুটির মত আরকি। যেমন প্রথম অ্যারের প্রথম রো যদি হয়: 1, 2, 3, 4, 5 তাহলে দ্বিতীয় অ্যারের প্রথম কলাম হবে 1, 2, 3, 4, 5। তোমার কি বিষয়টি একটু জটিল মনে হচ্ছে? তাহলে কিছুক্ষণ বিশ্রাম নিয়ে তারপর নিচের প্রোগ্রামটি কম্পাইল করো, রান করো, আউটপুট দেখো এবং কীভাবে কাজ করছে বোঝার চেষ্টা করো।

 #include <stdio.h>  
 #include <string.h>  
 int main()  
 {  
     int ara1[5][5] = {{1, 2, 3, 4, 5}, {10, 20, 30, 40, 50}, {100, 200, 300, 400, 500}, {1000, 2000, 3000, 4000, 5000}, {10000, 20000, 30000, 40000, 50000}};  
     int ara2[5][5];  
     int r, c;  
     printf("Content of first array (ara1): \n");  
     for (r = 0; r < 5; r++) {  
         for(c = 0; c < 5; c++) {  
             printf("%d ", ara1[r][c]);  
         }  
         printf("\n");  
     }  
     printf("\n");  
     // now start copy  
     for (r = 0; r < 5; r++) {  
         for(c = 0; c < 5; c++) {  
             ara2[c][r] = ara1[r][c];  
         }  
     }  
     printf("Content of second array (ara2): \n");  
     for (r = 0; r < 5; r++) {  
         for(c = 0; c < 5; c++) {  
             printf("%d ", ara2[r][c]);  
         }  
         printf("\n");  
     }  
     return 0;  
 }  
 প্রোগ্রাম: ১১.৬  

তোমরা যদি এতক্ষণ 2-D অ্যারের সব উদাহরণ এবং যেসব প্রোগ্রাম নিজে লিখতে বলেছি, সেগুলো সব কম্পিউটারে রান করে থাকো এবং বুঝে থাকো (বুঝতে হলে অবশ্যই চিন্তা করতে হবে) তবে তোমাদের আর 2-D অ্যারে নিয়ে সমস্যা হওয়ার কথা নয়। অ্যারে কিন্তু 3-D, 4-D কিংবা আরও বেশি ডাইমেনশনের হতে পারে, তবে সেগুলো নিয়ে আর আলোচনা করব না।

No comments:

Post a Comment