女人吃芡实有什么好处| 甲状腺做什么检查| 头晕做什么检查| nec投影仪是什么牌子| 工作单位是什么意思| 周海媚什么病| 什么是流程| 香松是什么| 衡字五行属什么| 肺燥吃什么中成药| 下午4点半是什么时辰| 水马是什么| 湿疹是什么样的图片| 腿上长痣代表什么| 梦见下大雪是什么意思| allan英文名什么意思| 输卵管堵塞吃什么药可以疏通| 喝什么饮料解酒最快最有效| 尿酸高不能吃什么东西| 翡翠的五行属性是什么| 大便失禁是什么原因造成的| 性交是什么感觉| 金线莲有什么功效| 吐完后胃不舒服应该吃什么呢| 抵抗力差吃什么可以增强抵抗力| 早上起床咳嗽是什么原因| 莫名心慌是什么原因| 子宫颈肥大有什么危害| sys是什么意思| 黑白蛇是什么蛇| 大姨妈来了不能吃什么东西| 什么样的人容易猝死| 少将相当于什么级别| 钴蓝色是什么颜色| 媒婆是什么意思| 粤语点解什么意思| 一眼万年什么意思| 什么是真菌感染| 跖疣挂什么科| drgs付费是什么意思| 凉虾是什么| wbc白细胞高是什么原因| 胃不舒服想吐是什么原因| 梦到蜈蚣是什么意思| 伏脉常见于什么病| 小产和流产有什么区别| 李嘉诚属什么生肖| 散粉和粉饼有什么区别| 25度穿什么衣服合适| 人为什么会胡思乱想| 心脏供血不足吃什么药好| 宝宝不喝奶是什么原因| 牛奶有什么营养| 圣贤是什么意思| 吃了头孢不能吃什么| 晚上难入睡是什么原因| 88年属龙是什么命| 痰是棕色的是什么原因| 慢性萎缩性胃炎吃什么药可以根治| 天机不可泄露是什么意思| 二月一日是什么星座| 古埃及是什么人种| 乔迁之喜送什么| 礼佛是什么意思| 什么是穿刺检查| 父亲节送爸爸什么礼物| 三维和四维有什么区别| math是什么意思| 别开生面什么意思| 得了狂犬病有什么症状| 洗牙为什么要验血| 非浅表性胃炎是什么意思| 食欲不振吃什么药| 庹是什么意思| 有点想吐是什么原因| 糖尿病可以吃什么菜| 存款准备金率是什么意思| 来大姨妈前有什么症状| 双侧附睾头囊肿是什么意思| 北极和南极有什么区别| 口腔老是出血是什么原因| 微笑表情代表什么意思| 粘米是什么米| 4月10号是什么星座| 胆结石能吃什么水果| 521是什么意思| 眼睑痉挛是什么原因造成的| 血糖偏高吃什么水果好| 栖字五行属什么| 八珍胶囊适合什么人吃| 农历五月的别称是什么| 什么时间段买机票最便宜| 白砂糖是什么糖| 切除子宫有什么影响| 呼吸道感染吃什么药最好| 姨妈量少是什么原因| 白头发吃什么维生素能变黑| 蜻蜓是什么生肖| 条件致病菌是什么意思| 金兰之交是什么意思| 胯骨疼是什么原因| 看男科挂什么门诊| 脱发厉害是什么原因引起的| 为什么总打嗝| 肝岛是什么意思| yuri是什么意思| 电轴不偏是什么意思| 角膜炎滴什么眼药水| 去香港澳门需要什么证件| 牙齿黄是什么原因| 尿为什么是黄色的| 米酒不甜是什么原因| ova什么意思| 北京都有什么大学| 月经期间喝什么比较好| 什么水果含维c最多| 做胃镜之前需要注意什么| 月子里可以吃什么水果| 吃什么药减肥效果好| 杀生电影讲的什么意思| 遂的意思是什么| 为什么有脚气| ms是什么单位| 挑担是什么关系| 媒婆是什么意思| 什么是穿刺手术| arr是什么| 曲马多是什么药| dwi是什么意思| 厚黑学是什么意思| vca是什么意思| 4月份是什么星座| 想当演员考什么学校| 颈椎退行性变是什么意思| 无住生心是什么意思| 情绪波动是什么意思| 妈富隆是什么药| 鲁迅字什么| 精液少是什么原因| 梦见捡金首饰是什么意思| 投其所好是什么意思| 冰清玉洁是什么意思| 氨味是什么味道| 榴莲有什么功效| 喉咙痛有痰吃什么药| 外感风寒是什么意思| 什么是气溶胶| 疟疾病的症状是什么样| 两个立念什么| 88属什么生肖| 男人腿毛多代表什么| 美丽的近义词是什么| 鼻子出汗多是什么原因| 无名指戴戒指什么意思| 肝气郁结喝什么茶| 吃什么雌激素会增多| 什么叫肛瘘| 一什么山泉| 温饱是什么意思| lof是什么基金| 干巴得是什么意思| ct 是什么| 什么声什么气| 今年温度为什么这么高| 心口下面疼是什么原因| 人生百味下一句是什么| 四月份是什么星座| 怀字五行属什么| NT是检查什么的| 怀孕14天有什么症状| 尿道结石有什么症状| circle是什么意思| 月可以加什么偏旁| 西瓜霜是什么| 十月三十号什么星座| 3月25日什么星座| 睡觉打呼噜什么原因| 艺人是什么意思| 梵行是什么意思| 黑茶金花是什么菌| 双规是什么意思| 9月13号是什么星座| 静谧时光什么意思| 攥是什么意思| 什么时候征兵| 做腹腔镜手术后需要注意什么| 吃什么改善睡眠| 云州是现在的什么地方| 发烧一直不退是什么原因| 义眼是什么意思| 尿酸高什么水果不能吃| 精神科主要看什么病| 中耳炎去药店买什么药| 女人梦到地震预示什么| 老师结婚学生送什么礼物好| 喝酒手发抖是什么原因| 三九胃泰治什么胃病效果好| 夏令时是什么| b是什么牌子的衣服| 什么地爬| 生地麦冬汤有什么功效| pd是什么病| 水杯什么材质好| 肾炎是什么原因引起的| 肌电图挂什么科| 男性内分泌失调有什么症状| 肝气郁结吃什么中药| acne是什么意思| 胆囊炎不能吃什么| 手指关节疼痛吃什么药| 耳膜穿孔是什么症状| 脑震荡后眩晕吃什么药| 男士私处用什么清洗| 肾结石喝酒有什么影响| 脸大适合什么发型| 反目成仇是什么意思| 赛博朋克什么意思| 室缺是什么意思| 什么是香油| 过敏性皮肤用什么护肤品比较好| 高血压会引起什么病症| 重庆为什么这么热| 麦芽糊精是什么| 女生小便带血是什么原因| 牙结石有什么危害| 2005年什么年| hc是胎儿的什么| 包皮炎用什么药最有效| 脚心发凉是什么原因| 别人是什么意思| 嗓子痛吃什么消炎药| 吃什么补铁快| 腰疼去医院挂什么科| 86年属虎是什么命| 美尼尔综合症吃什么药| 双抗是什么意思| 肚子疼喝什么能缓解| 胃出血什么症状| 破冰是什么意思| 什么的天空填词语| crocs是什么牌子的鞋| 龟是什么结构| 序五行属什么| 咽炎吃什么| 8月份是什么星座| 一什么方式| 什么米好吃| 丰年虾是什么| 引什么大叫| 好看是什么意思| 全员加速中什么时候播| 生孩子前做什么检查| 支原体是什么病| 武汉市长是什么级别| 酵素什么牌子好| 老鼠长什么样子图片| 12月1日是什么日子| 水鸭跟什么煲汤最佳| 肛瘘是什么意思| 停职是什么意思| 外感发热什么意思| 知我者非你也什么意思| 什么是hr| 树大招风的意思是什么| 百度

