break, continue, నెస్టెడ్ లూప్స్ & స్టార్ ప్యాటర్న్స్
ఒక పెద్ద సినిమా థియేటర్లో సినిమా హౌస్ఫుల్ అయ్యి నడుస్తుందనుకోండి. ప్రతి ఒక్కరూ తమ సీట్లలో కూర్చుని 3 గంటల ప్రదర్శనను నిరంతరాయంగా చూస్తున్నారు. ఒకవేళ థియేటర్లో ప్రమాదవశాత్తు ఫైర్ అలారం మోగితే ఏం జరుగుతుంది? సినిమా పూర్తయ్యే వరకు ఎవరూ వేచి ఉండరు! అందరూ వెంటనే ఎమర్జెన్సీ ఎగ్జిట్ డోర్ (Emergency Exit) నుండి బయటకు పరుగులు తీస్తారు. ఇది ప్రోగ్రామింగ్లోని break స్టేట్మెంట్ లాంటిది — లూప్ సహజంగా ముగిసేవరకు వేచి చూడకుండా, మధ్యలోనే తక్షణమే బయటకు దూకేస్తుంది!
ఇప్పుడు మరొక దృశ్యాన్ని చూద్దాం: ఒక రైల్వే ట్రాక్ తనిఖీ చేసే ఇన్స్పెక్టర్ 1వ కిలోమీటరు నుండి 100వ కిలోమీటరు వరకు ప్రతి ట్రాక్ నట్ను తనిఖీ చేసుకుంటూ వెళ్తున్నారు. 45వ కిలోమీటరు వద్ద ఉన్న ట్రాక్ గేట్ ఇప్పటికే కొత్తగా అమర్చబడినట్లు రిపోర్ట్ ఉంది. అప్పుడు ఇన్స్పెక్టర్ ఆ ఒక్క గేట్ తనిఖీని స్కిప్ చేసి, వెంటనే 46వ కిలోమీటరుకు వెళ్లిపోతారు. ఇది continue స్టేట్మెంట్ లాంటిది — ప్రస్తుత రౌండ్ను మాత్రమే వదిలేసి, లూప్ను ఆపకుండా తర్వాతి రౌండ్కు దూసుకుపోతుంది!
ఈ ఎనిమిదవ అధ్యాయంతో మనం Phase 02 (కంట్రోల్ ఫ్లో & లూప్స్) ను విజయవంతంగా ముగించబోతున్నాం. ఇందులో లూప్ జంప్ స్టేట్మెంట్లు, నెస్టెడ్ లూప్స్ (Nested Loops) అంతర్గత గ్రిడ్ నిర్మాణం, ఇంటర్వ్యూలలో అడిగే అద్భుతమైన స్టార్ & పిరమిడ్ ప్యాటర్న్స్, మరియు కంప్యూటర్ సైన్స్ చరిత్రలో అత్యంత వివాదాస్పదమైన goto స్టేట్మెంట్ యొక్క రహస్యాలను లోతుగా నేర్చుకుందాం!
లూప్లను సమర్థవంతంగా నియంత్రించగలగడం అనేది ప్రొఫెషనల్ C డెవలపర్కు తప్పనిసరి నైపుణ్యం. ఈ అధ్యాయంలో కవర్ చేయబడే ప్రధాన అంశాలు:
- జంప్ స్టేట్మెంట్స్ (Jump Statements): C లో అన్కండిషనల్ మరియు కండిషనల్ జంప్ల అవసరం.
- break స్టేట్మెంట్ లోతైన విశ్లేషణ: లూప్ ఎగ్జిక్యూషన్ను మధ్యలోనే ముగించి లూప్ తర్వాతి లైన్కు కంట్రోల్ బదిలీ చేసే విధానం.
- continue స్టేట్మెంట్ పనితీరు: లూప్ బాడీలోని మిగిలిన కోడ్ను దాటవేసి తర్వాతి ఇటరేషన్కు దూకడం.
- for లూప్లో continue వర్సెస్ while లూప్లో continue: అప్డేట్ ఎక్స్ప్రెషన్ రన్ అయ్యే విధానంలో కీలక తేడాలు.
- సమగ్ర తులనాత్మక పట్టిక: break vs continue పక్కపక్కనే విశ్లేషణ.
- నెస్టెడ్ లూప్స్ (Nested Loops Architecture): ఔటర్ లూప్ (రోస్) మరియు ఇన్నర్ లూప్ (కాలమ్స్) 2D కోఆర్డినేట్ సిస్టమ్.
- టైమ్ కాంప్లెక్సిటీ విశ్లేషణ: నెస్టెడ్ లూప్స్ లో $O(N^2)$ కాంప్లెక్సిటీ మరియు CPU సైకిల్స్ నిర్వహణ.
- స్టార్ & పిరమిడ్ ప్యాటర్న్స్ లాజిక్: రైట్-యాంగిల్ ట్రయాంగిల్, ఇన్వర్టెడ్ ట్రయాంగిల్, మరియు సిమెట్రిక్ పిరమిడ్.
- సంఖ్యా ప్యాటర్న్స్: ఫ్లాయిడ్స్ ట్రయాంగిల్ (Floyd's Triangle) & బైనరీ ఆల్టర్నేటింగ్ ప్యాటర్న్స్.
- నెస్టెడ్ లూప్లలో break ప్రవర్తన: కేవలం లోపలి లూప్ నుండి మాత్రమే బయటకు రావడం (సింగిల్-లెవల్ బ్రేక్).
- goto స్టేట్మెంట్ వివాదం & నిజం: ఎడ్జర్ డిజ్క్స్ట్రా గారి "Go To Considered Harmful" వ్యాసం & లైనక్స్ కెర్నల్లో ఎర్రర్ క్లీనప్.
- సమగ్ర ప్రాజెక్ట్: ప్రైమ్ నంబర్ చెకర్ (Early Exit ఆప్టిమైజేషన్) & బ్యాంకింగ్ ట్రాన్సాక్షన్ ఫిల్టర్.
- స్వీయ మూల్యాంకన క్విజ్: 5 ట్రిక్కీ ఇంటర్వ్యూ ప్రశ్నలు & విశ్లేషణ.
మనం చాప్టర్ 06 లో switch కేస్ నుండి బయటపడటానికి break ను చూశాం. అయితే లూప్లలో (for, while, do-while) break పాత్ర మరింత శక్తివంతమైనది. లూప్ సాధారణ కండిషన్ ఇంకా ముగియకపోయినా, ఏదైనా ఒక ప్రత్యేక కండిషన్ తలెత్తినప్పుడు లూప్ను తక్షణమే బద్దలు కొట్టి (Terminate చేసి) బయటకు రావడానికి break ఉపయోగపడుతుంది.
ఎగ్జిక్యూషన్ ఫ్లో:
లూప్ బాడీ లోపల break; స్టేట్మెంట్ తారసపడగానే, కంపైలర్ లూప్ బాడీలోని తర్వాతి లైన్లను మరియు తర్వాతి అన్ని ఇటరేషన్లను పూర్తిగా విస్మరిస్తుంది. లూప్ ముగింపు కర్లీ బ్రేస్ } తర్వాత ఉన్న మొట్టమొదటి స్టేట్మెంట్కు కంట్రోల్ను బదిలీ చేస్తుంది.
#include <stdio.h>
int main() {
int target = 42;
int foundIndex = -1;
printf("1 నుండి 100 వరకు సంఖ్యలను వెతుకుతున్నాం...\n");
for (int i = 1; i <= 100; i++) {
if (i == target) {
foundIndex = i;
printf("🎯 టార్గెట్ సంఖ్య %d దొరికింది! లూప్ను మధ్యలోనే ఆపేస్తున్నాం.\n", target);
break; // 43 నుండి 100 వరకు మిగిలిన 58 ఇటరేషన్లు పూర్తిగా ఆదా అయ్యాయి!
}
}
printf("శోధన ముగిసింది. టార్గెట్: %d వద్ద ఉంది.\n", foundIndex);
return 0;
}
break లేకపోతే, టార్గెట్ సంఖ్య 42 దొరికిన తర్వాత కూడా లూప్ అనవసరంగా 100 వరకు 58 సార్లు తిరుగుతూ CPU సమయాన్ని వృధా చేస్తుంది. break వాడటం వలన ప్రోగ్రామ్ వేగం రెట్టింపు అవుతుంది!
break లూప్ను పూర్తిగా ఆపేస్తే, continue స్టేట్మెంట్ కేవలం ప్రస్తుత ఇటరేషన్ (Current Round) ను మాత్రమే మధ్యలో వదిలేసి, లూప్ను ఆపకుండా వెంటనే తర్వాతి ఇటరేషన్కు దూకుతుంది!
డేటాను ప్రాసెస్ చేసేటప్పుడు అనవసరమైన లేదా చెల్లని రికార్డులను ఫిల్టర్ చేయడానికి (ఉదా: సున్నాను భాగహారంలో నివారించడం, నెగెటివ్ నంబర్లను స్కిప్ చేయడం) continue అమితంగా ఉపయోగపడుతుంది.
#include <stdio.h>
int main() {
printf("1 నుండి 10 వరకు సరి సంఖ్యలు (Even Numbers):\n");
for (int i = 1; i <= 10; i++) {
// బేసి సంఖ్య (Odd number) అయితే ప్రింటింగ్ను స్కిప్ చేసి తర్వాతి సంఖ్యకు వెళ్లు
if (i % 2 != 0) {
continue; // కింద ఉన్న printf ని దాటవేసి, నేరుగా i++ కి వెళ్తుంది!
}
printf("%d ", i);
}
printf("\n");
return 0;
}
⚠️ ప్రాణాంతక ట్రాప్: while లూప్లో continue వాడేటప్పుడు జాగ్రత్త!
for లూప్లో continue జరిగినప్పుడు కంట్రోల్ నేరుగా హెడర్లోని అప్డేట్ ఎక్స్ప్రెషన్ (i++) వద్దకు వెళ్తుంది. కానీ while లూప్లో continue జరిగితే అది అప్డేట్ను దాటవేసి నేరుగా కండిషన్ వద్దకు దూకుతుంది! దీనివలన కౌంటర్ పెరగక ప్రోగ్రామ్ శాశ్వతంగా ఇన్ఫినిట్ లూప్లో ఇరుక్కుపోతుంది!
int i = 1;
while (i <= 5) {
if (i == 3) {
continue; // i++ దాటవేయబడుతుంది!
}
printf("%d ", i);
i++; // 3 వద్ద ఇది ఎప్పటికీ రన్ కాదు!
}
int i = 1;
while (i <= 5) {
if (i == 3) {
i++; // continue కి ముందే పెంచాలి!
continue;
}
printf("%d ", i);
i++;
}
break మరియు continue ల మధ్య ఉన్న కీలక తేడాలను ఒకే పట్టికలో పరిశీలిద్దాం:
| ఫీచర్ / అంశం | break స్టేట్మెంట్ | continue స్టేట్మెంట్ |
|---|---|---|
| ప్రాథమిక విధి | లూప్ను తక్షణమే బద్దలు కొట్టి శాశ్వతంగా ముగిస్తుంది. | ప్రస్తుత ఇటరేషన్ను మాత్రమే దాటవేసి తర్వాతి రౌండ్కు వెళ్తుంది. |
| కంట్రోల్ బదిలీ స్థానం | లూప్ బాడీ వెలుపల ఉన్న తర్వాతి స్టేట్మెంట్కు. | for లో అయితే అప్డేట్ (i++) కు; while లో అయితే కండిషన్కు. |
| లూప్ రౌండ్ల సంఖ్య | మిగిలిన అన్ని ఇటరేషన్లు పూర్తిగా రద్దు చేయబడతాయి. | కేవలం 1 ఇటరేషన్ స్కిప్ అవుతుంది, మిగిలినవి యథావిధిగా కొనసాగుతాయి. |
| ఎక్కడ వాడవచ్చు? | లూప్స్ (for, while, do-while) మరియు switch-case లో. | కేవలం లూప్లలో మాత్రమే (switch లో వాడకూడదు). |
| ఉత్తమ ఉదాహరణ | శోధనలో ఎలిమెంట్ దొరకగానే లూప్ ఆపడం (Search Exit). | చెల్లని డేటాను, నెగెటివ్ విలువల ప్రాసెసింగ్ను ఫిల్టర్ చేయడం. |
ఒక లూప్ లోపల మరొక లూప్ను రాయడాన్ని నెస్టెడ్ లూప్ (Nested Loop) అంటారు. బయటి లూప్ను ఔటర్ లూప్ (Outer Loop) అని, లోపలి లూప్ను ఇన్నర్ లూప్ (Inner Loop) అని పిలుస్తారు.
గడియారం పోలిక (Wall Clock Metaphor):
మీ గదిలోని గోడ గడియారాన్ని గమనించండి. అందులో పెద్ద ముల్లు (నిమిషాల ముల్లు), చిన్న ముల్లు (గంటల ముల్లు) ఉంటాయి. గంటల ముల్లు కేవలం 1 అడుగు ముందుకు వేయడానికి, నిమిషాల ముల్లు 60 రౌండ్లు పూర్తిగా తిరగాలి కదా? కంప్యూటర్ సైన్స్లో నెస్టెడ్ లూప్స్ కూడా సరిగ్గా ఇలాగే పనిచేస్తాయి:
#include <stdio.h>
int main() {
int totalRows = 3;
int totalCols = 4;
printf("=== 3x4 2D గ్రిడ్ కోఆర్డినేట్స్ (Row, Col) ===\n");
for (int row = 1; row <= totalRows; row++) { // ఔటర్ లూప్ (అడ్డు వరుసలు)
printf("Row %d: ", row);
for (int col = 1; col <= totalCols; col++) { // ఇన్నర్ లూప్ (నిలువు వరుసలు)
printf("(%d,%d) ", row, col);
}
printf("\n"); // ప్రతి అడ్డు వరుస పూర్తయిన తర్వాత కొత్త లైన్
}
return 0;
}
Row 1: (1,1) (1,2) (1,3) (1,4)Row 2: (2,1) (2,2) (2,3) (2,4)Row 3: (3,1) (3,2) (3,3) (3,4)మొత్తం ఇన్నర్ ప్రింటింగ్ స్టేట్మెంట్ రన్ అయిన సంఖ్య = 3 × 4 = 12 సార్లు.
డేటా స్ట్రక్చర్స్ & అల్గారిథమ్స్లో నెస్టెడ్ లూప్ల పనితీరును అర్థం చేసుకోవడం చాలా కీలకం. ఒక సాధారణ లూప్ N సార్లు రన్ అయితే దాని టైమ్ కాంప్లెక్సిటీ O(N) (Linear Time). కానీ రెండు స్థాయిల నెస్టెడ్ లూప్స్ ఉన్నప్పుడు:
ఇన్పుట్ సైజ్ $N$ పెరిగే కొద్దీ ఎగ్జిక్యూషన్ సమయం ఎలా పెరుగుతుందో క్రింది పట్టికలో గమనించండి:
| ఇన్పుట్ పరిమాణం ($N$) | సింగిల్ లూప్ ($O(N)$) ఇటరేషన్లు | నెస్టెడ్ లూప్ ($O(N^2)$) ఇటరేషన్లు | 3-స్థాయి లూప్ ($O(N^3)$) ఇటరేషన్లు |
|---|---|---|---|
| 10 | 10 | 100 | 1,000 |
| 100 | 100 | 10,000 | 10,00,000 (1 మిలియన్) |
| 1,000 | 1,000 | 10,00,000 (1 మిలియన్) | 1,00,00,00,000 (1 బిలియన్ - సెకన్ల సమయం!) |
అందుకే పెద్ద పెద్ద సాఫ్ట్వేర్లలో మరియు గేమింగ్ ఇంజిన్లలో అనవసరమైన నెస్టెడ్ లూప్లను నివారించి, బైనరీ సెర్చ్ లేదా హాష్ మ్యాప్ల ద్వారా ఆప్టిమైజ్ చేస్తారు!
కోడింగ్ ఇంటర్వ్యూలు మరియు యూనివర్సిటీ ప్రాక్టికల్స్లో నెస్టెడ్ లూప్ లాజిక్ను పరీక్షించడానికి అత్యంత ప్రాచుర్యం పొందినవి స్టార్ ప్యాటర్న్స్ (Star Patterns). ప్యాటర్న్ ప్రోగ్రామింగ్ చేయడానికి గోల్డెన్ ఫార్ములా ఇది:
- ఔటర్ లూప్ (i): ఎన్ని అడ్డు వరుసలు (Rows) కావాలో నిర్దేశిస్తుంది.
- ఇన్నర్ లూప్ (j): ప్రతి వరుసలో ఎన్ని నక్షత్రాలు లేదా ఖాళీలు ప్రింట్ కావాలో లెక్కిస్తుంది.
- వరుస ముగింపు: ఇన్నర్ లూప్ ముగియగానే ఖచ్చితంగా
printf("\n");ఇవ్వాలి.
#include <stdio.h>
int main() {
int rows = 5;
printf("=== రైట్-యాంగిల్ స్టార్ ట్రయాంగిల్ ===\n");
for (int i = 1; i <= rows; i++) { // వరుస నంబర్ 1 నుండి 5 వరకు
for (int j = 1; j <= i; j++) { // ప్రస్తుత వరుస సంఖ్య (i) సమానంగా స్టార్స్ ప్రింట్ చేయి
printf("* ");
}
printf("\n"); // కొత్త వరుసకు మళ్లు
}
return 0;
}
ఇన్వర్టెడ్ (తలకిందులైన) ట్రయాంగిల్:
మొదటి వరుసలో 5 స్టార్స్, తర్వాత 4, 3, 2, 1 కావాలంటే ఔటర్ లూప్ను రివర్స్లో for (int i = rows; i >= 1; i--) అని నడపాలి:
#include <stdio.h>
int main() {
int rows = 5;
printf("=== ఇన్వర్టెడ్ స్టార్ ట్రయాంగిల్ ===\n");
for (int i = rows; i >= 1; i--) {
for (int j = 1; j <= i; j++) {
printf("* ");
}
printf("\n");
}
return 0;
}
సిమెట్రిక్ పిరమిడ్ నిర్మించాలంటే రెండు విషయాలు అవసరం: ఖాళీ స్థలాలు (Leading Spaces) మరియు స్టార్స్ (Stars). ప్రతి వరుసలో ఎన్ని స్పేసెస్ ఉండాలి, ఎన్ని స్టార్స్ ఉండాలో గణిత సమీకరణం ద్వారా సాధిస్తాం:
- మొత్తం వరుసలు = $N$, ప్రస్తుత వరుస = $i$
- ముందు ఉండే స్పేసెస్ సంఖ్య = $N - i$
- ప్రింట్ అయ్యే స్టార్స్ సంఖ్య = $2i - 1$ (బేసి సంఖ్యల క్రమం: 1, 3, 5, 7, 9...)
#include <stdio.h>
int main() {
int n = 5;
printf("=== సిమెట్రిక్ స్టార్ పిరమిడ్ ===\n");
for (int i = 1; i <= n; i++) {
// భాగం 1: ముందు స్పేసెస్ ప్రింట్ చేయి (n - i)
for (int space = 1; space <= (n - i); space++) {
printf(" ");
}
// భాగం 2: బేసి సంఖ్యలో స్టార్స్ ప్రింట్ చేయి (2*i - 1)
for (int star = 1; star <= (2 * i - 1); star++) {
printf("*");
}
printf("\n");
}
return 0;
}
***
*****
*******
*********
ఫ్లాయిడ్స్ ట్రయాంగిల్ (Floyd's Triangle) అనేది సహజ సంఖ్యలను వరుసగా లెక్కిస్తూ త్రిభుజాకారంలో అమర్చే క్లాసిక్ ప్రోగ్రామ్. ఇందులో ఒక గ్లోబల్ కౌంటర్ వేరియబుల్ 1 నుండి మొదలై ప్రతి నంబర్ ప్రింట్ అయిన తర్వాత పెరుగుతూ ఉంటుంది:
#include <stdio.h>
int main() {
int rows = 4;
int num = 1; // గ్లోబల్ ఇంక్రిమెంట్ కౌంటర్
printf("=== ఫ్లాయిడ్స్ ట్రయాంగిల్ (Floyd's Triangle) ===\n");
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= i; j++) {
printf("%-3d ", num);
num++; // ప్రతి ప్రింట్ తర్వాత విలువ పెరుగుతుంది
}
printf("\n");
}
return 0;
}
2 3
4 5 6
7 8 9 10
చాలా మంది బిగినర్స్ అనుకునే అతిపెద్ద అపోహ: "ఇన్నర్ లూప్లో break రాస్తే మొత్తం అన్ని లూప్లు ఆగిపోతాయి". ఇది పూర్తిగా తప్పు!
break స్టేట్మెంట్ కేవలం అది ఉన్న ప్రస్తుత ఇన్నర్మోస్ట్ లూప్ (Innermost Loop) ను మాత్రమే బద్దలు కొడుతుంది! బయట ఉన్న ఔటర్ లూప్ యథావిధిగా తర్వాతి రౌండ్ను కొనసాగిస్తుంది!
మల్టీ-లెవల్ లూప్ల నుండి ఒకేసారి బయటపడటం ఎలా?
రెండు లేదా మూడు స్థాయిల నెస్టెడ్ లూప్ల నుండి ఒకేసారి బయటకు దూకడానికి C లో ప్రధానంగా రెండు శుభ్రమైన ఇంజనీరింగ్ పద్ధతులు ఉన్నాయి:
- ఫ్లాగ్ వేరియబుల్ వాడటం (Boolean Flag): ఇన్నర్ లూప్లో
found = 1అని సెట్ చేసి, ఔటర్ లూప్లోif (found) break;అని రాయడం. - క్లీనప్ లేబుల్కు goto వాడటం: డీప్ నెస్టెడ్ లూప్స్ నుండి నేరుగా ఫంక్షన్ ఎగ్జిట్ లేబుల్కు జంప్ చేయడం.
#include <stdio.h>
int main() {
int matrix[3][3] = {
{1, 2, 3},
{4, 99, 6},
{7, 8, 9}
};
int target = 99;
int found = 0; // బూలియన్ ఫ్లాగ్
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
if (matrix[r][c] == target) {
printf("🎯 సంఖ్య %d దొరికింది Matrix[%d][%d] వద్ద!\n", target, r, c);
found = 1; // ఫ్లాగ్ ఆన్ చేయి
break; // ఇన్నర్ లూప్ బ్రేక్ అవుతుంది
}
}
if (found) {
break; // ఔటర్ లూప్ కూడా తక్షణమే బ్రేక్ అవుతుంది!
}
}
printf("మల్టీ-లెవల్ సెర్చ్ పూర్తయింది.\n");
return 0;
}
C లాంగ్వేజ్లో goto స్టేట్మెంట్ ప్రోగ్రామ్లోని ఏదైనా ఒక లేబుల్ (Label) వద్దకు ఎటువంటి నిబంధన లేకుండా నేరుగా దూకడానికి అనుమతిస్తుంది. కానీ సాఫ్ట్వేర్ ఇంజనీరింగ్ రంగంలో ఇది అత్యంత చెడ్డ పేరు సంపాదించుకుంది.
ది స్పఘెట్టి కోడ్ డిజాస్టర్ (Spaghetti Code Crisis):
1968 లో ప్రఖ్యాత కంప్యూటర్ శాస్త్రవేత్త ఎడ్జర్ డిజ్క్స్ట్రా (Edsger Dijkstra) "Go To Statement Considered Harmful" అనే చారిత్రక పరిశోధనా పత్రాన్ని ప్రచురించారు. ప్రోగ్రామ్లో ఇష్టానుసారంగా అటూ ఇటూ goto జంప్స్ రాస్తే, కోడ్ ఫ్లో నూడుల్స్ లేదా స్పఘెట్టి లాగా గజిబిజిగా మారిపోయి డీబగ్ చేయడం అసాధ్యంగా మారుతుంది. అందుకే ఆధునిక స్ట్రక్చర్డ్ ప్రోగ్రామింగ్లో goto ను సాధారణ లాజిక్ కోసం వాడకూడదని నియమం విధించారు!
మరి Linux Kernel లో goto ను ఎందుకు విరివిగా వాడుతున్నారు?
లైనస్ టోర్వాల్డ్స్ (Linus Torvalds) రూపొందించిన Linux Kernel సోర్స్ కోడ్లో లక్షలాది goto స్టేట్మెంట్లు కనిపిస్తాయి! ఎందుకు? ఎందుకంటే సిస్టమ్ ప్రోగ్రామింగ్లో ఫైల్స్, మెమరీ లేదా లాక్లను కేటాయించిన తర్వాత మధ్యలో ఏదైనా ఎర్రర్ వస్తే — అన్ని వనరులను ఒకే చోట వరుసగా విడుదల చేయడానికి (Centralized Error Cleanup) goto కంటే సమర్థవంతమైన మార్గం మరొకటి లేదు!
#include <stdio.h>
#include <stdlib.h>
int processResource(int errorCode) {
printf("1. నెట్వర్క్ సాకెట్ ఓపెన్ చేయబడింది.\n");
printf("2. మెమరీ బఫర్ కేటాయించబడింది.\n");
if (errorCode == -1) {
printf("🚨 లోపం సంభవించింది! క్లీనప్ లేబుల్కు జంప్ చేస్తున్నాం...\n");
goto cleanup; // సురక్షితమైన ఎర్రర్ క్లీనప్
}
printf("3. డేటా ప్రాసెసింగ్ సక్సెస్ అయింది!\n");
cleanup:
printf("4. [CLEANUP] మెమరీ విడుదల చేయబడింది & సాకెట్ క్లోజ్ చేయబడింది.\n");
return errorCode;
}
int main() {
processResource(-1);
return 0;
}
ఈ పాఠంలో నేర్చుకున్న break మరియు continue కాన్సెప్ట్లను కలిపి ఒక సమగ్ర ప్రాక్టికల్ C ప్రోగ్రామ్ను రన్ చేద్దాం. ఒక సంఖ్య ప్రధాన సంఖ్య (Prime Number) కాదా అని పరీక్షించడానికి $O(sqrt{N})$ ఆప్టిమైజేషన్ మరియు break ఉపయోగపడుతుంది:
#include <stdio.h>
int main() {
int num = 29;
int isPrime = 1; // 1 అంటే Prime, 0 అంటే Not Prime
if (num <= 1) {
isPrime = 0;
} else {
// సంఖ్య యొక్క వర్గమూలం (sqrt) వరకు చెక్ చేస్తే సరిపోతుంది
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) {
isPrime = 0;
printf("-> %d చేత భాగించబడింది (%d * %d = %d)\n", i, i, num / i, num);
break; // ఒక్క కారణాంకం దొరికినా అది ప్రైమ్ కాదు, వెంటనే లూప్ ఆపేయి!
}
}
}
if (isPrime) {
printf("✅ %d అనేది ఒక ప్రధాన సంఖ్య (Prime Number)!\n", num);
} else {
printf("❌ %d అనేది సంయుక్త సంఖ్య (Composite Number).\n", num);
}
return 0;
}
బ్యాంకింగ్ ట్రాన్సాక్షన్ ఫిల్టర్ (continue వినియోగం):
బ్యాంకింగ్ లెడ్జర్లో నెగెటివ్ ఛార్జీలు లేదా సున్నా ట్రాన్సాక్షన్లను విస్మరించి, కేవలం పాజిటివ్ క్రెడిట్లను మాత్రమే మొత్తం లెక్కించే కోడ్ ఇది:
#include <stdio.h>
int main() {
int transactions[] = {500, -20, 1200, 0, -150, 3400, 800};
int totalValidCredits = 0;
int count = sizeof(transactions) / sizeof(transactions[0]);
printf("=== బ్యాంకింగ్ లెడ్జర్ క్రెడిట్ సమ్మరీ ===\n");
for (int i = 0; i < count; i++) {
if (transactions[i] <= 0) {
// ఫీజులు, పెనాల్టీలు లేదా సున్నా ఎంట్రీలను స్కిప్ చేయి
continue;
}
totalValidCredits += transactions[i];
printf("క్రెడిట్ రికార్డ్ #%d: రూ. %d జోడించబడింది\n", i + 1, transactions[i]);
}
printf("---------------------------------------\n");
printf("మొత్తం చెల్లుబాటు అయ్యే క్రెడిట్స్: రూ. %d\n", totalValidCredits);
return 0;
}
ఈ పాఠంలోని లోతైన అంశాలను క్రింది 5 ప్రాక్టికల్ ప్రశ్నల ద్వారా పరీక్షించుకోండి:
❓ ప్రశ్న 1: break మరియు continue మధ్య ఉన్న ప్రధాన వ్యత్యాసం ఏమిటి?
break లూప్ను పూర్తిగా ఆపేసి లూప్ వెలుపలికి పంపుతుంది. continue కేవలం ప్రస్తుత ఇటరేషన్ను మాత్రమే దాటవేసి తర్వాతి రౌండ్కు కంట్రోల్ను బదిలీ చేస్తుంది.
❓ ప్రశ్న 2: రెండు నెస్టెడ్ లూప్లు ఉన్నప్పుడు ఇన్నర్ లూప్లో break రాస్తే ఔటర్ లూప్ ఆగిపోతుందా?
break కేవలం అది ఉన్న లోపలి లూప్ను మాత్రమే బద్దలు కొడుతుంది. ఔటర్ లూప్ తర్వాతి వరుసను యథావిధిగా కొనసాగిస్తుంది.
❓ ప్రశ్న 3: while లూప్లో continue వాడేటప్పుడు తలెత్తే అతిపెద్ద ప్రమాదం ఏమిటి?
while లూప్లో continue అనేది లూప్ బాడీ కింద ఉండే అప్డేట్ ఎక్స్ప్రెషన్ (i++) ను దాటవేసి నేరుగా కండిషన్కు వెళ్తుంది. దీనివలన వేరియబుల్ విలువ పెరగక లూప్ ఇన్ఫినిట్ లూప్గా మారుతుంది.
❓ ప్రశ్న 4: C లో goto స్టేట్మెంట్ను సాధారణ ప్రోగ్రామింగ్లో ఎందుకు నిషేధించారు?
❓ ప్రశ్న 5: 3 అడ్డు వరుసలు మరియు 4 నిలువు వరుసలు ఉన్న నెస్టెడ్ లూప్ మొత్తం ఎన్ని సార్లు రన్ అవుతుంది?
పైన వివరించిన సిమెట్రిక్ పిరమిడ్, ఫ్లాయిడ్స్ ట్రయాంగిల్, మరియు ప్రైమ్ నంబర్ ఫైండర్ ప్రోగ్రామ్లను మన ఆన్లైన్ C కంపైలర్లో ఓపెన్ చేసి స్వయంగా రన్ చేయండి. రోస్ సంఖ్యను మార్చి కొత్త ప్యాటర్న్లను సృష్టించండి!
📌 Phase 02 ముగింపు సారాంశం (Phase 02 Wrap-up):
- కంట్రోల్ ఫ్లో విజయవంతంగా పూర్తి:
if-elseడెసిషన్ మేకింగ్,switch-caseజంప్ టేబుల్స్,for/while/do-whileలూప్స్ మరియుbreak/continueజంప్ స్టేట్మెంట్లపై పూర్తి పట్టు సాధించారు! - break: అత్యవసర ఎగ్జిట్ డోర్; లూప్ను మధ్యలోనే ముగిస్తుంది.
- continue: ప్రస్తుత రౌండ్ను మాత్రమే స్కిప్ చేసి తర్వాతి రౌండ్కు దూకుతుంది.
- నెస్టెడ్ లూప్స్: 2D గ్రిడ్లు, మ్యాట్రిక్స్ ఆపరేషన్లు మరియు ప్యాటర్న్ ప్రింటింగ్ కోసం ఉపయోగించే $O(N^2)$ పవర్ టూల్.