1.基本语法的含义
#include<stdio.h>
//stdio拆分来就是 standard 标准input输入out输出 h指head 头文件 stdio.h。include是预命令。
//这个文件可能会包含一个标准输入输出的头文件
int main(void)
{
/* 我的第一个C程序 */
printf("Hello,World!\n");
//print 打印 f format 格式化
//printf 格式化输出
return 0;
}
2.char ch的作用
#include<stdio.h>
int main(void)
{
char ch = 'a';//存储a
//char-字符类型 像abc。。。 //ch是 向内存申请空间的变量【可以理解为指令】
return 0;
}
3.%c与\n的含义
#include<stdio.h>
int main(void)
{
printf("%c\n,ch"); //%c--打印字符格式的数据【指令】\n表示换行 整个意思是 我以字符的形式来打印ch
return 0;
}
4.打印 printf 格式化输出
#include<stdio.h>
int main(void)
{
int age = 20;//age是年龄 在这一行年龄已被注释为20
printf("%d\n", age);//%d--打印整型十进制数据,将age以整型十进制的形式打印出来 而上一行age已被定义为20 所以会打印出20
return 0;
}
5.理解变量
#include<stdio.h>
int main(void)
{
float a = 2.0;//像float int 等等后面是变量 不仅是a 等等
printf("%f\n", a);
return 0;
}
6.全局变量与局部变量
int num1 = 20;//全局变量,定义在代码块{}外的变量
#include<stdio.h>
int main(void)
{
int num2 = 10;//局部变量,定义在代码块{}内的变量
return 0;
}
7.计算两个数的和
#include<stdio.h>
int main(void)
{
int num1 = 10;
int num2 = 20;
int sum = 0;//c语言语法规定,变量要定义在当前代码块的最前面 不然会报错
scanf("%d%d", &num1, &num2);//scanf是输入函数,输入数据时使用.scanf是C语言标准。但新版vs要用scanf_s
sum = num1 + num2;
printf("sum = %d\n", sum);
return 0;
}
8.变量的作用域与生命周期
#include<stdio.h>
int main(void)
{
{
int num = 10;
}//这里面的括号才是num的作用域
printf("%d\n", num);//这里会出现报错是因为printf所在位置不是num的作用域【就是可以发挥作用的区域】
return 0;
}//生命周期 局部变量 进入作用域 开始 出作用域结束
//全局变量 整个程序的生命周期
9.声明符号 extern
#include<stdio.h>
int main(void)
{
extern int wwf;//声明符号。若我创建了另一个c文件 在其中定义 例 int wwf = 10
//那么在此文件中我需要输入 extern int wwf;来声明 int wwf这个外部符号【即不在本c文件内的符号】
printf("%d\n", wwf);
//只有这样才能打印出wwf = 10
return 0;
}
10. 宏定义
#define _CRT_SECURE_NO_WARNINGS 1//像scanf等c语言传统函数是不安全的,一些编译器会报错并且给出安全的版本。但也可以像前面一样宏定义来让他不警告。
int main(void)
{
int num1 = 0;
int num2 = 0;
int sum = 0;
scanf("%d%d", &num1, &num2);
sum = num1 + num2;
printf("sum =%d", sum);
return 0;
}
11.scanf与scanf_s的认知
scanf()在读取数据时不检查边界,所以可能会造成内存访问越界:
1 //例如:分配了5字节的空间但是用户输入了10字节,就会导致scanf()读到10个字节
2 char buf[5]={‘\0’};
3 scanf(“%s”, buf);
4 //如果输入1234567890,则5以后的部分会被写到别的变量所在的空间上去,从而可能会导致程序运行异常。
以上代码如果用scanf_s()则可避免此问题:
1 char buf[5]={‘\0’};
2 scanf_s(“%s”,buf,5); //最多读取4个字符,因为buf[4]要放’\0’
3 //如果输入1234567890,则buf只会接受前4个字符
12.const的含义与用法
#include <stdio.h>
int main(void)
{
int num = 4;
printf("%d\n", num);
num = 8;
printf("%d\n", num);
return 0;
}
//打印出来后有4和8
#include <stdio.h>
int main(void)
{ //num是一个变量,但在前面加上const后就拥有了常属性,所以const num中的num是常变量-num是变量,但拥有常属性。
//但是在需要用到常量表达式(包含常量,例一个数字9)时,不能用常变量。
// int arr[10] 创建数组,[]中只能输入常量表达式,不能const int num = 10,再int arr[num]这是错误的。
//const-const是一个C语言(ANSI C)的关键字,具有着举足轻重的地位。它限定一个变量不允许被改变,产生静态作用。
const int num = 4;//但如果我们在int num前加上const,那么这个代码就跑不起来了,因为const修饰常变量,num用const修饰以后就不能变了
printf("%d\n", num);
num = 8;//而我们又在这里定义为8,所以发生错误
printf("%d\n", num);
return 0;
}
13.define 定义标识符常量
#include<stdio.h>
int main(void)
#define max 10
{
int arr[max] = { 0 };//不像12中用int定义的一样,用define定义一个常量 define max 10 ----定义max为常量10,此时int arr []中可以写入max
printf("%d\n", max);//此时max也是可以打印的 打印出为10.而且max不在代码块里面,所以他是一个全局常量【应该可以这样理解】
return 0;
}
14.枚举常量,enum-枚举名
为什么要用枚举?
#define MON 1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7
用枚举后
enum DAY{MON=1,TUE,WED, THU, FRI, SAT, SUN};
枚举后默认的第一个元素的整型为0 往后以此类推加一加一
15.常量总结
一.字面常量
二.const定义的常变量
三.define定义的常量
四.枚举常量
16.枚举
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
enum color
{
red,
yellow = 10
};
int main(void)
{
printf("%d\n", yellow);
return 0;
}
//打印出是10 red默认为0 yellow默认为1 但在enum的代码块中我将他 = 10
//但如果我是在int main的代码块中将yellow = 10 写入 那么会产生错误
17.字符串以及其结束标志\0
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{ //字符串---由双引号引起来的一串字符称为字符串字面值,或者简称字符串.
char arr1[] = "abc";//数组
char arr2[] = { 'a','b','c'};
printf("%s\n", arr1);//打印出来是 abc
printf("%s\n", arr2);//打印出来是abc烫烫烫烫
//用调试中的监控来监控"abc"和{'a','b','c'}我们可以发现 前者除了abc外还有个\0 而后者没有.
//但如果我们把arr2改成{'a','b','c',\0}, (\0也可改为0)因为\0也表示0再来打印就是只打印abc了。\0是一个转义字符,计算字符串长度时是结束标志,不算作字符内容。
// \0是字符串结束的标志,printf中检测到\0就会停止打印了。而出现烫烫烫烫是因为打印完abc后没有结束标志 继续随机生成的。
return 0;
}
18.ASCII表
//数据在计算机上存储的时候,是以二进制来存储的。那么像一些特殊字符 %¥a等等,就用数字来指代他们。而为此制定了一个ASCII表
//例如a-97 A-65 字符所对的值叫做 ASCII码值
ASCII表
19.srtlen—计算字符串长度
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
char arr1[] = "abc";
char arr2[] = { 'a','b','c'};
printf("%d\n", strlen(arr1));//输出为3 ( \0 ) 不计为字符串长度
printf("%d\n", strlen(arr2));//输出为42,不是3是因为读完c后,后面有一些随机值被读取,因为没有\0结束标志所以会继续读取。
//如果回答,第一个 3 第二个 随机值
//如果arr2定义为 { 'a','b','c','\0'};则也是3
return 0;
}
strlen不会将\0计入字符长度。
20.转义字符–把原来的意思转变了
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
printf("abcn");//会打印出abcn
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
printf("abc\n");//此时只会打印abc,因为\n是一个转义字符,意思为换行。上面\0 是字符串读取的中止标志是一样的转义字符
return 0;
}
// \加一些字符有一些特殊作用,称为转义字符 除了上面的\n \0 还有\t--水平制表符 【在\t的位置加上一个tab大小的空】 空格只是一个字符 tab是一段字符
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
printf("c:\test\32\tect.c");//此时打印出来并不是我们想要的内容,是因为\加一些字符被识别成了转义字符。
return 0;
// c:\\test\\32\\tect.c 如果改成这个样子,那么\\t表示我将\t中的\转义成了普通\,而不是转义字符中的\
// \\用于表示一个反斜杠,防止它被解释为一个转义序列符
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
printf("%c\n",''');//此时会报错,因为前两个''是括字符串的 而里面又是空的,那么我们只需要'\''这样写就可以打印出'了。\'让他变成了一个普通的'。一个字符
return 0;
}// \' \"也是转义字符。\'用于表示字符常量' \"用于表示一个字符串内部的双引号
21.选择语句if,else
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
int input = 0;
printf("会好好学习吗,会请输入1;不会请输入0.>:");
scanf("%d",&input);//&去地址,%d以十进制打印符号整数,scanf输入函数
if (input == 1)
{
printf("好工作\n");
}
else//else是其他的意思,如果你不输入if定义的1,那么无论你输入什么都会得到farmer。
//但我们也可以不写else,写两个if也是可以的。如果输入两个if定义以外的就不会有输出。
{
printf("farmer\n");
}
return 0;
}
22.循环语句
while循环
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
int line = 0;
while (line < 5)//while循环语句
{
line++;//行数加一,一开始设定行数是0,如果去掉这个,那么会陷入死循环打印"代码".虽然输出代码有很多"行",但真正的行数还是为0(开启显示行数就知道了),所以要加line++
printf("代码\n");//如果要显示行数则改为 printf("代码:%d\n",line);
}
if (line >= 5)
printf("good job\n");//这个if后可加{}可不加
}
易错点:while语句不加;且要花括号.
do-while循环
#include<stdio.h>
int main(void)
{
int line = 0;
do
{
line++;
printf("代码\n");
} while (line < 5);
if (line >= 5)
printf("good job\n");
return 0;
}
上述while循环的代码转换为do-while如上所示。
for循环
for(1;2;3)1是初始条件,2是循环继续的条件,3是每一轮循环要做的事情(变量作运算来调整循环)。
且for循环的每一个表达式都是可以省略的,for( ;条件; )==while(条件)。
#include<stdio.h>
int main(void)
{
int line = 0;
for (line = 0; line < 5; line++)
printf("代码\n");
if (line >= 5)
printf("good job\n");
return 0;
}
for循环转换上述代码如上所示。
选用循环语句:
- 如果有固定循环次数,用for。
- 如果必须先执行一次循环体再循环,用do-while。
- 其他情况用while。
23.函数
一.自定义函数
在使用自定义函数时,要把函数定义写在所有使用函数地方的前面。
且自定义函数有声明和定义,两个要一致。
需要说明的是:每个函数有自己的变量空间,参数也位于这个独立的空间,与其他函数没有关系。
用下面的代码进一步说明
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void swap(int a, int b);//参数
int main()
{
int a = 5;
int b = 6;
swap(a, b);//值
printf("a=%d b=%d\n", a, b);
return 0;
}
void swap(int a, int b)//参数
{
int t = a;
a = b;
b = t;
}
这个函数不能交换出a b的值,main中的a和b和swap中的int a int b除了传递值外没有任何关系。swap中的a,b和main中的a,b没有任何关系,更不相等。
#include<stdio.h>
int add(int x, int y)
{
int z = x + y;
return z;
}
//上面称为函数体。
//这个add就是自定义函数,意义:用于定义一些反复使用的方法,例如上面举例的相加,当然还有更复杂的。
//简化代码,代码复用。
-------------------------------------------------------------------------------------
int main(void)
{
int a = 10;
int b = 20;
int sum = 0;
sum = add(a, b);
printf("sum =%d\n", sum);
return 0;
}
以下面这段代码来进行自定义函数转换。(代码复制是代码质量低的一种体现)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
int i;
int sum;
for (i = 1, sum = 0; i <= 10; i++) {
sum += i;
}
printf("1到10的和是%d\n", sum);
for (i = 20, sum = 0; i <= 30; i++) {
sum += i;
}
printf("20到30的和是%d\n", sum);
return 0;
}
转换结果如下
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void sum(int begin, int end)//函数头
//(int begin,int end)是参数表
//sum是函数名
//void是返回类型-没有,就是说sum函数不返回任何东西。
//{}内是函数体
{
int i;
int sum = 0;
for (i = begin; i <= end; i++)
{
sum += i;
}
printf("从 %d到 %d的和是 % d\n",begin, end, i);
}
int main(void)
{
sum(10, 20);//函数知道每一次是哪里调用它,会返回到正确的地方。
sum(20, 30);//第一个sum执行完返回到第二个sum,再返回到return 0;
return 0;
}
上面是void类型的,那我们下面再跑一个int类型的。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int bj(int a,int b)
{
int max;
if (a > b)
{
max = a;
}
else {
max = b;
}
return max;//void换成int,表明bj这个函数要返回一个int类型的值,即max。
}
int main(void)
{
int end;
end = bj(20, 30);
printf("%d\n", end);
return 0;
}
调用函数时给的值必须要和参数的类型匹配,虽然编译器会帮你转换好,但结果可能不是你想要的,C中不严格,C++/Java这方面严格。
同样的,这里面也有return的作用,在下节会讲。
当我们需要调用函数时,需要注意几点:
- 函数名(参数值);
- ()起到了表示函数调用的重要作用
- 即使没有参数也需要()
- 如果有参数,则需要给出正确的数量和顺序
- 这些值会被按照顺序以此用来初始化函数中的参数
圆括号()
自定义函数时,如果圆括号内不填写任何东西,则不代表没有参数,只是表示这个自定义函数的参数不知道。
那么编译器遇到swap(a,b)时会猜测参数是什么类型
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void swap();
int main()
{
int a = 5;
int b = 6;
swap(a, b);
printf("a=%d b=%d\n", a, b);
return 0;
}
void swap(int a, int b)
{
int t = a;
a = b;
b = t;
}
当然这里没有任何问题,如果把swap定义中的换成void swap(double a,double b)
那结果就会有偏差。
还有就是main函数的圆括号。
以后我们就不止会用到main函数,有时会需要main函数返回一个值,而main(void)表示main不返回任何值。
二.库函数
常用的头文件有**<ctype.h>** <time.h> <stdio.h> <stdlib.h> <math.h> <string.h>
每个头文件中都包含着不同的库函数。详情移步----------->:C语言标准库函数大全
24.return
return停止函数的执行,并送回一个值。
return;
return 表达式;
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int bj(int a,int b)
{
int max;
if (a > b)
{
max = a;
}
else {
max = b;
}
return max;//可以把这个值传递给变量,或者函数,也可以丢掉(没有把这个值给任何东西)
//函数要单一出口,虽然多个return不会报错,但是不好维护,所以最好单一出口.
}
int main(void)
{
int end;
end = bj(20, 30);//上面bj中的return max;送回max这个值就是在这里体现,把送回的max赋给end,打印end就是sum的值
printf("%d\n", end);//即bj(20,30) = 30
return 0;
}
如果函数有返回值,则必须使用带值的return。
没有返回值的函数
- void 函数名(参数表)
- 不能使用带值的return
- 可以没有return
- 调用的时候不能做返回值的赋值
25.数组
一.数组的定义
一组相同类型元素的集合。
<类型>变量名称[元素数量];//元素数量是整数。
eg:
int grades[100];
double weight[20];
#include<stdio.h>
int main(void)
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//定义一个存放10个整型的数组.
float arr2[2];//定义一个存放2个浮点型的数组.
char ch[3];//定义一个存放3个字符的数组.
return 0;
}
二.数组的特点
- 其中所有的元素具有相同的数据类型(int,double等)。
- 一旦创建,不能改变大小。
- 数组中的元素在内存中是连续依次排列的。
三.数组的使用
如上 int arr[10] = …
其中的 1,2,3,4,5,6,7,8,9,10其实是有下标的,如下
0,1,2,3,4,5,6,7,8,9
这个下标是编译时机器识别的序号。
而编译器和运行环境都不会检查数组下标是否越界,无论对数组单元做读还是写。所以一旦程序运行,越界的数组访问可能造成问题,导致程序崩溃。所以要保证程序只使用有效的下标值。
有效的下标范围[0,数组的大小-1]
#include<stdio.h>
int main(void)
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d\n",arr[4]);//数组的下标默认从0开始,打印数组中下标为4的数,那么就是5。
return 0;
}
代码跑起来打印出来的是5.
那么再与while循环语句结合一下
#include<stdio.h>
int main(void)
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
while (i < 10)
{
printf("%d\n", arr[i]);//此处的i还是数组下标,因为arr中10的下标为9(<10),所以可以打印10
i++;
}
return 0;
}
数组应用
输入数,计算出平均数并给出大于平均数的数。的代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
int x;
double sum = 0;
int cnt = 0;
int number[100];//定义数组
scanf("%d", &x);
while (x != 1)
{
number[cnt] = x;//对数组中的元素赋值
sum += x;
cnt++;
scanf("%d", &x);
}
if(cnt>0)
{
int i;
double average = sum / cnt;
for (i = 0; i < cnt; i++)
{
if(number[i]>average)//使用数组中的元素
{
printf("%d", number[i]);
}//遍历数组
}
}
return 0;
}
但这个代码有安全隐患,如果cnt超过数组的大小就会有隐患。
26.操作符(简单介绍)
一.算数操作符
+ - * / %
前四个是加减乘除,不作过多赘述。
%是取模,例如
#include<stdio.h>
int main(void)
{
int a = 5%2;
printf("%d\n", a);
return 0;
}
5➗2 = 2…1 余数为1,
那么5%2=1。
二.移(二进制)位操作符
<<左移 >>右移
#include<stdio.h>
int main(void)
{
int a = 1;
int b = a << 1;
printf("%d\n", b);
return 0;
}
整型1占4个字节,也就是32个bit位,也就是0000000000000…0001.
如果把1左移一个(二进制)位–b,成为0000000000000…0010.(想象32个bit位是一个框,左移最左边的0出去了,然后右边空出自动补0).
那么再以十进制打印b的话就会打印出2.
所以上述代码打印出的是2
#include<stdio.h>
int main(void)
{
int a = 1;
int b = a << 2;
printf("%d\n", b);
return 0;
}
同样,如果左移两个(二进制)位。b就是0000000000000…0100.
也就是二进制100打印输出为十进制数,也就是4.
三.(二进制)位操作符
&按位与 |按位或 ^按位异或
&按位与
#include<stdio.h>
int main(void)
{
int a = 3;
int b = 5;
int c = a & b;
printf("%d\n", c);
return 0;
}
代码跑起来输出结果为1.
3的二进制数是011,5的二进制数是101.
011
101
001(结果)
按位与的运算法则就是,对位有0就得0,两个1才为1.
001为二进制数,转化为十进制仍然为1.
|按位或
#include<stdio.h>
int main(void)
{
int a = 3;
int b = 5;
int c = a|b;
printf("%d\n", c);
return 0;
}
输出结果为7.
011
101
111(结果)
按位或的运算法则就是,对位只要有1,那么结果就为1.
二进制数111转化为十进制为7.
^按位异或
#include<stdio.h>
int main(void)
{
int a = 3;
int b = 5;
int c = a^b;
printf("%d\n", c);
return 0;
}
输出结果为6.
011
101
110(结果)
按位或与的运算法则就是,对位的二进制位相同则为0,二进制位相异则为1.(二进制位就是0和1)
二进制数110转化为十进制数为6.
四.赋值操作符
= += -= *= /= &= |= ^= >>= <<=
#include<stdio.h>
int main(void)
{
int a = 10;
a = 20;//需要说明的是, = 是复制,== 判断相等.
a = a + 10;
a += 10;//这两种写法是等价的
a = a & 10;
a &= 10;//等价
return 0;
}
其他的以此类推.
五.单目操作符
除了单目操作符还有双目操作符,三目操作符。
例如a+b。 +是一个双目操作符,因为它有两个操作数。
! 逻辑取反操作
#include<stdio.h>
int main(void)
{
int a = 10;
printf("%d\n", a);//打印出10
printf("%d\n", !a);//打印出0
return 0;
}
在C语言中,0定义为假,非0为真。逻辑取反操作就是让假为真,真为假。
那么10是非0,为真,逻辑取反操作后就为假,即为0.
sizeof
sizeof 计算变量/类型所占空间的大小,单位是字节.
#include<stdio.h>
int main(void)
{
int a = 10;
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(int));
printf("%d\n", sizeof a);
printf("%d\n", sizeof int)://这种写法是错误的.
return 0;
}
如上,我们给出了四行printf。第一二三行是正确的,第四行是错误的。
sizeof在计算变量所占空间的大小时,可以省略().而计算类型所占空间大小时不能省略.
第一行,第二行的结果是一样的.(int类型普遍占4个字节)
与数组结合
#include<stdio.h>
int main(void)
{
int arr[10] = { 0 };//10个整型元素的数组。1个整型4个字节。
printf("%d\n", sizeof(arr));
}
格式化输出为40.
#include<stdio.h>
int main(void)
{
int arr[10] = { 0 };
int number = 0;
number = sizeof(arr) / sizeof(arr[0]);
printf("number =%d\n", number);
}
上为计算数组内元素个数的方法,用数组大小除以元素大小(同类型元素大小相同,而数组是相同类型元素的集合).
输出为10.
++和–的前置与后置
设变量a。
++a是先执行a = a+1,然后再使用a。
a++是先使用a,再执行a = a+1。
–同原理
27.格式字符
28.关系运算符
实例
29.逻辑运算
如果要表达数学中的区间 x∈(4,6).那么不能写成4<x<6.
这样写c语言会先将4<x看成一个逻辑运算,结果是0或1。
不论结果是0还是1都是小于6的,所以最后结果是1.
正确写法应为:x>4&&x<6.
下面看一些例子
1.20<age<30
2.小于0或大于99
3.虽然逻辑运算符优先级小于比较运算符,但!是单目运算符,单目运算符优先级高于双目运算符。
所以!age先处理,结果为1或0,然后再与20比较。整个表达式是1.(若要先处理age<20,则要加括号).
整体优先级:!>&&>||
30.switch-case(多分支处理代替if else)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
int type = 0;
scanf("%d", &type);
if (type == 1)
printf("你好");
else if (type == 2)
printf("早上好");
else
printf("what?");
return 0;
}
转换为switch-case
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
int type;
scanf("%d",&type);
switch (type) {
case 1:printf("你好"); break;
case 2:printf("早上好"); break;
default:printf("what?");break;
}
return 0;
}
有几点需要说明的是
- break是c语言中的一个关键字,在这里专门用于跳出switch语句。所谓“跳出”,是指一旦遇到 break,就不再执行 switch 中的任何语句,包括当前分支中的语句和其他分支中的语句;也就是说,整个 switch 执行结束了,接着会执行整个 switch 后面的代码。
- 如果直到最后一个“整型数值n”都没有找到相等的值,那么就执行 default 后的“语句 n+1”。
- 当和某个整型数值匹配成功后,会执行该分支以及后面所有分支的语句。
- 由于 default 是最后一个分支,匹配后不会再执行其他分支,所以也可以不添加break;语句。
- case 后面必须是一个整数,或者是结果为整数的表达式,但不能包含任何变量。
- default 不是必须的。当没有 default 时,如果所有 case 都匹配失败,那么就什么都不执行。
在循环中,有两个词组是经常用到的
- break,跳出循环。
- continue,跳过循环这一轮剩下的语句进入下一轮。
31.嵌套循环
下面是用 1角 2角 5角 得到x元的程序
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
int x;
int one, two, five;
scanf("%d", &x);
for (one = 1; one < x * 10; one++)
{
for (two = 1;two < x * 10 / 2; two++)
{
for (five = 1; five < x * 10 / 5; five++)
{
if (one + two * 2 + five * 5 == x * 10)
{
printf("可以用%d个1角加%d个2角加%d个5角得到%d元\n", one, two, five, x);
}
}
}
}
return 0;
}
他可以罗列出所有可能,但如果我们只要他输出一种的话就要跳出这个嵌套的循环。
如果光用一个break加在printf后面那是不行的。
因为break和continue都只能跳出他所在的循环,也就是说如果放break只能跳出第三个for循环,第一个和第二个for循环仍然进行。
所以我们可以接力break,如下:
接力break
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
int x;
int one, two, five;
int exit=0;
scanf("%d", &x);
for (one = 1; one < x * 10; one++)
{
for (two = 1;two < x * 10 / 2; two++)
{
for (five = 1; five < x * 10 / 5; five++)
{
if (one + two * 2 + five * 5 == x * 10)
{
printf("可以用%d个1角加%d个2角加%d个5角得到%d元\n", one, two, five, x);
exit = 1;
break;
}
}if (exit == 1)break;
}if (exit == 1)break;
}
return 0;
}
加一个exit变量,在得到一个结果赋予他1,然后在第一个for第二个for循环末接上if-break。
还有一种更简单的方式goto out,如下:
goto out
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)
{
int x;
int one, two, five;
scanf("%d", &x);
for (one = 1; one < x * 10; one++) {
for (two = 1;two < x * 10 / 2; two++)
{
for (five = 1; five < x * 10 / 5; five++)
{
if (one + two * 2 + five * 5 == x * 10)
{
printf("可以用%d个1角加%d个2角加%d个5角得到%d元\n", one, two, five, x);
goto out;
}
}
}
}
out:
return 0;
}
goto out 顾名思义 去到out的地方 ,out的地方用 out:来代替。
这种方法虽然看起来好,但是goto out是臭名昭著的。
因为goto 语句是在源码级上的跳转,这使其招致了不好的声誉。若一个程序总是从一个地方跳
到另一个地方,还有什么办法能识别程序的控制流程呢?随着 Edsger Dijkstra 著名的《Goto
considered harmful》论文的出版,众人开始痛斥 goto 的不是,甚至建议从关键字集合中扫
地出门。
所以尽量不要使用goto out,仅在break和continue需要用来跳出嵌套循环时再使用它。
32.system
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdlib.h>
int main(void)
{
system("calc");
return 0;
}
system用于打开系统应用,calc是计算器,那么这个程序运行后就会打开计算器。
需要注意的是system所对应的头文件是<stdlib.h>.
33.本地变量(自动变量)
-
函数的每次运行,就产生了一个独行的变量空间,在这个空间中的变量,是函数的这次运行所独有的,称作本地变量
-
定义在函数内部的变量就是本地变量
-
参数也是本地变量
-
对于本地变量来说,生存期和作用域是一样的:大括号内–块
-
本地变量是定义在块内的,这个块可以是函数的块内也可以是语句的块内
-
程序运行进入这个块之前,其中的变量不存在,离开这个块,其中的变量就消失了
-
块外面定义的变量在块里面仍然有效
-
块里面定义了和外面同名的变量则掩盖了外面的(全局变量和局部变量)
-
不能再同一个块内定义同名的变量
-
本地变量不会被默认初始化
-
参数在进入函数的时候被初始化了(调用函数的时候,一定要给参数对应的值,那个值会在进入函数时被用来初始化函数)
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main() { int a; int b; scanf("%d %d",&a,&b) if(a<b) { int i =10;//i只在块里面 } i++;//这里的i会显示未被声明,i只在块里面 }
一.生存期
什么时候这个变量开始出现了,到什么时候它消亡了
称为自动变量是因为生存期是自动的。
二.作用域
前面也提到,在代码的什么范围内可以访问这个变量(这个变量可以起作用)
下面用代码来进一步说明
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void swap(int a, int b);//参数
int main()
{
int a = 5;
int b = 6;
swap(a, b);//从这里开始就进入到下面的swap的变量空间,做完swap里的代码后,swap的变量空间就消失了,再调用时才会出现。
printf("a=%d b=%d\n", a, b);
return 0;
}
void swap(int a, int b)//参数
{
int t = a;//swap变量空间中的a,b,t是swap自己的,和main里的a,b没有关系,无论怎么赋值,main中的ab都不会被影响
a = b;
b = t;
}
小技巧:
- alt+方向键 可以把一行代码向上移或者向下移。
- alt+caps+a 鼠标左键拉选要修改的连续行的同一列 或者 按住鼠标滚轮拉选要修改的连续行的同一列。
杂记:
每次召唤rand()就得到一个随机的整数。
x%n的结果是[0,n-1]的一个整数