说明:这是本人在学习C语言的时候整理的笔记,因文字限制,所以分为三篇文章,即上中下来分享这份笔记。
看完这三部分,C语言基础、计算机C语言二级(关于C语言的部分)、期末考试。考研数据结构(如考408的话,数据结果这本书需要C语言基础)什么的,这三篇笔记基本上就够了,代码绝对能看懂了。
因为我是跟X站的教程学的,看不懂代码或者想看视频学的话可以点击这个链接直达: C语言教程视频
注:
因为是个人笔记,难免有错误,见谅。
完整的电子版笔记我会分享在第三篇的文章开头。
目录
- C语言学习笔记
- 第1章、什么是C语言
- 第2章、第一个C语言程序
- 第3章、数据类型
- 第4章、变量、常量
- 4.1 定义变量的方法
- 4.2 变量的分类
- 4.3 变量的使用
- 4.4 变量的作用域和生命周期
- 4.5 常量
- 第5章、字符串+转义字符+注释
- 5.1 字符串
- 5.2 转义字符
- 5.3 注释
- 第6章、分支语句
- 6.1 什么是语句
- 6.2 分支语句(选择结构)
- 6.2.1 **if**语句
- 6.2.1.1 if语句的语法结构
- 6.2.1.2 悬空 else
- 6.2.1.3 if 书写形式的对比
- 6.2.1.4 练习
- 6.2.2 switch语句
- 6.2.2.1 在switch语句中的 break
- 6.2.2.2 default子句
- 6.2.2.3 练习
- 第7章、循环语句
- 7.1 while循环
- 7.1.1 while语句中的break和continue
- 7.2 for循环
- 7.2.2break和continue在for循环中
- 7.2.3 for语句的循环控制变量
- 7.2.4 一些for循环的变种
- 7.2.5 一道笔试题
- 7.3 do...while()循环
- 7.3.1 do...while语句的语法
- 7.3.2 执行流程
- 7.3.3 do语句的特点
- 7.3.4 do while循环中的break和continue
- 7.4 练习
- 7.4.1 练习代码参考
- 7.4.2 折半查找算法/二分查找算法
- 7.4.3 猜数字游戏实现
- 7.5 goto语句
C语言学习笔记
第1章、什么是C语言
C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。
二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制定了一套完整的美国国家标准语
法,称为ANSI C,作为C语言最初的标准。 [1] 目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。
C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。
其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。
第2章、第一个C语言程序
#include <stdio.h>
int main()
{
printf("hello bit\n");
printf("he he\n");
return 0;
}
//解释:
//main函数是程序的入口
//一个工程中main函数有且仅有一个
第3章、数据类型
char //字符数据类型
short //短整型
int //整型
long //长整型
long long //更长的整型
float //单精度浮点数
double //双精度浮点数
//C语言有没有字符串类型?
这里的 string 有 二义性。
(1) 如果 string 是普通词汇,“C语言中有字符类型变量吗”, 答,有。 字符类型 用 char 声明。
char str[]="This is a string";
(2) 如果 string 是专用词汇,“C语言中有string类型变量吗”,答,没有。string 是 类,是 class, 不是 类型,不是 type.
类 的 声明 用 构造函数初始化,或 new 声明。
类 -- C++, 不是 C
c语言中没有string这个字符类型变量,只有char字符类型变量,如非要用string定义可以这样使用:
typeof char *string;
string s="";
其原理就是在声明了一个字符串数组后对其进行了初始化.
string s="";相当于char s[]="";
- 为什么出现这么多的类型?
- 每种类型的大小是多少?
#include <stdio.h>
int main()
{
printf("%d\n", sizeof(char));
printf("%d\n", sizeof(short));
printf("%d\n", sizeof(int));
printf("%d\n", sizeof(long));
printf("%d\n", sizeof(long long));
printf("%d\n", sizeof(float));
printf("%d\n", sizeof(double));
printf("%d\n", sizeof(long double));
return 0;
}
注意:存在这么多的类型,其实是为了更加丰富的表达生活中的各种值。
类型的使用:
char ch = 'w';
int weight = 120;
int salary = 20000;
第4章、变量、常量
生活中的有些值是不变的(比如:圆周率,性别,身份证号码,血型等等)
有些值是可变的(比如:年龄,体重,薪资)。
不变的值,C语言中用常量的概念来表示,变的值C语言中用变量来表示。
4.1 定义变量的方法
int age = 150;
float weight = 45.5f;
char ch = 'w';
4.2 变量的分类
- 局部变量
- 全局变量
#include <stdio.h>
int global = 2019;//全局变量
int main()
{
int local = 2018;//局部变量
//下面定义的global会不会有问题?
int global = 2020;//局部变量
printf("global = %d\n", global);
return 0;
}
总结:
上面的局部变量global变量的定义其实没有什么问题的!
当局部变量和全局变量同名的时候,局部变量优先使用。
4.3 变量的使用
#include <stdio.h>
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = num1 + num2;
printf("sum = %d\n", sum);
return 0;
}
//这里介绍一下输入,输出语句
//scanf
//printf
4.4 变量的作用域和生命周期
作用域
-
作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码
范围就是这个名字的作用域。
- 局部变量的作用域是变量所在的局部范围。
- 全局变量的作用域是整个工程。
生命周期
- 变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
-
局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
-
全局变量的生命周期是:整个程序的生命周期。
4.5 常量
C语言中的常量和变量的定义的形式有所差异。
C语言中的常量分为以下以下几种:
- 字面常量
- const 修饰的常变量
- #define 定义的标识符常量
- 枚举常量
#include <stdio.h>
//举例
enum Sex
{
MALE,
FEMALE,
SECRET
};
//括号中的MALE,FEMALE,SECRET是枚举常量
int main()
{
//字面常量演示
3.14;//字面常量
1000;//字面常量
//const 修饰的常变量
const float pai = 3.14f; //这里的pai是const修饰的常变量
pai = 5.14;//是不能直接修改的!
//#define的标识符常量 演示
#define MAX 100
printf("max = %d\n", MAX);
//枚举常量演示
printf("%d\n", MALE);
printf("%d\n", FEMALE);
printf("%d\n", SECRET);
//注:枚举常量的默认是从0开始,依次向下递增1的
return 0;
}
注:
上面例子上的 pai 被称为 const 修饰的常变量, const 修饰的常变量在C语言中只是在语法层面限制了
变量 pai 不能直接被改变,但是 pai 本质上还是一个变量的, 所以叫常变量。
第5章、字符串+转义字符+注释
5.1 字符串
"hello!\n"
这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。
注:字符串的结束标志是一个 \0 的转义字符,隐藏在字符串末尾的,值为0,==在计算字符串长度的时候 \0 是结束标志,不算作字符串内容,但占一个字符的空间。==记住要有单引号。
#include <stdio.h>
//下面代码,打印结果是什么?为什么?(突出'\0'的重要性)
int main()
{
char arr1[] ="abc";
char arr2[] = {'a', 'b', 'c'};//abc烫烫烫
char arr3[] = {'a', 'b', 'c','\0'};//abc
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
//strlen()----C语言提供的函数,需要使用头文件 #include<string.h>
//strlen----string length---计算字符串长度的
printf("%d\n",strlen(arr1));//3,因为arr1后面隐藏了一个\0
printf("%d\n",strlen(arr2));//随机数,如15,有'、0',arr2的长度才为3,不然是随机值,直到遇到\0为止
return0;
}
5.2 转义字符
顾名思义就是转变原来的意思
#include <stdio.h>
#include <string.h>
int main()
{
printf("abcn");
printf("abc\n");
printf("%d\n", strlen("c:\test\32\test.c"))//13, \t,\32,\为一个字符
// /32-----32是2个八进制数
//32作为八进制代表的那个十进制数字,作为ASCII值,对应的字符,为一个向右的箭头
return 0;
}
5.3 注释
第6章、分支语句
C语言是一门 结构化 的程序设计语言
1.顺序结构
2.选择结构
3.循环结构
6.1 什么是语句
C语言由一个分号(;)隔开的就是一条语句。比如:
#include <stdio.h>
printf("hehe");
1 + 2;
;//空语句
C语句可分为以下五类:
-
表达式语句
-
函数调用语句
-
控制语句
-
复合语句
-
空语句
控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成,C语言有九种控制语句。
可分成以下三类:
-
条件判断语句也叫分支语句:if 语句、switch 语句;
-
循环执行语句:do while 语句、while 语句、for 语句;
-
转向语句:break 语句、goto 语句、continue 语句、return 语句。
6.2 分支语句(选择结构)
如果你好好学习,校招时拿一个好offer,走上人生巅峰。
如果你不学习,毕业等于失业,回家卖红薯。
这就是选择!
#include <stdio.h>
int main()
{
int input= 0;
printf("加入比特\n");
printf("你要好好学习吗?(1/0):");
sacnf("%d", &input);// 1/0
if(input == 1)
{
printf("坚持,你会有好offer\n");
} else
{
printf("放弃,回家卖红薯\n");
}
return 0;
}
6.2.1 if语句
6.2.1.1 if语句的语法结构
语法结构:
//单分支
if(表达式)//如果表达式的结果为真,非0,就执行语句,否则什么都不执行
语句;
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)
{
printf("青年\n");
}
else if(age >= 30 && age < 50)
{
printf("中年\n");
}
else if(age >= 50 && age < 80)
{
printf("老年\n");
}
else
{
printf("老寿星\n");
}
}
解释一下:
如果表达式的结果为真,则语句执行。
在C语言中如何表示真假?
0表示假,非0表示真。
如果条件成立,要执行多条语句,应该使用代码块。
#include <stdio.h>
//这里的一对 { } 就是一个代码块。
int main()
{
if(表达式)
{
语句列表1;
}
else
{
语句列表2;
}
return 0;
}
这里的一对 { } 就是一个代码块。
6.2.1.2 悬空 else
当你写了这个代码:
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if(a == 1)
if(b == 2)
printf("hehe\n");
else//else 是和它离的最近的 if 匹配的
printf("haha\n");
return 0;
}
//没有任何输出
//第一个if没有执行
改正:
//适当的使用{}可以使代码的逻辑更加清楚。
//代码风格很重要
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if(a == 1)
{
if(b == 2)
{
printf("hehe\n");
}
}
else
{
printf("haha\n");
}
return 0;
}
else的匹配:else 是和它离的最近的 if 匹配的。
6.2.1.3 if 书写形式的对比
//代码1
if (condition) {//condition : 条件
return x;
}
return y;
//做错了,我以为是条件成立才返回x,y始终返回
//答案是如果条件成立,返回x,否则返回y
//代码2
if(condition)
{
return x;
}
else
{
return y;
}//等价代码1
//代码3
int num = 1;
//if(num == 5)
if(num = 5)//==
{
printf("hehe\n");
}// = 是赋值,== 才是判断,能打印 hehe
//代码4
int num = 1;
if(5 == num)
{
printf("hehe\n");
}
代码2和代码4更好,逻辑更加清晰,不容易出错。更加容易发现代码中的问题
6.2.1.4 练习
-
判断一个数是否为奇数
-
输出1-100之间的奇数
6.2.2 switch语句
switch语句也是一种分支语句。
常常用于多分支的情况。
比如:
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期日
那我没写成 if…else if …else if 的形式太复杂,那我们就得有不一样的语法形式。
这就是switch 语句。
switch( 整型 表达式)//如 double 类型就不行
{
语句项;
}
而语句项是什么呢?
//是一些case语句:
//如下:
//整型 常量
case 整型常量表达式://可以写1,1 + 0,但不能写1.0 //非法的case表达式
语句;
6.2.2.1 在switch语句中的 break
在switch语句中,我们没办法直接实现分支,搭配break使用才能实现真正的分支。
case决定入口,break 决定出口,跳出当前所在的switch语句
比如:
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &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;
}
有时候我们的需求变了:
-
输入1-5,输出的是 “weekday”;
-
输入6-7,输出 “weekend”
-
所以我们的代码就应该这样实现了:
#include <stdio.h>
//switch代码演示
int main()
{
int day = 0;
switch(day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("weekday\n");
break;
case 6:
case 7:
printf("weekend\n");
break;
}
return 0;
}
break语句 不是一定在case后面都要有,有的实际效果是把语句列表划分为不同的分支部分。
编程好习惯:
在最后一个 case 语句的后面加上一条 break语句。
(之所以这么写是可以避免出现在以前的最后一个 case 语句后面忘了添加 break语句)。
6.2.2.2 default子句
如果表达的值与所有的case标签的值都不匹配怎么办?
其实也没什么,结构就是所有的语句都被跳过而已。
程序并不会终止,也不会报错,因为这种情况在C中并不认为是个错误。
但是,如果你并不想忽略不匹配所有标签的表达式的值时该怎么办呢?
你可以在语句列表中增加一条default子句,把下面的标签
default:
写在任何一个 case 标签可以出现的位置。
当 switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。
所以,每个switch语句中只能出现一条default子句。
但是它可以出现在语句列表的任何位置,而且语句流会像执行一个case标签一样执行default子句。
6.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
//没有遇到break就往下执行
编程好习惯
在每个 switch 语句中都放一条default子句是个好习惯,甚至可以在后边再加一个 break 。
第7章、循环语句
有些事必须一直做,比如我日复一日的讲课,比如大家,日复一日的学习。
C语言中如何实现循环呢?
-
while循环
-
for循环
-
do … while语句
7.1 while循环
我们已经掌握了,if 语句:
if(条件)//如果条件成立,非0就为真
语句;
当 条件满足 的情况下,if语句后的语句执行,否则不执行。
但是这个语句只会执行一次。
由于我们发现生活中很多的实际的例子是:同一件事情我们需要完成很多次。
那我们怎么做呢?
C语言中给我们引入了: while 语句,可以实现循环。
//while 语法结构
while(表达式)
循环语句;
while语句执行的流程:
比如我们实现:
在屏幕上打印1-10的数字。
#include <stdio.h>
int main()
{
int i = 1;
while(i <= 10)
{
printf("%d ", i);
i = i + 1;
}
return 0;
}
//while循环的实例
#include <stdio.h>
int main()
{
printf("加入比特\n");
int line = 0;
while(line <= 20000)
{
line++;
printf("我要继续努力敲代码 :\n", line);
}
if (line > 20000)
{
printf("好offer\n");
}
return 0;
}
上面的代码已经帮我了解了 while 语句的基本语法,那我们再了解一下:
7.1.1 while语句中的break和continue
break介绍
//break 代码实例
#include <stdio.h>
int main()
{
int i = 1;
while(i <= 10)
{
if(i == 5)
break;
printf("%d ", i);
i = i + 1;
}
return 0;
}
这里代码输出的结果是什么?
1 2 3 4
总结:
break在while循环中的作用:
其实在循环中只要遇到 break,就停止后期的所有的循环,直接终止跳出循环。
所以:while中的break是用于永久终止循环的。
continue介绍
//continue 代码实例1
#include <stdio.h>
int main()
{
int i = 1;
while(i <= 10)
{
if(i == 5)
continue;
printf("%d ", i);
i++;
}
return 0;
}
//陷入了死循环
这里代码输出的结果是什么?
1 2 3 4 光标还在一直动
//continue 代码实例2
#include <stdio.h>
int main()
{
int i = 1;
while(i <= 10)
{
i++;
if(i == 5)
{
continue;
}
printf("%d ", i);
}
return 0;
}
这里代码输出的结果是什么?
2 3 4 6 7 8 9 10 11
总结:
continue 在while 循环中的作用就是:
continue 是用于终止本次循环的,也就是本次循环 中 continue 后边的代码不会再执行,
而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。
再看几个代码:
//代码什么意思?
//代码1
#include <stdio.h>
int main()
{
// int ch = getchar();接收字符,把ch传给putchar,putchar就可以把ch打印在屏幕上,与printf("%c\n",ch);的作用相同,
//putchar(ch);更加简洁
// putchar(ch);输出字符
int ch = 0
//ctrl + z
//EOF----end of file(文件结束标志) ---- 本质的值是 -1(负一)
while ((ch = getchar()) != EOF)//get char -- 获取字符,接收一个键盘输入的一个无符号字符
putchar(ch);
return 0;
}
这里的代码适当的修改是可以用来清理 缓冲区 的.
//代码2
#include <stdio.h>
int main()
{
char ch = '\0';
while ((ch = getchar()) != EOF)
{
if (ch < ‘0’ || ch > ‘9’)
continue;
putchar(ch);
}
return 0;
}
//这个代码的作用是:只打印数字字符,跳过其他字符
#inclde <stdio.h>
int main()
{
int ret = 0;
char password[20] = {0};
int ch = 0;
printf("请输入密码:");
scanf("%s", password);//输入密码,并存放在password数组中
//缓冲区还剩一个'\n'
//可添加一行 :getchar();
while(ch = getchar() != '\n')
{
;//空语句
}
printf("请确认(Y/N):");
if (ret == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0;
}
//scanf()和getchar()都是输入函数,读取数据的时候先进入输入缓冲区,里面可以放一些数据,输入函数在接收数据的时候,scanf去看输入缓冲区里面有没有数据,第一次读的时候什么都没有,因为你还没有从键盘输入数据,此时scanf会等待你输入一个东西,一旦输入了,scanf会拿走它想要的一部分,拿走之后scanf函数就过去了,然后到getchar函数,看缓冲区还有没有数据,没有就继续等待
//如果在scanf输入123456你后按一下回车,实际结果是123456\n,回车前的123456被scanf读走了,缓冲区还剩下一个\n,被getchar直接读走,不会等待了。
//但这个结果不是我们想要的;运行到getchar我们希望它等待
//所以:
//补一行getchar();
//但你输入123456 ABCD\n
//运行结果还是放弃确认
//scanf只会把空格前面的数据读走
//此时缓冲区还剩下: ABCD\n
//第一个gechar把空格读走了
//还剩下ABCD\n,ABCD直接被第二个getchar()读走了
//现在的思路,一直读,直到把\n读走
7.2 for循环
我们已经知道了while循环,但是我们为什么还要一个for循环呢?
首先来看看for循环的语法:
语法:
for(表达式1; 表达式2; 表达式3)
循环语句;
表达式1
表达式1为初始化部分,用于初始化循环变量的。
表达式2
表达式2为条件判断部分,用于判断循环时候终止。
表达式3
表达式3为调整部分,用于循环条件的调整。
实际的问题:
使用for循环 在屏幕上打印1-10的数字。
#include <stdio.h>
int main()
{
int i = 0;
//for(i = 1/*初始化*/; i <= 10/*判断部分*/; i++/*调整部分*/)
for(i = 1; i <= 10; i++)
{
printf("%d ", i);
}
return 0;
}
for循环的执行流程图:
现在我们对比一下for循环和while循环:
int i = 0;
//实现相同的功能,使用while
i = 1;//初始化部分
while(i <= 10)//判断部分
{
printf("hehe\n");
i++;//调整部分
}
//实现相同的功能,使用for
for(i = 1; i <= 10; i++)
{
printf("hehe\n");
}
可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹;for循环使用的频率也最高。
7.2.2break和continue在for循环中
我们发现在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。
但是还是有些差异:
//代码1
#include <stdio.h>
int main()
{
int i = 0;
i = 1;
while (i <= 10) {
if (i == 5)
continue;
printf("%d ", i);
i++;
}
return 0;
}
//代码2
#include <stdio.h>
int main()
{
int i = 0;
for(i = 1; i <= 10; i++)//执行continue后来到这里
{
if(i == 5)
continue;
printf("%d ", i);
}
return 0;
}
//continue在for循环中没有死循环
//continue在while循环中死循环
7.2.3 for语句的循环控制变量
建议:
-
不可在 for 循环体内修改循环变量,防止 for 循环失去控制。
-
建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
int i = 0;
//前闭后开的写法
for(i = 0; i < 10; i++)
{}
//两边都是闭区间
for(i = 0; i <= 9; i++)
{}
7.2.4 一些for循环的变种
#include <stdio.h>
int main()
{
//代码1
for(;;)
{
printf("hehe\n");
}
//死循环
//for循环中的初始化部分,判断部分,调整部分是可以省略的,那判断条件就:恒为真,
//但是不建议初学时省略,容易导致问题。
//代码2
int i = 0;
int j = 0;
//这里打印多少个hehe?
//10 * 10 == 100
for(i = 0; i < 10; i++)
{
for(j = 0; j < 10; j++)
{
printf("hehe\n");
}
}
//代码3
int i = 0;
int j = 0;
//如果省略掉初始化部分,这里打印多少个hehe?
//10
//第一次循环: i = 0,j = 0,1,2,3,4,5,6,7,8,9,j = 10时跳出内层循环,i = 2,进入外层循环,但j = 10,内层循环条件不执行,所 以只打印10次hehe,i也是从0到9;
for(; i < 10; i++)
{
for(; j < 10; j++)
{
printf("hehe\n");
}
}
//代码4-使用多余一个变量控制循环
int x, y;//没有初始化
for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)//初始化部分:逗号表达式
{
printf("hehe\n");
}
return 0;
}
//输出2个hehe
7.2.5 一道笔试题
//请问循环要循环多少次?
#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为假
//一次循环都不执行
}
7.3 do…while()循环
7.3.1 do…while语句的语法
do
循环语句;
while(表达式);
7.3.2 执行流程
7.3.3 do语句的特点
循环至少执行一次,使用的场景有限,所以不是经常使用。
#include <stdio.h>
int main()
{
int i = 10;
do
{
printf("%d\n", i);
} while (i < 10);
return 0;
}
7.3.4 do while循环中的break和continue
#include <stdio.h>
int main()
{
int i = 10;
do
{
if(5 == i)
break;
printf("%d\n", i);
} while(i < 10);
return 0;
}
#include <stdio.h>
int main()
{
int i = 1;
do
{
if(5 == i)
continue;
printf("%d \n", i);
i++;
}
while(i <= 10); //continue来到这
return 0;
}
//1 2 3 4 _ 死循环了,4后面光标一直在闪
7.4 练习
-
计算 n 的阶乘。
-
计算 1! + 2! + 3! + ……+ 10!
-
在一个有序数组中查找具体的某个数字n。(讲解二分查找)
-
编写代码,演示多个字符从两端移动,向中间汇聚。
-
编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则
提示登录成,如果三次均输入错误,则退出程序。
7.4.1 练习代码参考
//代码1--第4题
//编写代码,演示多个字符从两端移动,向中间汇聚
//思路:
//welcome to bit...
//#################
//w################
//we###############
//...
//welcome to bit...
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <stdlib.h>
int main()
{
char arr1[] = "welcome to bit...";
char arr2[] = "#################";
int left = 0;
//右下标怎么算
//int right = sizeof(arr1) / sizeof(arr1[0]) - 1;//错误的算法
//比如:
//cahr arr[] = "abc"
//[a b c \0]
// 0 1 2 3
//多一个隐藏元素
//得 - 2:int right = sizeof(arr1) / sizeof(arr1[0]) - 2;
//但这种方法比较难以理解
int right = strlen(arr1) - 1;//strlen(arr)遇到\0就停止了,不包含\0
printf("%s\n", arr2);
//while循环实现
while(left <= right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
Sleep(1000);//Sleep()函数,每打印一次休息一秒,用来感受变化
system("cls");//执行系统命令的一个函数-cls-清空屏幕
left++;
right--;
}
printf("%s\n", arr2);
//for循环实现
for (left = 0, right = strlen(src) - 1;
left <= right;
left++, right--)
{
Sleep(1000);
rr2[left] = arr1[left];
arr2[right] = arr1[right];
printf( "%s\n", target);
}
retutn 0;
}
//代码2
int main()
{
int i = 0;
char password[20] = { 0 };
for (i = 0; i < 3; i++)
{
printf("请输入密码:");
scanf("%s", &password);
//if (password == "123456")
//== 不能用来比较两个字符串是否相等,应该使用一个库函数-strcmp()-string compare
//C 库函数 int strcmp(const char *str1, const char *str2) 把 str1 所指向的字符串和 str2 所指向的字符串进行比较。
//该函数返回值如下:
//如果返回值小于 0,则表示 str1 小于 str2。
//如果返回值大于 0,则表示 str1 大于 str2。
//如果返回值等于 0,则表示 str1 等于 str2。
if(strcmp(password,"123456") == 0)
{
printf("密码正确\n");
break;
}
else
{
printf("密码错误\n")
}
}
if (i == 3)
{
printf("三次密码均错误,退出程序\n");
}
return 0;
}
7.4.2 折半查找算法/二分查找算法
比如我买了一双鞋,你好奇问我多少钱,我说不超过300元。你还是好奇,你想知道到底多少,我就让你猜,你会怎么猜?
答案:你每次猜中间数。
代码实现:
实现在主函数内:
//找有序数组的元素下标
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int key = 7;//找目标元素7
int left = 0;//左下标
int sz = sizeof(arr) / sizeof(arr[0]);//计算元素个数
int right = sz - 1;//右下标
while(left <= right)
{
int mid = (left + right) / 2;//中间元素下标
//缩小左右下标的范围
//判断目标元素与中间元素大小
if (arr[mid] > key)
{
right = mid - 1;
} else if(arr[mid] < key)
{
left = mid + 1;
}
else
{
printf("找到了,下标是: %d", mid);
break;
}
}
if (left > right)
{
printf("找不到\n");
}
return 0;
如果实现一个二分查找函数:
int bin_search(int arr[], int left, int right, int key)
{
int mid = 0;
while(left <= right)
{
mid = (left + right) > >1;
if(arr[mid] > key)
{
right = mid-1;
}
else if(arr[mid] < key)
{
left = mid+1;
}
else
return mid;//找到了,返回下标
}
return -1;//找不到
}
7.4.3 猜数字游戏实现
参考代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void menu()
{
printf("**********************************\n");
printf("*********** 1.play **********\n");
printf("*********** 0.exit **********\n");
printf("**********************************\n");
}
//RAND_MAX--rand函数能返回随机数的最大值。
void game()
{
int random_num = rand()%100+1;
int input = 0;
while(1)
{
printf("请输入猜的数字>:");
scanf("%d", &input);
if(input > random_num)
{
printf("猜大了\n");
}
else if(input < random_num)
{
printf("猜小了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
printf("请选择>:");
scanf("%d", &input);
switch(input)
{
case 1:
game();
break;
case 0:
break;
default:
printf("选择错误,请重新输入!\n");
break;
}
}while(input);
return 0;
}
7.5 goto语句
C语言中提供了可以随意滥用的 goto 语句和标记跳转的标号。
从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。
但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。
例如:一次跳出两层或多层循环。
多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。
goto语言真正适合的场景如下:
for(...)
for(...)
{
for(...)
{
if(disaster)
goto error;
}
}
…
error:
if(disaster)
// 处理错误情况
下面是使用goto语句的一个例子,然后使用循环的实现方式替换goto语句:
一个关机程序
#include <stdio.h>
int main()
{
char input[10] = {0};
system("shutdown -s -t 60");
again:
printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
scanf("%s", input);
if(0 == strcmp(input, "我是猪"))
{
system("shutdown -a");
}
else
{
goto again;
}
return 0;
}
而如果不适用goto语句,则可以使用循环:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char input[10] = {0};
system("shutdown -s -t 60");
while(1)
{
printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
scanf("%s", input);
if(0 == strcmp(input, "我是猪"))
{
system("shutdown -a");
break;
}
}
return 0;
}