C语言的语句分为五类:
- 表达式语句
- 函数调用语句
- 控制语句
- 复合语句
- 空语句
C语言是结构化的程序设计语言,存在三种结构顺序结构、选择结构、循环结构。
; 再C语言表示语句的结束
分支语句
if条件控制语句:
0表示假,1表示真
当要执行多条语句时,使用代码块(用{ }括起来)。
if(表达式)
{
语句1;
}
---------------------------
if(表达式)
{
语句1;
}
else
{
语句2;
}
---------------------------
if(表达式1)
{
语句1;
}
else if(表达式2)
{
语句2;
}
else if(表达式3)
{
语句3;
}
else
{
语句4;
}
switch语句
case只是一个入口,没有终止执行的能力,需要break来跳出当前的switch。
!!!没有break或者default,switch只会不断进行!!!
多个case公用一个break,可以实现同一句的执行效果。
switch允许嵌套使用。
形成良好习惯:
- 在最后一个case后加上一个break。
- 在每个switch最后都加一个default。
switch的条件必须是整型表达式,case必须是整型常量表达式。
- 这里的整型包括char(存放的是ASCII码值,本质上是整型)和int。
switch (整型表达式)
{
case 整型常量表达式1:
语句1;
break;
case 整型常量表达式2:
语句2;
break;
case 整型常量表达式3:
语句3;
break;
default: //匹配失败
语句;
break;
}
switch (整型表达式)
{
case 整型常量表达式1:
case 整型常量表达式2:
case 整型常量表达式3:
语句1;
break;
default: //匹配失败
语句;
break;
}
循环语句
while循环
while(表达式)
{
循环语句;
}
//表达式为真循环语句,否则停止循环
break:会跳出本层循环。是永久的终止循环。在嵌套循环中,break打破的是break所在的循环。
continue:跳过本次循环,直接去判断部分。是跳过本次循环后面的代码,直接进行下一次循环的判断。
while和getchar清理缓冲区
getchar(),是从缓冲区中读取一个字符。可以是空格、换行、回车等。
putchar(),是输出读取的字符。
int ch = 0;
while ((ch = getchar()) != EOF)
{ //EOF是'\0',在清理缓冲区时,适当替换
putchar(ch);
}
eg:输入密码
此时,getchar从缓冲区读取的是 '\n' ,此时没有第二次输入。
若缓冲区是一串字符,则不能用getchar直接清理。应用上述清理缓冲的循环清理。
scanf 和 printf 函数,只是在初识C语言中,对代码进行测试的输入输出语句,在以后得开发中并不重要。(不需要花费太大精力)。
通过scanf函数的%m格式控制可以指定输入域宽,输入数据域宽(列数),按此宽度截取所需数据;通过printf函数的%0格式控制符,输出数值时指定左面不使用的空位置自动填0。
for循环
for(表达式1;表达式2;表达式3)
{
语句;
}
for(初始化;判断;调整)
{
语句;
}
初始化:初始化循环变量。
判断:循环的终止条件,判断循环的下一步操作。
调整:变更循环变量。
- 不可在for循环更改循环变量,防止for循环失去控制。
- 建议for循环控制变量的取值采用“前闭后开”的写法。
for循环的变种
省略
省略会带来一些意想不到的后果,尽量避免省略。
循环变量的初始化最好放在for循环的外面:一些编译器不支持该操作。
可以多个变量控制一个循环。
do while 循环
do while循环先执行一次在判断循环条件。
do
{
语句;
}while(判断);
利用循环查找有序数列数据
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int k = 7;
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
/*for (i = 0; i < sz; i++)
{
if (arr[i] == k)
{
printf("找到了\n");
break;
}
}
if (i == sz)
{
printf("找不到\n");
}*/
//折半查找(二分查找):前提条件是数据有序
int left = 0;
int right = sz - 1;
while (left<=right)//循环的终止条件:必须含有等号
{
int mid = (left + right) / 2;
//mid的查找必须在循环里面
//防止mid越界的mid定义写法:
int mid =left+(right-left)/2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
printf("找到了,下标是:%d\n",mid);
break;
}
}
if (left > right)
{
printf("找不到");
}
return 0;
}
折半查找就是利用循环实现的,每次查找数据减少一半。
- 循环的终止条件:必须含有等号。
- mid的值必须定义在循环里面。
- mid=(left+right)/2,可能会越界(mid的最终值超过数组长度)
system("cls");//是一个库函数,可以执行系统命令
Sleep(1000);//是头文件<windows.h>里面的函数,表示系统休眠,单位是毫秒。
数组传参时传递的是数组首元素的地址。
利用循环猜数字
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//#include <cstdlib>
//猜数字
//电脑产生一个随机数
//
//猜大了
//猜小了
//直到猜对结束
#include<stdlib.h>//rand、srand函数
#include <time.h>//time函数
//猜数字菜单
void menu()
{
printf("***********************\n");
printf("******** 1.play *******\n");
printf("******** 0.exit *******\n");
printf("***********************\n");
}
void game()
{
int guess = 0;
//RAND_MAX;
//1.生成随机数
//0~99--->1~100
int ret = rand()%100+1;//随机数在1~100之间
//生成随机数函数
//printf("%d\n",ret);
while (1)
{
printf("请猜数字\n");
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));//time的参数放一个空指针
//strand设置随机数起点
//使用time函数返回的时间戳作为随机数生成器的起点
//不是每次使用都要设置起点,只用设置一次
do
{
menu();
printf("请选择->");
scanf("%d", &input);
switch (input)
{
case 1:
//printf("猜数字\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!");
break;
}
} while (input);
return 0;
}
时间戳:是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数(不考虑闰秒),用于表示一个时间点。然而,这种格式对于人类阅读并不友好,因此需要转换成可读的日期和时间格式。
利用时间戳使用随机数:
srand((unsigned int)time(NULL));
//strand设置随机数起点
//使用time函数返回的时间戳作为随机数生成器的起点
//不是每次使用都要设置起点,只用设置一次
int ret = rand();//生成随机数函数
printf("%d\n",ret);
time函数的头文件:<time.h>
rand、srand的头文件:<stdlib.h>
time函数每次使用时,最好使用空指针参数;
srand函数的参数是unsigned int 型的,利用时间戳要强制转换;
goto语句
goto语句不能跨函数跳跃,在实践中尽量避免goto语句(容易大量报错)。
goto语句常用于终止深层的嵌套循环;(break只能一层层的跳出循环)。
debug是调试版本——是程序调试的版本;
release是发布版本——是发布用户使用的版本;
函数
- 在计算机科学中,函数是一个子程序,有一个或多个语句块组成,完成某项特定的任务,具有相对的独立性。
- 一般有输入参数和返回值,提供对过程的封装和细节的隐藏。
一个工程里面,可以有多个.c文件,但只能有一个main函数。
函数的分类:
1、库函数:
C语言封装的函数,方便程序员的使用。(IO函数、字符串操作函数、字符操作函数、内存操作函数、时间\日期函数等)。
库函数的使用必须使用 #include 包含对应的头文件。
库函数的学习利用:https://cplusplus.com/ 或 msdn 或 cppreference.com
虚拟机:虚拟出来一台电脑。
虚拟出来的电脑(.vmk文件)。
2、自定义函数
程序员自己设计的函数,函数的基本组成包含函数名、函数体、函数参数、返回类型。
实参和形参
实参:真是传给函数的参数。实参可以是常量、变量、表达式、函数。
形参:函数名后括号内的参数。在函数调用完后就自动销毁了。
当实参传递给形参时,形参是实参的一份拷贝--->形参的改变不会影响实参
当函数传递的参数是指针--->改变实参
px、py是指针变量,也是形参。它们存放的是啊a、b的地址。
&px、&py才是形参的地址。
*px、*py是对a、b地址的的解引用。
函数调用
1.传值调用
函数的形参和实参分别占用不同的内存块,对形参的修改不会影响实参。
2.传址调用
把函数外部创建的变量的地址传给函数参数,使得在函数内部可以直接操作函数外部的变量。
C语言在C99之后引入布尔类型 bool ,在头文件#include<stdbool.h>中。
bool类型不是C语言的内置类型,本质上是0和1的封装,只占1个字节。
函数嵌套
函数可以嵌套调用,不能嵌套定义。
链式访问
把函数的返回值作为另一个函数的参数。
若函数没有返回类型(void),则没有办法实现链式访问。
main函数本质上还是有参数的:
int main(int argc, char* argv[], char* envp[])
{
}
//声明禁止传参:
int main(void)
{
}
函数声明
函数定义放在调用的后面,则需要在调用前声明。
- 函数声明:是告诉编译器函数叫什么,参数是什么,返回类型是什么。函数声明不能决定该函数具体是否存在。
- 函数的声明一般在函数使用之前,满足先声明后使用。
- 函数的声明一般放在头文件。
- 函数的定义指函数的具体实现。
将函数的声明、函数的实现、主函数分开存放,可以提高程序的可读性、实现程序模块化、方便多个程序员的协作完成。
声明和定义的分割:可以使程序以静态库的形式出售项目。