目录
读取输入
将输入打印到"标准输出流"(即控制台窗口)是一件非常容易的事情,只要调用System.out.println即可。然而,读取"标准输入流"System.in就没那么简单了。要想通过控制台进行输入,首先需要构造一个与"标准输入流"System.in关联的Scanner对象。
Scanner in = new Scanner(System.in);
现在就可以使用Scanner类的各种方法读取输入了。例如:nextLine方法将读取一行输入。
System.out.print("What is your name?");
String name = in.nextLine();
在这里,使用nextLine()方法是因为在输入行中有可能包含空格。想要读取一个单词(以空白符作为分隔符),可以调用
String firstName = in.next();
想要读取一个整数,就调用nextInt方法。
System.out.print("How old are you?");
int age = in.nextInt();
与此类似,要想读取下一个浮点数,就调用nextDouble方法。
Java使用条件语句和循环结构控制流程。
块作用域
块(即复合语句)是指由若干条Java语句组成的语句,并用一对大括号括起来。块确定了变量的作用域。一个块可以嵌套在另一个块中。
public static void main(String[] args){
int n;
…
{
int k;
…
}
}
局部变量不能与局部变量同名,也就是说不能在嵌套的两个块中声明同名的变量。
public static void main(String[] args){
int n;
…
{
int k;
int n;
…
}
}
//报错
原因:在内层定义的变量会覆盖在外层定义地变量。
条件语句
Java中,条件语句的形式为:
if(声明条件){
…
}
例如:
if(yourSales >= target){
performance = "Satisfactory";
bonus = 100;
}
- 使用块(有时称为复合语句)可以在Java程序结构中原本只能放置一条(简单)语句的地方放置多条语句。
if(声明条件) {
…
} else {
…
}
例如:
if(yourSales >= target){
performance = "Satisfactory";
bonus = 100 + 0.01 * (yourSales - target);
} else{
performance = "Unsatisfactory";
bonus = 0;
}
else部分总是可选的。else子句与最邻近的if构成一组。
if(声明条件) {
…
} else if(声明条件){
…
}else {
…
}
例如;
if(yourSales >= 2 * target) {
performance = "Excellent";
bonus = 1000;
} else if(yourSales >= 1.5 * target) {
performance = "Fine";
bonus = 500;
} else if(yourSales >= target) {
performance = "Satisfactory";
bonus = 100;
} else {
System.out.println("You're fired");
}
循环
当条件为true时,while循环执行一条语句(也可以是一个语句块)。形式:
while(声明条件){
…
}
如果开始时循环条件的值就为false,那么while循环一次也不执行。
这个语句在最前面检测循环条件。因此,循环体中的代码有可能一次都不执行。如果希望循环体至少执行一次,需要使用do/while循环将检测放在最后。
do {
…
} while(声明条件);
这种循环语句先执行语句(通常是一个语句块),然后再检测循环条件。如果为true,就重复执行语句,然后再次检测循环条件,以此类推。
do {
balance += payment;
double interest = balance * interestRate / 100;
balance += interest;
year++;
…
}while(input.equals("N"));
例如:
public class Retirement{
public static void main(String[]args){
Scanner sc = new Scanner(System.in);
System.out.println("你退休的时候需要多少钱?");
double goal = sc.nextDouble();
System.out.println("你每年上交过多少钱?");
double payment = sc.nextDouble();
System.out.print("银行利率是:%");
double interestRate = sc.nextDouble();
double balance = 0;
int years = 0;
//未达到目标时,更新账户余额
while(balance<goal){
//加上今年的付款和利息
balance += payment;
double interest = balance*interestRate/100;
balance += interest;
years++;
}
System.out.println("你会在"+years+"年退休");
}
}
public class Retirement01{
public static void main(String[]args){
Scanner in = new Scanner(System.in);
System.out.println("你每年上交过多少钱?");
double payment = in.nextDouble();
System.out.print("银行利率是:%");
double interestRate = in.nextDouble();
double balance = 0;
int years = 0;
String input;
//在用户尚未准备退休时更新账户余额
do {
//加上今年的付款和利息
balance += payment;
double interest = balance * interestRate / 100;
balance += interest;
years++;
//输出当前余额
System.out.println(String.format("在%d年后,你的余额是%,.2f%n",years,balance));
//询问是否准备好退休并获取信息
System.out.println("是否准备退休?(N/Y)");
input = in.next();
} while(input.equals("N"));
}
}
确定循环
for(初始化 ; 条件 ; 单步动作){
…
}
1.第一个部分是初始化,可以定义一个新的变量:int count = 10或者直接赋值:I = 10。
2.第二个部分是循环维持的条件。这个条件是先验的,与while循环一样,进入循环之前,首先要检验条件是否满足,条件满足才执行循环;条件不满足就结束循环。
3.第三个部分是步进,即每轮执行了循环体之后,必须执行的表达式。通常我们在这里改变循环变量,进行加或减的操作。
for循环语句是支持迭代的一种通用结构,由一个计数器或类似的变量控制迭代次数,每次迭代后这个变量将会更新。
for(int i = 1 ; i <= 10 ; i++) {
System.out.println(i);
}
for语句的第1部分通常是对计数器初始化;第2部分给出每次新一轮循环执行前要检测的循环条件;第3部分指定如何更新计数器。
- 注意:for语句的3各部分应该对同一个计数器变量进行初始化。若不遵守这一规则,编写的循环常常晦涩难懂。
- 警告:在循环中,检测两个浮点数是否相等需要格外小心。
例如:
for(double x = 0 ; x != 10 ; x += 0.1){
…
}
可能永远不会结束。由于舍入的误差,可能永远都达不到精确的最终值。例如:在上面的循环中,因为0.1无法精确的用二进制表示,所以,x将从9.999 999 999 999 98跳到10.099 999 999 999 98。
当在for语句的第1部分中声明了一个变量后,这个变量的作用域就扩展到这个for循环体的末尾。
for(int i = 1 ; i <= 10 ; i++){
…
}
特别指出,如果在for语句内定义一个变量,这个变量就不能在循环体之外使用。因此,如果希望在for循环体之外使用循环计数器的最终值,就要确保这个变量在循环之外声明!
int i;
for(i = 1 ; i <= 10 ; i++){
…
}
另一方面,可以在不同的for循环中定义同名的变量:
for(int i = 1 ; i <= 10 ; i++){
…
}
…
for(int i = 11 ; i <= 20 ; i++) {
…
}
for循环语句只不过是wile循环的一种简化形式,例如:
for(int i = 10 ; i > 0 ; i--){
System.out.println("…" + i);
}
可以重写为:
int i = 10;
while(i > 0) {
System.out.println("…" + i);
i--;
}
例如:
public class LotteryOdds{//LotteryOdds:彩票赔率
public static void main(String[]args) {
Scanner in = new Scanner(System.in);
System.out.println("你认为你抽取多少个数字就能中奖?");
int k = in.nextInt();
System.out.println("你能抽到的最大数字为:");
int num = in.nextInt();
int lotteryodds = 1;
for(int i = 1 ; i <= k ; i++) {
Lotteryodds = lotteryodds * (num - i + 1) / i;
}
System.out.println("你中奖的概率是:"+lotteryodds+".祝你好运!");
}
}
多重选择:switch语句
在处理多个选项时,使用if/else结构显得有些笨拙。Java有一个与C/C++完全一样的switch语句。
Scanner in = new Scanner(System.in);
System.out.println("请选择:(1 ,2 ,3 ,4)");
int Choice = in.nextInt();
switch(choice){
case 1:
…
break;
case 2:
…
break;
case 3:
…
break;
case 4:
…
break;
case 5:
…
break;
default:
…
break;
}
switch语句将从与选项值相匹配的case标签开始执行,直到遇到break语句,或者执行到switch语句的结束为止。如果没有相匹配的case标签,而有default子句,就执行这个子句。
警告:有可能触发多个case分支。如果在case分支语句的末尾没有break语句,那么就会接着执行下一个case分支语句。这种情况相当危险,常常会引发错误。为此,我们在程序中从不使用switch语句。如果比较喜欢switch语句,编译代码时,可以考虑加上-Xlint:fallthrough选项,如下所示:
javac -Xlint:fallthrough Test.java
这样一来,如果某个分支最后缺少一个break语句,编译器就会给出一个警告消息。
如果你确实正是想使用这种“直通式”(fallthrough)行为,可以为其外围方法加一个注释@SuppressWarnings("fallthrough")。这样就不会对这个方法生成警告了。(注释是为编译器或处理Java源文件或类文件的工具提供信息的一种机制。)
case标签:
- 类型为char、byte、short或int的常量表达式。
- 枚举常量。
- 从Java7开始,case标签还可以是字符串字面量。
例如:
String input = …;
switch (input.toLowerCase()) {
case "yes":
…
break;
…
}
当在switch语句中使用枚举常量时,不必在每个标签中指明枚举名,可以由switch的表达式值推导得出。例如:
Size sz = …;
switch(sz) {
case SMALL:
…
break;
…
}
中断控制流程的语句
通常,使用goto语句被认为是一种拙略的程序设计风格。尽管java设计者将goto作为保留字,但实际上并没有打算在语言中使用它。无限制的使用goto语句容易导致错误,但在某种情况下,偶尔使用goto跳出循环还是有益处的。Java设计者同意这种看法,甚至在Java语句中增加了一条新语句:带标签的break,以此来支持这种程序设计风格。不带标签的break语句,与用于退出switch语句的break语句一样,它也可以用于退出循环语句。例如:
while(years <= 100) {
balance += payment;
double interest = balance * interestRate / 100;
balance += interest;
if(balance >= goal) break;
years++;
}
在循环开始时,如果years > 100 , 或者在循环体中balance ≥ goal , 则退出循环语句。当然也可以在不可以使用break的情况下计算years的值,如下所示:
while(years <= 100 && balance < goal) {
balance += payment;
double interest = balance * interestRate / 100;
balance += interest;
if(balance < goal)
years++;
}
但需要注意的是,这个版本检测了两次balance <goal。为了避免重复检测,可以使用break语句。
Java还提供了一种带标签的break语句,用于跳出多重嵌套的循环语句。因为有些时候,嵌套很深的循环语句会发生一些不可预料的事。此时可能更加希望完全跳出所有循环嵌套之外。
这里有一个示例说明了break语句的工作状态。
- 请注意:标签必须放在希望跳出的最外层循环之前,并且必须紧跟一个冒号。
Scanner in = new Scanner(System.in);
int n;
read_date:
while(…) {
…
for(…) {
System.out.print("Enter a number >= 0:");
n = in.nextInt();
if(n < 0)
Break read_date;
…
}
}
if(n < 0) {
…
} else {
…
}
如果执行有误,执行带标签的break会跳转到带标签的语句块末尾。与任何使用break语句的代码一样,然后需要检测循环是正常结束,还是由break跳出。事实上,可以将标签应用到任何语句,甚至可以将其应用到if语句或者块语句,如下所示:
label:
{
…
if(condition) break label;
…
}
因此,如果确实希望使用goto语句,而且一个代码块恰好在你想要转跳的位置之前结束,就可以使用break语句!
continue语句与break语句一样,他将中断正常的流程控制。continue语句将控制转移到最内层循环的首部。
例如:
Scanner in = new Scanner(System.in);
while(sum < goal) {
System.out.print("Enter a number:");
n = in.nextInt();
if(n < 0) continue;
sum += n;
}
如果n < 0 , 则continue语句越过了当前循环体的剩余部分,立刻跳到循环首部。
如果将continue语句用于for循环中,就可以跳到for循环的“更新”部分。
例如:
for(count = 1 ; count <= 100 ; count++){
System.out.print("Enter a number , -1 to quit:");
n = in.nextInt();
if(n < 0) continue;
sum += n;
}
如果n < 0 , 则continue语句将跳到count++语句。
还有一种标签的continue语句,将跳到与标签匹配的循环的首部。
例子:
public class YuanAnglePenny {
public static void main(String[]args) {
Scanner in = new Scanner(System.in);
System.out.println("请输入你现存的金额:");
int amount = in.nextInt();
int isExit = 0;
for(int one = 0 ; one <= amount ; ++one) {
for(int five = 0 ; five <= amount / 5 ; ++five) {
for(int ten = 0 ; ten <= amount / 10 ; ++ten) {
for(int twenty = 0 ; twenty <= amount / 20 ; ++twenty) {
if(one + five * 5 + ten * 10 + twenty * 20 == amount) {
System.out.println(one+"张1元,"+five+"张5元,"+ten+"张10元,"+twenty+"张20元。");
isExit = 1;
break;
}
}
if(isExit == 1) break;
}
if(isExit == 1) break;
}
if(isExit == 1) break;
}
}
}
public class YuanAnglePenny {
public static void main(String[]args) {
Scanner in = new Scanner(System.in);
System.out.println("请输入你现存的金额:");
int amount = in.nextInt();
OUT://标号
for(int one = 0 ; one <= amount ; ++one) {
for(int five = 0 ; five <= amount / 5 ; ++five) {
for(int ten = 0 ; ten <= amount / 10 ; ++ten) {
for(int twenty = 0 ; twenty <= amount / 20 ; ++twenty) {
if(one + five * 5 + ten * 10 + twenty * 20 == amount) {
System.out.println(one+"张1元,"+five+"张5元,"+ten+"张10元,"+twenty+"张20元。");
Break OUT;
}
}
}
}
}
}
}
for each循环
Java有一种功能很强的循环结构,可以用来依次处理数组(或者其他元素集合)中的每个元素,而不必考虑指定下指标。
这种增强的for循环的语句格式为:
for(variable : collection)statement
它定义一个变量用于暂存集合中的每一个元素,并执行相应的语句(也有可能是语句块)。collection这一集合表达式必须是一个数组或者是一个实现了Iterable接口的类对象(例如:ArrayList)。
例如:
for(int element : a){
System.out.println(element);
}
打印数组a的每一个元素,一个元素占一行。
这个循环应该读作”循环a中的每一个元素(for each element in a)“。Java语言的设计者认为应该使用诸如foreach、in这样的关键字,但这种循环语句并不是最初就包含在Java语言中的,二十后来添加进去的,而且没有人希望破坏已经包含同名(例如:System.in)方法或变量的旧代码。
使用传统的for循环也可以获得同样的效果:
for(int i = 0 ; i < a.length ; i++){
System.out.println(a[i])
}
但是,for each循环语句显得更简洁、更不容易出错,因为你不必为下标的起始值和终止值而操心。
- 注释:for each循环语句的循环变量将会遍历数组中的每个元素,而不是下标值。
如果需要处理一个集合中的所有元素,for each循环语句相对于传统循环语句所做的改进很让人欣喜。然而,在很多情况下还是需要用传统的for循环。例如,如果不希望遍历整个集合,或者在循环内部需要使用下标值时。
- 提示:有一个更加简单的方式可以打印数组中的所有值,即利用Arrays类的toString方法。调用Arrays.toString(a),返回一个包含数组元素的字符串,这些元素包围在中括号内,并用逗号分隔,例如:"[2 , 3 , 5 , 7 , 11 , 13]"。想要打印数组,只需要调用
System.out.println(Arrays.toString(a));
题目:
f(n)=1-1/2+1/3-1/4+…+1/n;
public class ConvergentSeriesTwo{
public static void main(String[]args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
double sum = 0.0;
int sign = 1;
//for(int i=1;i<=n;i++){
//sum+=sign*(1.0/i);
//sign=-sign;
//}
for(int i =1 ; i <= n ; i++){
if(i % 2 == 1){
sum += 1.0/i;
}else{
sum -= 1.0/i;
}
}
System.out.printf("%.2f",sum);
}
}