《计算机程式设计》Week2 课堂笔记

本笔记记录自 Coursera课程 《计算机程式设计》 台湾大学 刘邦锋老师

Week2 Control Structure

2-1 If-then-else

if then 判断

if (condition)
    statement;

根据condition决定是否执行statement。

例子:(if-then.c) 只显示正数

#include <stdio.h>
main()
{
    int i;
    scanf("%d", &i);
    if (i > 0)
        printf("%d\n", i);
}

if then else 判断

if (condition)
    statement1;
else
    statement2;

例子:(abs.c)显示绝对值

#include <stdio.h>
main()
{
    int i;
    int k;
    scanf("%d", &i);
    if (i > 0)
        k = i;
    else
        k = -i;
    printf("%d\n", k);
}

例子:(max-3.c)决定三个数中的最大值

#include <stdio.h>
main()
{
    int i, j, k, max;
    scanf("%d", &i);
    scanf("%d", &j);
    scanf("%d", &k);
    if (i > j)
        max = i;
    else
        max = j;
    if (k > max)
        max = k;
    printf("%d\n", max);
}

else if

if (condition1)
    statement1;
else if (condition2)
    statement2;
else
    statement3;

这种多层次的if-then-else结构称为巢状结构。

例子:(leap-year-else-if.c)使用 else if 判定闰年

#include <stdio.h>
main()
{
    int year, k;
    scanf("%d", &year);
    if (year % 400 == 0)
        k = 1;
    else if ((year % 4 == 0) && (year % 100 != 0))
        k = 1;
    else
        k = 0;
    printf("%d\n", k);
}

2-2 Condition expression

判断式值

(cond)? expression1 : expression2

如果cond为真,那么算式的值是expression1,否则为expression2

例子:(cond-abs.c)使用判断式值计算绝对值

#include <stdio.h>
main()
{
    int i;
    int k;
    scanf("%d", &i);
    k = (i > 0)? i: -i;
    printf("%d\n", k);
}

2-3 Switch

switch 判断

switch (flag){
    case 1:
        statement1;
        break;
    case 2:
        statement2;
        break;
        ...
    case n:
        statementn;
        break;
    default:
        default_statement;
}

根据flag的值决定要执行的statement

【注】

  • flag必须是变量,而不是算式
  • case之后的必须是常数,不能是算式
  • statement之后的break不可省略
  • 可以把一开始的switch(flag)想象成一个根据flag的值的“跳跃”
  • 当执行完对应的statement之后必须跳出switch

例子:(switch-power.c)计算power

int i, j, power;
scanf("%d", &power);
scanf("%d", &i);
switch (power){
    case 1:
        j = i;
        break;
    case 2:
        j = i * i;
        break;
    case 3:
        j = i* i * i;
        break;
    default:
        j = 0;
}
printf("%d\n",j);

例子:(month.c)决定一个月的天数

#include <stdio.h>
main()
{
    int year, month, days;
    scanf("%d", &year);
    scanf("%d", &month);
    switch (month){
        case 1: case 3: case 5: case 7: case 8: case 10: case 12:
            days = 31;
            break;
        case 4: case 6: case 9: case 11:
            days = 30;
            break;
        case 2:
            if ((year % 400 == 0) || (year % 4 == 0 && (year % 100 != 0)))
                days = 29;
            else
                days = 28;
            break;
        default:
            days = 0;
    }
    printf("%d\n", days);
    return 0;
}

为了程序的正确性,我们必须在每个switch加上default用以处理例外的状况。

2-4 While loop

while循环

while (condition)
    statement;

当condition为真时,就会重复执行statement,直到condition为假。

例子:(not-less-than.c)5的倍数中不小于j的最小值

#include <stdio.h>
main()
{
    int i = 0;
    int j;
    scanf("%d", &j);
    while (i < j)
        i += 5;
    printf("%d\n", i);
}

2-5 For loop

for循环

for (initialization; condition; adjustment)
    statement;

首先会执行初始化(initialization)的部分,而且每一次循环之前都会检查条件,条件为真则执行statement,再执行调整(adjustment)并回到循环的开始,否则结束循环。

当然也可以使用while循环来表示for循环,就是不够精简。

initialization;
while (condition){
    statement;
    adjustment;
}

对于固定次数的for循环,应该如下这样写

for (i = 0; i < 100; i++)
    statement;

这个代码也就是i的值在初始化中被设为了0,每一次进循环前都要检查条件(i < 100),调整的部分则为(i++)。

例子:(for-print.c)在for循环中列印i的值

#include <stdio.h>
main()
{
    int i;
    int j;
    scanf("%d", &j);
    for (i = 0; i < j; i++)
        printf("%d\n", i);
}

2-6 Do While loop

do while循环

do
    statement;
while (condition);

先执行循环的主体部分一次,再测试条件。如果条件成立,则继续执行循环的主体部分;如果条件不成立,则结束循环。

