目录
- 1. 什么是语句?
- 2. 分支语句(选择结构)
- 2.1 if 语句
- 2.1.1 语法结构
- 2.1.2 悬空else
- 2.2 switch 语句
- 2.2.1 语法格式
- 2.2.2 default 子句
- 2.2.3 练习
- 3. 循环语句 (循环结构)
- 3.1 while 语句
- 3.1.1 语法结构
- 3.1.2 while 语句中的 break 和 continue
- 3.2 for 语句
- 3.2.1 语法格式
- 3.2.2 for 循环 和 while 循环的对比
- 3.2.3 for 语句中的 break 和 continue
- 3.2.3 for 循环的一些变种
- 3.2.4 一道笔试题
- 3.3 do … while 语句
- 3.3.1 语法格式
- 3.3.2 do 语句的特点
- 3.3.4 do…while 语句中的 break 和 continue
- 3.4 练习
- 3.5 goto 语句
1. 什么是语句?
C语言中由一个分号;
,隔开的就是一条语句。
比如:
printf("hello world!");
1+2;
2. 分支语句(选择结构)
2.1 if 语句
2.1.1 语法结构
if(表达式)
语句;
if(表达式)
语句1;
else
语句2;
// 多分支
if(表达式1)
语句1;
else if(表达式2)
语句2;
else
语句3;
举例:
#include <stdio.h>
//代码1
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
{
printf("未成年\n");
}
}
//代码2
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
{
printf("未成年\n");
}
else
{
printf("成年\n");
}
}
//代码3
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
{
printf("少年\n");
}
else if (age >= 18 && age < 30) // 18<=age<=30 => (18<=age)<=30
{
printf("青年\n");
}
else if (age >= 30 && age < 50)
{
printf("中年\n");
}
else if (age >= 50 && age < 80)
{
printf("老年\n");
}
else
{
printf("老寿星\n");
}
}
2.1.2 悬空else
《高质量C++编程指南》
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if (a == 1)
if (b == 2)
printf("hhe\n");
else
printf("haha\n");
return 0;
}
// 运行结果: 什么都不输出
// else 与离得最近的未匹配的if 进行匹配
// 改正
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if (a == 1) // 判断条件建议写成 1 == a
{
if (b == 2)
printf("hhe\n");
}
else
printf("haha\n");
return 0;
}
// 输出 haha
2.2 switch 语句
2.2.1 语法格式
switch(整形表达式)
{
case 整型常量表达式;
语句;
break;
}
// 在 switch 语句中,我们没法直接实现分支,搭配 break,使用才能实现真正的分支。
// break 语句的实际效果是把语句列表划分为不同的部分。
举例
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期日
#include <stdio.h>
int main()
{
int a;
printf("请输入一个数,\n");
scanf("%d", &a);
switch (a) // 括号内必须是整型表达式
{
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;
}
输入1-5输出的是“weekday”;
输入6-7输出“weekend”;
#include <stdio.h>
int main()
{
int a;
printf("请输入一个数,\n");
scanf("%d", &a);
switch (a)
{
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");
break;
}
return 0;
}
2.2.2 default 子句
-
default
语句可有可无,其作用是处理语句中的非法状况。 -
defaule
和case
没有顺序所言,但是一般建议把default
放到最后。 -
编程好习惯
在每个
switch
语句中都放一条default
子句是个好习惯,甚至可以在后边再追加一个break
。
2.2.3 练习
#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;
}
// 运行结果
// m = 5,n = 3
3. 循环语句 (循环结构)
3.1 while 语句
3.1.1 语法结构
while(判断条件) // 符合判断条件。就执行语句体。
{
语句体;
}
3.1.2 while 语句中的 break 和 continue
break 介绍
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (5 == i)
break;
printf("%d ", i);
i++;
}
return 0;
}
// 运行结果: 1 2 3 4
总结:
break 在 while 循环中的作用:
其实在循环中只要遇到
break
,就停止后期的所有的循环,直接终止循环。所以:
while
中的break
是用于 永久 终止循环的。
continue 介绍
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (5 == i)
continue;
printf("%d ", i);
i++;
}
return 0;
}
// 运行结果: 1 2 3 4 之后光标闪着不动,程序进入死循环。
#include <stdio.h>
int main()
{
int i = 0;
while (i <= 10)
{
i++;
if (5 == i)
continue;
printf("%d ", i);
}
return 0;
}
// 运行结果: 1 2 3 4 6 7 8 9 10 11
总结:
continue 在 while 循环中的作用是:
continue
是用于终止本次循环的,也就是本次循环中continue
后边的代码不会再执行,而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。
再来看几个代码吧
#include <stdio.h>
int main()
{
int ch = getchar();
putchar(ch);
return 0;
}
// getchar 是读取字符
// 为什么返回类型是int 呢?
// 1. getchar 既然返回的是字符,其实返回的是字符的ascii码值(整数)
// 2. getchar 在读取结束或者失败的时候,会返回EOF(文件的结束符)
// EOF -- end of file --> -1
#include <stdio.h>
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
putchar(ch);
return 0;
}
// EOF -- end of file --文件结束标志
// 输入EOF 循环并不会结束,而是执行三次循环,读取三次,输出EOF,只有按ctrl+z才能终止循环。
输入密码确认案例
#include <stdio.h>
int main()
{
int ret = 0;
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
printf("请确认(Y/N):>");
ret = getchar();
if (ret == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0;
}
// 上述代码存在问题,输入密码后按回车,自动输出放弃确认。
解析:
造成上述问题的原因是,在输入密码并按回车后,缓冲区的内容是
12345\n
,%s只会读取\n
之前的字符,而\n
就会被ret
所读取。这就造成了,未进行确认就输出放弃确认的结果。
// 改正后代码
#include <stdio.h>
int main()
{
int ch = 0;
int ret = 0;
char pass[20] = { 0 };
printf("请输入密码:>");
// scanf() 读取字符串会在末尾自动加'\0'
scanf("%s", pass);
// 把缓冲区中的内容清空
while((ch = getchar()) != '\n')
{
;
}
printf("请确认(Y/N):>");
ret = getchar();
if ('Y' == ret)
printf("确认正确\n");
else
printf("确认失败\n");
return 0;
}
3.2 for 语句
3.2.1 语法格式
for(表达式1;表达式2;表达式3)
循环语句;
- 表达式1:为 初始化部分,用于初始化循环变量;表达式2:为 条件判断部分,用于判断循环时候终止;表达式3:为 调整部分,用于循环条件的调整。
建议
for
语句的循环控制变量的取值采用 **“前闭后开区间”**的写法不可在
for
循环体内修改循环变量,防止for
循环失去控制。
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
// 10次循环
// 10次打印
// 10个元素
for (i = 0; i<10; i++) {
printf("%d ", arr[i]);
}
return 0;
}
// C 语言语法
int main()
{
int i = 0;
for(i = 0;i<=12;i++)
{
printf("hehe\n");
}
}
// C++ 语法
int main()
{
for(int i = 0;i<=12;i++)
{
printf("hehe\n");
}
}
3.2.2 for 循环 和 while 循环的对比
#include <stdio.h>
int main()
{
int i = 0;
//实现相同的功能,使用while
i = 1;//初始化部分
while (i <= 10)//判断部分
{
printf("hehe\n");
i = i + 1;//调整部分
}
//实现相同的功能,使用while
for (i = 1; i <= 10; i++) {
printf("hehe\n");
}
return 0;
}
可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹。
for循环使用的频率也最高。
3.2.3 for 语句中的 break 和 continue
可以发现在
for
循环中也可以出现break
和continue
,他们的意义和在while
循环中是一样的。但是还是有些差异:
//代码1
#include <stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
break;
printf("%d ", i);
}
return 0;
}
//代码2
#include <stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
continue;
printf("%d ", i);
}
return 0;
}
3.2.3 for 循环的一些变种
变种1
#include <stdio.h>
int main()
{
for(;;)
{
printf("hehe\n");
}
return 0;
}
// 结果: 死循环打印 hehe
// 1. for循环的初始化、调整、判断,都可以被省略,
// 但是:
// for 循环的判断部分如果被省略,那判断条件就是:恒为真
// 2. 不要随便省略相应的代码
变种2
#include <stdio.h>
int main()
{
int x, y;
for (x = 0, y = 0; x<2 && y<5; ++x, y++)
{
printf("hehe\n");
}
return 0;
}
3.2.4 一道笔试题
请问循环要循环多少次
#include <stdio.h>
int main()
{
int i = 0;
int k = 0;
for (i = 0, k = 0; k = 0; i++, k++)
k++;
return 0;
}
// 循环执行0次,因为判断表达式中 k = 0 ,0为假,所以循环执行0次。
3.3 do … while 语句
3.3.1 语法格式
do
循环语句;
while(表达式);
3.3.2 do 语句的特点
循环至少执行一次,使用的场景有限,所以不是经常使用。
#include <stdio.h>
it main()
{
int i = 10;
do
{
printf("%d\n", i);
} while (i < 10);
return 0;
}
3.3.4 do…while 语句中的 break 和 continue
#include <stdio.h>
int main()
{
int i = 1;
do
{
if (5 == i)
break;
printf("%d ", i);
i++;
} while (i < 10);
return 0;
}
// 运行结果: 1 2 3 4
#include <stdio.h>
int main()
{
int i = 1;
do
{
if (5 == i)
continue;
printf("%d ", i);
i++;
} while (i < 10);
return 0;
}
// 运行结果: 1 2 3 4 闪光标
// do while 和 while 较相似
3.4 练习
计算 n 的阶乘。
#include <stdio.h>
int main()
{
int i = 0;
int n = 0;
int sum = 1;
printf("请输入一个数,将输出这个数的阶乘\n");
scanf("%d", &n);
for (i = 1; i <= n; i++)
sum *= i;
printf("%d的阶乘为:>%d", n, sum);
return 0;
}
计算 1!+2!+3!+……+10!
// 方法一
#include <stdio.h>
int main()
{
int i = 0;
int j = 0;
int n = 0;
int sum = 0;
for (n = 1; n <= 10; n++)
{
j = 1;
for (i = 1; i <= n; i++)
j *= i;
printf("%d的阶乘为:>%d\n", n, j);
sum += j;
}
printf("1!+2!+3!+……+10!的和为%d",sum);
return 0;
}
// 方法二
#include <stdio.h>
int main()
{
int i = 0;
int j = 1;
int n = 0;
int sum = 0;
for (n = 1; n <= 10; n++)
{
j *= n;
sum += j;
}
printf("1!+2!+3!+……+10!的和为%d",sum);
return 0;
}
在一个有序数组中查找具体的某个数字n。
编写int binsearch(int x, int v[], int n);
功能:在v[0]<=v[1]<=v[2]<= ….<=v[n-1]的数组中查找x。
// 方法一 -- O(n)
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 17;
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
if (k == arr[i])
{
printf("找到了,下标为:%d\n", i);
break;
}
}
if (i == sz)
printf("找不到\n");
return 0;
}
// 方法二 -- O(log~2~^n^)
// 折半查找、二分查找算法
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 7;
int sz = sizeof(arr) / sizeof(arr[0]); // 计算元素个数
int left = 0; // 左下标
int right = sz - 1; // 右下标
while(left <= right)// 即使是left == right 也有一个元素要查找
{
int mid = (left + right) / 2; // 中间元素下标
if (arr[mid] > k)
{
right = mid - 1;
}
else if (arr[mid] < k)
{
left = mid + 1;
}
else
{
printf("找到了,下标为:%d\n", mid);
break;
}
}
if (left > right)
printf("找不到\n");
return 0;
}
编写代码,演示多个字符从两端移动,向中间汇聚。
#include <stdio.h>
#include <string.h>
#include <Windows.h> // 调用sleep函数
#include <stdlib.h> // 调用清屏函数
int main()
{
char arr1[] = "hello world!!!!!!";
char arr2[] = "####################";
int left = 0;
// char arr[] = "abc";
// [a b c \0]
// 0 1 2 3
// 表示下标时应该 4-2 -- sizeof(arr)/sizeof(arr[0])-2
// int right = sizeof(arr1)/sizeof(arr1[0])-2;
int right = strlen(arr1) - 1;
while (left <= right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
// 休息1秒 -- 1000毫秒
Sleep(1000);
system("cls"); // 执行系统命令的一个函数 - cls - 清空屏幕
left++;
right--;
}
printf("%s\n", arr2);
return 0;
}
模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确,提示登录成功,如果三次均输入错误,则退出程序。)
#include <stdio.h>
#include <string.h
int main()
{
int i = 0;
char password[20] = { 0 };
for (i = 0; i < 3; i++)
{
printf("请输入密码:>");
scanf("%s", password);
if (0 == strcmp(password, "123")) // == 不能用来比较两个字符串是否相等,应该使用一个库函数strcmp
{
printf("登录成功\n");
break;
}
else
printf("密码错误\n");
}
if (i == 3)
printf("三次密码均错误,退出程序\n");
return 0;
}
求最大公约数
// 辗转相除法
#include <stdio.h>
int main()
{
int m = 24;
int n = 6;
int r = 0;
while (r = m % n)
{
// r = m % n;
m = n;
n = r;
}
printf("%d\n", n);
return 0;
}
打印1000~2000 之间的闰年
// 方法1
#include <stdio.h>
int main()
{
int year = 0;
int count = 0;
for (year = 1000; year <= 2000; year++)
{
// 判断闰年的方法:
// 1. 能被4整除并且不能被100整除是闰年
// 2. 能被400整除是闰年
if (0 == year % 4 && 0 != year % 100)
{
printf("%d ", year);
count++;
}
else if (0 == year % 400)
{
printf("%d ", year);
count++;
}
}
printf("\n有%d个闰年", count);
return 0;
}
// 方法二
#include <stdio.h>
int main()
{
int year = 0;
int count = 0;
for (year = 1000; year <= 2000; year++)
{
// 判断闰年的方法:
// 1. 能被4整除并且不能被100整除是闰年
// 2. 能被400整除是闰年
if ((0 == year % 4 && 0 != year % 100) || (0 == year % 400))
{
printf("%d ", year);
count++;
}
}
printf("\n有%d个闰年", count);
return 0;
}
打印 100 ~ 200 之间的素数。
《素数求解的n种境界》
#include <stdio.h>
#include <math.h>
int main()
{
int i = 0;
int count = 0;
for (i = 101; i <= 200; i+=2)
{
int j = 0;
// sqrt() -- 开平方的数学库函数
for (j = 2; j <= sqrt(i); j++)
{
if (0 == i % j)
{
break;
}
}
if (j > sqrt(i))
{
count++;
printf("%d是素数\n", i);
}
}
printf("count = %d\n", count);
return 0;
}
计算1/1-1/2+1/3+1/4+1/5+……+1/99-1/100的值,打印结果。
#include <stdio.h>
int main()
{
int i = 0;
int flag = 1;
double sum = 0;
for (i = 1; i < 101; i++)
{
sum += flag * 1.0 / i;
flag = -flag;
}
printf("sum = %lf", sum);
return 0;
}
求十个整数中的最大值
#include <stdio.h>
int main()
{
int arr[] = { -1,-2,-3,-4,-5,-6,-7,-8,-9,-10 };
int max = arr[0]; // 由于数组中的数都是小于0 的,如果将max初始化为0,则将找不出该数组中的最大值。所以用数组的第一个数对max进行初始化。
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
if (arr[i] > max) {
max = arr[i];
}
}
printf("max = %d\n", max);
return 0;
}
打印九九乘法表
#include <stdio.h>
#include <math.h>
int main()
{
int i = 0;
int j = 0;
for (i = 1; i <= 9; i++)
{
for (j = 1; j <= i; j++)
// %xd , x指定的域宽,默认是右对齐的
// %-xd,x指定的域宽,默认是左对齐的
printf("%d*%d=%d\t", j, i, i * j);
printf("\n");
}
return 0;
}
猜大小游戏
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void menu()
{
//system("cls");
printf("***************************************\n");
printf("**** 1.play 0.exit ****\n");
printf("***************************************\n");
}
// 0x123 -- 十六进制
// 0123 -- 八进制
void game()
{
// 1. 生成一个随机数
int ret = 0;
int guess = 0; // 接收猜的数字
// 拿时间戳来设置随机数的生成起始点
// time_t time(time_t *timer)
// time_t
//srand((unsigned int)time(NULL));
// rand() 生成 0~0x7fff 的随机值
ret = rand()%100+1; // 生成1-100之间的随机数
// printf("%d\n", ret);
// 2. 猜数字
while (1)
{
printf("请猜数字:>");
scanf("%d", &guess);
if (guess > ret)
printf("猜大了\n");
else if (guess < ret)
printf("猜小了\n");
else
{
printf("猜对了\n");
break;
}
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
3.5 goto 语句
- 不建议使用
goto
语句。
#include <stdio.h>
int main()
{
again:
printf("hello bit\n");
goto again;
return 0;
}
goto
语句最常见的用法: 就是终止某些深度嵌套的结构的处理过程,例如一次跳出多层循环。
for(...)
for(...)
{
for(...)
{
if(disaster)
goto error;
}
}
…
error:
if(disaster)
// 处理错误情况
希望可以对大家有所帮助,如果有什么不对的地方,还烦请指教,谢谢!