泪奔!手机中那些舍不得删除的聊天记录

(Redirected from Program flow)
百度 六是《办法》明确了残疾人服务机构的监督管理要求。

In computer science, control flow (or flow of control) is the order in which individual statements, instructions or function calls of an imperative program are executed or evaluated. The emphasis on explicit control flow distinguishes an imperative programming language from a declarative programming language.

Within an imperative programming language, a control flow statement is a statement that results in a choice being made as to which of two or more paths to follow. For non-strict functional languages, functions and language constructs exist to achieve the same result, but they are usually not termed control flow statements.

A set of statements is in turn generally structured as a block, which in addition to grouping, also defines a lexical scope.

Interrupts and signals are low-level mechanisms that can alter the flow of control in a way similar to a subroutine, but usually occur as a response to some external stimulus or event (that can occur asynchronously), rather than execution of an in-line control flow statement.

At the level of machine language or assembly language, control flow instructions usually work by altering the program counter. For some central processing units (CPUs), the only control flow instructions available are conditional or unconditional branch instructions, also termed jumps. However there is also predication which conditionally enables or disables instructions without branching: as an alternative technique it can have both advantages and disadvantages over branching.

Categories

edit
?
A state diagram of a peptide ion mass mapping search process

The kinds of control flow statements supported by different languages vary, but can be categorized by their effect:

  • Continuation at a different statement (unconditional branch or jump)
  • Executing a set of statements only if some condition is met (choice - i.e., conditional branch)
  • Executing a set of statements zero or more times, until some condition is met (i.e., loop - the same as conditional branch)
  • Executing a set of distant statements, after which the flow of control usually returns (subroutines, coroutines, and continuations)
  • Stopping the program, preventing any further execution (unconditional halt)

Primitives

edit

Labels

edit

A label is an explicit name or number assigned to a fixed position within the source code, and which may be referenced by control flow statements appearing elsewhere in the source code. A label marks a position within source code and has no other effect.

Line numbers are an alternative to a named label used in some languages (such as BASIC). They are whole numbers placed at the start of each line of text in the source code. Languages which use these often impose the constraint that the line numbers must increase in value in each following line, but may not require that they be consecutive. For example, in BASIC:

10 LET X = 3
20 PRINT X

In other languages such as C and Ada, a label is an identifier, usually appearing at the start of a line and immediately followed by a colon. For example, in C:

Success: printf("The operation was successful.\n");

The language ALGOL 60 allowed both whole numbers and identifiers as labels (both linked by colons to the following statement), but few if any other ALGOL variants allowed whole numbers. Early Fortran compilers only allowed whole numbers as labels. Beginning with Fortran-90, alphanumeric labels have also been allowed.

Goto

edit

The goto statement (a combination of the English words go and to, and pronounced accordingly) is the most basic form of unconditional transfer of control.

Although the keyword may either be in upper or lower case depending on the language, it is usually written as:

   goto label

The effect of a goto statement is to cause the next statement to be executed to be the statement appearing at (or immediately after) the indicated label.

Goto statements have been considered harmful by many computer scientists, notably Dijkstra.

Subroutines

edit

The terminology for subroutines varies; they may alternatively be known as routines, procedures, functions (especially if they return results) or methods (especially if they belong to classes or type classes).

In the 1950s, computer memories were very small by current standards so subroutines were used mainly to reduce program size. A piece of code was written once and then used many times from various other places in a program.

Today, subroutines are more often used to help make a program more structured, e.g., by isolating some algorithm or hiding some data access method. If many programmers are working on one program, subroutines are one kind of modularity that can help divide the work.

Sequence

edit

In structured programming, the ordered sequencing of successive commands is considered one of the basic control structures, which is used as a building block for programs alongside iteration, recursion and choice.

Minimal structured control flow

edit

In May 1966, B?hm and Jacopini published an article[1] in Communications of the ACM which showed that any program with gotos could be transformed into a goto-free form involving only choice (IF THEN ELSE) and loops (WHILE condition DO xxx), possibly with duplicated code and/or the addition of Boolean variables (true/false flags). Later authors showed that choice can be replaced by loops (and yet more Boolean variables).

That such minimalism is possible does not mean that it is necessarily desirable; computers theoretically need only one machine instruction (subtract one number from another and branch if the result is negative), but practical computers have dozens or even hundreds of machine instructions.

Other research showed that control structures with one entry and one exit were much easier to understand than any other form,[citation needed] mainly because they could be used anywhere as a statement without disrupting the control flow. In other words, they were composable. (Later developments, such as non-strict programming languages – and more recently, composable software transactions – have continued this strategy, making components of programs even more freely composable.)

