- 控制语句:顺序、选择、循环
- 程序的三种基本结构:顺序结构、选择结构、循环结构。
顺序结构中的语句可能是简单语句,也可能是复合语句,还可能是空语句。
- 三种语句:
1. 简单语句:以";"结尾的语句。
2. 复合语句:用"{}"把“说明”和若干个有序的简单语句组合在一起构成的集合。
3. 空语句:什么动作都不执行,只有一个分号。
选择语句:if, if-else, switch
1. if语句的功能:单选、多选一
单选:
if(表达式) 语句(或复合语句)
多选一:if-else, if-else if-else if-…-else
程序1:三个人的平均成绩大于90分,则输出平均成绩和excellence。
/* 三个人的平均成绩大于90分,则输出平均成绩和excellence */ /* 我写的程序 */ # include"stdio.h" #include"stdlib.h" int main() { float a, b, c, sum, average; scanf_s("%f%f%f", &a, &b, &c); sum = a + b + c; average = sum / 3; if (average > 90) { printf("这三个人的平均成绩是%.2f:\n", average); printf("excellence!\n"); } system("pause"); return 0; }
程序2:求b的绝对值。
/* 取b的绝对值 */ /* 我写的程序 */ # include"stdio.h" #include"stdlib.h" int main() { int b; scanf_s("%d", &b); if (b >= 0) { printf("b的绝对值为%d\n", b); } else { printf("b的绝对值为%d\n", -b); } system("pause"); return 0; }
/* 取b的绝对值 */ # include"stdio.h" #include"stdlib.h" int main() { int b,a; scanf_s("%d", &b); if (b >= 0) { a = b; } else { a = -b; } printf("b的绝对值是:%d\n", a); system("pause"); return 0; }
可以优化:用三目运算符表示!!!像下面这样:
/* 取b的绝对值 */ /* 用三目运算符表示 */ # include"stdio.h" #include"stdlib.h" int main() { int b,a; scanf_s("%d", &b); a = b >= 0 ? b : -b; printf("b的绝对值是:%d\n", a); system("pause"); return 0; }
心得:如果要求较大值,那么可以用if-else,也可以用三目运算符,表示为max = a>=b?a:b;
注意配对问题!!!if-else可以嵌套使用(注意配对问题!注意:不是对齐就是配对!配对时不看缩进,以最近配对为原则!因此为了不出错,养成加括号的好习惯!)。
2. C语言提供了另一种更方便简洁的进行多重选择的语句:switch语句。
switch(表达式) // 表达式只能是整数类型或字符类型 { case 常数1:语句1 break; // 跳出switch语句,如果没有break,那么也会执行后面的case中的语句。 case 常数2:语句2 break; … case 常数n:语句n break; default:语句n-1; }
程序3:从键盘输入一个月号(1~12),并显示该月号的英文名称。
/* 从键盘输入一个月号(1~12),并显示该月号的英文名称 */ # include"stdio.h" #include"stdlib.h" int main() { int month; printf("请输入一个月号:\n"); scanf_s("%d", &month); switch (month) // 即使只有一个变量,也要加括号!! { case 1:printf("January"); // 注意:case后面的语句也要加分号;!! break; case 2:printf("February"); break; case 3:printf("March"); break; case 4:printf("April"); break; case 5:printf("May"); break; case 6:printf("June"); break; case 7:printf("July"); break; case 8:printf("August"); break; case 9:printf("September"); break; case 10:printf("October"); break; case 11:printf("November"); break; case 12:printf("December"); break; default:printf("Data Error!"); break; } system("pause"); return 0; }
- 选择结构小结:
1. if语句:单选、二选一、多选一。
2. switch语句:多选一。
- 三种循环语句:for,while,do while。
1. for语句:
for(表达式1;表达式2;表达式3) // 后面的三个表达式要用分号分隔开! 循环体; // 养成加花括号的好习惯!
for语句执行过程:先计算表达式1(只执行一次),然后判断表达式2,如果2为真则进行循环体执行,循环体执行完毕执行表达式3,表达式3执行完再判断表达式2……
程序4:求n的1~5次方。
/* 求n的1~5次方 */ /* 我写的程序 */ # include"stdio.h" #include"stdlib.h" int main() { int n,i,m; scanf_s("%d", &n); for (i = 1;i < 6;i++) { m = pow(n, i); // error: "pow"未定义,假设外部返回int(原因:没有加头文件math.h)。 printf("n的%d次方为%d:\n", i,m); } system("pause"); return 0; }
/* 求n的1~5次方 */ /* 我写的程序 */ # include"stdio.h" #include"stdlib.h" #include"math.h" int main() { int n, i, m; scanf_s("%d", &n); for (i = 1;i < 6;i++) { m = pow(n, i); // error: 从double到int可能丢失数据(因为pow函数两个参数都是double型数据),但最终还是正确输出了。 printf("n的%d次方为%d:\n", i, m); } system("pause"); return 0; }
由于丢失数据,因此会出现结果错误的情况:
/* 求n的1~5次方 */ /* 用一个变量result来存储之前的n-1次方,也就是递归的思想,优点:降低复杂度,减小所需内存空间 */ # include"stdio.h" #include"stdlib.h" int main() { int n, I; long result = 1; scanf_s("%d", &n); for (i = 1;i < 6;i++) { result *= n; printf("n的%d次方为%ld:\n", i,result); } system("pause"); return 0; }
注意:for语句十分灵活,里面三个表达式可以对多个变量进行处理,方法是:for(i=0,=100; (j-i)>10; i++,j--)。也就是说三个表达式使用分号分隔,一个表达式内部可以对多个变量进行处理,用逗号分隔。
允许在循环体内改变循环控制变量的值(即表达式2的值),这样可以控制(改变循环次数)。
三个表达式均可缺省:
1. 不需要修改循环变量的值,可缺省表达式3:
for(i=0;i!=100;)
2. 如果不再需要对循环变量进行初始化,可缺省表达式1:
for(;i>20;i++)
3.一直循环下去(死循环):(前面提到的,循环体内是可以修改循环次数的,并且我们可以借用其他关键字来退出死循环。)
for(; ;)
4. 省略循环体(其实是把循环体放到了for后面的三个表达式中):
for(i=1,j=1;i<1000;i++,j*=1);
它和下面一种表达方式是等价的!
for(i=1,j=1;i<1000;i++) j*=1;
程序5:输出9*9乘法表。
/* 输出一个9*9乘法表 */ # include"stdio.h" #include"stdlib.h" int main() { for (int i = 1;i <= 9;i++) { printf("%4d", i); // 若想输出的数据有空格,那么可以在%d后面加一个空格:'%d '。 } printf("\n----------------------------------------\n"); for (int i = 1;i < 10;i++) // 控制行 for (int j = 1;j < 10;j++) // 控制列 { if (j != 9) printf("%4d", i*j); else printf("%4d\n", i*j); // 每行的第9列要进行换行,因此这里用了if-else语句! } system("pause"); return 0; }
- for语句常用于已知循环次数,若事先不知道循环次数,用while和do-while。
1. while语句功能:表达式为真,执行循环体。一般形式为:
while(表达式) { 循环体 }
2. do-while语句功能:先执行一次循环体,再判断表达式是否为真,因此do-while语句至少执行一次循环体。一般形式为:
do { 循环体 }while(表达式);
循环类型:
1. 当型循环(先判断再执行,当表达式为假停止循环)
2. 直到型循环(先执行循环体,再判断)
程序6:读入字符并回显,直到读入'*'为止。
/* 读入字符并回显,直到读入'*'为止 */ #include "stdio.h" #include<stdlib.h> int main() { char c; printf("请输入字符:\n"); c = getchar(); // 注意:键盘输入一个字符,可以用getchar(),这个函数括号里面没有参数! //scanf_s("%c", &c, 1); // 键盘输入一个字符,也可以用scanf_s函数,注意scanf_s函数用于字符型变量时,应该注明字符个数! while (c != '*') // 注意:这里要加单引号! { putchar(c); // 输出一个字符,也可用printf函数 c = getchar(); } system("pause"); return 0; }
/* 读入字符并回显,直到读入'*'为止 */ /* 优化的程序,getchar在while外面和里面都执行到了,因此可以放到while表达式里面 */ #include "stdio.h" #include<stdlib.h> int main() { char c; printf("请输入字符:\n"); while ((c = getchar()) != '*') { putchar(c); } system("pause"); return 0; }
- 循环结构总结:
for语句、while语句、do-while语句。
表达式为真执行循环体。
- 其他流程控制语句:
1. break两个作用:switch语句中分隔case; 立即跳出循环语句。
2. continue作用:循环中遇到continue,直接跳过continue下面的所有语句,直接进入下一次循环操作。
3. goto语句:无条件转移语句,直接跳到标号所指语句。( 一般形式如下)
goto 标号; …… 标号:语句;
注意:goto语句十分灵活,很容易改变我们的运行流程,尽量避免使用,否则出错不容易找原因。
程序7:输入n个实型数,只对正实型数进行输出。
/* 输入n个实型数,只对正实型数进行输出 */ #include "stdio.h" #include<stdlib.h> int main() { float x; for (int i = 1;i < 100;++i) { scanf_s("%f", &x); if (x < 0.0) continue; // 跳过后面的printf函数,直接进入下一次循环 printf("%f\n", x); } }
程序8:买苹果。每个苹果0.8元,第一天买两个,以后每天买的个数是前一天的两倍,直至购买的苹果个数达到不超过100的最大值,求每天平均花多少钱。
/* 买苹果 */ #include "stdio.h" #include<stdlib.h> int main() { float s, m = 0.8, sum=0, msum; int n = 2,d; for (d=0;n <= 100;++d) { sum += n; n *= 2; } s = sum * m; printf("%d天一共花了%f元!\n", d,s); msum = s / d; printf("平均每天花费%.2f元\n", msum); system("pause"); return 0; }
注意:for语句中int d和for前面就int d是不一样的!在外面int d,那么for循环之后d依然可用。但如果是for语句中int d,那么只有在for循环中d可以用,for循环之后不可以用!(我的错误!)
/* n天一共买了多少苹果 */ #include <stdio.h> #include<stdlib.h> #include"math.h" int main() { int n, i, m = 2, sum = 0; printf("Input n...\n"); scanf_s("%d", &n); for (i = 1;i <= n;++i) { sum += m; m *= 2; } printf("%d天共买了%d个苹果!\n", n, sum); system("pause"); return 0; }
程序9:猜数游戏。计算机想一个[1,100]数,然后猜一个数,计算机给出大了还是小了。
思路:
计算机中随机函数rand()函数可以模拟“想”一个数,它是用来产生[0,rand_max]之间的随机数,头文件是<stdlib.h>,rand_max在头文件中定义,是不大于双字节整数的最大值32767。
产生[0,b-1]之间的随机数:magic = rand() % b;
产生[a,a+b-1]之间的随机数:magic = rand() % b + a;
/* 猜数游戏 */ /* 只猜一次 */ #include "stdio.h" #include<stdlib.h> int main() { int a, b; a = rand() % 100 + 1; // 计算机“想”一个[1,100]之间的数! scanf_s("%d", &b); if (b > a) { printf("大了\n"); } else if (b < a) { printf("小了\n"); } else { printf("right!"); printf("%d", b); } system("pause"); return 0; }
/* 猜数游戏 */ /* 直到猜对为止 */ #include "stdio.h" #include<stdlib.h> int main() { int magic, guess; int counter = 0; // 增加了人猜次数的计数器变量 magic = rand() % 100 + 1; // 计算机“想”一个[1,100]之间的数! while (1) { scanf_s("%d", &guess); ++counter; if (guess > magic) { printf("大了,请输入小于%d的值......\n",guess); } else if (guess < magic) { printf("小了,请输入大于%d的值......\n", guess); } else { printf("right!"); printf("%d", guess); break; } continue; } system("pause"); return 0; }
问题:为什么计算机“想”的数都是42,每次都一样?
答:函数rand()产生的是伪随机数,是用算法得到的,初始值一样,算法一样,因此每次得到的伪随机数都一样。为了得到不同的伪随机数,需要对初始值(随机种子)随机化,随机函数srand()是设置随机种子(产生不同的初始值),因此它可实现对rand()函数的随机化。用法如下:
scanf("%u",&seed); srand(seed); // 产生随机种子 magic=rand()%100+1;
计算机自动产生随机种子,因为计算机执行的时间不同,因此我们用计算机的时钟值作为随机种子,产生[1,100]间的随机数。函数time()返回以秒计算的当前时间值,该值被转换为无符号整数并用作随机数发生器的种子。time能为程序员提供代表时间的字符串,使用NULL作为函数参数,使其不具备此功能。如下:
#include<time.h> srand(time(NULL)); magic=rand()%100+1;
/* 猜数游戏 */ /* 直到猜对为止 */ #include "stdio.h" #include<stdlib.h> #include<time.h> int main() { int magic, guess; int counter = 0; // 增加了人猜次数的计数器变量 srand((unsigned int)time(NULL)); // 从“time_t”转换到“unsigned int”,可能丢失数据,因此我们做强制转换。 // time()函数在头文件"time.h"中! magic = rand() % 100 + 1; // 计算机“想”一个[1,100]之间的数! while (1) { scanf_s("%d", &guess); ++counter; if (guess > magic) { printf("大了,请输入小于%d的值......\n",guess); } else if (guess < magic) { printf("小了,请输入大于%d的值......\n", guess); } else { printf("right!"); printf("%d", guess); break; } continue; } system("pause"); return 0; }
/* 猜数游戏 */ /* 最多猜10次 */ #include "stdio.h" #include<stdlib.h> #include<time.h> int main() { int magic, guess; int counter = 0; // 增加了人猜次数的计数器变量 srand((unsigned int)time(NULL)); // 从“time_t”转换到“unsigned int”,可能丢失数据,因此我们做强制转换。 // time()函数在头文件"time.h"中! magic = rand() % 100 + 1; // 计算机“想”一个[1,100]之间的数! do { scanf_s("%d", &guess); ++counter; if (guess > magic) { printf("大了,请输入小于%d的值......\n",guess); } else if (guess < magic) { printf("小了,请输入大于%d的值......\n", guess); } else { printf("right!"); printf("%d", guess); } } while ((guess != magic) && (counter < 10)); // 注意:do-while语句的while后面还有分号! // 注意:逻辑与是两个&! system("pause"); return 0; }
程序10:求素数。给定一个数,判断它是不是素数。
判断方法:看2~n-1能不能被n整除,如果能则它不是素数。
/* 求素数 */ /* 编程思路是检查跳出循环时被除数的大小,如果跳出时小于n,则说明不是素数 */ #include <stdio.h> #include<stdlib.h> int main() { int m, i, n; printf("请输入一个数:\n"); scanf_s("%d", &n); do { i = 2; m = n % i; if (m == 0) { ++i; } else { printf("%d不是素数!\n", n); break; } while (i = n) { printf("%d是素数!\n", n); break; } } while (i < n); system("pause"); return 0; }
/* 求素数简化的程序1 */ #include <stdio.h> #include<stdlib.h> int main() { int i, n; printf("请输入一个数:\n"); scanf_s("%d", &n); for (i = 2;i < n;++i) { if (n%i == 0) break; } if (i < n) printf("%d is not prim!\n", n); else printf("%d is prim!\n", n); system("pause"); return 0; }
/* 求素数简化的程序2 */ /* 大于根号n的那些数一定不能被n整除 */ /* 不再检查大于根号n的那些值,省去了很多无用功,但问题是这样即使它是素数,i的退出值也是小于n */ #include <stdio.h> #include<stdlib.h> #include"math.h" int main() { int i, n, bprim = 1; // 引入一个变量bprim,初始值设为1,表示是素数,如果中途判断不是素数,则只需修改它的值 printf("请输入一个数:\n"); scanf_s("%d", &n); for (i = 2;i < sqrt(n);++i) // sqrt()函数需要头文件<math.h> { if (n%i == 0) { bprim = 0; break; } } if (bprim==0) // 只需判断bprim的值即可! printf("%d is not prim!\n", n); else printf("%d is prim!\n", n); system("pause"); return 0; }
/* 输入一个正整数,输出1~n之间的所有素数 */ #include <stdio.h> #include<stdlib.h> #include"math.h" int main() { int n, i,m ; printf("Print n...\n"); scanf_s("%d", &n); for (i = 1;i <= n;++i) { int bprim = 1; for (m = 2;m <= sqrt(i);++m) { if (i%m == 0) { bprim = 0; break; } } if (bprim == 1) printf("%d is prim!\n", i); else printf("%d is not prim!\n", i); } system("pause"); return 0; }
我的错误:scanf_s("%d\n", &n); // 这样会没有输出结果!!!
结果不对的话要进行调试(调试技术):逐过程、逐步。调试方法:加断点!