(1)#define 定义符号常量(为了和变量区分,使用大写)
#define MAX 100
int main()
{
int arr[MAX] = { 0 }; //定义的是常量,可以放在数组的下标中
}
(2)#define 定义宏
#define ADD(X,Y) ((X)+(Y))
//编程习惯,为了防止出错,把x和y分别加上括号,例如X是表达式
// ADD和(X,Y)之间没有空格
int main()
{
int sum = ADD(3, 4);
printf("%d\n", sum);
}
//错误示例
#define ADD(X,Y) (X*Y) //编程习惯,为了防止出错,把x和y分别加上括号 ADD和(X,Y)之间没有空格
int main()
{
int multiply = ADD(3+5, 4); //输出的是23,实际应该是32
printf("%d\n", sum);
}
2.13内存的划分
从 *** 作系统的角度对内存进行划分,可以分为
栈区:局部变量
堆区:动态分配内存
静态区:全局变量,静态变量
类似将国土面积,划分为一个个省市等,找到房间,需要找到房间的编号,即地址。把内存划分为一个个小的内存单元,访问内存单元需要提供地址,每个内存单元的编号就是内存单元的地址。计算机中的内存划分是以字节为单位的,即1Byte=8bit,每一个地址都对应一个内存单元,8个比特对应一个地址。
根据地址线的数量,计算机分为32位和64位。以32位 *** 作系统为例,(包含32根物理的电线)计算机通电之后,电信号转为数字信号(正电1负电0),
数据类型(int ,char float)每次申请空间以字节为单位,所以1个内存单元代表1个字节,内存划分为一个个小的内存单元,一个内存单元的大小是一个字节,为了使用内存单元,对其进行编号,编号是通过地址线产生的二进制序列。
2.14指针指针是用来存放地址的变量。在定义指针类型的时候,前面的*代表所定义的变量是一个指针,int 代表所指向的变量是一个整型变量
int main()
{
int a = 100;
int* p = &a; //取地址 *** 作符
//*p代表p是指针,前面的int代表p指向的是一个整型变量 a
//
}
在定义时候使用*p代表的是指针,代表所指向变量的地址,在使用时候*p代表对地址的解引用,即得到所指向的变量。
int main()
{
int a=100;
int *p=&a; //定义指针,指向的是a的地址
*p=20; //解引用指针,修改的是a的值
printf("%d\n",a);
return 0;
}
每个内存单元都有一个编号,就是地址。指针变量的大小由地址决定的,32位需要32个bit位存放,即4个字节,而与指向变量的类型无关。
int main()
{
int a = 10;
int* pa = &a; //定义了一个指向a的指针pa
//*pa 得到a的值
char c = 'a';
char* pc = &c;
float f = 2.13;
float* pf = &f;
double d = 3.22;
double* pd = &d;
printf("%d ", sizeof(pa));//4
printf("%d ", sizeof(pc));//4
printf("%d ", sizeof(pf));//4
printf("%d ", sizeof(pd));//4
}
2.15结构体
C语言提供了一些内置的简单数据类型,但是并不能满足构造复杂对象的需求,例如人是复杂的对象(年龄,身高,身份z,性别等),不能用一个或者一种简单的数据类型进行表达。需要创建一个复杂类型即结构体类型,使得C语言有能力描述复杂类型。
struct Stu
{
char name[20];
int age;
char sex[5];
char id[15];
}; // 一般的编辑器会提供,注意末尾的分号一定不能省
int main()
{
//汉字占两个字符,所以不可以使用''
//创建并初始化结构体对象
struct Stu s1 = { "张三",30,"男","340604" };
//结构体对象使用.进行引用
printf("name = %s age = %d sex=%s id = %s\n ", s1.name, s1.age, s1.sex, s1.id);
//创建结构体指针,使用->访问结构体成员
struct Stu* ps = &s1;
printf("name = %s age = %d sex=%s id = %s\n ", ps->name, ps->age, ps->sex, ps->id);
printf("name = %s age = %d sex=%s id = %s\n ", (*ps).name,(*ps).age,(*ps).sex,(*ps).id);
}
2.16循环和分支
C语言中由一个分号;隔开的就是一条语句。
例如:1+2;
printf("hello world");
分支语句(选择结构)
(1) if (表达式)
语句;
(2) if (表达式)
语句1;
else
语句2;
(3)多分支
if(表达式1)
语句1;
else if(表达式2)
语句2;
else
语句3;
注意:《1》if后面的表达式没有分号,表达式结果为真(非0)则执行后面的语句
《2》只能跟着一条语句,多条语句使用复合结构
int main()
{
int score=10;
scanf("%d",&score);
if(score>60) //输入的语句多于一条,使用复合语句
{
printf("输入的成绩大于60\n");
printf("考试成绩合格\n");
}
《3》else语句和最近的if配对,而不是和形式上对齐的if配对
int main()
{
int score=0;
scanf("%d",&score);
if(score>60)
if(score>90)
printf("输入的分数大于90,成绩良好\n");
else //else语句和第二个if配对而不是和形式上对齐的第一个if配对
printf("需要补考\n");
}
书写建议是多使用{}把逻辑的关系理清
int main()
{
int score=0;
scanf("%d",&score);
if(score>60)
{
if(score>90)
printf("输入的分数大于90,成绩良好\n");
}
else //使用{}之后 ,第二个if语句成了第一个if语句的一部分,else和第一个if配对
printf("需要补考\n");
}
《4》if后面的表达式包含多个判断条件时,例如
int main()
{
int score=0;
scanf("%d",&score);
if(9090得到的结果是1,再和100进行判断,即1<100结果为真
//假设输入的是10,则10>90得到的结果是0,再和100进行判断,即0<100结果为真
//所以需要使用逻辑运算符&&
//代码修改为if(score>90&&score<100)
printf("成绩优异\n");
}
《5》if if else 和if else if else的区别
在if if else语句的结构中,if都会被执行,如果下面这个程序输入的是99,则会输出两次
int main()
{
int score = 0;
scanf("%d", &score);
if (score > 90)
printf("恭喜您,考试成绩为%d\n",score);
if(score>80)
printf("还不错,考试成绩为%d\n",score);
else
printf("加把油,考试成绩为%d",score);
}
在if else if语句的结构中,只有一个if会被执行,如果下面这个程序输入的是99,则会输出1次
int main()
{
int score = 0;
scanf("%d", &score);
if (score > 90)
printf("恭喜您,考试成绩为%d\n",score);
else if(score>80)
printf("还不错,考试成绩为%d\n",score);
else
printf("加把油,考试成绩为%d",score);
}
return作为语句的结束标志,可以直接返回,即结束函数
2.17 switch语句switch是一种分支语句,常用于处理多个分支的情况。例如输入每个星期对应的日期,如果使用if else语句,显得过于繁琐。
int main()
{
int day = 0;
scanf("%d", &day);
if (1==day)
printf("星期1\n");
else if(2==day)
printf("星期2\n");
else if(3==day)
printf("星期3\n");
else if(4==day)
printf("星期4\n");
else if(5==day)
printf("星期5\n");
else if(6==day)
printf("星期6\n");
else
printf("星期天\n");
}
使用switch语句进行判断,
int main()
{
int day = 0;
scanf("%d", &day);
switch(day)
{
case 1:
printf("星期1\n");
break;
case 2:
printf("星期2\n");
break;
case 3:
printf("星期3\n");
break;
case 4:
printf("星期4\n");
break;
case 5:
printf("星期5\n");
break;
case 6:
printf("星期6\n");
break;
case 7:
printf("星期7\n");
break;
}
}
注意:《1》switch(整型表达式)建议定义为int ,short有时候会出现溢出的错误
《2》case语句是分支,不是循环,不可以使用continue
《3》使用break跳出当前的循环,如果没有break,case语句会顺序接着执行
《4》switch中的语句是可以任意调换的
int main()
{
int day = 0;
scanf("%d", &day);
switch(day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("工作日\n");
break;
case 6:
case 7:
printf("休息日\n");
break;
}
}
只能在循环中使用continue,跳出此次循环的后面部分,进行下一次的循环,跳转到while语句的判断部分
//1 2 3 4 死循环
int main()
{
int i = 1;
while(i<=10)
{
if(i==5)
{
continue;
}
printf("%d ",i);
i++;
}
}
如果是break,则跳出当前的循环
//1 2 3 4
int main()
{
int i = 1;
while(i<=10)
{
if(i==5)
{
break;
}
printf("%d ",i);
i++;
}
}
在windows系统安装的vs2019使用ctrl+z作为EOF(文件结束标识符),getchar是从输入缓冲区中获取的一个字符,其函数原型是
int getchar( void ); 函数返回的是一个int型,因为字符在计算机中以整数的形式存储
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
putchar(ch);
return 0;
}
scanf函数触发中断,程序等待用户输入,在输入\n后把缓冲区中的数据取出放到对应的地址中,getchar在输入缓冲区中读取到输入时候的\n,所以程序直接跳过。
int main()
{
int ch = 0;
char password[20] = { 0 };
printf("请输入密码>:");
scanf("%s", password);
printf("请输入(Y/N);>");
ch = getchar();
if ('Y' == ch)
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
}
修改方案一:此时可以获取一个\n,但是当scanf输入的数字类似 12 3 4 ,程序依然出错
int main()
{
int ch = 0;
char password[20] = { 0 };
printf("请输入密码>:");
scanf("%s", password);
ch = getchar();//获取输入的\n
printf("请输入(Y/N);>");
ch = getchar();
if ('Y' == ch)
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
}
修改方案二:使用scanf进行输入的时候以空白(空格,TAB,换行)作为输入结束的标识符
\n表示的时输入结束,真正被scanf读取的是第一个空白之前的数据
int main()
{
int ch = 0;
char password[20] = { 0 };
printf("请输入密码>:");
scanf("%s", password);
while ((ch = getchar()) !='\n') //使用scanf输入时,\n表示输入结束,所以当不是\n时
//把输入的字符使用getchar()存储,表示的时输入结束,真正被scanf读取的是第一个空白之前的数据
{
}
printf("请输入(Y/N);>");
ch = getchar();
if ('Y' == ch)
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
}
2.18循环语句
while语句
int main()
{
int i=0; //初始化部分
while(i<10) //判断部分
{
printf("%d ",i);
i+=2; //调整部分
}
}
由于while语句三个部分不集中,为了解决这个问题引入for循环,
int main()
{
for(i=0;i<10;i++) //初始化;条件判断部分;调整部分;
{
if(i==5)
continue;
printf("%d ",i);
}
}
int main()
{
for(i=0;i<10;i++) //初始化;条件判断部分;调整部分;
{
if(i==5)
break;
printf("%d ",i);
}
}
不要随意省略表达式,否则会出现各种未知错误,出了错误学会自己调节
int main()
{
int i = 0;
int j = 0;
int count = 1;
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
printf("%d\n", count);
count++;//循环100次
}
}
}
但是下面的代码仅仅执行20次,因为在第一次执行完j的循环之后,j=10,再次进行i=1的判断时,j的循环变量不满足条件,所以并不进入,但是此时i仍然需要增加。
int main()
{
int i = 0;
int j = 0;
int count = 1;
int count1= 1;
for (; i < 10; i++)
{
printf("%d\n", count1);
for (; j < 10; j++)
{
printf("%d\n", count);
count++;//循环10次
}
}
}
如果判断条件为假,则一次也不执行。
int main()
{
int i = 0;
int k = 0;
for (i=0,k=0; k=0; i++,k++)
{
k++;
}
}
任何表达式都是有值的,b=(a=3) 赋值符号是右结合性,a的值等于3。
int main()
{
int i = 0;
do
{
if(i==5)
continue;
printf("%d ",i);
i++;
}while(i<=10);
return 0;
}
全局变量:在所有函数之前定义的变量
局部变量:在函数内或者复合语句内部定义的变量
int main()
{
int i = 0; //局部变量
int j = 0;
int count = 1;
int count1= 1;
for (; i < 10; i++)
{
printf("%d\n", count1);
for (; j < 10; j++)
{
printf("%d\n", count);
count++;//循环10次
}
}
}
局部变量实在执行该函数或复合语句时自动建立的,当该函数或者复合语句执行完毕后自动释放,所以在不同的函数或者复合语句中定义同名的局部变量,也不会相互干扰。
写代码都是进行累计的,不会写循环,先写一次,在考虑循环的环境
例子:查找数字
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
int n = 7;
int i = 0;
for (i = 0; i < 10; i++)
{
if (arr[i] == n)
{
printf("找到了:%d\n", i);
break;
}
}
if (i == 10)
{
printf("找不到\n");
}
return 0;
}
使用srand我们规定只定义一次就可以,参数是unsigned int 类型
但是time返回的是time_t类型,所以需要类型转换
void game()
{
int guess = 0;
int ret = rand() % 100 + 1;
while (1)
{
printf("请输入猜测的数字:>");
scanf("%d", &guess);
if (guess > ret)
{
printf("猜大了\n");
}
else if (guess < ret)
{
printf("猜小了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
}
void menu()
{
printf("*******************\n");
printf("***** 0.exit *****\n");
printf("***** 1.play******\n");
printf("*******************\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do {
menu();
scanf("%d", &input);
switch (input)
{
case 0:
printf("游戏结束\n");
break;
case 1:
game();
break;
default:
printf("输入错误\n");
break;
}
} while (input);
}
system("shutdown -s -t 60"); 关机
system("shutdown -a");取消关机 等价于在cmd中输入
if else if 和if if的区别,如果一个进去了,if else if就不在进去,对于if 和if来说,一个进去了,另一个还需要再次进入判断
函数使用函数,
1.提高了开发的效率
2.提供统一的标准。
函数分为两种,库函数和自定义函数。
库函数:把一些常用的功能用C语言封装成了函数,放在C语言的库函数中
#include
#include
int main()
{
char arr1[]="hello bit";
char arr2[20]={0};
strcpy(arr2,arr1);
printf("%s\n",arr2);
}
#include
#include
int main()
{
char arr1[]="hello bit";
memset(arr,'*',5);
printf("%s\n",arr);
}
函数内部想要改变函数外部的值,使用指针传递。
void Swap(int a,int b) //当实参传给形参的时候,形参是实参的临时拷贝
{
int tmp=a;
a=b;
b=tmp;
}
void Swap1(int *a,int *b)//当实参传给形参的时候,形参是实参的临时拷贝
{
int tmp=a;
a=b;
b=tmp;
}
int main()
{
int x=0,y=0;
scanf("%d%d",&x,&y);
printf("交换前:x=%d y=%d\n",x,y);
Swap(x,y);
Swap1(&x,&y);
return 0;
}
自定义函数:根据用户需求定义的函数。和库函数一样,有函数名,返回值类型和函数参数。
函数的组成:
ret_type fun_name(para1,*) 返回类型 函数名 函数参数
{
statement;
}
函数参数(实参):
真实传递给函数的参数,即实参,实参可以是常量,变量,表达式,函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须要有确定的值,以便把这些值传递给形参。
int a=10;
int max=get_max(1,2);
max=get_max(1,a);
max=get_max(1+4,get_max(2,3));
形式参数(形参):
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中实例化,调用完成后自动销毁,只在函数中有效。
形参可以是变量,表达式和函数调用
int a=10;
int max=get_max(1,a); //变量
max = get_max(1+4,get_max(2,3)); //表达式,函数
不需要返回值的时候,前面一定要加上void,有些编辑器返回的默认值是int
一般不在函数内部进行打印,因为这样就相当于在一个函数内部生成了两个功能。例如程序员A仅需要得到max的值,所以函数功能不完善,建议一个函数仅仅实现一个功能。代码的复用性高。让函数的功能更加独立。
void get_max(int a,int b)
{
int max=(a>b)?(a):(b);
printf("%d\n",max); //实现了打印的功能
}
int get_max(int a,int b)
{
int max=(a>b)?(a):(b);
return max; //为了保证函数代码的独立性
}
int main()
{
int a=0;
int b=0;
scanf("%d%d",&a,&b);
int m=get_max(a,b);
printf("%d\n",m);//实现了打印的功能
}
最害怕的是没开始就放弃,第一篇博客的约定是什么?
void new_line()
{
printf("hehe\n");
}
void three_line()
{
int i = 0;
for (i = 0;i < 3; i++)
{
new_line();// 函数可以嵌套使用
}
printf("hehe\n");
}
void Add(int *p)
{
void test() //函数不可以嵌套定义
{
}
*p=*p+1;
}
链式访问
把一个函数的返回值作为另外一个函数的参数
int main()
{
int len=strlen("abcdef");
printf("%d\n",len);
//链式访问
printf("%d\n",strlen("abcdef"));
// 4321 print返回打印的字符的个数
printf("%d",printf("%d",printf("%d",43)));
// 4322 换行也是一个字符
printf("%d",printf("%d\n",printf("%d",43)));
}
程序从main函数开始执行,
int Add(int x,int y)
{
int z=x+y;
return z;
}
int main()
{
int a=10;
int b=20;
int ret=Add(a,b);
printf("%d\n",ret);
}
如果想把Add函数写在主函数的后面,则需要在main之前进行函数声明,即
int Add(int x,int y);
int main()
{
int a=10;
int b=20;
int ret=Add(a,b);
printf("%d\n",ret);
}
int Add(int x,int y)
{
int z=x+y;
return z;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)