А.В. Столяров - Оформление программного кода (1108519), страница 13
Текст из файла (страница 13)
Îäíàêî èç ýòîãî ïðàâèëà åñòüèñêëþ÷åíèå. Åñëè êàæäàÿ èç âåòâåé îïåðàòîðà âûáîðà ñîñòîèòèç îäíîãî äåéñòâèÿ (íàïðèìåð, âûçîâà ïîäïðîãðàììû), ìîæíîçàïèñàòü êàæäóþ âåòâü íà îäíîé ñòðîêå (ìåòêó âìåñòå ñ äåéñòâèåì).  ýòîì ñëó÷àå äëÿ äîñòèæåíèÿ ëó÷øåãî ýñòåòè÷åñêîãî ýôôåê-òà ðåêîìåíäóåòñÿ òåëà âåòâåé âûáîðà ðàñïîëîæèòü, íà÷èíàÿ ñ îäíîé èòîé æå ïîçèöèè, õîòÿ ýòî è íå îáÿçàòåëüíî. Íàïðèìåð:case State ofStHome:StString:StEscape:StNum:elseendHandleHome();HandleString();HandleEscape();HandleNumber();HandleError()switch (state) {case st_home:case st_string:case st_escape:case st_num:default:}handle_home();handle_string();handle_escape();handle_number();handle_error();53break;break;break;break;2.3.
Ïîñëåäîâàòåëüíîñòüâçàèìîèñêëþ÷àþùèõif'îâÎïåðàòîð âûáîðà â îáîèõ ðàññìàòðèâàåìûõ ÿçûêàõ èìååò î÷åíü âàæíîå îãðàíè÷åíèå: óñëîâèåì ïåðåõîäà íà îäíó èç ìåòîê ÿâëÿåòñÿ ðàâåíñòâîñåëåêòèðóþùåãî âûðàæåíèÿ îäíîé èç êîíñòàíò, ïðè÷¼ì êàê êîíñòàíòû, òàê è âûðàæåíèå îáÿçàíû èìåòü ïîðÿäêîâûé òèï.
×àñòî âîçíèêàåòñèòóàöèÿ, ïðè êîòîðîé íåîáõîäèìî ñäåëàòü âûáîð îäíîé èç íåñêîëüêèõâîçìîæíûõ âåòâåé ðàáîòû, îñíîâûâàÿñü íà áîëåå ñëîæíûõ óñëîâèÿõ èëèíà âûðàæåíèè âûáîðà, èìåþùåì íåïîðÿäêîâûé òèï (íàïðèìåð, âûáîð ïîçíà÷åíèþ ñòðîêè ). Òàêîé âûáîð ïðèõîäèòñÿ ðåàëèçîâûâàòü ñ ïîìîùüþäëèííîé öåïî÷êè îïåðàòîðîâ âåòâëåíèÿ: if // else if // else if //... // else.
Åñëè ôîðìàëüíî ñëåäîâàòü ïðàâèëàì, èçëîæåííûì â 2.1.2,òåëà âåòâåé òàêîé êîíñòðóêöèè âûáîðà ïðèä¼òñÿ ñäâèãàòü âñ¼ äàëüøå èäàëüøå âïðàâî, ïðèìåðíî òàê:if cmd = "Save" then beginwriteln('Saving...');SaveFile();end elseif cmd = "Load" then beginwriteln('Loading...');LoadFile();end elseif cmd = "Quit" then beginwriteln('Good bye...');QuitProgram();end else beginwriteln('Unknown command');endif (0 == strcmp(cmd, "Save")) {printf("Saving...\n");save_file();} elseif (0 == strcmp(cmd, "Load")) {printf("Loading...\n");load_file();} elseif (0 == strcmp(cmd, "Quit")) {printf("Good bye...\n");quit_program();} else {printf("Unknown command\n");}54Íåñëîæíî âèäåòü, ÷òî ïðè òàêîì ïîäõîäå îêàæåòñÿ äîñòàòî÷íî ñåìèâîñüìè âåòâåé, ÷òîáû ãîðèçîíòàëüíîå ïðîñòðàíñòâî ýêðàíà êîí÷èëîñü;ìåæäó òåì, âåòâåé ìîæåò ïîòðåáîâàòüñÿ ãîðàçäî áîëüøå. Îäíàêî, ÷òîãîðàçäî âàæíåå, òàêîé (ôîðìàëüíî àáñîëþòíî ïðàâèëüíûé) ñòèëü ôîðìàòèðîâàíèÿ ââîäèò ÷èòàòåëÿ ïðîãðàììû â çàáëóæäåíèå îòíîñèòåëüíîñîîòíîøåíèÿ ìåæäó âåòâÿìè êîíñòðóêöèè.
ßñíî, ÷òî ýòè âåòâè èìåþòîäèíàêîâûé ðàíã âëîæåííîñòè 6 . Íî ïðè ýòîì ñäâèíóòû îíè íà ðàçíûåïîçèöèè!Ïîÿñíèòü âîçíèêàþùóþ ïðîáëåìó ìîæíî è äðóãèì ñïîñîáîì. ßñíî,÷òî òàêàÿ öåïî÷êà if'îâ ïðåäñòàâëÿåò ñîáîé îáîáùåíèå îïåðàòîðà âûáîðàè ñëóæèò òåì æå öåëÿì, ÷òî è îïåðàòîð âûáîðà; ðàçíèöà ëèøü â âûðàçèòåëüíîé ìîùíîñòè. Íî âåòâè îïåðàòîðà âûáîðà ïèøóòñÿ íà îäíîì óðîâíåâëîæåííîñòè.
Ñëåäîâàòåëüíî, âïîëíå ëîãè÷íî ñ÷èòàòü, ÷òî è âåòâè òàêîéêîíñòðóêöèè èç if'îâ äîëæíû ðàñïîëàãàòüñÿ íà îäíîì óðîâíå îòñòóïà.Äîñòèãàåòñÿ ýòî ðàññìîòðåíèåì ñòîÿùèõ ðÿäîì êëþ÷åâûõ ñëîâ else èif êàê åäèíîãî öåëîãî. Âíå çàâèñèìîñòè îò èçáðàííîãî ñòèëÿ, âû ìîæåòåíàïèñàòü else if íà îäíîé ñòðîêå ÷åðåç ïðîáåë, ëèáî ðàçíåñòè èõ íà ðàçíûå ñòðîêè, íà÷èíàþùèåñÿ â îäíîé è òîé æå ïîçèöèè.  ÷àñòíîñòè, åñëèâû íå ñíîñèòå îòêðûâàþùóþ îïåðàòîðíóþ ñêîáêó íà îòäåëüíóþ ñòðîêó, òî âûøåïðèâåä¼ííûå ôðàãìåíòû âû ìîæåòå îôîðìèòü âîò òàê (ifêàæäûé ðàç ñ íîâîé ñòðîêè):if (0 == strcmp(cmd, "Save")) {printf("Saving...\n");save_file();} elseif (0 == strcmp(cmd, "Load")) {printf("Loading...\n");load_file();} elseif (0 == strcmp(cmd, "Quit")) {printf("Good bye...\n");quit_program();} else {printf("Unknown command\n");}if cmd = "Save" then beginwriteln('Saving...');SaveFile();end elseif cmd = "Load" then beginwriteln('Loading...');LoadFile();end elseif cmd = "Quit" then beginwriteln('Good bye...');QuitProgram();end else beginwriteln('Unknown command');endëèáî âîò òàê (if íà îäíîé ñòðîêå ñ ïðåäûäóùèì else; ýòî òîæå äîïóñòèìî):6 Åñëè âû ñîìíåâàåòåñü â ýòîì, ïîïðîáóéòå ïîìåíÿòü âåòâè ìåñòàìè.
Î÷åâèäíî, ÷òîðàáîòà ïðîãðàììû ïðè ýòîì íèêàê íå èçìåíèòñÿ. À ðàç ýòî òàê çíà÷èò, ïðåäïîëîæåíèå î òîì, ÷òî, íàïðèìåð, ïåðâàÿ èç âåòâåé ¾ãëàâíåå¿ âòîðîé, à âòîðàÿ ¾ãëàâíåå¿òðåòüåé, îêàçûâàåòñÿ íåâåðíî.55if cmd = "Save" then beginwriteln('Saving...');SaveFile();end else if cmd = "Load" then beginwriteln('Loading...');LoadFile();end else if cmd = "Quit" then beginwriteln('Good bye...');QuitProgram();end else beginwriteln('Unknown command');endif (0 == strcmp(cmd, "Save")) {printf("Saving...\n");save_file();} else if (0 == strcmp(cmd, "Load")) {printf("Loading...\n");load_file();} else if (0 == strcmp(cmd, "Quit")) {printf("Good bye...\n");quit_program();} else {printf("Unknown command\n");}Àäàïòèðîâàòü ñêàçàííîå ê ñëó÷àÿì, êîãäà îòêðûâàþùàÿ ñêîáêà ñíîñèòñÿ íà ñëåäóþùóþ ñòðîêó, ìû ïðåäëàãàåì ÷èòàòåëþ ñàìîñòîÿòåëüíî;îòìåòèì, ÷òî âàðèàíò ñ else if íà îäíîé ñòðîêå ïðè ýòîì âûãëÿäèòíåñêîëüêî ñòðàííî, íî âñ¼ ðàâíî îñòà¼òñÿ äîïóñòèìûì.Ïîä÷åðêí¼ì, ÷òî âñ¼ ñêàçàííîå â ýòîì ïàðàãðàôå îòíîñèòñÿ òîëüêî êñëó÷àþ, êîãäà âåòêà else ñîñòîèò ðîâíî èç îäíîãî îïåðàòîðà if.
Åñëèýòî íå òàê, ñëåäóåò ïðèìåíÿòü îáû÷íûå ïðàâèëà ôîðìàòèðîâàíèÿ îïåðàòîðà âåòâëåíèÿ.2.4. Ìåòêè è îïåðàòîðgoto ëèòåðàòóðå ÷àñòî ìîæíî âñòðåòèòü óòâåðæäåíèå î òîì, ÷òî îïåðàòîð goto ÿêîáû ¾íåëüçÿ èñïîëüçîâàòü¿, ïîòîìó ÷òî îí çàïóòûâàåò ïðîãðàììó.  áîëüøèíñòâå ñëó÷àåâ ýòî äåéñòâèòåëüíî òàê, íî ñóùåñòâóþòäâå (sic! íå îäíà, íå òðè, à èìåííî äâå) ñèòóàöèè, â êîòîðûõ ïðèìåíåíèågoto íå òîëüêî äîïóñòèìî, íî è æåëàòåëüíî.Ïåðâàÿ èç äâóõ ñèòóàöèé î÷åíü ïðîñòàÿ: âûõîä èç ìíîãîêðàòíî âëîæåííûõ óïðàâëÿþùèõ êîíñòðóêöèé, íàïðèìåð öèêëîâ.
Ñ âûõîäîì èç îäíîãî öèêëà ñïðàâÿòñÿ ñïåöèàëüíî ïðåäíàçíà÷åííûå äëÿ ýòîãî îïåðàòîðûbreak è continue (â Ñè îíè ïðèñóòñòâîâàëè ñ ñàìîãî íà÷àëà, â ñòàíäàðò Ïàñêàëÿ ýòè îïåðàòîðû íå âõîäèëè, íî âñå ñîâðåìåííûå ðåàëèçàöèèÏàñêàëÿ èõ ïîääåðæèâàþò), íî ÷òî äåëàòü, åñëè ¾âûïðûãíóòü¿ íóæíî,ñêàæåì, èç òð¼õ öèêëîâ, âëîæåííûõ äðóã â äðóãà? Êîíå÷íî, îáîéòèñüáåç goto, ñòðîãî ãîâîðÿ, ìîæíî è çäåñü: â óñëîâèÿ öèêëîâ âñòàâèòü ïðîâåðêè êàêîãî-íèáóäü ñïåöèàëüíîãî ôëàæêà, â ñàìîì âíóòðåííåì öèêëåýòîò ôëàæîê âçâåñòè è ñäåëàòü break;, è òîãäà âñå öèêëû çàâåðøàòñÿ. Îòìåòèì, ÷òî â áîëüøèíñòâå ñëó÷àåâ ïðåñëîâóòûé ôëàæîê ïðèä¼òñÿïðîâåðÿòü íå òîëüêî â óñëîâèÿõ öèêëîâ, íî è íåêîòîðûå ÷àñòè òåë ýòèõöèêëîâ îáðàìëÿòü if'àìè, ïðîâåðÿþùèìè âñ¼ òîò æå ôëàæîê. Áûëî áûïî ìåíüøåé ìåðå ñòðàííî óòâåðæäàòü, ÷òî âñå ýòè íàãðîìîæäåíèÿ îêàæóòñÿ áîëåå ÿñíûìè, íåæåëè îäèí îïåðàòîð goto (êîíå÷íî, ïðè óñëîâèè,÷òî èìÿ ìåòêè âûáðàíî óäà÷íî è ñîîòâåòñòâóåò ñèòóàöèè, â êîòîðîé íàíå¼ äåëàåòñÿ ïåðåõîä).56Âòîðóþ ñèòóàöèþ îïèñàòü íåñêîëüêî ñëîæíåå.
Ïðåäñòàâüòå ñåáå, ÷òîâû ïèøåòå ïîäïðîãðàììó, êîòîðàÿ â íà÷àëå ñâîåé ðàáîòû çàáèðàåò ñåáåíåêèé ðåñóðñ (âûäåëÿåò äèíàìè÷åñêóþ ïàìÿòü, îòêðûâàåò ôàéë è ò. ï.),à ïî çàâåðøåíèè ðàáîòû äîëæíà ýòîò ðåñóðñ îñâîáîäèòü (ñîîòâåòñòâåííî, âûñâîáîäèòü ïàìÿòü, çàêðûòü ôàéë). Òàêàÿ ñõåìà ðàáîòû âñòðå÷àåòñÿ äîñòàòî÷íî ÷àñòî; ïî-àíãëèéñêè âûñâîáîæäåíèå çàõâà÷åííûõ ðåñóðñîâïåðåä îêîí÷àíèåì ðàáîòû íàçûâàåòñÿ cleanup, ÷òî ìîæåò áûòü ïðèáëèçèòåëüíî ïåðåâåäåíî ñëîâîì î÷èñòêà. Íåîáõîäèìîñòü ïðîèçâåñòè î÷èñòêóïåðåä âûõîäîì èç ïîäïðîãðàììû íå ïðåäñòàâëÿåò íèêàêèõ ïðîáëåì, åñëè òî÷êà âûõîäà ó íàñ îäíà; ïðîáëåìû íà÷èíàþòñÿ, åñëè ãäå-íèáóäü âñåðåäèíå êîäà ïîäïðîãðàììû âîçíèêàåò ïîòðåáíîñòü äîñðî÷íîãî å¼ çàâåðøåíèÿ (â ÿçûêå Ñè äëÿ ýòîãî èñïîëüçóåòñÿ îïåðàòîð return, â Ïàñêàëå ïñåâäîïðîöåäóðà exit).
Ïóñòü, äëÿ ïðèìåðà, â íà÷àëå íàøåé ïîäïðîãðàììû ïðîèçâîäÿòñÿ òðè îïåðàöèè ïî âûäåëåíèþ ïàìÿòè, â êîíöå òðè ñîîòâåòñòâóþùèå îïåðàöèè ïî å¼ îñâîáîæäåíèþ, è íàì ïîòðåáîâàëîñü â äâóõ ìåñòàõ êîäà ïîäïðîãðàììû ñäåëàòü äîñðî÷íîå çàâåðøåíèå.Ïîïûòêà îáîéòèñü áåç goto ïðèâåä¼ò ê òîìó, ÷òî â ýòèõ äâóõ ìåñòàõ íåïîñðåäñòâåííî ïåðåä çàâåðøåíèåì (ò.
å. ïåðåä return èëè exit) ïðèä¼òñÿïðîäóáëèðîâàòü êîä âñåõ òð¼õ îïåðàöèé ïî âûñâîáîæäåíèþ ïàìÿòè. Êàêèçâåñòíî, äóáëèðîâàíèå êîäà äî äîáðà îáû÷íî íå äîâîäèò: åñëè ìû òåïåðüèçìåíèì íà÷àëî ïîäïðîãðàììû, äîáàâèâ èëè óáðàâ îïåðàöèè ïî çàõâàòóðåñóðñà, âåëèêà âåðîÿòíîñòü òîãî, ÷òî èç ïîëó÷èâøèõñÿ òð¼õ ôðàãìåíòîâ, îñóùåñòâëÿþùèõ î÷èñòêó (îäèí â êîíöå ïîäïðîãðàììû, äâà ïåðåäòî÷êàìè äîñðî÷íîãî çàâåðøåíèÿ) ìû èñïðàâèì òîëüêî äâà, à ïðî òðåòèéçàáóäåì. Ïîýòîìó â òàêîé ñèòóàöèè îáû÷íî ïîñòóïàþò èíà÷å: ïåðåä îïåðàöèÿìè î÷èñòêè, íàõîäÿùèìèñÿ â êîíöå ïîäïðîãðàììû, ñòàâÿò ìåòêó(êàê ïðàâèëî, å¼ íàçûâàþò quit èëè cleanup), à âìåñòî return èëè exitäåëàþò goto íà ýòó ìåòêó.Ñëåäóåò îáðàòèòü âíèìàíèå, ÷òî â îáîèõ ñëó÷àÿõ ïåðåõîä äåëàåòñÿ¾âíèç¿ ïî êîäó, ò. å.
âïåð¼ä ïî ïîñëåäîâàòåëüíîñòè âûïîëíåíèÿ (òî åñòüìåòêà ñòîèò â òåêñòå ïðîãðàììû íèæå îïåðàòîðà goto) è ¾íàðóæó¿ èçóïðàâëÿþùèõ êîíñòðóêöèé. Åñëè ó âàñ âîçíèêëî æåëàíèå ñäåëàòü gotoíàçàä ýòî îçíà÷àåò, ÷òî âû ñîçäà¼òå öèêë, à äëÿ öèêëîâ åñòü ñïåöèàëüíûå îïåðàòîðû. Åñëè æå âàì çàõîòåëîñü ¾âïðûãíóòü¿ âíóòðü óïðàâëÿþùåé êîíñòðóêöèè, òî, ñëåäîâàòåëüíî, ó âàñ ÷òî-òî ïîøëî ñîâñåì íå òàê,êàê íàäî, è íóæíî ñðî÷íî ïîíÿòü ïðè÷èíû âîçíèêíîâåíèÿ òàêèõ ñòðàííûõ æåëàíèé; îòìåòèì, ÷òî Ïàñêàëü òàêîãî ïðîñòî íå ïîçâîëèò, à Ñèòàêîå õîòÿ è äîïóñêàåò, íî ýòî íå çíà÷èò, ÷òî òàê äåéñòâèòåëüíî ìîæíîäåëàòü.Òåïåðü, êîãäà ìû çíàåì, ÷òî goto èñïîëüçîâàòü â íåêîòîðûõ ñëó÷àÿõíå òîëüêî ìîæíî, íî è íóæíî, è, áîëåå òîãî, ìû òî÷íî çíàåì, êàêèå ýòîñëó÷àè (ïîâòîðèì åù¼ ðàç, ýòèõ ñëó÷àåâ ðîâíî äâà, è òðåòüåãî íåò) îñòà¼òñÿ îòâåòèòü íà âîïðîñ, êàê âñ¼ ýòî îôîðìëÿòü.
Òî÷íåå, ñàì îïå57ðàòîð goto íèêàêèõ ïðîáëåì ñ îôîðìëåíèåì íå âûçûâàåò, ýòî îáûêíîâåííûé îïåðàòîð, îôîðìëÿåìûé ïî îáû÷íûì ïðàâèëàì; íî âîò òî, êàêñëåäóåò ñòàâèòü ìåòêó, ìîæåò ñòàòü ïðåäìåòîì æàðêîé äèñêóññèè.Íàïîìíèì, ÷òî ìåòêîé âñåãäà ïîìå÷àåòñÿ îïåðàòîð, òî åñòü ïîìåòèòüìåòêîé ïóñòîå ìåñòî íåëüçÿ. Âîïðîñîâ, íà êîòîðûå íóæíî äàòü (çàôèêñèðîâàòü) îòâåò, îêàçûâàåòñÿ äâà: (1) ñäâèãàòü ëè ìåòêó îòíîñèòåëüíî îáúåìëþùåé êîíñòðóêöèè (îòìåòèì, ÷òî ñ àíàëîãè÷íîé äèëåììîé ìû óæåâñòðå÷àëèñü ïðè îáñóæäåíèè îïåðàòîðîâ âûáîðà â 2.2) è (2) ðàçìåùàòüëè ïîìå÷åííûé îïåðàòîð íà òîé æå ñòðîêå, ãäå ìåòêà, èëè íà îòäåëüíîéñòðîêå.Íàèáîëåå ïîïóëÿðåí âàðèàíò, ïðè êîòîðîì ìåòêà íå ñäâèãàåòñÿ, òîåñòü ïèøåòñÿ â òîé æå ãîðèçîíòàëüíîé ïîçèöèè, â êîòîðîé ðàçìåùåíûíà÷àëî è êîíåö îáúåìëþùåé óïðàâëÿþùåé ñòðóêòóðû, à ïîìå÷åííûé îïåðàòîð ñíîñèòñÿ íà ñëåäóþùóþ ñòðîêó, íàïðèìåð:procedure GoodProc;label quit;var p, q: ^SomethingBig;beginnew(p);new(q);{ ...