目录
一、C语言常用的输入输出函数
1.putchar()/getchar()
1.1putchar()
功能:
向终端输出一个字符
头文件:
#include
函数原型:
int putchar(int c);
参数:
c : 要输出的字符
#include <stdio.h>
int main(int argc, const char *argv[])
{
//可以直接输出一个字符
putchar('M');
putchar('\n');
//也可以输出字符的 ascii 码
putchar(77);
putchar(10);
//也可以传一个保存的字符的变量
char value = 'M';
putchar(value);
putchar(10);
//也可以传一个能计算出字符ascii码的表达式
putchar('D'-3);//A
putchar('\n');
return 0;
}
1.2getchar()
功能:
从终端获取一个字符
头文件:
#include
函数原型:
int getchar(void);
#include <stdio.h>
int main(int argc, const char *argv[])
{
#if 0
char v1 = 0;
v1 = getchar();
printf("v1 = %d [%c]\n", v1, v1);
#endif
char v1 = getchar();
getchar();//清理垃圾字符 回车
char v2 = getchar();
getchar();
char v3 = getchar();
printf("v1 = %d [%c]\n", v1, v1);
printf("v2 = %d [%c]\n", v2, v2);
printf("v3 = %d [%c]\n", v3, v3);
return 0;
}
2.puts()/gets()
2.1puts()
功能:
向终端输出一个字符串,自带换行
头文件:
#include
函数原型:
int puts(const char *s);
参数:
s : 要输出的字符串
#include <stdio.h>
int main(int argc, const char *argv[])
{
//可以直接输出字符串
puts("hello world");
//也可以输出保存字符串的数组的首地址
char str1[] = "www.hqyj.com";
puts(str1);
//也可以输出指向字符串常量的指针
char *p = "DC22021";
puts(p);
//puts 输出字符串时遇到 \0 就结束了
puts("www.b\0aidu.com");// www.b
return 0;
}
2.2gets()
功能:
从终端获取一个字符串
头文件:
#include
函数原型:
char *gets(char *s);
参数:
s : 要保存输入字符串的缓冲区的首地址
返回值:
成功返回获取的字符串
失败返回NULL
#include <stdio.h>
int main(int argc, const char *argv[])
{
//缓冲区要足够大,否则可能出现访问越界的风险
char str[32];
gets(str);//输入 遇到回车结束输入
//gets可以获取带有空格的字符串
puts(str);//输出
return 0;
}
3.printf()/scanf
3.1printf()
功能:
向终端按照一定格式输出一个字符串,----格式化输出
头文件:
#include
函数原型:
int printf(const char *format, ...);
参数:
format : 格式
%c 输出字符
%d 输出十进制整型
%u 按无符号输出十进制整型
%o 输出八进制整型
%x 输出十六进制整型
%f 输出浮点型
%e 按指数形式输出
%% 输出%
附加格式说明:
l 输出long 或者long long 或者double时会用到
# 按照八进制或十六进制输出时 输出前导符 0 0x
m m是一个实际的数字,表示输出数据的位宽
0 指定位宽后,不足的宽度用0来补
- 左对齐
+ 输出正数时 带正号
.n 保留n位小数
...:可变参
#include <stdio.h>
int main(int argc, const char *argv[])
{
unsigned char a = 255;
printf("%u\n",a);
int hour = 13;
int min = 45;
int sec = 6;
// 13:45:06
printf("%02d:%02d:%02d\n", hour, min, sec);
printf("hour=%d\n", hour);
printf("hour=%8d\n", hour);
printf("hour=%-8d\n", hour);
hour = -5;//如果是负数 +号就不显示了
printf("hour=%+d\n", hour);
hour = 12345;
printf("hour=%3d\n", hour);//指定的位宽不够时,以实际为准
return 0;
}
3.2scanf()
功能:
从终端按照一定格式获取数据,----格式化输入
头文件:
#include
函数原型:
int scanf(const char *format, ...);
参数:
format:格式 类似于printf 的格式
scanf的格式是怎么的,就要怎么输入,否则获取不到
... :可变参,需要写存储改输入的地址需要用到&
#include <stdio.h>
int main(int argc, const char *argv[])
{
#if 0
int hour = 0;
int min = 0;
int sec = 0;
//输入时 必须以 - 分隔,否则获取不到
scanf("%d-%d-%d", &hour, &min, &sec);
printf("%02d:%02d:%02d\n", hour, min, sec);
#endif
#if 0
//---------------char-----
char a;
scanf("%c", &a);
putchar(a);
#endif
#if 0
//----------------int-----
int b;
int c;
scanf("%d%d", &b, &c);//输入时 以空格或回车分隔 都可以
//%d 输入的就必须是整数
printf("b = %d c = %d\n", b, c);
#endif
#if 0
//--------------long------------
long d;
scanf("%ld", &d);
printf("d = %ld\n", d);
#endif
#if 0
//--------------float-----------------
float f1;
float f2;
scanf("%f%f", &f1, &f2);
printf("f1 = %f f2 = %f\n", f1, f2);
#endif
//----------------string-------------------
#if 0
char str[32];
scanf("%s", str);//数组名本身就是首地址 无需加 &
puts(str);
#endif
//scanf 直接使用%s 无法获取带有空格的字符串
//可以使用 gets() 来获取
//也可以使用下面的方式获取
char str[32];
scanf("%[^\n]", str);
puts(str);
return 0;
}
垃圾字符的处理:
#include <stdio.h>
int main(int argc, const char *argv[])
{
char a, b, c;
//垃圾字符场景1 :scanf中连续使用多个%c
//scanf("%c%c%c", &a, &b, &c);
//处理方式1:多个%c 之间使用空格分隔
//scanf("%c %c %c", &a, &b, &c);
//处理方式2:使用 抑制符 来处理
//--这种方法 要谨慎使用 因为正常的字符也会被吃掉
scanf("%c%*c%c%*c%c", &a, &b, &c);
printf("a = %d [%c]\n", a, a);
printf("b = %d [%c]\n", b, b);
printf("c = %d [%c]\n", c, c);
//垃圾字符场景2 :多个scanf %c 连续调用时
scanf("%c", &a);
getchar();
scanf("%c", &b);
getchar();
scanf("%c", &c);
//场景3:如果不知道前面输入了什么,而要获取一个字符时
char d;
%c 前面加一个 空格 来清空所有的垃圾字符
scanf(" %c", &d);
return 0;
}
二、分支控制语句
C语言的程序结构只有三种:顺序结构、分支结构(选择结构)、循环结构。
1.if..else 语句
1.1格式
1.简化格式:
if(表达式){
//代码块
}
执行逻辑:如果表达式为真 则执行代码块,否则不执行代码块
if(表达式){
//代码块1
}else{
//代码块2
}
执行逻辑:如果表达式为真 则执行代码块1,否则执行代码块2
2.阶梯格式
if(表达式1){
//代码块1
}else if(表达式2){
//代码块2
}else if(表达式n){
//代码块n
}else{
//其他分支
}
执行逻辑:如果表达式1为真 则执行代码块1,
否则继续判断表达式2,如果表达式2为真 则执行代码块2
....依次类推
之前else分支之前的所有表达式如果都为假,则执行else分支
3.嵌套格式
if(表达式1){
//代码块1
if(表达式11){
//代码块11
if(表达式111){
//代码块111
}else{
//代码块112
}
}else{
//代码块12
}
}else if(表达式2){
//代码块2
}else if(表达式n){
//代码块n
}else{
//其他分支
}
执行逻辑:阶梯形式的嵌套使用
例:
#include <stdio.h>
int main(int argc, const char *argv[])
{
int m = 10;
int n = 20;
//简化格式
printf("-----start----\n");
if(m > n){
printf("yes\n");
}
printf("-----end----\n");
printf("--------------------------------------\n");
//简化格式
printf("-----start----\n");
if(m > n){
printf("yes\n");
}else{
printf("no\n");
}
printf("-----end----\n");
printf("--------------------------------------\n");
//阶梯格式
printf("-----start----\n");
if(m < 0){
printf("m<0\n");
}else if(n < 0){
printf("n<0\n");
}else{
printf("m>0 n>0\n");
}
printf("-----end----\n");
printf("--------------------------------------\n");
//嵌套格式
printf("-----start----\n");
if(m > 0){
printf("m>0\n");
if(m>5){
printf("m>5\n");
}else{
printf("m<5\n");
}
}else{
printf("m<=0 n>0\n");
}
printf("-----end----\n");
return 0;
}
从终端输入一个字符
如果是大写的,转换成小写输出
如果是小写的,转换成大写输出
如果是0-9,输出对应的整型的 0-9
其他字符输出 #
#include <stdio.h>
int main(int argc, const char *argv[])
{
char num = 0;
printf("请输入一个字符:");
scanf("%c", &num);
/*
if(num 是大写){
转换成小写
}else if(num 是小写){
转换成大写
}else if(num [0,9]){
转换成整型 0-9
}else{
输出 #
}
*/
if(num >= 'A' && num <= 'Z'){
num += 32;
printf("%c\n", num);
}else if(num >= 'a' && num <= 'z'){
num -= 32;
printf("%c\n", num);
}else if(num >= '0' && num <= '9'){
num -= '0';
printf("%d\n", num);
}else{
printf("#\n");
}
return 0;
}
1.2 if..else语句注意事项
1.如果if..else语句对应代码块只有一行,那么后面的{}可以不加
如果有多行的时候,{}必须加,否则if只对下面的一行生效
2.else 必须有if与之对应,否则会报错
3.else 与同层次的前面与之最近的if结合
4.if 中的表达式一般是一个由关系运算符和逻辑运算符组成的表达式,
表达式的结果是一个bool类型,是能判断出真假的。
如果表达式是一个不正常的,要注意下面的用法
if(a) <==> if(a!=0)
if(!a) <==> if(a == 0)
if(a = b) 这种情况下,表达式的结果和 b 的值有关
b != 0 表达式为真
b == 0 表达式为假
if(10 == a) 变量和常量比较相等时,防止少写等号可以将常量写左边
因为 if(10 = a) 编译就过不去了
5. 同一层次的两个if..else语句是独立的,互不影响
if(){}
if(){}
思考:
下面的代码会输出什么?
int m = 10;
printf("start\n");
if(m > 0){
printf("aa\n");
m = -10;
}else if(m < 0){
printf("bb\n");
}
printf("end\n");
bb不会输出,因为分支控制语句只能走一条分支
1.输入一个年份(如:2000 1999 1970 2022)
输出这个年份是 平年 还是 闰年。
闰年:能被4整除并且不能被100整除,或者能被400整除。
1999 --> 平年
2000 --> 闰年
1900 --> 平年
2022 --> 平年
2020 --> 闰年
#include <stdio.h>
int main(int argc, const char *argv[])
{
int year = 0;
printf("输入一个年份:");
scanf("%d", &year);
//闰年:能被4整除并且不能被100整除,或者能被400整除
if((year%4==0 && year%100!=0) || year%400==0){
printf("闰年\n");
}else{
printf("平年\n");
}
return 0;
}
输入三角形的三个边长(int),判断能否构成三角形
如果能:
判断是什么三角形
等边
等腰
直角
普通
如果不能:
输出不能构成
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a = 0, b = 0, c = 0;
scanf("%d%d%d", &a, &b, &c);
if(a+b>c && b+c>a && a+c>b){
printf("能构成\n");
if(a==b && b==c){
printf("等边三角形\n");
}else if(a==b || b==c || a==c){
printf("等腰三角形\n");
if(a*a+b*b==c*c || b*b+c*c==a*a || a*a+c*c==b*b){
printf("等腰直角三角形\n");
}
}else if(a*a+b*b==c*c || b*b+c*c==a*a || a*a+c*c==b*b){
printf("直角三角形\n");
}else{
printf("普通三角形\n");
}
}else{
printf("不能构成\n");
}
return 0;
}
输入一个成绩 [0,100],输出学生成绩的等级
[90,100] A
[80,90) B
[70,80) C
[60,70) D
[0,60) 不及格
#include <stdio.h>
int main(int argc, const char *argv[])
{
int score = 0;
scanf("%d", &score);
if(90<=score && score<=100){
printf("A\n");
}else if(80<=score && score<90){
printf("B\n");
}else if(70<=score && score<80){
printf("C\n");
}else if(60<=score && score<70){
printf("D\n");
}else{
printf("不及格\n");
}
return 0;
}
2.switch..case 语句
2.1 格式
switch(表达式){
case 常量表达式1:
//代码块1
break;
case 常量表达式2:
//代码块2
break;
case 常量表达式n:
//代码块n
break;
default:
//其他分支逻辑
break;
}
2.2 注意事项
1.switch后面()里面一般是一个变量
2.case 后面的常量表达式就是 switch后面变量的所有可能值
3.case 后面的常量表达式一般是一个整型的或者字符型的,不能是浮点型的。
4.如果前面任意一个case都没有进,那么都走default分支,如果没有需要,default分支可以不写,default相当于if..else语句中的else
5.break 表示执行完某个分支后,就退出switch..case语句,如果不加break,那么程序会继续向下执行下面case中的代码块,直到遇到break 或者整个switch..case语句结束
#include <stdio.h>
int main(int argc, const char *argv[])
{
char num = 0;
scanf("%c", &num);
//switch后面的括号里也可以是一个表达式
//如 switch(num-1)
switch(num){
case 'a':
printf("aaa\n");
break;
case 'b':
printf("bbb\n");
break;
case 'c':
printf("ccc\n");
break;
default:
printf("other\n");
break;
}
printf("end\n");
return 0;
}
使用switch..case 语句 实现
输入一个成绩 [0,100],输出学生成绩的等级
[90,100] A
[80,90) B
[70,80) C
[60,70) D
[0,60) 不及格
#include <stdio.h>
int main(int argc, const char *argv[])
{
int score = 0;
scanf("%d", &score);
switch(score/10){
case 10:
case 9:
printf("A\n");
break;
case 8:
printf("B\n");
break;
case 7:
printf("C\n");
break;
case 6:
printf("D\n");
break;
default:
printf("不及格\n");
break;
}
return 0;
}
练习:
使用switch..case语句实现简易计算器的功能(+ - * /)
输入一个表达式 int char int
输出表达式的结果
如 输入 5+3
输出 8
#include <stdio.h>
int main(int argc, const char *argv[])
{
int v1 = 0;
int v2 = 0;
char operator = 0;
scanf("%d%c%d", &v1, &operator, &v2);
switch(operator){
case '+':
printf("%d %c %d = %d\n", v1, operator, v2, v1+v2);
break;
case '-':
printf("%d %c %d = %d\n", v1, operator, v2, v1-v2);
break;
case '*':
printf("%d %c %d = %d\n", v1, operator, v2, v1*v2);
break;
case '/':
printf("%d %c %d = %f\n", v1, operator, v2, (float)v1/(float)v2);
break;
}
return 0;
}
三、循环控制语句
1. goto实现循环
goto 本身是用来实现代码跳转的。
goto只能在同一个函数中完成跳转。
goto 会破坏代码的结构和可读性,所以,使用 goto 时要谨慎!!!
#include <stdio.h>
int main(int argc, const char *argv[])
{
printf("11111111\n");
goto NEXT;//跳转到对应的标签运行
printf("22222222\n");//这一行会被跳过
NEXT:
printf("33333333\n");
return 0;
}
使用goto实现循环
格式:
代码块1
标签:
循环体;--->会一直循环执行
goto 标签;
代码块3
#include <stdio.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
int count = 1;
printf("11111111\n");
NEXT:
printf("22222222\n");
//我们一般情况下使用的循环都是有条件的
//否则 无条件的循环 我们叫做死循环 程序就出不去了
if(count < 5){
count++;
goto NEXT;
}
printf("33333333\n");
return 0;
}
练习:
使用 goto 循环,计算 1+2+3+...+100 的和
int sum = 0;
/*
sum = sum + 1;
sum = sum + 2;
。。。
sum = sum + 100;
*/
/*
int i = 1;
sum = sum + i;
i++;
sum = sum + i;
i++;
。。。
sum = sum + i;
i++;
*/
#include <stdio.h>
int main(){
//sum 初始化成0 是必须的 否则可能会有随机值的影响
int sum = 0;//使用来保存求和结果的
int i = 1;//循环变量
LOOP:
sum = sum + i;
i++;
if(i <= 100){
goto LOOP;
}
printf("sum = %d\n", sum);
return 0;
}
2.while 循环
格式:
while(表达式){
//循环体
}
//循环后面的代码
执行流程:
先执行表达式,如果表达式为真,则执行循环体,
然后再执行表达式,如果还为真,则继续执行循环体,
直到表达式为假,循环立即结束,继续执行循环后面的代码
表达式:和 if 语句中 表达式的用法一样
一般而言,循环体要有能改变表达式结果的语句,否则就是死循环。
#include <stdio.h>
int main(int argc, const char *argv[])
{
int i = 0;
printf("start\n");
while(i < 5){
printf("hello world\n");
i++;
}
printf("end\n");
return 0;
}
练习:
1.使用 while 求 1~100 求和。
#include <stdio.h>
int main(){
int sum = 0;
int i = 1;
//while后面的表达式 本质是决定循环的出口
while(i<=100){
sum = sum + i;
i++;
}
printf("sum = %d\n", sum);
return 0;
}
2.猴子吃桃问题
猴子第一天摘了若干了桃,
当即就吃了一半数量的桃,没吃过瘾,又多吃了一个
第二天,又将剩下桃吃了一半,没吃过瘾,又多吃了一个
依次类推,直到第十天想吃桃的时候,发现只剩下一个了。
问:猴子第一天摘了多少个桃?
第十天 1
第九天 4 (1+1)*2
第八天 10 (4+1)*2
第七天 22 (10+1)*2
n = 1;
循环执行的语句
n = (n+1)*2;
#include <stdio.h>
int main(){
int num = 1;//保存当天桃的数量 1 是第十天的数量
int i = 0;//控制循环执行的次数的
//第十天没吃 一共吃了9 天
while(i < 9){
num = (num+1)*2;
i++;
}
//当循环结束的时候,num 里存储的就是 第一天的桃子的数量
printf("num = %d\n", num);
}
把天数 和 每天吃之前桃子有多少个 输出出来
#include <stdio.h>
int main(){
int num = 1;
int i = 0;
while(i < 9){
printf("第 %d 天 有 %d 个桃\n", 10-i, num);
num = (num+1)*2;
i++;
}
printf("第 %d 天 有 %d 个桃\n", 10-i, num);
}
3. do..while 循环
格式:
do{
代码块
}while(表达式); //后面要有一个分号!!!!
执行流程:
先执行代码块,然后执行表达式,如果表达式为真,
则继续执行代码块,直到表达式为假,循环立即结束。
#include <stdio.h>
int main(int argc, const char *argv[])
{
#if 0
int i = 0;
printf("start\n");
do{
printf("hello world\n");
i++;
}while(i < 5);
printf("end\n");
#endif
//while 和 do..while 的区别
//while是先判断 后执行
while(0){
printf("while:hello world\n");//不会执行
}
//do..while是先执行 后判断
do{
printf("do..while:hello world\n");//会执行一次
}while(0);
return 0;
}
4. for循环
格式:
for(表达式1;表达式2;表达式3){ //表达式之间用 分号 分隔!!
//代码块
}
执行逻辑:
先执行表达式1,然后执行表达式2,如果表达式2为真,
则执行代码块,然后执行表达式3,
然后再执行表达式2,如果还为真,继续执行代码块和表达式3,
直到表达式2为假,循环立即结束。
表达式1:只执行一次,一般是用来给循环变量赋初值的
表达式2:和 if while 语句中的表达式是一样的
表达式3:是用来改变循环变量的值从而控制循环结束的,如 i++
#include <stdio.h>
int main(int argc, const char *argv[])
{
int i = 0;
printf("start\n");
for(i = 0; i < 5; i++){
printf("hello world\n");
}
printf("end\n");
return 0;
}
练习:
使用 for 循环 求 1~100 的和。
#include <stdio.h>
int main(int argc, const char *argv[])
{
int sum = 0;
//for 循环的第一个表达式 是可以定义变量的
//但是 定义的变量 只在for循环的 ()和{}里面生效
//后面再使用就不行了
//只有 C99 以上标准的编译器才支持
for(int i = 1; i <= 100; i++){
sum += i;
}
//printf("%d\n", i);//错误的 因为此时 i 所占用的空间已经被回收了
printf("sum = %d\n", sum);
return 0;
}
练习:
输出 (100,1000) 范围内所有的 水仙花 数
水仙花数:自身 == 个位*个位*个位 + 十位*十位*十位 + 百*百*百
例:
153 = 3*3*3 + 5*5*5 + 1*1*1 = 27 + 125 +1 = 153
#include <stdio.h>
int main(int argc, const char *argv[])
{
int i = 101;
int ge = 0;
int shi = 0;
int bai = 0;
for(i = 101; i < 1000; i++){
//在循环中 每次进循环 i 就表示当前这个三位数
//获取这个三位数的个位 十位 百位
//因为每次进循环时 i 都不同 所以每次要重新获取 i 的 个 十 百
ge = i % 10;
shi = i / 10 % 10;
bai = i / 100;
//判断是否是水仙花数
if(ge*ge*ge + shi*shi*shi + bai*bai*bai == i){
printf("%d\n", i);
}
}
return 0;
}
输入一个日期 年-月-日 %d-%d-%d
输出这个日期是这一年的第几天。(要考虑平年、闰年的问题)
闰年 二月 29天
平年 二月 28天
如:2020-3-1 ---> 2020年3月1日是2020年的第 61 天
#include <stdio.h>
//输入一个日期,输出当前日期是这一年的第几天
#define MONTH_1 31
#define MONTH_2 28
#define MONTH_3 31
#define MONTH_4 30
#define MONTH_5 31
#define MONTH_6 30
#define MONTH_7 31
#define MONTH_8 31
#define MONTH_9 30
#define MONTH_10 31
#define MONTH_11 30
#define MONTH_12 31
int main()
{
int year, month, day;
printf("请输入要查询的日期(年/月/日):");
scanf("%d/%d/%d", &year, &month, &day);
int leap = 0;//闰年 二月的增量
//printf("%d/%d/%d\n", year, month, day);
//判断输入的日期是否有误
//判断年是闰年还是平年
if(((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
{
leap = 1;
}
//判断月份输入的是否有误
if(month < 1 || month > 12)
{
printf("您输入的月份有误,请重新输入\n");
//在main函数里面使用return,结束整个程序
return -1;
}
//判断日是否有误
//月份:1 3 5 7 8 10 12 最多31天
if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12)
{
if(day < 1 || day > 31)
{
printf("您输入的日期有误,请重新输入\n");
return -1;
}
}
//月份:4 6 9 11 最多30天
if(month==4 || month==6 || month==9 || month==11)
{
if(day < 1 || day > 30)
{
printf("您输入的日期有误,请重新输入\n");
return -1;
}
}
//月份:2 闰年最多29天 平年最多28天
if(month == 2)
{
if(leap == 1) //闰年
{
if(day < 1 || day > 29)
{
printf("您输入的日期有误,请重新输入\n");
return -1;
}
}
else if(leap == 0) //平年
{
if(day < 1 || day > 28)
{
printf("您输入的日期有误,请重新输入\n");
return -1;
}
}
}
int days = 0;
switch(month)
{
case 12:
days += MONTH_11;
case 11:
days += MONTH_10;
case 10:
days += MONTH_9;
case 9:
days += MONTH_8;
case 8:
days += MONTH_7;
case 7:
days += MONTH_6;
case 6:
days += MONTH_5;
case 5:
days += MONTH_4;
case 4:
days += MONTH_3;
case 3:
days += MONTH_2 + leap;
case 2:
days += MONTH_1;
case 1:
days += day;
break;
}
printf("%d年%d月%d日是%d年的第%d天\n", year, month, day, year, days);
return 0;
}
5. C语言中求次方和开平方的函数
5.1 pow()函数
功能:
计算x的y的方
头文件:
#include
//使用 math 库的函数,需要加编译选项 -lm
函数原型:
double pow(double x, double y);
参数:
x:底数
y:指数
返回值:
计算的结果
#include <stdio.h>
#include <math.h>
int main(int argc, const char *argv[])
{
double x = 2;
double y = 3;
//计算x的y次方
double ret = pow(x ,y);
printf("%.1lf\n", ret);//8.0
return 0;
}
5.2 sqrt()函数
功能:
计算x的非负平方根
头文件:
#include
//使用 math 库的函数,需要加编译选项 -lm
否则报错:
函数原型:
double sqrt(double x);
参数:
x:要开根号的数
返回值:
计算的结果
#include <stdio.h>
#include <math.h>
int main(int argc, const char *argv[])
{
double a = 16;
double ret = sqrt(a);
printf("%.1lf\n", ret);//4
return 0;
}
6. 死循环
所谓的死循环就是,判断条件恒为真,程序永远都在循环体里面执行的一种逻辑。
一般而言,我们使用的循环都是有结束条件的,
但是某些场景,也需要用到死循环,如 如后台的服务器程序,
需要一直等待客户端连接收发数据,这时就可以用死循环。
死循环的写法:
//一般while(1) 比较常用
while(1){
//循环体
}
for(;;){ //表达式可以不写,但是分号必须写
//循环体
}
四、辅助控制关键字
1. break
break语句可以用在switch..case语句中,表示执行完某个分支后,
跳出当前switch..case语句
break也可以用在循环中,表示结束本层循环。
2. continue
continue 只能用在循环语句中,用在其他位置会报错,
continue 表示退出本层的本次循环。
3. return
return 一般用在函数中,表示结束函数,并返回函数执行的结果。
return 如果用在主函数中,表示结束整个程序。
#include <stdio.h>
int main(int argc, const char *argv[])
{
int i = 0;
int j = 0;
for(i = 1; i <= 5; i++){
for(j = 1; j <= 5; j++){
if(j == 3){
//break;
//continue;
return 0;
}
printf("%d--%d\n", i, j);
}
}
return 0;
}
.c文件补齐 设置:
vi .vim/snippets/c.snippets
在文件最后面的 snippet main 下面 加如两行(注意以table键开头, 空行也要有table键开头)
然后 :wq 保存退出即可
修改之后,打开任意的 .c 文件 输入main后按table键即可补齐
五、控制语句综合练习
1.练习:
使用C语言的控制语句输出下面的图案
F
_FE
__FED
___FEDC
____FEDCB
_____FEDCBA
答案:
#include <stdio.h>
int main(int argc, const char *argv[])
{
int i = 0;
int j = 0;
int k = 0;
char value = 'F';
//外层循环控制输出的行数
for(i = 0; i < 6; i++){
//内层循环控制输出 下划线 的个数
for(j = 0; j < i; j++){
printf("_");
}
value = 'F';//每次都从 F 开始输出
//控制输出 字母 的个数
for(k = 0; k <= i ; k++){
printf("%c", value);
value--;
}
//每行内容都输出完之后 再换行
printf("\n");
}
return 0;
}
2.练习:
输入一个数,输出这个数的所有因子。
如:12 --> 1 2 3 4 6 12
6 --> 1 2 3 6
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 0;
scanf("%d", &num);
int i = 0;
//因为 从1到num 的每一个数都有可能是 num 的因子
//所以每一个数都要判断
//这种每个数都访问的方式我们称之为 遍历
for(i = 1; i <= num; i++){
if(num%i == 0){
printf("%d 是 %d 的因子\n", i, num);
}
}
return 0;
}
3.练习:
输出 [1,1000] 范围内的所有完数,并输出完数的个数。
完数:除了自身之外所有因子之和还等于自身
如:6 ---> 1 2 3 1+2+3 == 6
#include <stdio.h>
int main(int argc, const char *argv[])
{
int i = 0;
int j = 0;
int sum = 0;//统计因子和
int count = 0;//统计个数
//外层循环遍历 1-1000
for(i = 1; i <= 1000; i++){
sum = 0;//此处sum = 0是必须的,因为重新进入循环时
//sum中还保存着上一个数的因子之和呢
//内存循环是对每次的i计算因子值和
//int j = 0; //一般不在循环内部定义变量
for(j = 1; j < i ; j++){
if(i%j == 0){
sum += j;
}
}
//当内层循环结束时,sum中保存的就是当前这个i所有的因子之和(不包括自身)
if(sum == i){
printf("%d 是一个完数\n", i);
count++;//如果是完数 计数+1
}
}
printf("一共有 %d 个完数\n", count);
return 0;
}
4.练习:
输出 [100,1000] 范围内的所有质数,并输出质数的个数。
质数:只能被 1 和 自身 整除的数。
12 ---》不是质数
7 13 是质数
#include <stdio.h>
int main(int argc, const char *argv[])
{
int i = 0;
int j = 0;
int count = 0;
for(i = 100; i <= 1000; i++){
for(j = 2; j < i; j++){
if(i % j == 0){
break;
}
}
//内层循环有两种结束条件 一种是 break 结束的
//另一中是 正常结束的(j==i)
//如果是break结束的 说明再[2,i-1] 范围内找到了一个i的因子
//说明i不是质数
//
//如果是 j==i 退出的,说明 [2,i-1] 范围内都没有 i 的因子
//说明 i 是一个质数
if(j == i){
printf("质数:%d\n", i);
count++;
}
}
printf("共有 %d 个质数\n", count);
return 0;
}
第二种处理方式,是用标志位。
#include <stdio.h>
int main(int argc, const char *argv[])
{
int i = 0;
int j = 0;
int count = 0;
//我们规定 flag 为 0 时,不是质数,为 1 时是质数
int flag = 0;
for(i = 100; i <= 1000; i++){
flag = 1;//每次都默认是质数
for(j = 2; j < i; j++){
if(i % j == 0){
flag = 0;//如果找到其他因子了,再将标志位置 0
break;
}
}
if(1 == flag){
printf("%d 是质数\n", i);
count++;
}
}
printf("共有 %d 个质数\n", count);
return 0;
}