- 1 1. परिचय
- 2 2. संरचना र पोइन्टरको आधारभूत ज्ञान
- 3 3. संरचना के हो?
- 4 सारांश
- 5 4. पोइन्टरको आधारभूत
- 6 सारांश
- 7 5. संरचना र सूचकको संयोजन
- 8 सारांश
- 9 6. कार्यहरू र संरचना पोइन्टरको सहकार्य
- 10 सारांश
- 11 7. संरचना भित्र पोइन्टरको उपयोग
- 12 सारांश
- 13 8. व्यावहारिक उदाहरण: लिंक्ड लिस्टको निर्माण
- 14 सारांश
- 15 9. सामान्य त्रुटिहरू र डिबग गर्ने तरिका
- 16 सारांश
- 17 10. सारांश
- 18 अन्तमा
1. परिचय
C भाषा प्रणाली विकास र एम्बेडेड प्रोग्रामहरूमा व्यापक रूपमा प्रयोग गरिने प्रोग्रामिङ भाषा हो।यसमा पनि 「संरचना」 र 「पोइन्टर」 ले कुशल डाटा व्यवस्थापन र मेमोरी सञ्चालन प्राप्त गर्न आवश्यक तत्वहरू हुन्।यस लेखमा, यी अवधारणाहरूको आधारभूत देखि व्यावहारिकसम्म विस्तृत रूपमा व्याख्या गरिनेछ।
यस लेख पढेर, सी भाषामा संरचना र पोइन्टरको भूमिका बुझ्न सकिन्छ, व्यावहारिक कोड उदाहरणहरू मार्फत प्रयोग विधि सिद्ध गर्न सकिन्छ।शुरुआतीहरूले पनि सजिलै बुझ्न सकून् भन्ने गरी, ठोस उदाहरणहरू सहित अगाडि बढाइनेछ।
2. संरचना र पोइन्टरको आधारभूत ज्ञान
संरचना भनेको के हो?
संरचना भनेको विभिन्न प्रकारका डेटा एकै ठाउँमा समेटेर प्रयोग गर्ने डेटा संरचना हो। उदाहरणका लागि, व्यक्तिको जानकारी (नाम, उमेर, उचाइ आदि) एकै इकाइको रूपमा व्यवस्थापन गर्न चाहँदा उपयोगी हुन्छ।
तलको कोडले संरचनाको आधारभूत परिभाषा र प्रयोग उदाहरण देखाउँछ।
#include <stdio.h>
// संरचना परिभाषा
struct Person {
char name[50];
int age;
float height;
};
int main() {
struct Person person1; // संरचना चर घोषणा
// डेटा असाइन
strcpy(person1.name, "Taro");
person1.age = 20;
person1.height = 170.5;
// डेटा प्रदर्शन
printf("नाम: %sn", person1.name);
printf("उमेर: %dn", person1.age);
printf("उचाइ: %.1fcmn", person1.height);
return 0;
}
यस उदाहरणमा, Person
नामको संरचना परिभाषित गरी, तीन विभिन्न डेटा प्रकारलाई एकै डेटा संरचनामा समेटिएको छ। यसले सम्बन्धित डेटा एकै ठाउँमा व्यवस्थापन गर्न सम्भव बनाउँछ।
पोइन्टर भनेको के हो?
पोइन्टर भनेको चलको मेमोरी ठेगाना भण्डारण गर्ने चल हो। प्रोग्रामभित्र गतिशील रूपमा मेमोरीलाई सञ्चालन गर्न प्रयोग गरिन्छ। तल पोइन्टरको आधारभूत उदाहरण छ।
#include <stdio.h>
int main() {
int a = 10;
int *p; // पोइन्टर चरको घोषणा
p = &a; // पोइन्टरमा चर a को ठेगाना असाइन गर्नुहोस्
printf("चर a को मान: %dn", a);
printf("पोइन्टर p ले सूच्याएको मान: %dn", *p);
return 0;
}
यस उदाहरणमा, पोइन्टर चल p
प्रयोग गरी चल a
को मानमा पहुँच गरिन्छ। पोइन्टरले मेमोरी सञ्चालनमा शक्तिशाली भूमिका खेल्छ, तर गलत प्रयोगले बग वा मेमोरी लीक उत्पन्न हुन सक्छ, त्यसैले सावधानी आवश्यक छ।
संरचना र पोइन्टरको सम्बन्ध
संरचना र पोइन्टरलाई संयोजन गरेर, अझ लचिलो डेटा सञ्चालन सम्भव हुन्छ। यसबारे पछि उल्लेखित खण्डमा विस्तृत रूपमा व्याख्या गरिनेछ, तर आधारभूत अवधारणा बुझेर प्रयोगमा सहजता ल्याउन सकिन्छ।

