目录
3.2 计算1!+ 2! + 3! + …… + n! (n可以输入)
3.4 算 1/1 - 1/2 + 1/3 - 1/4 ..... + 1/100 = ?
1.分支语句
分支语句和接下来讲的循环语句都是控制语句。
1.1 选择结构(if)
1.1.1 if的语法结构
需要使用if,语法结构为:
if() //如果括号内为真(为1),执行下面语句 语句; else 语句; //可以添加else if(condition) 在 if 和 else 之间 //但由于是分支语句,所以最多执行一个if或者else里面的语句
示例语句
int main() { int a = 0; if (a == 3) printf("%d\n,a"); return 0; }
注意:if 和 else后都没有分号。
默认if后面只加一条语句,作为判断条件为真的时候的执行语句。如果if后面需要加多条语句的时候需要用大括号括起来,形成代码块。
if,else示例
#include<stdio.h> //单分支 int main() { int a = 10; if (a = 3) printf("hehe\n"); return 0; } //双分支 int main() { int age = 10; scanf("%d", &age); if (age > 18) printf("成年\n"); else printf("未成年\n"); return 0; }
1.1.2 if else的应用示例:
1.判断一个数是否为奇数:
#include<stdio.h> int main() { int num = 0; scanf("%d",&num); if (num % 2 == 1) printf("奇数\n"); else printf("偶数\n"); return 0; }
2.输出 1 - 100 之间的奇数:
#include<stdio.h> int main() { int num = 0; for (num = 0; num < 100; num++) { if (num % 2 == 1) printf("%d\n", num); } return 0; }
3.给三个整型数字比较大小并按照从大到小的顺序排列
#include<stdio.h> int main() { int a, b, c, t; scanf("%d %d %d", &a, &b, &c); if(a > b) { t = a; a = b; b = t; } if (a > c) { t = a; a = c; c = t; } if (b > c) { t = b; b = c; c = t; } printf("%d %d %d", c,b,a) ; return 0; }
4.打印闰年 1000 - 2000
闰年的条件:如果N能够被4整除,并且不能被100整除,则是闰年
或者:N能被400整除,也是闰年
即:4年一润并且百年不润,每400年再润一次#include<stdio.h> int main() { int a; for (a = 1000; a < 2000; a++) { if (a % 4 == 0) { if (a % 100 != 0) { printf("%d ", a); } } if (a % 400 == 0) { printf("%d ", a); } } return 0; }
5.打印100-200中的素数
#include<stdio.h> int main() { int a, j; int i = 0; for (a = 100; a <= 200; a++) { for (j = 2; j < a; j++) { if (a % j == 0) { break; } } if (j == a) { printf("%d ", a); i++; } } printf("\ncount=%d ", i); return 0; }
1.1.3 补充:
1.纠错,在编写代码时不能写连续的两个大于等于号,示例:
#include<stdio.h> int main() { int age = 10; if (18 <= age < 28) printf("青年\n"); //打印成功 return 0; } //应该写: int main() { int age = 10; if (18 <= age && age < 28) printf("青年\n"); return 0; }
2.if 判断的时候,常会搞错 = 与 ==:
= 为赋值, == 为判断相等,
我们可以把数字 放在 等号的左边 如 5 == num 这样如果少写了等号,可以报错
1.2 switch语句
1.2.1 switch语句的语法结构
常常用于多分支的情况
switch(整型表达式)
{
语句项
}
(整形表达式)为整形和枚举类型 如 int char long short等 不能是float
switch(date) { case 数值: 语句; case 数值: 语句; case 数值: 语句; .. default : 语句; }
switch语句一般需要使用:
1)break:跳出分支语句
每个后面加break 就是 判断出case 几后面跳出分支语句。
case 判断后,如果后面没有break 就会一直往下执行,直到出现
2)default:
case 一般列举不完全所有的情况,就需要加入default,用于其他没有列举到的情况的分支。
没有规定case必须在default之前,一般case最好放在default之前。
3)case 后面 要加 整型 常量表达式,可以是字符 (case语句后一般放整形结果的常量表达式或者枚举类型,枚举类型也可以看成是一个特殊的常量。
4)case 可以合并。
5)switch 可以嵌套,但是break只会跳出他所在的switch语句。
1.2.2示例
1.
输入1-5 输出weekday
输出6-7 输出weekend#include<stdio.h> int main() { int date; scanf("%d", &date); switch (date) { case 1: printf("星期1\n"); break; case 2: printf("星期2\n"); break; case 3: printf("星期3\n"); break; case 4: printf("星期4\n"); break; case 5: printf("星期5\n"); break; case 6: printf("星期6\n"); break; case 7: printf("星期7\n"); break; } return 0; }
2.
输入1-5 输出weekday
输出6-7 输出weekend(写法2)#include<stdio.h> int main() { int d; scanf("%d", &d); switch (d) { case 1: case 2: case 3: case 4: case 5: printf("weekday\n"); break; case 6: case 7: printf("weekend\n"); break; default: printf("错误\n"); } return 0; }
2.循环语句
2.1 while 语句
2.1.1 while的语法结构
while( 判断条件 ) { 语句; }
#include<stdio.h> //while循环 int main() { int i = 0; //初始化部分 while (i < 10) //判断部分 { printf("%d ", i); i += 2; //调整部分 } return 0; }
while的使用:
1)break:直接跳出循环。
2)continue:后续语句不再执行,跳过本次循环,再从while开始判断,执行
3)while内部有函数,会自动执行函数。
2.1.2 使用示例
1.用while打印1—10
#include<stdio.h> int main() { int i = 1; while (i <= 10) { printf("%d\n", i); i++; } return 0; }
2.只打印数字字符而忽略其他字符
#include<stdio.h> int main() { char ch = '\0'; while ((ch = getchar()) != EOF) { if (ch < '0' || ch > '9') //ch 的ASCII值小于 0 的值 或者 大于9的 continue; putchar(ch); } //只打印数字字符 return 0; }
3.写一个代码打印1-100之间所有3的倍数的数字(for)
#include<stdio.h> int main() { int i = 1; for (i = 1; i < 100; i++) { if (i % 3 == 0) printf("%d ", i); } return 0; }
4.找两个数的最大公约数
用辗转相除法,找t作为a和b的余数, b 令成 a , t 再令成 b,
#include<stdio.h> int main() { int a, b, t; int i = 0; scanf("%d %d", &a, &b); while (t = a % b) { a = b; b = t; } printf("%d\n", b); return 0; }
2.1.3getchar,putchar 函数
1. 输入缓冲区:
scanf 和 getchar 都是输入进 输入缓冲区 内部,
假如我前面 scanf 输入了123456 需要用 \n(空格) 去 让scanf 执行,但是scanf 不读取 \n
这个\n 就储存在输入缓冲区里了,
如果getchar 在scanf 之后,就会直接读取scanf剩下的\n,
可以在getchar 前面放个 getchar 读取\n 缓冲区清空,程序可以正常运行
但是getchar 只拿一个字符,所以面对缓冲区里面有多个字符的时候,不可以如此清除输入缓冲区。
举例子来看:
#include<stdio.h> int main() { char a = 0; scanf("%c", &a); int ch = getchar(); putchar(ch); return 0; }
分析:先输入回车,a = '\n',输入a\n,getchar读取到a,ch = a,putchar()就输出ch = a
分析:输入a \n,a = 'a', getchar发现输入缓冲区内有\n,直接读取'\n',所以输出空行。
2.getchar()
输入一个整型,包括字符和数字
eg.
char ch = getchar(); //意思是赋值给ch 输入进去的值 //使用<stdio.h>头文件
3. putchar()
同getchar,只不过是输出一个整型。
和scanf的区别在于:scanf 不读取 \n,但是会将输入的\n储存在输入缓存区中,而getchar读取到\n会即可中止,如
scanf("%s",&a); //输入abcedf 按回车(\n) char ch = getchar(); //输入一串字符值 按回车 putchar(ch); //只会输出空行,因为getchar读取到了scanf后的回车。
int putchar( int c ); //使用<stdio.h>头文件
#include<stdio.h> int main() { int ch = 0; while ((ch = getchar())!= EOF) //getchar() 就是输入一个 整型 (字符也是整型) { // =EOF 就是按ctrl + Z 会中止 // !=EOF 就是不等于 EOF // 也就是只要不按Ctrl z 就会一直循环 putchar(ch); //putchar(ch) 就是输出 ch } return 0; }
4.清空输入缓冲区的方法:
1)如果输入缓冲区只有一个字符'\n',那么很简单,只需要在后面的getchar()前面加一个getchar()函数读取\n就可以。
2)但是,一般情况下 \n前面还有其他字符,我们要清空所有的输入缓冲区,需要写一个循环:
int ch = 0; while ((ch = getchar()!= '\n')) { ; //只有一个分号的意思是 执行while 括号内的程序 }
5.putchar & getchar & 输入缓存区的实际应用
输入密码并确认,最多输入三次,三次不通过则输出:密码错误,请稍后再试。
1)如果我们不考虑输入缓冲区,直接用getchar 和 putchar 会发现
#include<stdio.h> int main() { char password[20] = { 0 }; printf("请输入密码:> "); int ret = "abcdefg"; int i = 0; while(i<3) { int ch = getchar(); if (ch == ret) { printf("登陆成功!\n"); break; } else { printf("\n密码输入错误,请重新输入:>"); } i++; } return 0; }
输入错误的密码之后,会跳出两次密码输入错误,请重新输入。这是因为,getchar收到的是 1 \n ,虽然只接收到了 1 ,但是下一次循环中getchar 接收到了 \n 导致 ch = '\n',从而密码错误,此时我们就应该使用,清除输入缓冲区的方法。修正如下:
#include<stdio.h> int main() { char password[20] = { 0 }; printf("请输入密码:> "); int ret = "abcdefg"; int i = 0; while(i<3) { int ch = getchar(); int h = 0; while ((h = getchar() != '\n')) { ; } if (ch == ret) { printf("登陆成功!\n"); break; } else { if(i < 2) printf("\n密码输入错误,请重新输入:>"); else { printf("\n密码错误次数过多,请稍后再试!"); } } i++; } return 0; }
2.2 for 语句
2.2.1 for 的使用范例
for(初始化 ; 判断部分 ; 调整部分) { 语句; //判断成功需要执行 }
for 相比较于 while 循环更加紧凑,因为 判断部分,调整部分和执行语句都更加地紧凑,容易调整。
注意事项:
1)continue作用:
判断成功时,直接跳过下面执行部分,(跳过本次循环),进入下一步。
while循环直接跳过本次循环,甚至可能会跳过i++ 但是 for 会主动调整 i 的值
2)break 作用:
判断成功时,直接跳出循环。
3)不要在for循环内部对循环变量进行调整,否则可能会出错;
4)for语句的循环控制变量,最好前闭后开
5)for后加( ;;) 死循环
因为没判断条件,默认条件为真。
6)for的嵌套
嵌套循环,且 for 循环内有初始化 : 10 * 10 = 100 次(下图)
嵌套循环,且for 循环内无初始化 10次(下图)
j 先循环, j 到10 的时候 i = 1, i = 2 , ....... 此时 j 都等于10
7)判断部分加 && 或 | |
8)for中判断部分的本质
本质是判断出是真是假,真则为非零,假则为0,如果判断部分本身写成赋值,或者错写成赋值,那么值是非零数 为真, 值是零 为假。
2.2.2 for的应用
1.for中break的应用:跳出循环
#include<stdio.h> int main() { int i; for (i = 0; i < 10; i += 2) { if (i == 6) break; printf("%d ", i); } return 0; }
2.for的死循环 ; ;
int main() { for (;;) { printf("hehe\n"); } return 0; }
2.3 do while 语句
2.3.1 范例
do 循环语句; while(表达式);
可以发现,do while 循环,无论while中判断条件为真为假,至少会执行一次循环语句。
注意事项:
1)break满足条件,停止做事,直接跳出循环。
2)continue的作用:停止执行循环语句,进入while判断阶段,这样经常会导致 调整部分被跳过,出错,死循环。如:
2.2.2 示例
上述的输出死循环的例子 :
#include<stdio.h> int main() { int i = 1; do { if (i == 5) continue; printf("%d ", i); i++; } while (i<10); return 0; }
如果修改成:将循环语句中的调整部分放在continue的前面,会避免错误。
#include<stdio.h> int main() { int i = 1; do { i++; printf("%d ", i); if (i == 5) continue; } while (i<10); return 0; }
3.分支与循环语句的综合题目
3.1 计算n的阶乘
#include<stdio.h> int main() { int n = 0; int i; int f = 1; scanf("%d", &n); for (i = 1; i < n + 1; i++) { f = i * f; } printf("%d", f); return 0; }
3.2 计算1!+ 2! + 3! + …… + n! (n可以输入)
#include<stdio.h> int main() { int i = 0; int n = 0; int j = 0; int k = 1; int sum = 0; scanf("%d", &n); for (j = 1; j <= n; j++) { for (i = 1; i <= j; i++) { k = 1; k = i * k; } sum = k + sum; } printf("%d", sum); return 0; }
需要注意的是第二个嵌套for中 要添加初始化k = 1,否则上一个循环中的k依旧存在,使数值有误。但是可以看到我们每次 i 的值变化时,都需要重新计算k(阶乘),比较繁琐。
我写出了ret作为阶乘值,每次只需要* 新的i即可。
错误例子:(错的点在于,每次都对n进行了初始化, ret值错误)修改后,我把n的初始化放在前面,for循环中n的初始化拿走。3#include<stdio.h> int main() { int n , i; int ret = 1; int sum = 0; int j = 1; int num; scanf("%d", &num); for (j = 1; j <= num; j++) { for (n = 1; n <= j; n++) { ret *= n; } sum += ret; } printf("%d", sum); return 0; }
#include<stdio.h> int main() { int n = 1; int i; int ret = 1; int sum = 0; int j = 1; int num; scanf("%d", &num); for (j = 1; j <= num; j++) { for (; n <= j; n++) { ret *= n; } sum += ret; } printf("%d", sum); return 0; }
3.3 二分查找:(在有序数组中查找某个数字n)
在一个有序数组中查找具体的某个数字n。
编写int binsearch(int x,inv[],int n);
功能:在v[0]<=v[1]<=v[2]....<=v[n-1]的数组中查找x逻辑:判断数组下标最左和中间的数和待查找值的大小关系,若未查找成功则重新定义left和mid值,继续查找,若left 和 mid 大小关系出现错误,结束查找,输出找不到。
#include<stdio.h> int main() { int arr[10]={1,2,3,4,5,6,7,8,9,10}; int left = 0; int sz = sizeof(arr) / sizeof(arr[0]); int right = sz - 1; int mid = left + (right - left) / 2; int x = 1; int flag = 0; while (left <= mid) { if (x < arr[mid]) { right = mid; mid = left + (right - left) / 2; } else if (x > arr[mid]) { left = mid; mid = left + (right - left) / 2; } else { printf("%d", mid); flag = 1; break; } } if (0 == flag) printf("找不到!\n"); return 0; }
3.4 算 1/1 - 1/2 + 1/3 - 1/4 ..... + 1/100 = ?
注意:
如果有浮点数,应该要所有的类型都定义为float 或 double类型才可以。
#include<stdio.h> int main() { float i = 1.0; float sum = 0.0; float a = 1.0; float flag = 1.0; for (i = 1.0; i <= 100.0; i++) { a = (flag / i); sum += a; flag *= -1; } printf("%.2f", sum); return 0; }
其中flag 是一个 + - + - + - 循环的符号。
3.5 十个数里找最大值
先设置max函数,两者求最大,然后用for循环,从数组第 0 , 1 位开始比较,然后选 0 1 中的较大值,和2 比较,以此类推求取最大值。
#include<stdio.h> int max(int x, int y) { if (x < y) return y; else return x; } int main() { int arr[10]; int i = 0; int m = arr[0]; for (i = 0; i < 9; i++) { m = max(m, arr[i + 1]); } printf("%d", m); return 0; }
3.6 输出乘法口诀表
9*9 需要嵌套
#include<stdio.h> int main() { int i = 1; int j = 1; for (i = 1; i < 10; i++) { for (j = 1; j < i + 1; j++) { printf("%d * %d = %d ", j, i, i*j); } printf("\n"); } return 0; }
3.7 设计出字符可以跳跃的程序
比如 *****************
h***************!
he************d!
需要使用替换,注意的是,字符串的长度最好用strlen - 1 ,也可以用sz - 2
整型数组求元素个数用 sz - 1
字符数组求元素个数用 sz - 2(需要减一个\0)或者 strlen - 1
#include<stdio.h> #include<windows.h> #include<stdlib.h> int main() { char arr1[] = { "hellllllllllllloo world!" }; char arr2[] = { " " }; //也可以用*************** int r = strlen(arr1) - 1; int l = 0; while (r+1 >= l) { printf("%s\n", arr2); arr2[r] = arr1[r]; arr2[l] = arr1[l]; r = r - 1; l = l + 1; Sleep(1000); system("cls"); } return 0; }
Sleep(1000) 休眠1000ms 用windows.h 头文件
system库函数 cls---清屏 用stdlib.h 头文件
3.8 编写代码实现登录情景
假设密码是字符串:abcdef
字符数组和字符数组或者字符串比较是用strcmp,头文件string.h
使用方法:strcmp(password,"abcdefg") 为 0 则为相等
#include<stdio.h> #include<string.h> int main() { int ret = "abcdefg"; int password[20] = { 0 }; int i = 0; int flag = 0; printf("请输入密码:>"); for (i = 0; i < 3; i++) { scanf("%s", password); //字符串本身就是地址,不用取地址 if (strcmp(password, "abcdefg") == 0) { flag = 1; printf("\n登陆成功!\n"); } else if(i < 2) printf("\n密码输入错误,请重新输入:>"); else printf("\n登陆失败,请稍后再试!"); } return 0; }
3.9 整蛊小程序
#include<stdio.h> #include<string.h> #include<stdlib.h> int main() { char input[20] = { 0 }; again: system("shutdown -s -t 60"); printf("在60s后关机,输入我是猪\n"); scanf("%s", input); if (strcmp(input, "我是猪") == 0) { system("shutdown -a"); } else { goto again; } return 0; }
goto的用法:可以回到again处
分支与循环语句的总结内容到此结束,感谢大家的支持,谢谢!