Some academics took a purist approach to the B?hm–Jacopini result and argued that even instructions like break and return from the middle of loops are bad practice as they are not needed in the B?hm–Jacopini proof, and thus they advocated that all loops should have a single exit point. This purist approach is embodied in the language Pascal (designed in 1968–1969), which up to the mid-1990s was the preferred tool for teaching introductory programming in academia.[2] The direct application of the B?hm–Jacopini theorem may result in additional local variables being introduced in the structured chart, and may also result in some code duplication.[3] Pascal is affected by both of these problems and according to empirical studies cited by Eric S. Roberts, student programmers had difficulty formulating correct solutions in Pascal for several simple problems, including writing a function for searching an element in an array. A 1980 study by Henry Shapiro cited by Roberts found that using only the Pascal-provided control structures, the correct solution was given by only 20% of the subjects, while no subject wrote incorrect code for this problem if allowed to write a return from the middle of a loop.[2]

Control structures in practice

edit

Most programming languages with control structures have an initial keyword which indicates the type of control structure involved.[clarification needed] Languages then divide as to whether or not control structures have a final keyword.

  • No final keyword: ALGOL 60, C, C++, Go, Haskell, Java, Pascal, Perl, PHP, PL/I, Python, PowerShell. Such languages need some way of grouping statements together:
    • ALGOL 60 and Pascal: begin ... end
    • C, C++, Go, Java, Perl, PHP, and PowerShell: curly brackets { ... }
    • PL/I: DO ... END
    • Python: uses indent level (see Off-side rule)
    • Haskell: either indent level or curly brackets can be used, and they can be freely mixed
    • Lua: uses do ... end
  • Final keyword: Ada, APL, ALGOL 68, Modula-2, Fortran 77, Mythryl, Visual Basic. The forms of the final keyword vary:
    • Ada: final keyword is end + space + initial keyword e.g., if ... end if, loop ... end loop
    • APL: final keyword is :End optionally + initial keyword, e.g., :If ... :End or :If ... :EndIf, Select ... :End or :Select ... :EndSelect, however, if adding an end condition, the end keyword becomes :Until
    • ALGOL 68, Mythryl: initial keyword spelled backwards e.g., if ... fi, case ... esac
    • Fortran 77: final keyword is END + initial keyword e.g., IF ... ENDIF, DO ... ENDDO
    • Modula-2: same final keyword END for everything
    • Visual Basic: every control structure has its own keyword. If ... End If; For ... Next; Do ... Loop; While ... Wend

Choice

edit

If-then-(else) statements

edit

Conditional expressions and conditional constructs are features of a programming language that perform different computations or actions depending on whether a programmer-specified Boolean condition evaluates to true or false.

  • IF..GOTO. A form found in unstructured languages, mimicking a typical machine code instruction, would jump to (GOTO) a label or line number when the condition was met.
  • IF..THEN..(ENDIF). Rather than being restricted to a jump, any simple statement, or nested block, could follow the THEN key keyword. This a structured form.
  • IF..THEN..ELSE..(ENDIF). As above, but with a second action to be performed if the condition is false. This is one of the most common forms, with many variations. Some require a terminal ENDIF, others do not. C and related languages do not require a terminal keyword, or a 'then', but do require parentheses around the condition.
  • Conditional statements can be and often are nested inside other conditional statements. Some languages allow ELSE and IF to be combined into ELSEIF, avoiding the need to have a series of ENDIF or other final statements at the end of a compound statement.
Pascal: Ada:
if a > 0 then
  writeln("yes")
else
  writeln("no");
if a > 0 then
      Put_Line("yes");
else
      Put_Line("no");
end if;
C: Shell script:
if (a > 0) { 
    puts("yes");
}
else {
    puts("no");
}
if [ $a -gt 0 ]; then
      echo "yes"
else
      echo "no"
fi
Python: Lisp:
if a > 0: 
    print("yes")
else:
    print("no")
(princ
  (if (plusp a)
      "yes"
      "no"))

Less common variations include:

  • Some languages, such as early Fortran,[a] have a three-way or arithmetic if, testing whether a numeric value is negative, zero, or positive.
  • Some languages have a functional form of an if statement, for instance Lisp's cond.
  • Some languages have an operator form of an if statement, such as C's ternary operator.
  • Perl supplements a C-style if with when and unless.
  • Smalltalk uses ifTrue and ifFalse messages to implement conditionals, rather than any fundamental language construct.

Case and switch statements

edit

Switch statements (or case statements, or multiway branches) compare a given value with specified constants and take action according to the first constant to match. There is usually a provision for a default action ("else", "otherwise") to be taken if no match succeeds. Switch statements can allow compiler optimizations, such as lookup tables. In dynamic languages, the cases may not be limited to constant expressions, and might extend to pattern matching, as in the shell script example on the right, where the *) implements the default case as a glob matching any string. Case logic can also be implemented in functional form, as in SQL's decode statement.

Pascal: Ada:
case someChar of
  'a': actionOnA;
  'x': actionOnX;
  'y','z':actionOnYandZ;
  else actionOnNoMatch;
end;
case someChar is
  when 'a' => actionOnA;
  when 'x' => actionOnX;
  when 'y' | 'z' => actionOnYandZ;
  when others => actionOnNoMatch;
end;
C: Shell script:
switch (someChar) {
  case 'a': actionOnA; break;
  case 'x': actionOnX; break;
  case 'y':
  case 'z': actionOnYandZ; break;
  default: actionOnNoMatch;
}
case $someChar in 
   a)    actionOnA ;;
   x)    actionOnX ;;
   [yz]) actionOnYandZ ;;
   *)    actionOnNoMatch  ;;