3. संरचना के हो?
संरचनाको आधारभूत परिभाषा
संरचना भनेको विभिन्न प्रकारका डेटा एकै साथ समेटेर ह्यान्डल गर्नको लागि डेटा संरचना हो। C भाषा मा, सम्बन्धित जानकारीलाई समूहबद्ध गरेर डेटा व्यवस्थापनलाई सरल बनाउन प्रायः प्रयोग गरिन्छ।
तलको कोड संरचनाको परिभाषा उदाहरण हो।
struct Person {
char name[50];
int age;
float height;
};
यस उदाहरणमा, Person
नामको संरचना परिभाषित गरी, तलका 3 वटा सदस्यहरू छन्।
name
: स्ट्रिङ (एरे) को रूपमा नाम भण्डारणage
: पूर्णांक मानको रूपमा उमेर भण्डारणheight
: फ्लोटिङ पोइन्ट नम्बरको रूपमा उचाइ भण्डारण
संरचनाको परिभाषा भनेको “प्रकार” को घोषणा हो, र यसलाई प्रयोग गरेर विशिष्ट भेरिएबलहरू सिर्जना गरिन्छ।
संरचना भेरिएबलको घोषणा र प्रयोग
संरचना प्रयोग गर्न, पहिले भेरिएबल घोषणा गर्नु पर्छ। तल यसको उदाहरण छ।
#include <stdio.h>
#include <string.h>
struct Person {
char name[50];
int age;
float height;
};
int main() {
struct Person person1; // संरचना चर घोषणा
// डेटा असाइन
strcpy(person1.name, "Taro");
person1.age = 20;
person1.height = 170.5;
// डेटा प्रदर्शन
printf("नाम: %sn", person1.name);
printf("उमेर: %dn", person1.age);
printf("उचाइ: %.1fcmn", person1.height);
return 0;
}
यस कोडमा, person1
नामको संरचना भेरिएबल घोषणा गरी, प्रत्येक सदस्यमा मानहरू असाइन गरिएका छन्।
संरचनाको आरम्भिकरण
संरचना भेरिएबललाई घोषणा गर्दा नै आरम्भिकरण गर्न सकिन्छ।
struct Person person2 = {"Hanako", 25, 160.0};
यसरी समूहमा आरम्भिकरण गरेर, कोडलाई संक्षिप्त रूपमा लेख्न सकिन्छ।
संरचनाको एरे
बहु डेटा व्यवस्थापन गर्नुपर्दा, संरचनाको एरे प्रयोग गरिन्छ।
struct Person people[2] = {
{"Taro", 20, 170.5},
{"Hanako", 25, 160.0}
};
for (int i = 0; i < 2; i++) {
printf("नाम: %s, उमेर: %d, उचाइ: %.1fcmn", people[i].name, people[i].age, people[i].height);
}
यस उदाहरणमा, २ जनाको डेटा एरेमा व्यवस्थापन गरी, लूप प्रयोग गरेर एकै पटक प्रक्रिया गरिन्छ।
संरचनालाई कार्यमा पास गर्ने
संरचनालाई कार्यमा पास गरेर प्रक्रिया गर्न पनि सम्भव छ। तल यसको उदाहरण छ।
void printPerson(struct Person p) {
printf("नाम: %s, उमेर: %d, उचाइ: %.1fcmn", p.name, p.age, p.height);
}
यो कार्यले, आर्गुमेन्टको रूपमा संरचना लिन्छ र त्यसको जानकारी देखाउँछ।
सारांश
संरचना सम्बन्धित डेटा एकै समूहमा व्यवस्थापन गर्न अत्यन्त उपयोगी डेटा प्रकार हो। मूलभूत प्रयोग विधि मास्टर गरेर, डेटा को व्यवस्थितिकरण र पहुँचलाई प्रभावकारी बनाइन्छ।

