【补】使C语言结构化的程序设计语言,分为:顺序结构、选择结构、循环结构
目录
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
一、分支语句
1、if-else 分支语句
(1)【补】代码风格——好的代码风格可以消除歧义,并且利于读者理解——书籍《高质量 C\C++编程》
注意格式的书写,善用大括号的规范书写格式,形成好的代码风格;
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if (a == 1)
{
if (b == 2)
{
printf("呵呵\n");
}
else
{
printf("呜呜\n");
}
}
return 0;
}
(2)练习
①判断一个数是否为奇数
int main()
{
int input = 0;
scanf("%d", &input);
if (1 == input % 2)
{
printf("是奇数\n");
}
else
{
printf("不是奇数\n");
}
return 0;
}
②输出1-100之间的奇数
【补】for循环的条件语句用分号; for( exp1 ; exp2 ; exp3 )
方法一:
int main()
{
int i = 0;
for (i=1 ; i <= 100 ; i++ ) //for循环的条件语句用分号; for( exp1 ; exp2 ; exp3 )
{
if(1==i%2)
{
printf("%d ", i);
}
}
return 0;
}
方法二 不用 if 判断 ,直接+=2, 奇数循环
int main()
{
int i = 0;
for (i = 1; i <= 100; i+=2)
{
printf("%d ", i);
}
return 0;
}
2、switch 分支语句-用于存在很多分支时
1、switch “开关”——必须是整型/整型常量表达式,字符也可以,因为字符存储是用的阿斯格码值;
2、格式:
switch(整型表达式)
{
语句项
}
语句项,就是一些case语句,比如:
case 整型常量表达式:
语句
例1:输入的数值对应打印出星期几,1-星期一,2-星期二,3-星期三……
break 结束进程,后面不再继续输入,没有break ,case会一直运行!
case 决定入口,break决定出口
#include <stdio.h>
int main()
{
int day = 0;
scanf_s("%d\n",&day);
switch (day)
{
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
case 5:
printf("星期五\n");
break;
case 6:
printf("星期六\n");
break;
case 7:
printf("星期天\n");
break;
}
return 0;
}
例2 输入1 2 3 4 5 打印工作日; 输入6 7打印休息日;
输入其他数字打印“输入错误”——default
#include <stdio.h>
int main()
{
int day = 0;
scanf_s("%d\n",&day);
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("工作日\n");
break;
case 6:
case 7:
printf("休息日\n");
break;
default :
printf("输入错误\n");
}
return 0;
}
练习题:求m=? n=?
【补】
switch可以嵌套使用;
没有break,case会一直运行下去
#include <stdio.h>
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:
m++;
case 2:
n++;
case 3:
switch (n)
{//switch允许嵌套使用
case 1:
n++;
case 2:
m++;
n++;
break;
}
case 4:
m++;
break;
default:
break;
}
printf("m = %d, n = %d\n", m, n);
return 0;
}
二、循环语句
1、while循环
(1)在while循环中,break用于永久终止循环,
(2)while执行流程:
(3)while中的continue
* continue用于跳过本次循环continue后面的代码,直接去判断部分看能否进行下一步循环
//结果= 1234死循环
//分析 continue的作用是跳过当前的后续操作,直接进入下一次判断,意思是,当i==5进入if语句,直接跳到下一次判断i<=10能否进入whle循环,此时因为i没有经过printf,也没有经过 i++,因此i还是=5,打印的只是1234,后面死循环;
//结果= 1234死循环
//分析 continue的作用是跳过当前的后续操作,直接进入下一次判断,意思是,当i==5进入if语句,直接跳到下一次判断i<=10能否进入whle循环,此时因为i没有经过printf,也没有经过 i++,因此i还是=5,打印的只是1234,后面死循环;
int main()
{
int i = 1;
while (i <= 10)
{
if(i==5)
{
continue;
}
printf("%d ",i);
i++;
}
return 0;
}
(2)【补】
getchar / putchar——从键盘(标准输入)读取 / 输出一个字符;
EOF= end of file 文件结束;
字符是以阿斯格码值的形式存储,因此char可以用int;
getchar 与 键盘之间有一个 缓冲区,getchar不会忽略缓冲区中的任何字符,包括 \n ;
int main()
{
int ch = 0;
while (ch = getchar() != EOF)
{
putchar(ch);
}
return 0;
}
(3)
scanf()其实在生活中不常用,因为它只能读一个字符
gets()可以读一整行
(4)password是数组 arr[ ],数组的数组名本来就是地址,因此sacnf 不用 取地址& pasaword
① 如果输入的密码只是数字,比如,12345
上诉情况的缓冲区里有'\n',此时应该清理缓冲区,用一个gerchar把'\n'拿走
①把'\n'拿走了
#include <stdio.h>
//① 如果输入的密码只是数字,比如,12345
int main()
{
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s",password);
printf("请确认密码(Y/N):>");
//上诉情况的缓冲区里有'\n',此时应该清理缓冲区,用一个gerchar把'\n'拿走
getchar(); // ①把'\n'拿走了
int ch = getchar();
if (ch == 'Y')
{
printf("确认成功");
}
else
{
printf("确认失败");
}
return 0;
}
②
#include <stdio.h>
//②如果输入的是字符串,比如,12345 abc,有空格——【不是很懂】
int main()
{
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
printf("请确认密码(Y/N):>");
//假设此时输入的是:12345 abc
//应该清理缓冲区的多个字符
int tmp = 0;
while (tmp = getchar() != '\n');
{
; //空格表示扔掉
}
int ch = getchar();
if (ch == 'Y')
{
printf("确认成功");
}
else
{
printf("确认失败");
}
return 0;
}
【补】只打印数字字符,跳过其他字符 -ASCII表
2、for循环
(1)格式
for(exp1 ; exp2 ; exp3)
{
循环语句;
}
exp1 初始化
exp2 判断
exp3 调整
stmt 执行
(3)for循环的执行流程:
【举例】 打印1-10
int main()
{
int i = 0;
for (i = 1; i <= 10 ; i++)
{
printf("%d ", i);
}
return 0;
}
建议左闭右开 for (i=0 ; ,i<10 ;i++}
一旦判断部分省略,会死循环
【问】打印几个 1 ?
结果:3*3= 9
int main()
{
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf("1 ");
}
}
return 0;
}
【问】如果省去初始化,打印几个1?
//结果= 3个
//分析: 最初i=0,符合i<3进入第一个for循环,然后j=0,符合j<3进入第二个for循环,直到j=3打印了3个1,但是因为生气了初始化,当i++时,j>3不能进入第二个for循环,不能形成 3*3
int main()
{
int i = 0;
int j = 0;
for ( ; i < 3; i++)
{
for ( ; j < 3; j++)
{
printf("1 ");
}
}
return 0;
}
【问】循环几次?
结果: k=0是赋值而非判断,k=0为假,不能循环,循环次0次;
#include <stdio.h>
int main()
{
int i = 0;
int k = 0;
for(i =0,k=0; k=0; i++,k++)
k++;
return 0;
}
3、do while循环
(1)do while的结构:
do
{
循环语句;
}
while(表达式);
(2)do while 先执行,后判断; while先判断,后执行
(3)do while循环的流程:
【举例】打印1-10
int main()
{
int i = 1;
do
{
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
[练习题]
1、计算n的阶乘 n!
int main()
{
int i = 0;
int n = 0;
int ret = 1;
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
ret *= i;
}
printf("%d\n", ret);
return 0;
}
2、计算1! + 2! + 3!+ ... + 10!
int main()
{
int i = 0;
int ret = 1; //ret初识为1
int sum = 0;
for (i = 1; i <= 10; i++)
{
ret *= i;
sum += ret;
}
printf("%d", sum);
return 0;
}
3 、在有序数组中查找具体的某个数字n——二分法
二分查找/折半查找 - 效率高 , 下标不会四舍五入,因为这是整型
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 7; // 要查找的数字
//在这个有序数组arr中查找k(7)的值
int left = 0;
int sz = sizeof(arr) / sizeof(arr[0]); //元素个数
int right = sz - 1;
int mid = (left + right) / 2; //mid是下标,arr[mid]对应数值
while (left <= right) //意思是数组里面有元素
{
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else //就是刚好 arr[mid]=k
{
printf("可找到,数值下标:%d", mid);
break;
}
}
if (left > right) //意思是数组里没元素,找不到
{
printf("找不到");
}
return 0;
}
4、编写代码,演示多个字符从两端移动,向中间汇聚——意思是字符串逐渐向中间显现
比如,
打印 welcome to Beijing!!
w##############!
we############!!
wel###########g!!
...
welcome to Beijing!!
【补】strlen( )需要头文件 include <string.h>
int main()
{
char arr1[] = "welcome to Beijing!"; //区别于 int arr[]={ 1,2,3,4,5 }
char arr2[] = "###################";
int left = 0;
int right = strlen(arr1) - 1; //区别于
while (left <= right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
left++;
right--;
}
return 0;
}
【补】*来个动态版,加上Sleep函数,其单位是毫秒,需要引用头文件 include<windows.h>
#include <string.h>
#include <windows.h>
int main()
{
char arr1[] = "welcome to beijing!"; //区别于 int arr[]={ 1,2,3,4,5 }
char arr2[] = "###################";
int left = 0;
int right = strlen(arr1) - 1; //区别于
while (left <= right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
sleep(1000); // 睡眠打印速度1000毫秒,s一定要大写!
left++;
right--;
}
return 0;
}
【补】来个清空屏幕动态版!!!!! 加上 system("cls");
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main()
{
char arr1[] = "welcome to beijing!"; //区别于 int arr[]={ 1,2,3,4,5 }
char arr2[] = "###################";
int left = 0;
int right = strlen(arr1) - 1; //区别于
while (left <= right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
Sleep(1000); // 睡眠打印速度1000毫秒,S一定要大写!
system("cls"); // 清空屏幕
left++;
right--;
}
printf("%s\n", arr1);
return 0;
}
5、strcmp()函数,会根据 ASCII 编码依次比较 str1 和 str2 的每一个字符,直到出现不到的字符,或者到达字符串末尾(遇见\0
)
strncmp ()还可以指定字符串里用于比较的字符数
返回值:
- 如果返回值 < 0,则表示 str1 小于 str2。
- 如果返回值 > 0,则表示 str2 小于 str1。
- 如果返回值 = 0,则表示 str1 等于 str2。
比较对应位置上的ASCII码值,比如abcqqqqq 与abd, 第三位c比d小,则第二个更大
5、输入密码,错误三次就退出程序
【补】比较两个字符串,不能用==,要用strcmp()函数
//输入密码,错误三次就退出程序
#include <stdio.h>
#include <string.h> //strcmp()函数的头文件
#include <windows.h> //system()函数的头文件
int main()
{
int i = 1;
//假设正确密码是字符串“1234567”
char password[20] = { 0 };
for (i = 0; i < 3; i++)
{
printf("请输入密码:");
scanf("%s", password);
system("cls");
if (strcmp(password, "1234567") == 0) //比较两个字符串,不能用==,要用strcmp()函数
{
printf("登录成功\n");
break;
}
}
if (i == 3)
{
printf("三次密码均错误,退出程序");
}
return 0;
}
6、写一个数字游戏,自动生成一个1-100之间的随机数
猜数字游戏的实现:
第一步:生成随机数 - rand() - "random 随意的"
如果不先引用srand,rand()有最大值限制,只能返回0-32767之间的数字 ,且不够随机
那么,要先调用srand先调整rand的生成器;
需要给srand()一个整数,但因为想要rand输出随机的数字,因此必须给srand一个变化的数
因此给srand输入 时间 !---。实际传递的是 *时间戳:由时间转换出的数字;
获取时间戳-time函数-<time.h>// 给time()传一个空值NULL
用unsigned int,将time的返回值,强制类型转化为srand需要的类型;
如果将time()放在game()里面,那就要每玩一次游戏就要设置一次,不合适--->整个工程,time()只需要设置一次,不然不够随机--->因此把srand((unsigned int)time(NULL));放到主函数main()里面去;
但此时随机数过大,超出1-100的要求范围,因此 取模%100,余数均为1-99,为了使范围为1-100,则+1;
第二步:猜数字
会才很多次,用while语句
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <time.h>
void menu()
{
printf("1.play \n");
printf("0.exit \n");
}
void game()
{
//生成随机数
int ret = rand() % 100 + 1;
//printf("%d\n", ret);
//猜数字
int guess = 0;
while (1)
{
printf("请猜数字:>");
scanf("%d", &guess);
if (guess < ret)
{
printf("猜小了\n");
}
else if (guess > ret)
{
printf("猜大了\n");
}
else (guess = ret);
{
printf("恭喜猜对\n");
break;
}
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu(); //打印菜单,menu函数不在库函数里面,需要上方viod 说明
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
//game(); //game 函数也是库函数里面没有的
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("请重新选择\n");
break;
}
} while (input);
return 0;
}
【补】goto语句
不可滥用,但是用于跳出多重嵌套语句很有效;
goto语句不可跨函数,只能在本函数内跳出;
比如://处理错误情况
for(...)
for(...)
{
for(...)
{
if (disaster)
goto error;
}
}
...
error:
if(disaster) //处理错误情况