流程控制语句
本章节系统介绍了GS语言中的流程控制语句,通过语法说明和代码示例,详细讲解了各种语句的结构、规则及适用场景。主要包括:
- 条件判断的if-else、?:、??、switch语句
- 循环的for、while语句
本章适用于:
- 正在学习GS语言编程基础的初学者
- 需要快速回顾GS流程控制语法要点的开发者。
通过阅读本章,您将能够:
- 理解并运用GS中的各种条件判断语句来编写分支逻辑。
- 掌握使用循环语句重复执行代码块的方法。
- 了解switch语句的语法规则及其与if-else的差异。
1 条件判断语句
和大部分其他编程语言相同,条件判断语句通过判定条件是否为真来决定是否执行某些代码。在 GS 中条件判断语句主要包含 if-else,?: ,?? 和 switch 四种类型。
先使用 gip init branches 创建一个 branches 的项目,来学习 if 表达式。
1.1 if-else型
if-else型语句允许根据条件执行不同的代码分支, if-else型判断语句又分成三种不同的使用方式
1.1.1 if
针对你提供的条件表示 “如果条件满足,运行这段代码;如果条件不满足,不运行这段代码”。
所有的if表达式都以 if 关键字开头,其后跟一对小括号 (...),小括号内部即为判断条件。在之后跟一对大括号{...},大括号内部为条件满足时希望执行的语句,if语句基本语法形式如下:
if(boolean_expression) // 如果boolean_expression == true, 就执行 execute body
{
// execute body
}
// 如果 boolean_expression == false,就不执行 execute body
接下来让我们实际尝试简单的 if 表达式语句,在 branches 项目新建 src/branch.gs 文件,并输入如下内容:
void run()
{
int number = 3;
if (number < 5)
{
writeln("condition was true");
}
}
run();
示例 1-1:if 条件判断
运行如上程序输出结果如下:
condition was true
在这个例子中,条件检查函数参数 number 的值是否小于 5。在条件满足时希望执行的代码块位于紧跟条件之后的大括号中。if 表达式中与条件关联的代码块有时被叫做 分支。
1.1.2 if-else
在简单if表达式的基础上我们可以在语句后续紧跟一个可选的 else 表达式来提供一个在if表达式条件不满足时应当执行的代码块。if-else语句基本语法如下:
if(boolean_expression) // 如果boolean_expression = true, 就执行body1,跳过else,否则执行body2
{
// execute body1
}
else
{
// execute body2
}
接下来让我们实际尝试简单的 if-else 表达式语句,在 branches src/branch.gs 文件中输入如下内容:
void run()
{
int number = 7;
if (number < 5)
{
writeln("condition was true");
}
else
{
writeln("condition was not true");
}
}
run();
示例 1-2:if-else 条件判断
示例执行的结果如下:
condition was not true
在这个例子中,条件检查函数参数 number 的值是否小于 5。在条件不满足的情况下执行了 else 分支的代码块。
1.1.3 if...else if...else
在简单if表达式的基础上我们可以在语句后续紧跟一个可选的 else if 表达式来提供一个在if表达式条件不满足时应当执行的条件判断,当else if 条件满足时,执行对应的分支代码块,并跳过后续其他 else if else的分支代码。if...else if...else语句基本语法如下:
if(boolean_expression_1) // 从上往下,如果boolean_expression_x = true, 就执行body_x,跳过下面的else if和else。
{
// execute body1
}
...
else if(boolean_expression_m)
{
// execute body_m
}
...
else
{
// execute bodyn
}
可以将将 else if 表达式与 if 和 else 组合来实现多重条件。例如:
void run()
{
int score = 85;
if(score >= 90)
{
writeln("Excellent");
}
else if (score >= 80)
{
writeln("Good");
}
else if (score >= 70)
{
writeln("Fair");
}
else if (score >= 60)
{
writeln("Pass");
}
else
{
writeln("Fail");
}
}
run();
示例 1-3:多重条件处理
这个程序有五个可能的执行分支。运行后应该能看到如下输出:
Good
当执行上述示例的多重条件判断时,GS 按顺序检查每个 if 或 else if 表达式,并执行第一个条件成立的的分支代码块。尽管 85 分满足 >= 70 以及 >= 60 的条件,但由于>= 80的条件先被满足,因此只有输出 Good 的分支代码会被执行。除此之外 if、else if、else 语句也可以逐层嵌套使用。
1.1.4 嵌套使用if-else
if-else型支持多层嵌套使用,在满足某个 if、else if、else 条件的情况下,其分支代码中带有嵌套的 if、else if、else 语句,会继续进行分支代码中的条件判断选择执行的分支。嵌套型if-else语句基本语法如下:
if(boolean_expression1)
{
if(boolean_expression2)
{
...
}
...
else
{
...
}
}
else if
{
if(boolean_expression3)
{
...
}
}
else
{
...
}
void attack()
{
int playerAttackPower = 5; // 玩家攻击力 (1-10)
int enemyHealth = 3; // 敌人血量 (1-10)
if (playerAttackPower >= 5) // 外部条件: 攻击受否有效
{
if (enemyHealth <= 3) // 内部条件: 敌人血量是否足够低?
{
writeln("One-hit kill!"); // // 高攻击力 + 低血量敌人
}
else
{
writeln("The enemy is injured but not dead!"); // 高攻击力但敌人血量较高
}
}
else if (playerAttackPower >= 2)
{
// 攻击力中等
writeln("The enemy takes minor damage!");
}
else
{
// 攻击力太低
writeln("The attack is ineffective! The enemy is laughing at you!");
}
}
attack();
示例 1-4:嵌套条件判断
这个程序有四个可能的执行分支。运行后应该能看到如下输出:
One-hit kill!
1.2 ?:型
?:型条件判断语句是一种三目运算符,与if-else型语句很相似,两者可以部分相互转换,但三目型判断语句的代码相对更简洁(只要一行)。同时三目运算符具有表达式返回值的概念。
下述的?:语句基本语法中当boolean_expression条件满足时则执行 expression1并将expression1作为?:型表达式返回值,否则执行 expression2并将expression2作为?:型表达式返回值。
:?语句基本语法如下:
boolean_expression ? expression1 : expression2 // 如果boolean_expression = true,则执行expression1,否则执行expression2
举个例子:
int a = 0, b = 1; // a = (a和b中的最大值)
if(a > b)
a = a;
else
a = b;
write(a);
等价于:
int a = 0, b = 1;
a = a > b ? a : b;
write(a);
示例 1-5:三目运算符与等效 if-else 语句示例 输出结果如下:
1
同样实现当 a > b 条件满足时将变量 a 赋值给自身,条件不满足时将变量b赋值给自身,?:语句的写法更加简洁。
1.3 ??型
参照下方基本语法,二目?? 型判断语句特别的是,判断条件不再是判断expression1是否为true,而是判断expression1是否不为 nil 或 void。首先执行expression1当expression1不为 nil 或 void 时表达式返回 epression1 否则执行并返回 expression2;
??语句基本语法:
expression1 ?? expression2 // expression1 为 nil 或 void 则取 expression2,若 expression1 不为 nil 或 void 则取 expression 1
举个例子:
write(0??1) // expr1=0 不为 void 或 nil,输出 0
write(1??0) // 输出 1
write(nil??1) // expr1=nil 为 nil,输出 1
write(nil??0) // 输出 0
示例 1-6:二目??型运算符示例 输出结果如下:
0110
1.4 switch型
switch型判断语句跟if-else型判断语句可以相互转换,当判断层次较多且比较简单时使用switch语句更好。 switch 语句的基本语法如下:
switch(expression)
{
case constant_expression1 :
statement1;
case constant_expression2 :
statement2;
case constant_expression3 :
statement3;
...
default : // 可选的
statement4;
}
- 语句会逐个比较
switch语句中的的表达式与case语句中的表达式,当两者相等时,对应case语句后的分支代码块均会执行。 - 当
expression与constant_expression1相等时后续分支中的statement1statement2statement3statement4等代码块均被执行。 - 当
expression与constant_expression2相等时后续分支中的statement2statement3statement4等代码块均被执行,而之前的statment1代码块不再被执行。后续以此类推。 - 注意可选的
default语句可以视为一个会匹配成功的case语句,当控制流执行到default语句时其后续代码块均会执行。
举个例子:
void run_switch(int n)
{
switch(n)
{
case 1:
write(1);
case 2:
write(2);
case 3:
write(3);
default:
write(4);
}
}
run_switch(3);
示例 1-7:switch 语句示例 输出结果如下:
34
但通常情况下,我们仅希望 case 语句对应的单个代码块被执行,比如expression与constant_expression1匹配时希望仅执行statment1,此时就需要在 statement 语句后添加break语句。
- 执行break语句直接跳出所在的一层循环或
switch型语句,在下面的switch-break基本语法中可以理解为跳到'}'的后面,也就是这个块的下一条语句前面。
switch-break 语句基本语法为:
switch(expression)
{
case constant_expression1 :
statement;
break; // 可选的
case constant_expression2 :
statement;
break; // 可选的
case constant_expression3 :
statement;
break; // 可选的
...
default : // 可选的
statement;
}
举个例子:
void run_switch(int n)
{
switch(n)
{
case 1:
write(1);
break;
case 2:
write(2);
break;
case 3:
write(3);
break;
default:
write(4);
}
}
run_switch(3);
示例1-8:switch-break 示例
输出结果如下:
3
需要注意的是,switch语句必须遵循以下规则:
- case语句中的待匹配值应当是一个编译期可以求得的常量即编译期常量;
- 一个switch中可以有任意个case语句,每个case语句后面加一个跟expression比较的值和一个冒号;
- case中的constant_expression必须和expression具有相同的数据类型;
- 当程序进入一个case中执行之后还会继续执行下面的case,直到遇到break语句为止。
- 每个case都可以选择break
- switch最后一个default表示前面所有的case都不符合就执行default,相当于if-else语句中的else,它是可选的。
同样,switch语句也是可以和if-else语句一样多层嵌套,具体语法类似if-else
2 循环语句
多次执行同一段代码的需求是很常见的,GS 为此提供了多种循环语句。每次循环会执行循环体中的代码知道循环体结尾后再回到循环开头继续执行。 循环语句主要包含for循环和while循环两种类型
在循环语句中,我们常会有停止当前循环,或跳过当前循环的后续语句直接执行下一次循环的需求。此时我们就需要使用 break 或 continue 语句。
- 执行break语句直接跳出所在的一层循环,循环有''可以理解为就跳到循环结束的'}'符号后面的语句。
- 执行continue语句会跳过当前循环中后续的所有语句,并执行下一次循环,可以理解为跳 过'}'前面所有语句。
2.1 for型
for循环是一个允许执行特定次数的循环重复控制结构。 for循环语句基本语法有三种:
2.1.1 第一种for循环(常见)
第一种for循环的语法如下:
for( initial; condition; increment ) // initial、condition、increment两两之间要用分号分开,并且三者都可以为空
{
statements;
}
下面解释一下for循环的控制流:
- 1、for循环一开始
initial语句首先被执行,并且只会执行一次,initial语句一般充当初始化控制循环变量的作用。initial可以为空; - 2、接下来执行
condition判断语句,如果为真就执行循环体statements,否则跳出循环,跳到紧接着for循环结束的后续语句;condition也可以为空,如果条件表达式为空,则始终满足循环条件,要有break退出循环; - 3、在执行完
for循环主体之后,控制流会跳到increment语句,increment一般用来更新循环控制变量,这部分也可以为空; - 4、接下来控制流会跳到第2步。
举个例子:
for(int i = 0; i < 5; i ++)
{
write(i);
}
// 程序执行之后输出 01234