4. पोइन्टरको आधारभूत
पोइन्टर भनेको के हो?
पोइन्टर भनेको भेरिएबलको मेमोरी ठेगाना सिधै सञ्चालन गर्न सक्ने C भाषाको शक्तिशाली सुविधा हो। यस सेक्सनमा, पोइन्टरको मूल अवधारणा देखि घोषणा, प्रयोग विधि, र विशिष्ट उदाहरणहरू सम्म विस्तृत रूपमा व्याख्या गरिनेछ।
पोइन्टरको घोषणा र आरम्भिकरण
पोइन्टरलाई प्रकारको अगाडि *
जोडेर घोषणा गरिन्छ।
int a = 10; // साधारण चल
int *p; // प्वाइन्टर चलको घोषणा
p = &a; // p मा a को ठेगाना असाइन गर्नुहोस्
*p
पोइन्टरले संकेत गर्ने ठेगानाको “मान” दर्शाउँछ (अप्रत्यक्ष सन्दर्भ)।&a
भेरिएबल a को ठेगाना प्राप्त गर्छ (ठेगाना अपरेटर)।
पोइन्टरद्वारा मानको सञ्चालन
पोइन्टर प्रयोग गरेर मान सञ्चालन गर्ने उदाहरण हेर्नुहोस्।
#include <stdio.h>
int main() {
int a = 10; // सामान्य चर
int *p = &a; // पोइन्टर चर p घोषणा गर्नुहोस्, a को ठेगाना असाइन गर्नुहोस्
printf("a को मान: %dn", a); // 10
printf("a को ठेगाना: %pn", &a); // a को ठेगाना
printf("p को मान(ठेगाना): %pn", p); // p को मान(ठेगाना)
printf("p ले सूचाउने मान: %dn", *p); // 10
*p = 20; // पोइन्टर मार्फत मान परिवर्तन गर्नुहोस्
printf("a को नयाँ मान: %dn", a); // 20
return 0;
}
यस कोडमा, पोइन्टर p
प्रयोग गरेर भेरिएबल a
को मानलाई अप्रत्यक्ष रूपमा परिवर्तन गरिन्छ।
एरे र पोइन्टर
एरेका तत्वहरूमा पहुँच पनि पोइन्टर प्रयोग गरेर गर्न सकिन्छ।
#include <stdio.h>
int main() {
int arr[3] = {10, 20, 30};
int *p = arr; // एरेको पहिलो तत्वको ठेगाना सङ्केत गर्दछ
printf("पहिलो तत्व: %dn", *p); // 10
printf("दोस्रो तत्व: %dn", *(p+1)); // 20
printf("तेस्रो तत्व: %dn", *(p+2)); // 30
return 0;
}
यस उदाहरणमा, पोइन्टर p
प्रयोग गरेर एरेका प्रत्येक तत्वमा पहुँच गरिन्छ।
सारांश
प्वाइन्टर C भाषा मा अत्यन्त महत्वपूर्ण कार्य हो, जसले प्रभावकारी मेमोरी व्यवस्थापन र लचिलो प्रोग्राम डिजाइन सम्भव बनाउँछ। यस खण्डमा, प्वाइन्टरको आधारभूत अवधारणा र प्रयोग विधि सिक्यौं। अर्को पटक 「5. संरचना र प्वाइन्टरको संयोजन」 बारे विस्तृत रूपमा व्याख्या गर्नेछौं, कृपया प्रतीक्षा गर्नुहोस्!
5. संरचना र सूचकको संयोजन
संरचना सूचकको आधारभूत
संरचना र सूचकलाई संयोजन गरेर, थप लचिलो र कुशल डाटा व्यवस्थापन सम्भव हुन्छ। यो खण्डमा, संरचना सूचकको आधारभूत प्रयोगदेखि आवेदन उदाहरणसम्म व्याख्या गरिन्छ।
तल आधारभूत संरचना सूचकको उदाहरण छ।
#include <stdio.h>
#include <string.h>
// संरचना परिभाषा
struct Person {
char name[50];
int age;
float height;
};
int main() {
struct Person person1 = {"Taro", 20, 170.5}; // संरचना प्रारम्भ
struct Person *p = &person1; // संरचना सूचक घोषणा र प्रारम्भ
// सूचक प्रयोग गरेर डेटा पहुँच
printf("नाम: %sn", p->name);
printf("उमेर: %dn", p->age);
printf("उचाइ: %.1fcmn", p->height);
// सूचक मार्फत मान परिवर्तन
p->age = 25;
printf("परिवर्तन पछि उमेर: %dn", p->age);
return 0;
}
गतिशील स्मृति आवंटनसँगको सहकार्य
संरचना सूचक गतिशील स्मृति आवंटनसँग राम्रोसँग मेल खान्छ, ठूलो मात्रामा डाटा ह्यान्डल गर्दा सुविधाजनक हुन्छ। तल त्यसको उदाहरण छ।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// संरचना परिभाषा
struct Person {
char name[50];
int age;
float height;
};
int main() {
// गतिशील स्मृति आवंटन द्वारा संरचना निर्माण
struct Person *p = (struct Person *)malloc(sizeof(struct Person));
// डेटा असाइनमेन्ट
strcpy(p->name, "हनाको");
p->age = 22;
p->height = 160.0;
// डेटा प्रदर्शन
printf("नाम: %sn", p->name);
printf("उमेर: %dn", p->age);
printf("उचाइ: %.1fcmn", p->height);
// स्मृति मुक्त
free(p);
return 0;
}
अनुक्रम र संरचना सूचक
संरचनाको अनुक्रम र सूचकलाई संयोजन गरेर, धेरै डाटाहरूलाई कुशलतापूर्वक व्यवस्थापन गर्न सकिन्छ।
#include <stdio.h>
#include <string.h>
// संरचना परिभाषा
struct Person {
char name[50];
int age;
float height;
};
int main() {
struct Person people[2] = {{"Taro", 20, 170.5}, {"Hanako", 25, 160.0}};
struct Person *p = people; // एरेको पहिलो ठेगाना सूचक
for (int i = 0; i < 2; i++) {
printf("名前: %sn", (p + i)->name);
printf("उमेर: %d\n", (p + i)->age);
printf("उचाइ: %.1fcm\n", (p + i)->height);
}
return 0;
}
सारांश
संरचना र पोइन्टरलाई संयोजन गरेर, डेटा व्यवस्थापनको दक्षता र मेमोरी अपरेसनको लचीलापन सुधारिन्छ। यस खण्डमा आधारभूत प्रयोगबाट गतिशील मेमोरी आवंटनसम्म समेटिएको छ।