esac
Lisp: Fortran:
(case some-char
  ((#\a)     action-on-a)
  ((#\x)     action-on-x)
  ((#\y #\z) action-on-y-and-z)
  (else      action-on-no-match))
select case (someChar)
  case ('a')
    actionOnA
  case ('x')
    actionOnX
  case ('y','z')
    actionOnYandZ
  case default
    actionOnNoMatch
end select

Loops

edit

A loop is a sequence of statements which is specified once but which may be carried out several times in succession. The code "inside" the loop (the body of the loop, shown below as xxx) is obeyed a specified number of times, or once for each of a collection of items (both cases of definite iteration), or until some condition is met (indefinite iteration), or infinitely. When one of those items is itself also a loop, it is called a "nested loop".[4][5][6]

Some common situations are not well-handled by these basic control structures, and are generally addressed by early exit from the loop, in the form of a break from the loop, a return from the function, or an exception being raised.[7][2]

In functional programming languages, such as Haskell and Scheme, both recursive and iterative processes are expressed with tail recursive procedures instead of looping constructs that are syntactic.

Count-controlled loops

edit

Most programming languages have constructions for repeating a loop a certain number of times. In most cases counting can go downwards instead of upwards and step sizes other than 1 can be used.

 FOR I = 1 TO N
    xxx
 NEXT I
for I?:= 1 to N do begin
   xxx
end;
 DO I = 1,N
     xxx
 END DO
for ( I=1; I<=N; ++I ) {
    xxx
}

In these examples, if N < 1 then the body of loop may execute once (with I having value 1) or not at all, depending on the programming language.

In many programming languages, only integers can be reliably used in a count-controlled loop. Floating-point numbers are represented imprecisely due to hardware constraints, so a loop such as

   for X?:= 0.1 step 0.1 to 1.0 do

might be repeated 9 or 10 times, depending on rounding errors and/or the hardware and/or the compiler version. Furthermore, if the increment of X occurs by repeated addition, accumulated rounding errors may mean that the value of X in each iteration can differ quite significantly from the expected sequence 0.1, 0.2, 0.3, ..., 1.0.

Condition-controlled loops

edit

Most programming languages have constructions for repeating a loop until some condition changes. Some variations test the condition at the start of the loop; others test it at the end. If the test is at the start, the body may be skipped completely; if it is at the end, the body is always executed at least once.

DO WHILE (test)
    xxx
LOOP
repeat
    xxx
until test;
while (test) {
    xxx
}
do
    xxx
while (test);

A control break is a value change detection method used within ordinary loops to trigger processing for groups of values. Values are monitored within the loop and a change diverts program flow to the handling of the group event associated with them.

   DO UNTIL (End-of-File)
      IF new-zipcode <> current-zipcode
         display_tally(current-zipcode, zipcount)
         
         current-zipcode = new-zipcode
         zipcount = 0
      ENDIF
      
      zipcount++
   LOOP

Collection-controlled loops

edit

Several programming languages (e.g., Ada, APL, D, C++11, Smalltalk, PHP, Perl, Object Pascal, Java, C#, MATLAB, Visual Basic, Ruby, Python, JavaScript, Fortran 95 and later) have special constructs which allow implicit looping through all elements of an array, or all members of a set or collection.

   someCollection do: [:eachElement |xxx]. "Smalltalk"

   for Item in Collection do begin xxx end;

   foreach (item; myCollection) { xxx }

   foreach someArray { xxx }

   foreach ($someArray as $k => $v) { xxx } # PHP

   Collection<String> coll; for (String s?: coll) {}

   foreach (string s in myStringCollection) { xxx }

   someCollection | foreach { $_ } # Powershell: 'foreach' and '%' are the alias of 'ForEach-Object'

   forall ( index = first:last:step... )

Scala has for-expressions, which generalise collection-controlled loops, and also support other uses, such as asynchronous programming. Haskell has do-expressions and comprehensions, which together provide similar function to for-expressions in Scala.

General iteration

edit

General iteration constructs such as C's for statement and Common Lisp's do form can be used to express any of the above sorts of loops, and others, such as looping over some number of collections in parallel. Where a more specific looping construct can be used, it is usually preferred over the general iteration construct, since it often makes the purpose of the expression clearer.

Infinite loops

edit

Infinite loops are used to assure a program segment loops forever or until an exceptional condition arises, such as an error. For instance, an event-driven program (such as a server) should loop forever, handling events as they occur, only stopping when the process is terminated by an operator.

Infinite loops can be implemented using other control flow constructs. Most commonly, in unstructured programming this is jump back up (goto), while in structured programming this is an indefinite loop (while loop) set to never end, either by omitting the condition or explicitly setting it to true, as while (true) .... Some languages have special constructs for infinite loops, typically by omitting the condition from an indefinite loop. Examples include Ada (loop ... end loop),[8] Fortran (DO ... END DO), Go (for { ... }), and Ruby (loop do ... end).

Often, an infinite loop is unintentionally created by a programming error in a condition-controlled loop, wherein the loop condition uses variables that never change within the loop.

Continuation with next iteration

edit

Sometimes within the body of a loop there is a desire to skip the remainder of the loop body and continue with the next iteration of the loop. Some languages provide a statement such as continue (most languages), skip,[9] cycle (Fortran), or next (Perl and Ruby), which will do this. The effect is to prematurely terminate the innermost loop body and then resume as normal with the next iteration. If the iteration is the last one in the loop, the effect is to terminate the entire loop early.

Redo current iteration

edit

Some languages, like Perl[10] and Ruby,[11] have a redo statement that restarts the current iteration from the start.

Restart loop

edit

Ruby has a retry statement that restarts the entire loop from the initial iteration.[12]

Loop-and-a-half

edit

Common loop structures sometimes result in duplicated code, either repeated statements or repeated conditions. This arises for various reasons and has various proposed solutions to eliminate or minimize code duplication.[13] Other than the traditional unstructured solution of a goto statement,[14] general structured solutions include having a conditional (if statement) inside the loop (possibly duplicating the condition but not the statements) or wrapping repeated logic in a function (so there is a duplicated function call, but the statements are not duplicated).[13]

A common case is where the start of the loop is always executed, but the end may be skipped on the last iteration.[14] This was dubbed by Dijkstra a loop which is performed "n and a half times",[15] and is now called the loop-and-a-half problem.[2] Common cases include reading data in the first part, checking for end of data, and then processing the data in the second part; or processing, checking for end, and then preparing for the next iteration.[14][2] In these cases, the first part of the loop is executed ??? times, but the second part is only executed ??? times.

This problem has been recognized at least since 1967 by Knuth, with Wirth suggesting solving it via early loop exit.[16] Since the 1990s this has been the most commonly taught solution, using a break statement, as in:[2]


loop
    statements
    if condition break
    statements
repeat

A subtlety of this solution is that the condition is the opposite of a usual while condition: rewriting while condition ... repeat with an exit in the middle requires reversing the condition: loop ... if not condition exit ... repeat. The loop with test in the middle control structure explicitly supports the loop-an-a-half use case, without reversing the condition.[16]

Early exit from loops

edit

It is sometimes desirable to stop executing a loop before the end of the body; for example, when using a count-controlled loop to search through a table, one can stop as soon as the required item is found. Early exit is the most common way to solve the loop-and-a-half problem.[2]


Some programming languages provide a statement such as break (most languages), Exit (Visual Basic), or last (Perl), which effect is to terminate the current loop immediately, and transfer control to the statement immediately after that loop.

Other mechanisms for early exit include a return out of a subroutine executing the looped statements, breaking out of both the loop and the subroutine; and raising an exception. There are other proposed control structures, but they are not commonly implemented. This section treats early exit from only the loop ("break").

Most commonly, this is used by combining a conditional (if statement) with an unconditional break, as in Ada:

loop
    Get(X);
    if X = 0 then
        exit;
    end if;
    -- Do something with X.
end loop;

In this form, the condition is interpreted as until. Some languages, such as Ada, have syntax for a conditional break, here an exit when clause (not to be confused with the exitwhen statement in §?Proposed control structures); if available, this is more idiomatic:

loop
    Get(X);
    exit when X = 0;
    -- Do something with X.
end loop;

This functions similarly to a loop with test in the middle, but in that case the test is part of the structure of the loop, dividing the body of the loop in half (visually indented at the same level as the start/end of loop), while early exit is unstructured: simply a statement that can appear anywhere in the body of the loop, and in fact multiple break statements are possible.

Python supports conditional execution of code depending on whether a loop was exited early (with a break statement) or not by using an else-clause with the loop. For example,

for n in set_of_numbers:
    if isprime(n):
        print("Set contains a prime number")
        break
else:
    print("Set did not contain any prime numbers")

The else clause in the above example is linked to the for statement, and not the inner if statement. Both Python's for and while loops support such an else clause, which is executed only if early exit of the loop has not occurred.

Multi-level breaks

edit

Some languages support breaking out of nested loops; in theory circles, these are called multi-level breaks. One common use example is searching a multi-dimensional table. This can be done either via multilevel breaks (break out of N levels), as in bash[17] and PHP,[18] or via labeled breaks (break out and continue at given label), as in Ada. Go, Java and Perl.[19] Alternatives to multilevel breaks include single breaks, together with a state variable which is tested to break out another level; exceptions, which are caught at the level being broken out to; placing the nested loops in a function and using return to effect termination of the entire nested loop; or using a label and a goto statement. C does not include a multilevel break, and the usual alternative is to use a goto to implement a labeled break.[20] Python does not have a multilevel break or continue – this was proposed in PEP 3136, and rejected on the basis that the added complexity was not worth the rare legitimate use.[21]

The notion of multi-level breaks is of some interest in theoretical computer science, because it gives rise to what is today called the Kosaraju hierarchy.[22] In 1973 S. Rao Kosaraju refined the structured program theorem by proving that it is possible to avoid adding additional variables in structured programming, as long as arbitrary-depth, multi-level breaks from loops are allowed.[23] Furthermore, Kosaraju proved that a strict hierarchy of programs exists: for every integer n, there exists a program containing a multi-level break of depth n that cannot be rewritten as a program with multi-level breaks of depth less than n without introducing added variables.[22]

In his 2004 textbook, David Watt uses Tennent's notion of sequencer to explain the similarity between multi-level breaks and return statements. Watt notes that a class of sequencers known as escape sequencers, defined as "sequencer that terminates execution of a textually enclosing command or procedure", encompasses both breaks from loops (including multi-level breaks) and return statements. As commonly implemented, however, return sequencers may also carry a (return) value, whereas the break sequencer as implemented in contemporary languages usually cannot.[24]

Loop with test in the middle

edit

The following structure was proposed by Dahl in 1972:[25]

   loop                           loop
       xxx1                           read(char);
   while test;                    while not atEndOfFile;
       xxx2                           write(char);
   repeat;                        repeat;

The construction here can be thought of as a do loop with the while check in the middle, which allows clear loop-and-a-half logic. Further, by omitting individual components, this single construction can replace several constructions in most programming languages. If xxx1 is omitted, we get a loop with the test at the top (a traditional while loop). If xxx2 is omitted, we get a loop with the test at the bottom, equivalent to a do while loop in many languages. If while is omitted, we get an infinite loop. This construction also allows keeping the same polarity of the condition even when in the middle, unlike early exit, which requires reversing the polarity (adding a not),[16] functioning as until instead of while.

This structure is not widely supported, with most languages instead using if ... break for conditional early exit.

This is supported by some languages, such as Forth, where the syntax is BEGIN ... WHILE ... REPEAT,[26] and the shell script languages Bourne shell (sh) and bash, where the syntax is while ... do ... done or until ... do ... done, as:[27][28]

while
  statement-1
  statement-2
  ...
  condition
do
  statement-a
  statement-b
  ...
done

The shell syntax works because the while (or until) loop accepts a list of commands as a condition,[29] formally:

 while test-commands; do consequent-commands; done

The value (exit status) of the list of test-commands is the value of the last command, and these can be separated by newlines, resulting in the idiomatic form above.

Similar constructions are possible in C and C++ with the comma operator, and other languages with similar constructs, which allow shoehorning a list of statements into the while condition:

while (
  statement_1,
  statement_2,
  condition
) {
  statement_a;
  statement_b;
}

While legal, this is marginal, and it is primarily used, if at all, only for short modify-then-test cases, as in:[30]

while (read_string(s), strlen(s) > 0) {
  // ...
}

Loop variants and invariants

edit

Loop variants and loop invariants are used to express correctness of loops.[31]

In practical terms, a loop variant is an integer expression which has an initial non-negative value. The variant's value must decrease during each loop iteration but must never become negative during the correct execution of the loop. Loop variants are used to guarantee that loops will terminate.

A loop invariant is an assertion which must be true before the first loop iteration and remain true after each iteration. This implies that when a loop terminates correctly, both the exit condition and the loop invariant are satisfied. Loop invariants are used to monitor specific properties of a loop during successive iterations.

Some programming languages, such as Eiffel contain native support for loop variants and invariants. In other cases, support is an add-on, such as the Java Modeling Language's specification for loop statements in Java.

Loop sublanguage

edit

Some Lisp dialects provide an extensive sublanguage for describing Loops. An early example can be found in Conversional Lisp of Interlisp. Common Lisp[32] provides a Loop macro which implements such a sublanguage.

Loop system cross-reference table

edit
Programming language conditional loop early exit loop continuation redo retry correctness facilities
begin middle end count collection general infinite [1] variant invariant
Ada Yes Yes Yes Yes arrays No Yes deep nested No
APL Yes No Yes Yes Yes Yes Yes deep nested [3] Yes No No
C Yes No Yes No [2] No Yes No deep nested [3] deep nested [3] No
C++ Yes No Yes No [2] Yes [9] Yes No deep nested [3] deep nested [3] No
C# Yes No Yes No [2] Yes Yes No deep nested [3] deep nested [3]
COBOL Yes No Yes Yes No Yes No deep nested [15] deep nested [14] No
Common Lisp Yes Yes Yes Yes builtin only [16] Yes Yes deep nested No
D Yes No Yes Yes Yes Yes Yes[14] deep nested deep nested No
Eiffel Yes No No Yes [10] Yes Yes No one level [10] No No No [11] integer only [13] Yes
F# Yes No No Yes Yes No No No [6] No No
FORTRAN 77 Yes No No Yes No No No one level Yes No No
Fortran 90 Yes No No Yes No No Yes deep nested deep nested No No
Fortran 95 and later Yes No No Yes arrays No Yes deep nested deep nested No No
Go Yes No No Yes builtin only Yes Yes deep nested deep nested No
Haskell No No No No Yes No Yes No [6] No No
Java Yes No Yes No [2] Yes Yes No deep nested deep nested No non-native [12] non-native [12]
JavaScript Yes No Yes No [2] Yes Yes No deep nested deep nested No
Natural Yes Yes Yes Yes No Yes Yes Yes Yes Yes No
OCaml Yes No No Yes arrays,lists No No No [6] No No
PHP Yes No Yes No [2] [5] Yes [4] Yes No deep nested deep nested No
Perl Yes No Yes No [2] [5] Yes Yes No deep nested deep nested Yes
Python Yes No No No [5] Yes No No deep nested [6] deep nested [6] No
Rebol No [7] Yes Yes Yes Yes No [8] Yes one level [6] No No
Ruby Yes No Yes Yes Yes No Yes deep nested [6] deep nested [6] Yes Yes
Standard ML Yes No No No arrays,lists No No No [6] No No
Visual Basic .NET Yes No Yes Yes Yes No Yes one level per type of loop one level per type of loop
PowerShell Yes No Yes No [2] Yes Yes No Yes Yes
  1. a while (true) does not count as an infinite loop for this purpose, because it is not a dedicated language structure.
  2. a b c d e f g h C's for (init; test; increment) loop is a general loop construct, not specifically a counting one, although it is often used for that.
  3. a b c Deep breaks may be accomplished in APL, C, C++ and C# through the use of labels and gotos.
  4. a Iteration over objects was added in PHP 5.
  5. a b c A counting loop can be simulated by iterating over an incrementing list or generator, for instance, Python's range().
  6. a b c d e Deep breaks may be accomplished through the use of exception handling.
  7. a There is no special construct, since the while function can be used for this.
  8. a There is no special construct, but users can define general loop functions.
  9. a The C++11 standard introduced the range-based for. In the STL, there is a std::for_each template function which can iterate on STL containers and call a unary function for each element.[33] The functionality also can be constructed as macro on these containers.[34]
  10. a Count-controlled looping is effected by iteration across an integer interval; early exit by including an additional condition for exit.
  11. a Eiffel supports a reserved word retry, however it is used in exception handling, not loop control.
  12. a Requires Java Modeling Language (JML) behavioral interface specification language.
  13. a Requires loop variants to be integers; transfinite variants are not supported. Eiffel: Why loop variants are integers
  14. a D supports infinite collections, and the ability to iterate over those collections. This does not require any special construct.
  15. a Deep breaks can be achieved using GO TO and procedures.
  16. a Common Lisp predates the concept of generic collection type.

Structured non-local control flow

edit

Many programming languages, especially those favoring more dynamic styles of programming, offer constructs for non-local control flow. These cause the flow of execution to jump out of a given context and resume at some predeclared point. Conditions, exceptions and continuations are three common sorts of non-local control constructs; more exotic ones also exist, such as generators, coroutines and the async keyword.

Conditions

edit

The earliest Fortran compilers had statements for testing exceptional conditions. These included the IF ACCUMULATOR OVERFLOW, IF QUOTIENT OVERFLOW, and IF DIVIDE CHECK statements. In the interest of machine independence, they were not included in FORTRAN IV and the Fortran 66 Standard. However since Fortran 2003 it is possible to test for numerical issues via calls to functions in the IEEE_EXCEPTIONS module.

PL/I has some 22 standard conditions (e.g., ZERODIVIDE SUBSCRIPTRANGE ENDFILE) which can be raised and which can be intercepted by: ON condition action; Programmers can also define and use their own named conditions.

Like the unstructured if, only one statement can be specified so in many cases a GOTO is needed to decide where flow of control should resume.

Unfortunately, some implementations had a substantial overhead in both space and time (especially SUBSCRIPTRANGE), so many programmers tried to avoid using conditions.

Common Syntax examples:

 ON condition GOTO label

Exceptions

edit

Modern languages have a specialized structured construct for exception handling which does not rely on the use of GOTO or (multi-level) breaks or returns. For example, in C++ one can write:

try {
    xxx1                                  // Somewhere in here
    xxx2                                  //     use: '''throw''' someValue;
    xxx3
} catch (someClass& someId) {             // catch value of someClass
    actionForSomeClass 
} catch (someType& anotherId) {           // catch value of someType
    actionForSomeType
} catch (...) {                           // catch anything not already caught
    actionForAnythingElse
}

Any number and variety of catch clauses can be used above. If there is no catch matching a particular throw, control percolates back through subroutine calls and/or nested blocks until a matching catch is found or until the end of the main program is reached, at which point the program is forcibly stopped with a suitable error message.

Via C++'s influence, catch is the keyword reserved for declaring a pattern-matching exception handler in other languages popular today, like Java or C#. Some other languages like Ada use the keyword exception to introduce an exception handler and then may even employ a different keyword (when in Ada) for the pattern matching. A few languages like AppleScript incorporate placeholders in the exception handler syntax to automatically extract several pieces of information when the exception occurs. This approach is exemplified below by the on error construct from AppleScript:

try
    set myNumber to myNumber / 0
on error e  number n  from f  to t  partial result pr
    if ( e = "Can't divide by zero" ) then display dialog "You must not do that"
end try

David Watt's 2004 textbook also analyzes exception handling in the framework of sequencers (introduced in this article in the section on early exits from loops). Watt notes that an abnormal situation, generally exemplified with arithmetic overflows or input/output failures like file not found, is a kind of error that "is detected in some low-level program unit, but [for which] a handler is more naturally located in a high-level program unit". For example, a program might contain several calls to read files, but the action to perform when a file is not found depends on the meaning (purpose) of the file in question to the program and thus a handling routine for this abnormal situation cannot be located in low-level system code. Watts further notes that introducing status flags testing in the caller, as single-exit structured programming or even (multi-exit) return sequencers would entail, results in a situation where "the application code tends to get cluttered by tests of status flags" and that "the programmer might forgetfully or lazily omit to test a status flag. In fact, abnormal situations represented by status flags are by default ignored!" Watt notes that in contrast to status flags testing, exceptions have the opposite default behavior, causing the program to terminate unless the program deals with the exception explicitly in some way, possibly by adding explicit code to ignore it. Based on these arguments, Watt concludes that jump sequencers or escape sequencers are less suitable as a dedicated exception sequencer with the semantics discussed above.[35]

In Object Pascal, D, Java, C#, and Python a finally clause can be added to the try construct. No matter how control leaves the try the code inside the finally clause is guaranteed to execute. This is useful when writing code that must relinquish an expensive resource (such as an opened file or a database connection) when finished processing:

FileStream stm = null;                    // C# example
try
{
    stm = new FileStream("logfile.txt", FileMode.Create);
    return ProcessStuff(stm);             // may throw an exception
} 
finally
{
    if (stm != null)
        stm.Close();
}

Since this pattern is fairly common, C# has a special syntax:

using (var stm = new FileStream("logfile.txt", FileMode.Create))
{
    return ProcessStuff(stm); // may throw an exception
}

Upon leaving the using-block, the compiler guarantees that the stm object is released, effectively binding the variable to the file stream while abstracting from the side effects of initializing and releasing the file. Python's with statement and Ruby's block argument to File.open are used to similar effect.

All the languages mentioned above define standard exceptions and the circumstances under which they are thrown. Users can throw exceptions of their own; C++ allows users to throw and catch almost any type, including basic types like int, whereas other languages like Java are less permissive.

Continuations

edit

Async

edit

C# 5.0 introduced the async keyword for supporting asynchronous I/O in a "direct style".

Generators

edit

Generators, also known as semicoroutines, allow control to be yielded to a consumer method temporarily, typically using a yield keyword (yield description) . Like the async keyword, this supports programming in a "direct style".

Coroutines

edit

Coroutines are functions that can yield control to each other - a form of co-operative multitasking without threads.

Coroutines can be implemented as a library if the programming language provides either continuations or generators - so the distinction between coroutines and generators in practice is a technical detail.

Non-local control flow cross reference

edit
Programming language conditions exceptions generators/coroutines async
Ada No Yes ? ?
APL No Yes No No
C No No No No
C++ No Yes Yes ?
C# No Yes Yes Yes
COBOL Yes Yes No No
Common Lisp Yes No ? ?
D No Yes Yes ?
Eiffel No Yes ? ?
Erlang No Yes Yes ?
F# No Yes Yes Yes
Go No Yes Yes ?
Haskell No Yes Yes No
Java No Yes No No
JavaScript ? Yes Yes Yes
Objective-C No Yes No ?
PHP No Yes Yes ?
PL/I Yes No No No
Python No Yes Yes Yes[36]
Rebol Yes Yes No ?
Ruby No Yes Yes via extension[37]
Rust No Yes experimental [38][39] Yes[40]
Scala No Yes via experimental extension[41] via experimental extension
Tcl via traces Yes Yes via event loop
Visual Basic .NET Yes Yes No ?
PowerShell No Yes No ?

Proposed control structures

edit

COMEFROM

edit

In a spoof Datamation article[42] in 1973, R. Lawrence Clark suggested that the GOTO statement could be replaced by the COMEFROM statement, and provides some entertaining examples. COMEFROM was implemented in one esoteric programming language named INTERCAL.

Event-based early exit from nested loops

edit

This construct was proposed by Zahn in 1974,[43] and discussed in Knuth (1974). A modified version is presented here.

   exitwhen EventA or EventB or EventC;
       xxx
   exits
       EventA: actionA
       EventB: actionB
       EventC: actionC
   endexit;

exitwhen is used to specify the events which may occur within xxx, their occurrence is indicated by using the name of the event as a statement. When some event does occur, the relevant action is carried out, and then control passes just after endexit. This construction provides a very clear separation between determining that some situation applies, and the action to be taken for that situation.

exitwhen is conceptually similar to exception handling, and exceptions or similar constructs are used for this purpose in many languages.

The following simple example involves searching a two-dimensional table for a particular item.

   exitwhen found or missing;
       for I?:= 1 to N do
           for J?:= 1 to M do
               if table[I,J] = target then found;
       missing;
   exits
       found:   print ("item is in table");
       missing: print ("item is not in table");
   endexit;

Security

edit

One way to attack a piece of software is to redirect the flow of execution of a program. A variety of control-flow integrity techniques, including stack canaries, buffer overflow protection, shadow stacks, and vtable pointer verification, are used to defend against these attacks.[44][45][46]

See also

edit

Notes

edit
  1. ^ In Fortran, this statement was deemed obsolescent in Fortran-90, and deleted as of Fortran 2018.

References

edit
  1. ^ B?hm, Jacopini. "Flow diagrams, turing machines and languages with only two formation rules" Comm. ACM, 9(5):366-371, May 1966.
  2. ^ a b c d e f g Roberts, E. [1995] "Loop Exits and Structured Programming: Reopening the Debate Archived 2025-08-14 at the Wayback Machine," ACM SIGCSE Bulletin, (27)1: 268–272.
  3. ^ David Anthony Watt; William Findlay (2004). Programming language design concepts. John Wiley & Sons. p.?228. ISBN?978-0-470-85320-7.
  4. ^ "Nested Loops in C with Examples". GeeksforGeeks. 2025-08-14. Retrieved 2025-08-14.
  5. ^ "Python Nested Loops". www.w3schools.com. Retrieved 2025-08-14.
  6. ^ Dean, Jenna (2025-08-14). "Nested Loops". The Startup. Retrieved 2025-08-14.
  7. ^ Knuth, Donald E. (1974). "Structured Programming with go to Statements". Computing Surveys. 6 (4): 261–301. CiteSeerX?10.1.1.103.6084. doi:10.1145/356635.356640. S2CID?207630080.
  8. ^ Ada Programming: Control: Endless Loop
  9. ^ "What is a loop and how we can use them?". Archived from the original on 2025-08-14. Retrieved 2025-08-14.
  10. ^ "redo - perldoc.perl.org". perldoc.perl.org. Retrieved 2025-08-14.
  11. ^ "control_expressions - Documentation for Ruby 2.4.0". docs.ruby-lang.org. Retrieved 2025-08-14.
  12. ^ "control_expressions - Documentation for Ruby 2.3.0". docs.ruby-lang.org. Retrieved 2025-08-14.
  13. ^ a b "Messy Loop Conditions". WikiWikiWeb. 2025-08-14.
  14. ^ a b c Knuth 1974, p.?278, Simple Iterations.
  15. ^ Edsger W. Dijkstra, personal communication to Donald Knuth on 2025-08-14, cited in Knuth (1974, p.?278, Simple Iterations)
  16. ^ a b c Knuth 1974, p.?279.
  17. ^ Advanced Bash Scripting Guide: 11.3. Loop Control
  18. ^ PHP Manual: "break"
  19. ^ perldoc: last
  20. ^ comp.lang.c FAQ list · "Question 20.20b"
  21. ^ [Python-3000] Announcing PEP 3136, Guido van Rossum
  22. ^ a b Kozen, Dexter (2008). "The B?hm–Jacopini Theorem is False, Propositionally". Mathematics of Program Construction (PDF). Lecture Notes in Computer Science. Vol.?5133. pp.?177–192. CiteSeerX?10.1.1.218.9241. doi:10.1007/978-3-540-70594-9_11. ISBN?978-3-540-70593-2.
  23. ^ Kosaraju, S. Rao. "Analysis of structured programs," Proc. Fifth Annual ACM Syrup. Theory of Computing, (May 1973), 240-252; also in J. Computer and System Sciences, 9, 3 (December 1974), cited by Knuth (1974).
  24. ^ David Anthony Watt; William Findlay (2004). Programming language design concepts. John Wiley & Sons. pp.?215–221. ISBN?978-0-470-85320-7.
  25. ^ Dahl & Dijkstra & Hoare, "Structured Programming" Academic Press, 1972.
  26. ^ "6. Throw It For a Loop".
  27. ^ "3.2.5.1 Looping Constructs", The GNU Bash Reference Manual, 2025-08-14
  28. ^ "How could a language make the loop-and-a-half less error-prone?". Stack Exchange: Programming Language Design and Implementation.
  29. ^ "3.2.4 Lists of Commands", The GNU Bash Reference Manual, 2025-08-14
  30. ^ "What does the comma operator , do?". Stack Overflow.
  31. ^ Meyer, Bertrand (1991). Eiffel: The Language. Prentice Hall. pp.?129–131.
  32. ^ "Common Lisp LOOP macro".
  33. ^ for_each. Sgi.com. Retrieved on 2025-08-14.
  34. ^ Chapter 1. Boost.Foreach Archived 2025-08-14 at the Wayback Machine. Boost-sandbox.sourceforge.net (2025-08-14). Retrieved on 2025-08-14.
  35. ^ David Anthony Watt; William Findlay (2004). Programming language design concepts. John Wiley & Sons. pp.?221–222. ISBN?978-0-470-85320-7.
  36. ^ "asyncio — Asynchronous I/O". Python documentation.
  37. ^ "Socketry/Async". GitHub. 25 February 2022.
  38. ^ "generators - The Rust Unstable Book". doc.rust-lang.org.
  39. ^ "corona - Rust". docs.rs.
  40. ^ "Introduction - Asynchronous Programming in Rust". rust-lang.github.io.
  41. ^ "Jitsi Meet". Storm-enroute.com. Retrieved 2025-08-14.
  42. ^ We don't know where to GOTO if we don't know where we've COME FROM. This (spoof) linguistic innovation lives up to all expectations. Archived 2025-08-14 at the Wayback Machine By R. Lawrence Clark* From Datamation, December, 1973
  43. ^ Zahn, C. T. "A control statement for natural top-down structured programming" presented at Symposium on Programming Languages, Paris, 1974.
  44. ^ Payer, Mathias; Kuznetsov, Volodymyr. "On differences between the CFI, CPS, and CPI properties". nebelwelt.net. Retrieved 2025-08-14.
  45. ^ "Adobe Flash Bug Discovery Leads To New Attack Mitigation Method". Dark Reading. 10 November 2015. Retrieved 2025-08-14.
  46. ^ Endgame. "Endgame to Present at Black Hat USA 2016". www.prnewswire.com (Press release). Retrieved 2025-08-14.

Further reading

edit
  • Hoare, C. A. R. "Partition: Algorithm 63," "Quicksort: Algorithm 64," and "Find: Algorithm 65." Comm. ACM 4, 321–322, 1961.
edit
半夏反什么药 小孩便秘吃什么药 知柏地黄丸治什么病 梦见粽子是什么预兆 睡美人叫什么名字
儿童用什么洗发水好 属鸡的适合干什么行业最赚钱 诅咒是什么意思 石斛长什么样子图片 早上出虚汗是什么原因
胃火喝什么茶降火 循序渐进是什么意思 鸡属于什么类动物 dodo是什么意思 尼维达手表什么档次
炝锅是什么意思 种牙是什么意思 小鸡吃什么食物 伊索寓言有什么故事 什么成什么就
前列腺ca是什么意思hcv9jop7ns3r.cn 品鉴是什么意思hcv9jop5ns8r.cn 至死不渝什么意思hcv9jop5ns2r.cn 指疣是什么病hcv9jop2ns8r.cn 梦见梳头发是什么意思hcv8jop0ns3r.cn
78属什么生肖hcv8jop1ns7r.cn 犀利哥什么意思hcv8jop6ns4r.cn igm是什么意思hkuteam.com 疱疹是什么hcv8jop8ns8r.cn 脚趾头麻木是什么原因引起的hcv7jop5ns1r.cn
寅时是什么时间hcv8jop4ns8r.cn 什么叫强直性脊柱炎hcv9jop2ns7r.cn 熟普属于什么茶hcv9jop2ns7r.cn 17592a是什么尺码男装hcv8jop2ns7r.cn 淘米水洗脸有什么好处hcv9jop4ns1r.cn
喉咙里的小肉球叫什么hcv9jop3ns6r.cn 勃艮第红是什么颜色hcv8jop9ns5r.cn 生理期能吃什么水果hcv8jop4ns4r.cn 左侧卵巢囊性回声是什么意思hcv9jop0ns0r.cn 那敢情好是什么意思hcv9jop7ns0r.cn
百度