例子:(do-while.c)将i由100加到101

#include <stdio.h>
main()
{
    int i;
    scanf("%d", &i);
    do
        i++;
    while (i < 0);
    printf("%d\n", i);
}

2-7 Loop break and continue

用break提早结束一个循环

其实对于其他类型的循环也差不多,这里以while为例子

while (loop_condition){
    ...
    if (break_condition)
        break;
    ...
}

使用break提早结束一个循环会让程序的流程较为模糊,因为我们比较希望一个循环只有一个入口和一个出口。

如果循环可以因为不满足循环条件而结束,或是由break结束,则就会有两个出口,这样会让读程序的人不容易了解程序的流程。

改进的办法是使用旗标将break的条件也纳入循环继续执行的条件,这样就可以避免两个出口的问题。

以下为使用旗标提早结束的for循环

#include <stdio.h>
main()
{
    int i;
    int j = 0;
    int n;
    scanf("%d", &n);
    for (i = 2; ((i * i) <= n) && (j == 0); i++)
        if ((n % i) == 0)
            j = 1;
    printf("%d\n", j);
}

用continue提前结束本次循环

使用continue可跳过本次循环的剩下的部分,直接进入下一个循环。

这通常是为了清楚表明程序的流程,表明在某种状况下,我们必须重新回到循环的起点。

比如说,从读入数字,但只挑选其中的正数相加。此时如读到非正数,则不予处理并重新回到循环的起点。

例子:(continue.c)挑选输入的正数相加

main()
{
    int sum = 0;
    int count, i, n;
    scanf("%d", &n);
    for (count = 0; count < n; count++){
        scanf("%d", &i);
        if (i <= 0)
            continue;
        sum += i;
    }
    printf("%d\n", sum);
}

附上测试自己写的代码

#include <stdio.h>

main()
{
	int year, day, month, week_usr, week_pre, days;
	int n;
	int flag = 0;
	int i, j;
	int sum;
	
	scanf("%d %d", &year, &week_usr);
	scanf("%d", &n);
	
	flag = year % 400 == 0 || ( year % 100 && year % 4 == 0 );
	
	for (i = 0; i < n; i++){
		if ( i ) printf ( " " );
		
		sum = 0;
		scanf("%d %d", &month, &day);
		if (month > 12 || month <= 0)
			printf("-1");
		else{
			switch (month){
				case 1: case 3: case 5: case 7: case 8: case 10: case 12:
					days = 31;
					break;
				case 4: case 6: case 9: case 11:
					days = 30;
					break;
				case 2:
					if (flag == 1)
						days = 29;
					else
						days = 28;
					break;
				default:
					days = 0;
			}
		
			
			if (day > days || day <= 0)
				printf("-2");
			else{
				for (j = 1; j < month; j++){
					switch (j){
						case 4: case 6: case 9: case 11:
							sum = sum + 30;
							break;
						case 2:
							if (flag == 1)
								sum = sum + 29;
							else
								sum = sum + 28;
							break;
						default:
							sum = sum + 31;
					}
				}
				sum = sum + day + week_usr - 1;
				week_pre = sum % 7;
				printf("%d", week_pre);
			}
		}
	}
}

以及老师给的答案代码

#include <stdio.h>
main()
{
   int y, d;
   int n;
   int month, day;
   int leap_year;
   int days;

   scanf ( "%d%d", &y, &d );
   scanf ( "%d", &n );

   // leap year or not
   leap_year = y % 400 == 0 || ( y % 100 && y % 4 == 0 );

   // calculate each input line
   for ( int i = 0; i < n; i++ ) {
      if ( i ) printf ( " " );

      days = d;
      scanf ( "%d%d", &month, &day );

      if ( month < 1 || month > 12 ) {
         printf ( "-1" );
         continue;
      }
      if ( day < 1 ) {
         printf ( "-2" );
         continue;
      }
      else {
         switch ( month ) {
            case 2:
               if ( ( leap_year && day > 29 ) ||
                    ( !leap_year && day > 28 ) ) {
                  printf ( "-2" );
                  continue;
               }
               break;
            case 4: case 6: case 9: case 11:
               if ( day > 30 ) {
                  printf ( "-2" );
                  continue;
               }
               break;
            default:
               if ( day > 31 ) {
                  printf ( "-2" );
                  continue;
               }
         }
      }

      for ( int m = 1; m < month; m++ ) {
         switch ( m ) {
            case 2:
               if ( leap_year ) days += 29;
               else days += 28;
               break;
            case 4: case 6: case 9: case 11:
               days += 30;
               break;
            default:
               days += 31;
         }
      }

      days += ( day - 1 );
      printf ( "%d", days % 7 );
   }

   return 0;
}
posted @ 2018-07-04 21:26  Yingjing  阅读(237)  评论(0编辑  收藏  举报