6. कार्यहरू र संरचना पोइन्टरको सहकार्य
संरचनालाई कार्यमा पास गर्ने तरिका
संरचनालाई कार्यमा पास गर्दा तलका दुईवटा विधिहरू छन्।
- मान पास
संरचनाको सम्पूर्ण प्रतिलिपि कार्यमा पास गरिन्छ, तर ठूलो डेटा भएमा धेरै मेमोरी खपत हुन्छ। - सन्दर्भ पास (पोइन्टर पास)
संरचनाको ठेगाना पास गरेर मेमोरी दक्षता सुधारिन्छ, र कार्यभित्र मूल डेटा सिधै सञ्चालन गर्न सकिन्छ।
मान पासको उदाहरण
#include <stdio.h>
#include <string.h>
// संरचना परिभाषा
struct Person {
char name[50];
int age;
};
// फंक्शन: मान पास
void printPerson(struct Person p) {
printf("नाम: %sn", p.name);
printf("उमेर: %dn", p.age);
}
int main() {
struct Person person1 = {"Taro", 20};
printPerson(person1); // मान पास
return 0;
}
यस उदाहरणमा, संरचनालाई कार्य printPerson
मा मान पास गरेर पास गरिन्छ। तर, ठूलो डेटा ह्यान्डल गर्दा मेमोरी दक्षता खराब हुन्छ।
सन्दर्भ पास (पोइन्टर पास) को उदाहरण
#include <stdio.h>
#include <string.h>
// संरचना परिभाषा
struct Person {
char name[50];
int age;
};
// फङ्क्शन: पोइन्टर पास
void updateAge(struct Person *p) {
p->age += 1; // उमेर 1 ले बढाउनुहोस्
}
void printPerson(const struct Person *p) {
printf("नाम: %sn", p->name);
printf("उमेर: %dn", p->age);
}
int main() {
struct Person person1 = {"Hanako", 25};
printf("परिवर्तन अघि:n");
printPerson(&person1);
updateAge(&person1); // पोइन्टर पास गरेर उमेर अपडेट गर्नुहोस्
printf("परिवर्तन पछि:n");
printPerson(&person1);
return 0;
}
यस उदाहरणमा, पोइन्टर प्रयोग गरेर संरचनालाई कार्यमा पास गरिन्छ। कार्य updateAge
पोइन्टर मार्फत मूल डेटा सिधै परिवर्तन गर्छ।
डायनामिक मेमोरी र कार्यको सहकार्य
डायनामिक रूपमा सुरक्षित गरिएको मेमोरी क्षेत्रको डेटा पनि कार्यद्वारा प्रक्रिया गर्न सकिन्छ।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// स्ट्रक्चरको परिभाषा
struct Person {
char name[50];
int age;
};
// फङ्क्शन: मेमोरी प्रारम्भ
struct Person *createPerson(const char *name, int age) {
struct Person *p = (struct Person *)malloc(sizeof(struct Person));
strcpy(p->name, name);
p->age = age;
return p;
}
// फङ्क्शन: जानकारी प्रदर्शन
void printPerson(const struct Person *p) {
printf("नाम: %sn", p->name);
printf("उमेर: %dn", p->age);
}
// फङ्क्शन: मेमोरी मुक्त
void deletePerson(struct Person *p) {
free(p);
}
int main() {
struct Person *person1 = createPerson("Taro", 30); // डायनामिक रूपमा मेमोरी सुरक्षित
printPerson(person1);
deletePerson(person1); // मेमोरी मुक्त
return 0;
}
यस उदाहरणमा, डायनामिक मेमोरीलाई आवंटन गरेर संरचनालाई व्यवस्थापन गरिन्छ, र कार्य प्रयोग गरेर डेटा सञ्चालन गरिन्छ। मेमोरी व्यवस्थापनलाई उचित रूपमा गर्ने हो भने, सुरक्षित र प्रभावकारी रूपमा प्रोग्राम निर्माण गर्न सकिन्छ।
सारांश
यस खण्डमा, कार्यहरू र संरचना पोइन्टरलाई संयोजन गरेर प्रयोग गर्ने तरिका व्याख्या गरिएको छ। पोइन्टर प्रयोग गरेर, कार्यहरू बीचको डेटा साझेदारी र गतिशील मेमोरी व्यवस्थापनलाई प्रभावकारी बनाउन सकिन्छ।

