如何在Scala中使用条件表达式
展开全部
条件表达式
Scala的if/else语法结构和Java或C++一样。不过,在Scala中if/else表达式有值,这个值就是跟在if或else之后的表达式的值。例如:
if (x > 0) 1 else -1
上述表达式的值是1或−1,具体是哪一个取决于x的值。你可以将if/else表达式的值赋值给变量:
val s = if (x > 0) 1 else -1
这与如下语句的效果一样:
if (x > 0) s = 1 else s = -1
不过,第一种写法更好,因为它可以用来初始化一个val。而在第二种写法当中,s必须是var。
(之前已经提过,Scala中的分号绝大多数情况下不是必需的。)
Java和C++有一个?:操作符用于同样目的。如下表达式
x > 0 ? 1 : -1 // Java或C++
等同于Scala表达式 if (x > 0) 1 else −1。不过,你不能在?:表达式中插入语句。Scala的if/else将在Java和C++中分开的两个语法结构if/else和?:结合在了一起。
在Scala中,每个表达式都有一个类型。举例来说,表达式 if (x > 0) 1 else −1的类型是Int,因为两个分支的类型都是Int。混合类型表达式,比如:
if (x > 0) "positive" else -1
上述表达式的类型是两个分支类型的公共超类型。在本例中,其中一个分支是java.lang.String,而另一个分支是Int。它们的公共超类型叫做Any。(详细内容参见8.11节。)
如果else部分缺失了,比如:
if (x > 0) 1
那么有可能if语句没有输出值。但是在Scala中,每个表达式都应该有某种值。这个问题的解决方案是引入一个Unit类,写做()。不带else的这个if语句等同于
if (x > 0) 1 else ()
你可以把()当做是表示“无有用值”的占位符,将Unit当做Java或C++中的void。(从技术上讲,void没有值但是Unit有一个表示“无值”的值。如果你一定要深究的话,这就好比空的钱包和里面有一张写着“没钱”的无面值钞票的钱包之间的区别。)
说明:Scala没有switch语句,不过它有一个强大得多的模式匹配机制,我们将在第14章中看到。在现阶段,用一系列的if语句就好。
注意:REPL比起编译器来更加“近视”——它在同一时间只能看到一行代码。
举例来说,当你键入如下代码时:
if (x > 0) 1
else if (x == 0) 0 else -1
REPL会执行 if (x > 0) 1,然后显示结果。之后它看到接下来的else关键字就会不知所措。
如果你想在else前换行的话,用花括号:
if (x > 0) { 1
} else if (x == 0) 0 else -1
只有在REPL中才会有这个顾虑。在被编译的程序中,解析器会找到下一行的else。
提示:如果你想在REPL中粘贴成块的代码,而又不想担心REPL的近视问题,可以使用粘贴模式。键入:
:paste
把代码块粘贴进去,然后按下Ctrl+D。这样REPL就会把代码块当做一个整体来分析。
语句终止
在Java和C++中,每个语句都以分号结束。而在Scala中——与JavaScript和其他脚本语言类似——行尾的位置不需要分号。同样,在}、else以及类似的位置也不必写分号,只要能够从上下文明确地判断出这里是语句的终止即可。
不过,如果你想在单行中写下多个语句,就需要将它们以分号隔开。例如:
if (n > 0) { r = r * n; n -= 1 }
我们需要用分号将 r = r * n 和 n -= 1 隔开。由于有},在第二个语句之后并不需要写分号。
如果你在写较长的语句,需要分两行来写的话,就要确保第一行以一个不能用做语句结尾的符号结尾。通常来说一个比较好的选择是操作符:
s = s0 + (v - v0) * t + // +告诉解析器这里不是语句的末尾
0.5 * (a - a0) * t * t
在实际编码时,长表达式通常涉及函数或方法调用,如此一来你并不需要过分担心——在左括号(之后,编译器直到看到匹配的)才会去推断某处是否为语句结尾。
正因如此,Scala程序员们更倾向于使用Kernighan & Ritchie风格的花括号:
if (n > 0) {
r = r * n
n -= 1
}
以{结束的行很清楚地表示了后面还有更多内容。
许多来自Java或C++的程序员一开始并不适应省去分号的做法。如果你倾向于使用分号,用就是了——它们没啥坏处。
块表达式和赋值
在Java或C++中,块语句是一个包含于{ }中的语句序列。每当你需要在逻辑分支或循环中放置多个动作时,你都可以使用块语句。
在Scala中,{ }块包含一系列表达式,其结果也是一个表达式。块中最后一个表达式的值就是块的值。
这个特性对于那种对某个val的初始化需要分多步完成的情况很有用。例如,
val distance = { val dx = x - x0; val dy = y - y0; sqrt(dx * dx + dy * dy) }
{ }块的值取其最后一个表达式,在此处以粗体标出。变量dx和dy仅作为计算所需要的中间值,很干净地对程序其他部分而言不可见了。
在Scala中,赋值动作本身是没有值的——或者,更严格地说,它们的值是Unit类型的。你应该还记得,Unit类型等同于Java和C++中的void,而这个类型只有一个值,写做()。
一个以赋值语句结束的块,比如
{ r = r * n; n -= 1}
的值是Unit类型的。这没有问题,只是当我们定义函数时需要意识到这一点。
由于赋值语句的值是Unit类型的,别把它们串接在一起。
x = y = 1 // 别这样做
y = 1的值是(),你几乎不太可能想把一个Unit类型的值赋值给x。(与此相对应,在Java和C++中,赋值语句的值是被赋的那个值。在这些语言中,将赋值语句串接在一起是有意义的。)
输入和输出
如果要打印一个值,我们用print或println函数。后者在打印完内容后会追加一个换行符。举例来说,
print("Answer: ")
println(42)
与下面的代码输出的内容相同:
println("Answer: " + 42)
另外,还有一个带有C风格格式化字符串的printf函数:
printf("Hello, %s! You are %d years old.\n", "Fred", 42)
你可以用readLine函数从控制台读取一行输入。如果要读取数字、Boolean或者是字符,可以用readInt、readDouble、readByte、readShort、readLong、readFloat、readBoolean或者readChar。与其他方法不同,readLine带一个参数作为提示字符串:
val name = readLine("Your name: ")
print("Your age: ")
val age = readInt()
printf("Hello, %s! Next year, your will be %d.\n", name, age + 1)
Scala的if/else语法结构和Java或C++一样。不过,在Scala中if/else表达式有值,这个值就是跟在if或else之后的表达式的值。例如:
if (x > 0) 1 else -1
上述表达式的值是1或−1,具体是哪一个取决于x的值。你可以将if/else表达式的值赋值给变量:
val s = if (x > 0) 1 else -1
这与如下语句的效果一样:
if (x > 0) s = 1 else s = -1
不过,第一种写法更好,因为它可以用来初始化一个val。而在第二种写法当中,s必须是var。
(之前已经提过,Scala中的分号绝大多数情况下不是必需的。)
Java和C++有一个?:操作符用于同样目的。如下表达式
x > 0 ? 1 : -1 // Java或C++
等同于Scala表达式 if (x > 0) 1 else −1。不过,你不能在?:表达式中插入语句。Scala的if/else将在Java和C++中分开的两个语法结构if/else和?:结合在了一起。
在Scala中,每个表达式都有一个类型。举例来说,表达式 if (x > 0) 1 else −1的类型是Int,因为两个分支的类型都是Int。混合类型表达式,比如:
if (x > 0) "positive" else -1
上述表达式的类型是两个分支类型的公共超类型。在本例中,其中一个分支是java.lang.String,而另一个分支是Int。它们的公共超类型叫做Any。(详细内容参见8.11节。)
如果else部分缺失了,比如:
if (x > 0) 1
那么有可能if语句没有输出值。但是在Scala中,每个表达式都应该有某种值。这个问题的解决方案是引入一个Unit类,写做()。不带else的这个if语句等同于
if (x > 0) 1 else ()
你可以把()当做是表示“无有用值”的占位符,将Unit当做Java或C++中的void。(从技术上讲,void没有值但是Unit有一个表示“无值”的值。如果你一定要深究的话,这就好比空的钱包和里面有一张写着“没钱”的无面值钞票的钱包之间的区别。)
说明:Scala没有switch语句,不过它有一个强大得多的模式匹配机制,我们将在第14章中看到。在现阶段,用一系列的if语句就好。
注意:REPL比起编译器来更加“近视”——它在同一时间只能看到一行代码。
举例来说,当你键入如下代码时:
if (x > 0) 1
else if (x == 0) 0 else -1
REPL会执行 if (x > 0) 1,然后显示结果。之后它看到接下来的else关键字就会不知所措。
如果你想在else前换行的话,用花括号:
if (x > 0) { 1
} else if (x == 0) 0 else -1
只有在REPL中才会有这个顾虑。在被编译的程序中,解析器会找到下一行的else。
提示:如果你想在REPL中粘贴成块的代码,而又不想担心REPL的近视问题,可以使用粘贴模式。键入:
:paste
把代码块粘贴进去,然后按下Ctrl+D。这样REPL就会把代码块当做一个整体来分析。
语句终止
在Java和C++中,每个语句都以分号结束。而在Scala中——与JavaScript和其他脚本语言类似——行尾的位置不需要分号。同样,在}、else以及类似的位置也不必写分号,只要能够从上下文明确地判断出这里是语句的终止即可。
不过,如果你想在单行中写下多个语句,就需要将它们以分号隔开。例如:
if (n > 0) { r = r * n; n -= 1 }
我们需要用分号将 r = r * n 和 n -= 1 隔开。由于有},在第二个语句之后并不需要写分号。
如果你在写较长的语句,需要分两行来写的话,就要确保第一行以一个不能用做语句结尾的符号结尾。通常来说一个比较好的选择是操作符:
s = s0 + (v - v0) * t + // +告诉解析器这里不是语句的末尾
0.5 * (a - a0) * t * t
在实际编码时,长表达式通常涉及函数或方法调用,如此一来你并不需要过分担心——在左括号(之后,编译器直到看到匹配的)才会去推断某处是否为语句结尾。
正因如此,Scala程序员们更倾向于使用Kernighan & Ritchie风格的花括号:
if (n > 0) {
r = r * n
n -= 1
}
以{结束的行很清楚地表示了后面还有更多内容。
许多来自Java或C++的程序员一开始并不适应省去分号的做法。如果你倾向于使用分号,用就是了——它们没啥坏处。
块表达式和赋值
在Java或C++中,块语句是一个包含于{ }中的语句序列。每当你需要在逻辑分支或循环中放置多个动作时,你都可以使用块语句。
在Scala中,{ }块包含一系列表达式,其结果也是一个表达式。块中最后一个表达式的值就是块的值。
这个特性对于那种对某个val的初始化需要分多步完成的情况很有用。例如,
val distance = { val dx = x - x0; val dy = y - y0; sqrt(dx * dx + dy * dy) }
{ }块的值取其最后一个表达式,在此处以粗体标出。变量dx和dy仅作为计算所需要的中间值,很干净地对程序其他部分而言不可见了。
在Scala中,赋值动作本身是没有值的——或者,更严格地说,它们的值是Unit类型的。你应该还记得,Unit类型等同于Java和C++中的void,而这个类型只有一个值,写做()。
一个以赋值语句结束的块,比如
{ r = r * n; n -= 1}
的值是Unit类型的。这没有问题,只是当我们定义函数时需要意识到这一点。
由于赋值语句的值是Unit类型的,别把它们串接在一起。
x = y = 1 // 别这样做
y = 1的值是(),你几乎不太可能想把一个Unit类型的值赋值给x。(与此相对应,在Java和C++中,赋值语句的值是被赋的那个值。在这些语言中,将赋值语句串接在一起是有意义的。)
输入和输出
如果要打印一个值,我们用print或println函数。后者在打印完内容后会追加一个换行符。举例来说,
print("Answer: ")
println(42)
与下面的代码输出的内容相同:
println("Answer: " + 42)
另外,还有一个带有C风格格式化字符串的printf函数:
printf("Hello, %s! You are %d years old.\n", "Fred", 42)
你可以用readLine函数从控制台读取一行输入。如果要读取数字、Boolean或者是字符,可以用readInt、readDouble、readByte、readShort、readLong、readFloat、readBoolean或者readChar。与其他方法不同,readLine带一个参数作为提示字符串:
val name = readLine("Your name: ")
print("Your age: ")
val age = readInt()
printf("Hello, %s! Next year, your will be %d.\n", name, age + 1)
展开全部
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct PCB {
char NAME[10]; /*进程名*/
int ROUND; /*进程轮转时间片*/
int REACHTIME; /*进程到达时间*/
int CPUTIME; /*进程占用CPU时间*/
int COUNT; /*计数器*/
int NEEDTIME; /*进程完成还要的CPU时间*/
char STATE; /*进程的状态*/
struct PCB *NEXT; /*链指针*/
};
struct LINK { /*PCB的链结构*/
struct PCB *RUN; /*当前运行进程指针*/
struct PCB *READY; /*就绪队列头指针*/
struct PCB *TAIL; /*就绪队列尾指针*/
struct PCB *FINISH; /*完成队列头指针*/
};
void INIT(LINK *); /*对PCB的链结构初始化*/
void INSERT(LINK *); /*将执行了一个单位时间片数且还未完成的进程的PCB插到就绪队列的队尾*/
void FIRSTIN(LINK *); /*将就绪队列中的第一个进程投入运行*/
void PRINT(LINK *); /*打印每执行一个时间片后的所有进程的状态*/
void PR(PCB *); /*打印一个进程的状态*/
int CREATE(LINK *,int); /*创建新的进程*/
void ROUNDSCH(LINK *); /*按时间片轮转法调度进程*/
void main() {
LINK pcbs;
int i;
INIT(&pcbs);
i=0;
printf("创建5个进程\n\n");
while(i<5) {
if(CREATE(&pcbs,i+1)==1) {
printf("进程已创建\n\n");
i++;
}
else
printf("进程创建失败\n\n");
}
FIRSTIN(&pcbs);
ROUNDSCH(&pcbs);
}
void ROUNDSCH(LINK *p) {
PCB *pcb;
while(p->RUN!=NULL) {
pcb=(PCB *)malloc(sizeof(PCB));
strcpy(pcb->NAME,p->RUN->NAME);
pcb->ROUND=p->RUN->ROUND;
pcb->REACHTIME=p->RUN->REACHTIME;
pcb->CPUTIME=p->RUN->CPUTIME;
pcb->COUNT=p->RUN->COUNT;
pcb->NEEDTIME=p->RUN->NEEDTIME;
pcb->STATE=p->RUN->STATE;
pcb->NEXT=p->RUN->NEXT;
pcb->CPUTIME++;
pcb->NEEDTIME--;
pcb->COUNT++;
if(pcb->NEEDTIME==0) {
pcb->NEXT=p->FINISH->NEXT;
p->FINISH->NEXT=pcb;
pcb->STATE='F';
p->RUN=NULL;
if(p->READY!=p->TAIL)
FIRSTIN(p);
}
else {
p->RUN=pcb;
if(pcb->COUNT==pcb->ROUND) {
pcb->COUNT=0;
if(p->READY!=p->TAIL) {
pcb->STATE='W';
INSERT(p);
FIRSTIN(p);
}
}
}
PRINT(p);
}
}
void INIT(LINK *p) {
p->RUN=NULL;
p->TAIL=p->READY=(PCB *)malloc(sizeof(PCB));
p->READY->NEXT=NULL;
p->FINISH=(PCB *)malloc(sizeof(PCB));
p->FINISH->NEXT=NULL;
}
int CREATE(LINK *p,int n) {
PCB *pcb,*q;
pcb=(PCB *)malloc(sizeof(PCB));
flushall();
printf("请输入第%d个进程的名称:\n",n);
gets(pcb->NAME);
printf("请输入第%d个进程的轮转时间片数:\n",n);
scanf("%d",&(pcb->ROUND));
printf("请输入第%d个进程的到达时间:\n",n);
scanf("%d",&(pcb->REACHTIME));
pcb->CPUTIME=0;
pcb->COUNT=0;
printf("请输入第%d个进程需运行的时间片数:\n",n);
scanf("%d",&(pcb->NEEDTIME));
pcb->STATE='W';
pcb->NEXT=NULL;
if(strcmp(pcb->NAME,"")==0||pcb->ROUND<=0||pcb->NEEDTIME<=0) /*输入错误*/
return 0;
q=p->READY;
while(q->NEXT!=NULL&&q->NEXT->REACHTIME<=pcb->REACHTIME)
q=q->NEXT;
pcb->NEXT=q->NEXT;
q->NEXT=pcb;
if(pcb->NEXT==NULL)
p->TAIL=pcb;
return 1;
}
void FIRSTIN(LINK *p) {
PCB *q;
q=p->READY->NEXT;
p->READY->NEXT=q->NEXT;
q->NEXT=NULL;
if(p->READY->NEXT==NULL)
p->TAIL=p->READY;
q->STATE='R';
p->RUN=q;
}
void INSERT(LINK *p) {
PCB *pcb;
pcb=(PCB *)malloc(sizeof(PCB));
strcpy(pcb->NAME,p->RUN->NAME);
pcb->ROUND=p->RUN->ROUND;
pcb->REACHTIME=p->RUN->REACHTIME;
pcb->CPUTIME=p->RUN->CPUTIME;
pcb->COUNT=p->RUN->COUNT;
pcb->NEEDTIME=p->RUN->NEEDTIME;
pcb->STATE=p->RUN->STATE;
pcb->NEXT=p->RUN->NEXT;
p->TAIL->NEXT=pcb;
p->TAIL=pcb;
p->RUN=NULL;
pcb->STATE='W';
}
void PRINT(LINK *p) {
PCB *pcb;
printf("执行一个时间片后的所有进程的状态:\n\n");
if(p->RUN!=NULL)
PR(p->RUN);
if(p->READY!=p->TAIL) {
pcb=p->READY->NEXT;
while(pcb!=NULL) {
PR(pcb);
pcb=pcb->NEXT;
}
}
pcb=p->FINISH->NEXT;
while(pcb!=NULL) {
PR(pcb);
pcb=pcb->NEXT;
}
}
void PR(PCB *p) {
printf("进程名:%s\n",p->NAME);
printf("进程轮转时间片:%d\n",p->ROUND);
printf("进程到达时间:%d\n",p->REACHTIME);
printf("进程占用CPU时间:%d\n",p->CPUTIME);
printf("计数器:%d\n",p->COUNT);
printf("进程完成还要的CPU时间:%d\n",p->NEEDTIME);
printf("进程的状态:%c\n\n",p->STATE);
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
2015-12-16
展开全部
个人正则表达式用处就是验证数据有效性和查找替换
正则其实和通配符类似的一个东西,不过比通配符灵活高级多了,正则是一个很有用的好东西
至于通配符就是查找文件是,比如我要查txt文档,只记得文件名a开头的,我可以这样搜,a*.txt,这个*就是一个通配符。正则就是类似一个东西,不过高级多了
正则其实和通配符类似的一个东西,不过比通配符灵活高级多了,正则是一个很有用的好东西
至于通配符就是查找文件是,比如我要查txt文档,只记得文件名a开头的,我可以这样搜,a*.txt,这个*就是一个通配符。正则就是类似一个东西,不过高级多了
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询