通过输出各种 * 来学习循环
A) 输出下面的图形
********** |
这个问题太简单了!
1 2 3 4 5 6 7 | #include <stdio.h> int main(int argc, char *argv[]) { printf("**********"); return 0; } |
如果从另一个角度来思考,也可以认为是输出 * 这个动作重复了十次。计算机最擅长的就是重复了,在程序设计中就是循环。
使用C-Free的 for 循环模板,可以得到下面的代码
1 2 3 4 5 6 7 | for ( ; ; ) { } for (表达式1; 表达式2 ; 表达式3) { 若干条语句 ; } |
这里要重复十次, 循环变量 i 可以从0~9,或者从1~10,当然从10~1 或 9~0也是相同的。 表达式1用来初始话变量;表达式2是判断表达式,决定是否继续循环;表达式3用于改变循环变量。
1 2 3 4 | int i; for(i=1; i<=10 ; i=i+1) { printf("*"); } |
上面的 for 循环可以解读为循环变量 i 由小到大的遍历集合 [1..10] 中的每一个数,集合中有几个数,循环体(大括号内的语句,这里是 printf("*");)就执行了多少次。
如果没有特定的上下文,最常用的循环变量为 i、j、k。
【再学一招】
输出一个字符时,可以使用 putchar 函数。printf 当然也可以,只是有点杀鸡用牛刀的感觉哦。
1 2 3 4 | int i; for(i=1; i<=10 ; i=i+1) { putchar('*'); } |
需要注意的是, 单个字符使用 单引号 ' ' ,字符串使用双引号 " "。 “*" 表示字符串的内容只有一个,但本质上还是字符串, '*' 则表示字符。
【再学一招】
由于递增1这个操作在计算机中是如此普遍,C语言特为此创建了专用的运算符 ++, i=i+1 可以写成 i++ 或者 ++i。你尝试把 上面代码中的 i=i+1 改写成 i++ 试试吧。
C语言还有专用的递减运算符,你猜猜递减运算符是怎样的?
B) 输出下面的图形
********** ********** ********** ********** ********** ********** ********** ********** |
下面的代码虽然不雅,但也能解决问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <stdio.h> int main(int argc, char *argv[]) { printf("**********\n"); printf("**********\n"); printf("**********\n"); printf("**********\n"); printf("**********\n"); printf("**********\n"); printf("**********\n"); printf("**********\n"); return 0; } |
再分析一下, 是 printf("**********\n"); 这个动作重复了8次。 这就可以使用循环来解决,请看下面的程序。
1 2 3 4 5 6 7 8 9 10 11 | #include <stdio.h> int main(int argc, char *argv[]) { int i; for (i=1; i<=8; i++) { printf("**********\n"); } return 0; } |
上面已经分析过, printf("**********\n"); 也可以用循环来实现,于是,有下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <stdio.h> int main(int argc, char *argv[]) { int i, j; for (i=1; i<=8; i=i+1) { for (j=1; j<=10; j=j+1) { printf("*"); } printf("\n"); } return 0; } |
i 从1~8,称为外层循环;j 从 1~10,称为内层循环。
我们可以把 m 和 n 来替代 8 和 10, m 和 n 可以从键盘输入,这样我们就可以通过两个数字来输出 * 图案了。
#include <stdio.h> int main(int argc, char *argv[]) { int i, j, m, n; scanf("%d%d", &m, &n); for (i=1; i<=m; i=i+1) { for (j=1; j<=n; j=j+1) { printf("*"); } printf("\n"); } return 0; } |
如果我们只需要输出 * 的正方形,则只需要一个参数,因为 m==n。
C) 输出下面的*三角形
* ** *** **** ***** ****** ******* ******** ********* |
每行输出 * 这个动作重复了9次,但不同的是,每次输出的 * 个数有差别,不再是统一的了。分析一下规律,可以发现第1次输出1个*,第2次输出2个*,第 i 次输出 i 个* 。从内层循环的角度来看,输出多少个 * 取决于 j 遍历的集合中的数的个数,由于 j 是从1开始的,那么集合 [1..i] 恰好有 i 个数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include <stdio.h> int main(int argc, char *argv[]) { int i, j, n; scanf("%d", &n); for (i=1; i<=n; i=i+1) { for (j=1; j<=i; j=j+1) { printf("*"); } printf("\n"); } return 0; } |
如果你还是觉得难以理解,那么请看下面的描述:
1 2 3 4 | for (i=1; i<=n; i=i+1) { 输出 i 个 * ; printf("\n"); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <stdio.h> void print_n_star(int n) { int j; for (j=1; j<=n; j++) putchar('*'); } int main(int argc, char *argv[]) { int i, j, n; scanf("%d", &n); for (i=1; i<=n; i=i+1) { print_n_star(i); printf("\n"); } return 0; } |
上面的代码中,我们使用了函数。 你可以体会到函数的作用了:1)简化主程序,使得结构更加清晰,便于理解;2)有利于代码复用。
之前我们使用过很多函数,如 scanf、printf、putchar等。由于这些函数是如此的常用,C语言提供了这些函数的实现,但使用这些函数时,需要 #include 命令。
很多时候,我们需要实现很个性化的功能,这是就需要自己来设计函数了。在上面的程序中,设计了 print_n_star 这个函数,从名字上就很容易理解:打印 n 个 * 。
1 2 3 4 5 6 | void print_n_star(int n) { int j; for (j=1; j<=n; j++) putchar('*'); } |
函数的构成: 返回值的类型(这里的void表示没有返回值),函数的名字(print_n_star),函数的形式参数(int n,函数体(大括号内的语句)。
形式参数:函数定义时所用的参数,如 n。之所以称为形式参数,是因为这个变量取 n 还是 k 还是 i 或者其他,都可以的,当然不能是 j,因为 j 在函数体内使用了。
实际参数:调用函数时的参数,上面的例子中是 i。实际参数的值会传递给形式参数。
小练习:输出下面的 * 三角形(下三角形)
********* ******** ******* ****** ***** **** *** ** * |
D) 输出下面的图案,奇数行是
********* --------- ********* --------- ********* --------- ********* |
在解决这个问题前,先来回顾一下所有输出都是 * 的程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include <stdio.h> int main(int argc, char *argv[]) { int i, j, m, n; scanf("%d%d", &m, &n); for (i=1; i<=m; i=i+1) { for (j=1; j<=n; j=j+1) { printf("*"); } printf("\n"); } return 0; } |
在上面程序的基础上,略作修改,就是
1 2 3 4 5 6 7 8 9 10 11 12 13 | int i, j, m, n; scanf("%d%d", &m, &n); for (i=1; i<=m; i=i+1) { for (j=1; j<=n; j=j+1) { if (i是奇数) { 输出 * ; } else { 输出 - ; } } printf("\n"); } |
思考一下,如何输出下面的图案(首末两行输出*,其余输出-)
1 2 3 4 5 6 7 | ********* --------- --------- --------- --------- --------- ********* |
提示:在C语言中, 使用运算符 || 表示或者, 如 if (i==1 || i==2),这样写的话第1行和第2行会输出 *,其余输出 - 。
思考一下,如何输出下面的图案(首末两列输出*,其余输出-)
1 2 3 4 5 6 7 | *-------* *-------* *-------* *-------* *-------* *-------* *-------* |
提示: 列和循环变量 j 有关。
再思考一下,如何输出下面的图案(四周*,其余输出-)
1 2 3 4 5 6 7 | ********* *-------* *-------* *-------* *-------* *-------* ********* |
E) 输出下面的图案
1 2 3 4 5 | * ** *** **** ***** |
在解答这道题之前,把前面的函数改成更为通用一些,字符可以在函数中指定
1 2 3 4 5 6 | void print_n_char(int n, char c) { int i; for (i=1; i<=n; i++) putchar(c); } |
当n=4时,输出的图案用语言描述就是
1 2 3 4 | 输出3个空格,输出1个*; 输出2个空格,输出2个*; 输出1个空格,输出3个*; 输出0个空格,输出4个*; |
如果把数字4改成更为通用的n,应用循环,就是
1 | 输出 n-i 个空格,输出 i 个*; |
改写成C语言,就是
1 2 | print_n_char(n-i, ' '); print_n_char(i, '*'); |
F) 终极挑战:美丽的蝴蝶
你用记事本尝试画画,比如当n=5时,图像是怎么画出来的,然后写下来,分析一下,就能写出程序了。
开始挑战吧!Top训练营挑战系列A