7. संरचना भित्र पोइन्टरको उपयोग
संरचना भित्र पोइन्टर प्रयोग गर्ने फाइदाहरू
संरचनामा पोइन्टर समावेश गरेर, लचिलो र प्रभावकारी डेटा व्यवस्थापन तथा मेमोरी अपरेसन सम्भव हुन्छ। यस भागमा, संरचना भित्र पोइन्टरको उपयोग गर्ने आधारभूत विधिहरू र प्रयोगात्मक उदाहरणहरू व्याख्या गरिन्छ।
मूल उदाहरण: स्ट्रिङ डेटा को गतिशील व्यवस्थापन
तलको उदाहरणमा, संरचना भित्र पोइन्टर समावेश गरेर स्ट्रिङलाई गतिशील रूपमा व्यवस्थापन गरिन्छ।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// संरचना परिभाषा
struct Person {
char *name; // नामको लागि पोइन्टर
int age;
};
// मेमोरी आवंटन र प्रारम्भिकरण
void setPerson(struct Person *p, const char *name, int age) {
p->name = (char *)malloc(strlen(name) + 1); // डायनामिक मेमोरी आवंटन
strcpy(p->name, name);
p->age = age;
}
// सूचना प्रदर्शन
void printPerson(const struct Person *p) {
printf("नाम: %sn", p->name);
printf("उमेर: %dn", p->age);
}
// मेमोरी मुक्त
void freePerson(struct Person *p) {
free(p->name); // डायनामिक मेमोरी मुक्त
}
int main() {
struct Person person;
// डेटा सेटिङ
setPerson(&person, "Taro", 30);
// डेटा प्रदर्शन
printPerson(&person);
// मेमोरी मुक्त
freePerson(&person);
return 0;
}
यस उदाहरणमा, स्ट्रिङ डेटा लाई गतिशील रूपमा आवंटन गरेर, नामको लम्बाइमा निर्भर नगर्ने डेटा व्यवस्थापन हासिल गरिएको छ। साथै, प्रयोग पछि free
फङ्सनले मेमोरी मुक्त गरिन्छ।
एरे र पोइन्टरको संयोजन
बहु डेटा व्यवस्थापन गर्दा पनि, पोइन्टर प्रयोग गरेर लचिलो रूपमा समाधान गर्न सकिन्छ।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// संरचना परिभाषा
struct Student {
char *name;
int score;
};
// स्मृति आवंटन र प्रारम्भ
struct Student *createStudent(const char *name, int score) {
struct Student *s = (struct Student *)malloc(sizeof(struct Student));
s->name = (char *)malloc(strlen(name) + 1);
strcpy(s->name, name);
s->score = score;
return s;
}
// स्मृति मुक्त
void freeStudent(struct Student *s) {
free(s->name);
free(s);
}
int main() {
// विद्यार्थी जानकारीको सरणी
struct Student *students[2];
students[0] = createStudent("Taro", 85);
students[1] = createStudent("Hanako", 90);
// डेटा प्रदर्शन
for (int i = 0; i < 2; i++) {
printf("名前: %s, 点数: %dn", students[i]->name, students[i]->score);
}
// स्मृति मुक्त
for (int i = 0; i < 2; i++) {
freeStudent(students[i]);
}
return 0;
}
यस कोडमा, विद्यार्थी डेटा लाई गतिशील रूपमा व्यवस्थापन गरी, आवश्यक अनुसार लचिलो रूपमा सञ्चालन गर्न सकिन्छ।
सारांश
संरचनाभित्र पोइन्टरको उपयोग गरेर, गतिशील मेमोरी व्यवस्थापन र जटिल डेटा संरचनाको डिजाइन सजिलो हुन्छ। यस खण्डमा आधारभूत उदाहरणहरूबाट लागू गर्ने तरिकासम्म व्याख्या गरिएको छ।

