Mar. 07, 2024
Mechanical Parts & Fabrication Services
Flow control is an integral part of all industries, such as in chemical plants, power stations, food factories, dyeing and finishing plants, or other factories, flow control is an essential part of process control. Flow controls meanings to control of the flow rate of the medium in an adjustable range according to the process requirements. For example, flow control may be utilized in the chemical industry to manage the flow of liquids between tanks or reactors during the manufacturing process. In an oil and gas plant, flow control may be used to control the flow of fluids through pipelines or to measure the amount of oil or gas being extracted.
Usually, this function is required flow control valves, which regulate the capacity of the fluid or gas in the pipeline and ensure smooth and safe operation. In this article, we will explore the different types of flow control valves, their applications, and the common problems associated with their use.
Flow control valves play a key role in regulating the flow of fluids and gases through pipelines, and if you walk into a plant, you can find flow control valves everywhere in the equipment, and they ensure that processes run efficiently and safely. Flow control valves can be found in a variety of industries such as textile mills, water treatment plants, chemical plants, refineries, and power plants. These valves offer several benefits, including improved process efficiency, precise control, reduced energy consumption, and enhanced safety measures.
control valves in food and beverage applicationGlobe valves are used for regulating fluid flow and can be found in various configurations, such as on/off globe control valves, single-seated globe control valves, double-seated control globe valves, 3-way globe control valves, and y-type globe valves.
three-way control valvesBall valves offer excellent shut-off capabilities and are commonly used in applications where tight sealing is required.
ball valve animationButterfly valves are designed for controlling the flow of fluids in pipelines and are known for their compact design and ease of operation.
butterfly valve gifCheck valves prevent fluid flow in the reverse direction, ensuring that processes run smoothly and efficiently.
api check valveARVs protect pumps from damage by maintaining a minimum flow rate even when the demand for fluid decreases.
Diaphragm valves use a flexible diaphragm to control fluid flow, making them suitable for use in sanitary applications or with abrasive and corrosive materials.
Pinch valves are designed to control the flow of fluids or gases in pipelines by pinching a flexible tube or sleeve. They are often used in industries such as wastewater treatment, mining, and food processing.
Pressure reducing valves regulate the pressure of a fluid or gas by reducing it to a specific set point.
Valves such as pneumatic angle type control valves and electric temperature control valves are equipped with actuators to enable remote or automated control of fluid flow.
Flow control valves are used in various industries and applications, including:
To select the right flow control valve for your applications, we need to consider many processing parameters, which include type of fluid or gas, operation temperature, operation pressure, desired flow rate, pressure drop, or differential pressure, control method, mode of operation and the desired level of control accuracy. Correct sizing not only reduces unnecessary downtime for maintenance for the end user, but also greatly accelerates productivity and accuracy. You can ask for a free consultation with THINKTANK to ensure the right selection.
Manual flow control valves require manual adjustment to regulate fluid flow, while automatic valves require the use of actuators such as pneumatic or electric to control fluid flow, via remote signals, or to adjust the valve position according to specific control parameters. You can find these different valves in the following pictures.
6inch 300lb cf8 control valve manufacturer handle control valve
Automatic valves are suitable for applications that require precise control, remote operation, or integration with control systems. In modern industry, automatic valves are being used more and more widely in production processes, not only to improve the efficiency of production, precise control, and greater energy savings.
Proper routine maintenance job of flow control valves includes periodic inspections for shell leaks, inner leaks, seals, signals, correct actuator action, and routine valve cleaning and lubrication. In addition, we should replace worn or damaged parts as needed to ensure optimum performance and extend the life of the flow control valve. The end-users need to follow the manufacturer’s guidelines and recommended maintenance schedule, which is essential to maintain valve efficiency and prevent unexpected failures. If you don’t have the manual book or maintenance book in hand, you can contact the equipment factory to ask them to send it again. Every single valve from THINKTANK will have a 100% test and inspection before shipment, ensuring the reliable quality of flow control valves. You can surely no worries about the quality and service.
Flow control valves provide precise control of the flow of fluid or gas in a system. The change of flow or pressure after the valve is controlled by the flow area of the valve core through which the fluid or gas passes. Flow control valves can improve industrial energy efficiency mainly through three aspects.
One is to reduce unnecessary energy consumption due to system pressure drop.
We know that when fluid or gas passes through a pipeline or system without a flow control valve, the flow will pass elbows to change direction in the pipeline, or generate friction with the pipeline wall and other reasons, so it will cause a pressure drop in the entire system, because the loss of fluid energy. The pressure drop not only causes energy loss but also wasted a lot of energy and power.
Flow control valves can help reduce pressure drops by regulating the flow capacity, and make sure fluid or gas passes through the system at a consistent pressure. By maintaining a certain pressure value, no need for much energy is required running the entire processing system.
The second is to improve the control of fluid or gas flow in the system.
Flow control valves can ensure that only the required amount of fluid or gas is used at any given time, precisely controlling the flow parameter value, which prevents overuse and wasted energy, resulting in significant energy savings.
Third, flow control valves can help improve energy efficiency by increasing the overall efficiency of the system.
For example, if a flow control valve works in an HVAC system, it can regulate the flow of water through heating and cooling circuits, maintaining the desired temperature and improving energy efficiency while optimizing heat transfer. It’s more and more important for end-users save costs during production efficiency. Standing for the customer position to thinking of the market is very valve manufacturer need to be consideration.
Flow control is the process of regulating the flow capacity or volume of a fluid, gas, or steam in a piping system. It involves the use of flow control valves and other devices to manage the flow of the medium to achieve the desired output. Welcome to choose THINKTANK as your reliable partner of flow control valves.
We can list 3 types of different valves to achieve flow controls.
Flow control systems are designed to modulate the process flow rate/capacity of fluids or gases in an industrial system. Based on different applications and types of flow control systems on-site, the operating principles may vary in design.
Generally, a standard flow control system consists of 4 key components.
We need to based on a variety of processing parameters to design the best control of flow solution for customers. Deeply knowing the specific requirements of the system running is very important for professional valve manufacturers, like THINKTANK. It will help us to design and provide precision and control systems for the desired levels as users need.
Here we will introduce the most 4 simple control of flow type systems for your reference.
This type of flow control adjusts the flow rate in proportion to changes in the input signal, such as 4-20mA, 0-10V, or 3-15psi signal. For example, if the input signal is 50%, the response flow rate of the control valve is just adjusted to 50% of the maximum capacity. Proportional control is often used for the high level of accuracy of control systems.
In an on/off control system, the flow control valve is either fully open or fully closed based on the input signal. This type of control is less precise than proportional control but can be simpler and less expensive to implement.
PID control is a type of proportional control that also takes into account the integral and derivative components of the input signal. The proportional component adjusts the flow rate in proportion to changes in the input signal, while the integral and derivative components help to reduce the “overshoot” and “undershoot” that can occur with proportional control. PID control can offer a good balance of precision and simplicity.
Flow limiting devices are passive devices (such as orifices, flow nozzles, and ventures) that are designed to limit the flow rate of a fluid or gas. These devices can be effective in applications where a fixed flow rate is required and no active control is necessary.
Ultimately, the best control of flow for a particular application will depend on the unique requirements of the system and will take into account factors such as precision, accuracy, cost, and ease of use. A qualified engineer or technician can help to determine the optimal flow control solution based on these factors.
The three types of control flow in computer programming are:
This type of control flow is the simplest and most straightforward. Programs with sequential control flow execute one instruction after the next, in the order that they are written. There is no branching or looping, and each instruction is executed exactly once.
In selection control flow, a program chooses between two or more paths based on some condition. This is typically accomplished using if-else statements, which allow the program to execute one block of code if a condition is true, and another block of code if the condition is false. Switch statements are another example of selection control flow, allowing programs to choose between multiple options based on the value of a variable.
Iteration control flow involves repeating a block of code multiple times, either a fixed number of times or until a certain condition is met. This is typically accomplished using loops, such as while loops or for loops, that allow the program to execute a block of code multiple times with different input values.
These three types of control flow are fundamental to most programming languages, and mastering their use is essential to becoming a skilled programmer. By combining sequential, selection, and iteration control flows, programmers can create complex systems that can perform a wide range of tasks.
The two types of flow control are open-loop and closed-loop control. Open-loop control is a non-feedback system where the output is not used to regulate the input, while closed-loop control is a feedback system where the output is used to regulate the input to maintain a desired output.
open loop control system closed-loop control systemFlow control should be used when it is necessary to regulate the flow rate or volume of a fluid, gas, or steam to achieve a desired output. It is commonly used in industrial processes, such as chemical and petrochemical plants, food and beverage production, and water treatment facilities. Here are 4 conditions you may consider for using flow control in programming.
Flow control is needed in any application where the flow rate or volume of a fluid, gas, or steam needs to be regulated. It is used in various industries, including oil and gas, power generation, water and wastewater treatment, and food and beverage production.
Flow control is used to prevent a range of issues, such as overpressure, overheating, cavitation, erosion, and water hammer, which can cause damage to piping systems, valves, and other components.
The benefits of flow control include improved efficiency, accuracy, and reliability in controlling the flow rate or volume of a fluid, gas, or steam. It can also reduce operating costs, improve product quality, and enhance safety by preventing damage to piping systems and components.
The reasons for flow control vary depending on the specific application and requirements. Some common reasons include ensuring safety and reliability, improving efficiency and accuracy, meeting regulatory requirements, and enhancing product quality.
Not to be confused with Flow control (data)
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.
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:
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
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[citation needed] 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; after all, 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.
What Böhm and Jacopini's article showed was that all programs could be goto-free. 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.
Choice
[
edit
]
If-then-(else) statements
[
edit
]
Conditional expressions and conditional constructs are features of a programming language which 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.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.if
a
>
0
then
writeln
(
"
yes
"
)
else
writeln
(
"
no
"
)
;
C: Shell script:if
a
>
0
then
Put_Line
(
"yes"
);
else
Put_Line
(
"no"
);
end
if
;
if
(
a
>
0
)
{
puts
(
"yes"
);
}
else
{
puts
(
"no"
);
}
Python: Lisp:if
[
$a
-gt
0
]
;
then
echo
"yes"
else
echo
"no"
fi
if
a
>
0
:
(
"yes"
)
else
:
(
"no"
)
(
princ
(
if
(
plusp
a
)
"yes"
"no"
))
Less common variations include:
if
statement, for instance Lisp's cond
.if
statement, such as C's ternary operator.if
with when
and unless
.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.
case
someChar
of
'a'
:
actionOnA
;
'x'
:
actionOnX
;
'y'
,
'z'
:
actionOnYandZ
;
else
actionOnNoMatch
;
end
;
C: Shell script:case
someChar
is
when
'
a
'
=>
actionOnA
;
when
'
x
'
=>
actionOnX
;
when
'
y
'
|
'
z
'
=>
actionOnYandZ
;
when
others
=>
actionOnNoMatch
;
end
;
switch
(
someChar
)
{
case
'a'
:
actionOnA
;
break
;
case
'x'
:
actionOnX
;
break
;
case
'y'
:
case
'z'
:
actionOnYandZ
;
break
;
default
:
actionOnNoMatch
;
}
Lisp: Fortran:case
$someChar
in
a
)
actionOnA
;;
x
)
actionOnX
;;
[
yz])
actionOnYandZ
;;
*
)
actionOnNoMatch
;;
esac
(
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
Featured content:[
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, or until some condition is met, or indefinitely.
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, 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]. for Item in Collection do begin xxx end; foreach (item; myCollection) { xxx } foreach someArray { xxx } foreach ($someArray as $k => $v) { xxx } Collection<String> coll; for (String s : coll) {} foreach (string s in myStringCollection) { xxx } someCollection | 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
),[4] 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
,[5] 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[6] and Ruby,[7] 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.[8]
Early exit from loops
[
edit
]
When using a count-controlled loop to search through a table, it might be desirable to stop searching as soon as the required item is found. 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. Another term for early-exit loops is loop-and-a-half.
The following example is done in Ada which supports both early exit from loops and loops with test in the middle. Both features are very similar and comparing both code snippets will show the difference: early exit must be combined with an if statement while a condition in the middle is a self-contained construct.
with
Ada.Text
IO
;
with
Ada.Integer
Text
IO
;
procedure
Print_Squares
is
X
:
Integer
;
begin
Read_Data
:
loop
Ada
.
Integer
Text
IO
.
Get
(
X
);
exit
Read_Data
when
X
=
0
;
Ada
.
Text
IO
.
Put
(
X
*
X
);
Ada
.
Text
IO
.
New_Line
;
end
loop
Read_Data
;
end
Print_Squares
;
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
):
(
"Set contains a prime number"
)
break
else
:
(
"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.
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[9] and PHP,[10] or via labeled breaks (break out and continue at given label), as in Java and Perl.[11] 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.[12] 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.[13]
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.[14] 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.[15] 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.[14]
One can also return
out of a subroutine executing the looped statements, breaking out of both the nested loop and the subroutine. There are other proposed control structures for multiple breaks, but these are generally implemented as exceptions instead.
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.[16]
Loop variants and invariants
[
edit
]
Loop variants and loop invariants are used to express correctness of loops.[17]
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[18] provides a Loop macro which implements such a sublanguage.
Loop system cross-reference table
[
edit
]
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
]
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.[21]
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
]
Proposed control structures
[
edit
]
In a spoof Datamation article[28] 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.
Donald Knuth's 1974 article "Structured Programming with go to Statements",[29] identifies two situations which were not covered by the control structures listed above, and gave examples of control structures which could handle these situations. Despite their utility, these constructs have not yet found their way into mainstream programming languages.
Loop with test in the middle
[
edit
]
The following was proposed by Dahl in 1972:[30]
loop loop xxx1 read(char); while test; while not atEndOfFile; xxx2 write(char); repeat; repeat;
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. The construction here can be thought of as a do loop with the while check in the middle. Hence this single construction can replace several constructions in most programming languages.
Languages lacking this construct generally emulate it using an equivalent infinite-loop-with-break idiom:
while (true) { xxx1 if (not test) break xxx2 }
A possible variant is to allow more than one while test; within the loop, but the use of exitwhen (see next section) appears to cover this case better.
In Ada, the above loop construct (loop-while-repeat) can be represented using a standard infinite loop (loop - end loop) that has an exit when clause in the middle (not to be confused with the exitwhen statement in the following section).
with
Ada.Text_IO
;
with
Ada.Integer_Text_IO
;
procedure
Print_Squares
is
X
:
Integer
;
begin
Read_Data
:
loop
Ada
.
Integer_Text_IO
.
Get
(
X
);
exit
Read_Data
when
X
=
0
;
Ada
.
Text
IO
.
Put
(
X
*
X
);
Ada
.
Text
IO
.
New_Line
;
end
loop
Read_Data
;
end
Print_Squares
;
Naming a loop (like Read_Data in this example) is optional but permits leaving the outer loop of several nested loops.
Multiple early exit/exit from nested loops
[
edit
]
This construct was proposed by Zahn in 1974.[31] 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.[32][33][34]
See also
[
edit
]
References
[
edit
]
Further reading
[
edit
]
Related Articles
If you are interested in sending in a Guest Blogger Submission,welcome to write for us!
All Comments ( 0 )