8. व्यावहारिक उदाहरण: लिंक्ड लिस्टको निर्माण
लिंक्ड लिस्टको आधारभूत संरचना
लिंक्ड लिस्ट भनेको डेटा नोड स्तरमा व्यवस्थापन गर्ने र गतिशील रूपमा तत्वहरू थप्न/हटाउन सक्ने डेटा संरचना हो। C gengo मा, संरचना र पोइन्टरलाई संयोजन गरेर कार्यान्वयन गर्न सकिन्छ।
यसमा तलको जस्तै संरचना हुन्छ।
[डेटा | अर्को नोडको सूचक] → [डेटा | अर्को नोडको सूचक] → NULL
प्रत्येक नोडले डेटा र अर्को नोडको पोइन्टरलाई धारण गर्दछ। अन्तिम नोडको पोइन्टर NULL लाई संकेत गर्दछ, जसले लिस्टको अन्त्य देखाउँछ।
नोडको परिभाषा
तलमा लिंक्ड लिस्टको नोडलाई प्रतिनिधित्व गर्ने संरचनाको परिभाषा छ।
#include <stdio.h>
#include <stdlib.h>
// नोडको परिभाषा
struct Node {
int data; // डेटा
struct Node *next; // अर्को नोडको सूचक
};
नोडको थप
तलको कोड लिंक्ड लिस्टको अन्त्यमा नोड थप्ने उदाहरण हो।
void append(struct Node **head, int newData) {
// नयाँ नोड बनाउने
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *last = *head; // सूचीको अन्तिम खोज्नको लागि पोइन्टर
newNode->data = newData; // डेटा सेट गर्ने
newNode->next = NULL; // नयाँ नोड अन्तिम हो त्यसैले अर्को NULL
// सूची खाली भए
if (*head == NULL) {
*head = newNode;
return;
}
// सूचीको अन्तिमसम्म जाने
while (last->next != NULL) {
last = last->next;
}
// अन्तिममा नयाँ नोड थप्ने
last->next = newNode;
}
नोडको प्रदर्शन
लिस्टका सबै तत्वहरू देखाउने फङ्क्शन तलको जस्तै छ।
void printList(struct Node *node) {
while (node != NULL) {
printf("%d -> ", node->data);
node = node->next;
}
printf("NULLn");
}
नोडको मेटाउने
विशिष्ट डेटा भएको नोडलाई मेटाउने फङ्क्शन तलको जस्तै छ।
void deleteNode(struct Node **head, int key) {
struct Node *temp = *head, *prev;
// यदि पहिलो नोड हटाउनको लक्ष्य हो भने
if (temp != NULL && temp->data == key) {
*head = temp->next;
free(temp);
return;
}
// हटाउनको लक्ष्य नोड खोज्दै
while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}
// यदि कुञ्जी फेला परेन भने
if (temp == NULL) return;
// नोडलाई सूचीबाट हटाउनुहोस्
prev->next = temp->next;
free(temp);
}
कार्यान्वयन उदाहरण: लिंक्ड लिस्टको सञ्चालन
उपरोक्त फङ्क्शनहरूलाई संयोजन गरेर बनाइएको पूर्ण प्रोग्राम उदाहरण हो।
#include <stdio.h>
#include <stdlib.h>
// नोडको परिभाषा
struct Node {
int data;
struct Node *next;
};
// नोडलाई अन्तिममा थप्नुहोस्
void append(struct Node **head, int newData) {
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *last = *head;
newNode->data = newData;
newNode->next = NULL;
if (*head == NULL) {
*head = newNode;
return;
}
while (last->next != NULL) {
last = last->next;
}
last->next = newNode;
}
// सूचीको सामग्री प्रदर्शन गर्नुहोस्
void printList(struct Node *node) {
while (node != NULL) {
printf("%d -> ", node->data);
node = node->next;
}
printf("NULLn");
}
// नोड हटाउनुहोस्
void deleteNode(struct Node **head, int key) {
struct Node *temp = *head, *prev;
if (temp != NULL && temp->data == key) {
*head = temp->next;
free(temp);
return;
}
while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}
if (temp == NULL) return;
prev->next = temp->next;
free(temp);
}
int main() {
struct Node *head = NULL;
// नोड थप्नुहोस्
append(&head, 10);
append(&head, 20);
append(&head, 30);
printf("जोडिएको सूचीको सामग्री:n");
printList(head);
// नोड हटाउनुहोस्
deleteNode(&head, 20);
printf("20 हटाइसकेपछि:n");
printList(head);
return 0;
}
सारांश
यस खण्डमा, संरचना र पोइन्टर प्रयोग गरेर जडान सूचीको कार्यान्वयन विधि बारे विस्तृत रूपमा व्याख्या गरिएको छ।
जडान सूचीहरू आकार परिवर्तन र डेटा थप्ने/हटाउने कार्यलाई सजिलो बनाउँछन्, त्यसैले धेरै एल्गोरिदम र डेटा व्यवस्थापन प्रणालीहरूमा प्रयोग गरिन्छ।

9. सामान्य त्रुटिहरू र डिबग गर्ने तरिका
C भाषा मा संरचना र पोइन्टरको प्रयोग अत्यन्त शक्तिशाली छ, तर गलत तरिकाले प्रयोग गर्दा प्रोग्राम क्र्यास हुन सक्छ वा अनपेक्षित व्यवहार उत्पन्न हुन सक्छ। यस भागमा, सामान्य त्रुटिहरू र तिनीहरूको समाधानबारे व्याख्या गरिन्छ।
1. पोइन्टरको अनइनिशियलाइजेशन
समस्या उदाहरण:
struct Node *p; // प्रारम्भ नभएको पोइन्टर
p->data = 10; // त्रुटि उत्पन्न
समस्याको कारण:
पोइन्टरp
इनिशियलाइज गरिएको छैन, अनिश्चित ठेगानामा इङ्गित गरिरहेको छ। त्यसकारण मेमोरी एक्सेस उल्लङ्घन हुन्छ।
समाधान:
पोइन्टरलाई सधैं वैध मेमोरी इङ्गित गर्ने गरी इनिशियलाइज गरौं।
struct Node *p = (struct Node *)malloc(sizeof(struct Node)); // स्मृति आवंटन
p->data = 10; // सामान्य रूपमा कार्य गर्दछ
2. मेमोरी लीक
समस्या उदाहरण:
struct Node *p = (struct Node *)malloc(sizeof(struct Node));
// प्रयोग पछि, मेमोरी फ्री नगर्नुहोस्
समस्याको कारण:
malloc
द्वारा सुरक्षित मेमोरी नछोडिएमा, प्रोग्राम समाप्ति सम्म त्यो मेमोरी कब्जा गरिएको रहन्छ।
समाधान:
प्रयोग पछि सधैं free
फङ्सनले मेमोरी मुक्त गरौं।
free(p);
त्यसै गरी, लिंक्ड लिस्ट जस्ता बहु नोडहरूलाई डायनामिक रूपमा सुरक्षित गरिएका अवस्थामा, सबै नोडहरूलाई मुक्त गर्ने प्रक्रिया थप्नुहोस्।
struct Node *current = head;
struct Node *next;
while (current != NULL) {
next = current->next; // पछिल्लो नोडलाई राख्नुहोस्
free(current); // हालको नोडलाई फ्री गर्नुहोस्
current = next; // पछिल्लो नोडमा सार्नुहोस्
}
3. ड्याङ्ग्लिङ पोइन्टर
समस्या उदाहरण:
struct Node *p = (struct Node *)malloc(sizeof(struct Node));
free(p); // मेमोरी मुक्त
p->data = 10; // मुक्त पछि पहुँच → अपरिभाषित व्यवहार
समस्याको कारण:
मेमोरी मुक्त गरेपछि, त्यस मेमोरीलाई इङ्गित गर्ने पोइन्टर प्रयोग गर्दा “ड्याङ्ग्लिङ पोइन्टर” बनिन्छ।
समाधान:
मेमोरी मुक्त गरेपछि, पोइन्टरलाई NULL
मा सेट गर्नुहोस्।
free(p);
p = NULL;
4. NULL पोइन्टरको अपरेशन
समस्या उदाहरण:
struct Node *p = NULL;
p->data = 10; // NULL प्वाइन्टरमा पहुँच → त्रुटि
समस्याको कारण:
NULL
पोइन्टरलाई रेफर गर्ने प्रयास गर्दा सेग्मेन्टेशन फॉल्ट हुन्छ।
समाधान:
पोइन्टर प्रयोग गर्नु अघि सधैं NULL
जाँच गर्नुहोस्।
if (p != NULL) {
p->data = 10;
} else {
printf("प्वाइन्टर NULL छn");
}
डिबग गर्ने तरिका
1. डिबगर प्रयोग गर्नु
GDB जस्ता डिबगर प्रयोग गरेर, रनटाइममा भेरिएबलको मान र प्रोग्रामको फ्लो जाँच गर्न सकिन्छ।
gcc -g program.c -o program // डिबगको लागि कम्पाइल
gdb ./program
2. printf
द्वारा डिबग
डेटा मान र ठेगाना आउटपुट गरेर, प्रोग्रामको व्यवहार जाँच गर्न सकिन्छ।
printf("ठेगाना: %p, मूल्य: %dn", (void *)p, *p);
3. मेमोरी लीकको पत्ता लगाउने
valgrind
प्रयोग गर्दा, मेमोरी लीक र अनइनिशियलाइज्ड मेमोरीको एक्सेस पत्ता लगाउन सकिन्छ।
valgrind --leak-check=full ./program
सारांश
यस खण्डमा, C भाषा मा संरचना र पोइन्टर प्रयोग गर्दा प्रायः हुने गल्तीहरू र तिनीहरूको डिबगिङ विधि बारे व्याख्या गरिएको छ।
- अप्रारम्भित पोइन्टर
- मेमोरी लीक
- ड्याङ्लिङ पोइन्टर
- NULL पोइन्टरमा सञ्चालन
यी समस्याहरूले प्रोग्राममा गम्भीर प्रभाव पार्न सक्छन्, त्यसैले उपाय र परीक्षण गर्दै कार्यान्वयन गर्नु महत्त्वपूर्ण छ।

10. सारांश
शिकेका बुँदाहरूको पुनरावलोकन
अहिलेसम्मको खण्डहरूमा, C भाषा मा संरचना र पोइन्टर बारे आधारदेखि अनुप्रयोगसम्म विस्तृत रूपमा व्याख्या गरिएको थियो। यस खण्डमा, ती सामग्रीलाई पुनरावलोकन गर्दै सिकेका बुँदाहरूलाई व्यवस्थित गरी, भविष्यको अनुप्रयोगमा सहयोगी संकेतहरू प्रदान गरिन्छ।
- संरचनाको आधारभूत
- विभिन्न डेटा प्रकारहरूलाई एकै साथ समेटेर व्यवस्थापन गर्ने उपयोगी डेटा संरचना।
- वास्तविक डेटा व्यवस्थापनका लागि उपयुक्त तरिकाले जानकारीलाई व्यवस्थित गर्न सकिन्छ।
- पोइन्टरको आधारभूत
- मेमोरीको ठेगाना प्रत्यक्ष रूपमा सञ्चालन गर्न सक्ने शक्तिशाली कार्य।
- डायनामिक मेमोरी आवंटन र डेटा सन्दर्भमा उपयोगी।
- संरचना र पोइन्टरको संयोजन
- संरचना पोइन्टरद्वारा डेटा व्यवस्थापन र सञ्चालनलाई प्रभावकारी बनाइन्छ।
- डायनामिक मेमोरी आवंटनसँग संयोजन गरेर लचिलो डेटा व्यवस्थापन सम्भव बनाइन्छ।
- फङ्सन र संरचना पोइन्टरको सहकार्य
- पोइन्टर मार्फत फङ्सनभित्र डेटा प्रत्यक्ष रूपमा परिवर्तन गर्न सकिन्छ।
- मेमोरी दक्षतालाई विचार गरी लचिलो प्रोग्राम डिजाइन सम्भव।
- संरचनाभित्र पोइन्टरको उपयोग
- डायनामिक मेमोरी व्यवस्थापन र बहु-आयामी डेटा प्रशोधनका लागि उपयुक्त डिजाइन सम्भव।
- जटिल डेटा संरचना (जडान सूची र म्याट्रिक्स) लाई प्रभावकारी रूपमा व्यवस्थापन गर्न सकिन्छ।
- जडान सूचीको कार्यान्वयन
- संरचना र पोइन्टरको संयोजनले बनाइएका डायनामिक डेटा संरचनाको निर्माण विधि सिक्ने।
- तत्वको थप/हटाउने जस्ता कार्यहरूलाई सरल रूपमा कार्यान्वयन गर्न सकिन्छ।
- सामान्य त्रुटिहरू र डिबग गर्ने तरिका
- अप्रारम्भिक पोइन्टर र मेमोरी लीक जस्ता समस्याहरूलाई बुझेर, उपयुक्त रूपमा समाधान गर्ने तरिका सिक्ने।
- डिबगर र प्रमाणीकरण उपकरणहरू प्रयोग गरेर सुरक्षित प्रोग्राम बनाउने।
व्यावहारिक प्रयोगमा लागू
सिकेको सामग्रीलाई प्रयोग गरेर, तलका जस्ता प्रोग्रामहरूमा चुनौती लिन सकिन्छ।
- फाइल व्यवस्थापन प्रणाली
- संरचना र पोइन्टर प्रयोग गरेर फाइल जानकारी व्यवस्थापन गर्ने प्रणाली बनाउने।
- डायनामिक डेटा संरचनाको विस्तार
- जडान सूचीलाई प्रयोग गरेर स्ट्याक र क्यू कार्यान्वयन।
- गेम विकास र सिमुलेशन
- संरचनाले क्यारेक्टर जानकारी र स्थितिलाई व्यवस्थापन गरी, प्रभावकारी प्रणाली निर्माण।
- डेटाबेस व्यवस्थापन प्रणाली
- संरचना र पोइन्टर प्रयोग गरेर रेकर्डको थप/हट/खोज गर्ने डेटा व्यवस्थापन प्रणाली विकास।
अर्को चरण
- कोडको अनुकूलन
- नमूना कोडलाई आधार बनाएर, आफ्नै प्रोजेक्टमा लागू गर्न अनुकूलन गर्ने।
- अधिक उन्नत डेटा संरचनामा चुनौती
- डबल जडान सूची, वृक्ष संरचना, ग्राफ आदि, अधिक जटिल डेटा संरचनाहरू सिक्ने।
- एल्गोरिदमसँग संयोजन
- संरचना र पोइन्टर प्रयोग गरेर सॉर्ट र खोज एल्गोरिदम कार्यान्वयन गरी, व्यावहारिकता बढाउने।
- डिबग र अनुकूलन कौशलको सुधार
- डिबगर र मेमोरी विश्लेषण उपकरणहरू प्रयोग गरी, कोडको अनुकूलन र सुरक्षा बढाउने।
अन्तमा
C भाषा को संरचना र पोइन्टरहरू, दक्ष र लचिलो प्रोग्राम डिजाइनलाई सम्भव बनाउने महत्वपूर्ण अवधारणा हुन्। यस लेखमा, आधारभूतदेखि अनुप्रयोगसम्म व्यापक रूपमा सिकाइ, व्यावहारिक कोड उदाहरणहरू मार्फत बुझाइलाई गहिरो बनायौं।
अब प्रोग्रामलाई वास्तविक रूपमा निर्माण गर्दै अनुप्रयोग क्षमतालाई बढाउँदै जाँदा, अझ उच्च स्तरको प्रणाली विकास र एल्गोरिदम डिजाइनमा पनि अनुकूल हुन सकिनेछ।
यो ज्ञानलाई उपयोग गरेर, थप प्रोग्रामिङ कौशल सुधारको लक्ष्य राख्नुहोस्!