c#title: C语言基础
编译器/C语言中的指令-机器指令
VC6版本
同学帮助安装
1.创建项目,选择win32控制台项目(Win32 console Application)
文件-新建-Win32 console Application(项目名字为时间的顺序2020_06_16)
2.添加文件
文件-新建-C++ Source File-Main.cpp
3.生成项目(编译):*.exe
#include
int main()
{
printf("Hello,World!\n");
getchar();
return 0;
}
F7(出现00error为程序已经创建成功)
2020_06_15.exe - 0 error(s), 0 warning(s)
4.运行项目
F5
cpp为C++文件
shift+F 程序结束
debug版本(调试版本)
release版本(发布版本) 编译器会优化掉一部分无用代码
内存的单位是字节(Byte) 每个字节占8个位(bit)
每个运行中的程序(进程)都有4G内存
内存的编号就是地址
内存不是内存条,是空头支票
变量就是内存
变量类型就是告诉系统(编译器)我需要的内存有多大
变量名告诉系统(编译器)我需要的内存在哪里,变量名是地址的别名
值是写到内存里的数据
变量类型 变量名称 = 值;
十六进制为"%x"
十进制为"%d"
取地址符号==&==
//变量类型 变量名(就是内存编号) 变量值
char x = 10;
short y = 100;
int z = 1000;
//打印内存中的数值
printf("值为:%d-%d-%d\n",x,y,z);
printf("值为:%x-%x-%x\n",x,y,z);
printf("变量内容为:%d-%d-%d\n",x,y,z);
printf("变量地址为:%p-%p-%p\n",&x,&y,&z)
溢出的右移,舍弃
char //0 - 0xFF
short //0 - 0xFFFF
int //0 - 0xFFFFFFFF
每种类型的变量,存储的数据都是有范围,超过这个范围的数据,将会被计算机丢弃,如:
float x = 100.12f; //4字节,float后面跟f
double y = 100.1234;//8字节(范围很大)
printf("%f %lf\n",x,y);//%f与%lf分别是存储float与double的形式
printf("%.2f %.4lf\n",x,y);//显示小数点后几位,.2位或者.4位定义输出的小数点位数
变量类型 | 变量宽度(字节byte)16进制 | 存储范围 |
---|---|---|
char | 1 | -128~127 |
short | 2 | -32768~32767 |
int | 4 | -2147483648~2147483747 |
float | 4(精度:整数+小数6-7) | -3.4·1038~3.4·1038 |
double | 8(15-16) | -1.7·10308~1.7·10308 |
一个内存为一个字节
内存编号就是内存地址,别名就是变量名
#include
char a = 10;
short b = 100;
int c = 100;
float e = 50.12f;
double f = 3432.3423;
int main()
{
printf("%d %d %d %f %lf\n", a,b,c,e,f);
printf("%d %d %d %.2f %.4f\n",a,b,c,e,f);
printf("%x %x %x %x %x\n",a,b,c,e,f);
printf("%p %p %p %p %p\n",a,b,c,e,f);
getchar();
return 0;
}
char 一个字节、
short 四个内存
int 八个字节
使用&地址符号,获得当前地址的内存
编译器替我们是申请
内存太多,使用编号代替,一个内存的编号就是地址,一个地址里面代表一个字节,一个字节就是八个0或者1
#include
//变量类型 变量名字 值
int main()
{
char x = 10;//可以放进程序里面可以放到程序外面,但是如果放进程序里面,仅仅是当前程序使用,其他程序无法使用
printf("%d",x);
getchar();
return 0;
}
放到函数里面必须有一个明确的初始值
放到函数外面称为全局变量
变量本身是一个内存
变量的本质是容器,里面可以存储任意类型的数据
实例
可以根据用户输入圆的半径,计算出圆的面积。
#include
#define PI 3.14//定义常量
int main()
{
double r;
double s;
scanf("%lf",&r);//变量的地址在哪里,控制台就会读入一个数,放入r的地址。
s = PI*r*r;
printf("%lf \n",r);
printf("%.4lf\n",s);
getchar();
getchar();
}
常量是一个数,不会变化
用变量是为了临时储存数据
内存就是变量
#include
char a = 0x12;//一个字节
short b = 0x1234;.//两个字节
int c = 0x12345678;//四个字节
printf("%p,%p,%p \n",&x,&y,&z)
大端小端针对的是数据超过1个字节的存储
小端模式:数据低位在内存地址编号低位,数据高位在高位
大端模式:数据高位在内存地址编号低位,数据高位在低位
程序在断点才可以看memory
float使用二进制规范存储,将小数点变为二进制IEEE规则
#include
int main()
{
char x = 0x12;
short y = 0x1234;
int z = 0x12345678;//12 34 56 78
//0019FF28-0019FF24
//78 56 34 12
printf("%p,%p,%p\n,"&x,&y,&z);
getchar();//断点在getchar不能看memory
return 0;
}
使用小手选择断点调试
getchar()因为程序一直在运行,所以无法进行调试,需要删除掉
选择断点-把要看的变量名输入到address输入框中-查看存储的内存地址
如何让程序运行到某阶段的存储下来
浮点型有自己的存储规范,课堂上不涉及
当存储的12时是12,负数的时候存储的是EE
原码:最高位为符号位,其余各位为数据本身的绝对值
0X12 = 0001 0010;//正数,最高位0正,最高位1为负
反码:
正数:反码与原码相同
负数:符号位为1,其余位取反
补码:
正数:补码与原码相同
负数:符号位为1,其余位对原码取反加1
0x12 0001 0010
原码:0001 0010
反码:0001 0010
补码:0001 0010
-0x12 EE
原码:1001 0010//符号位为1,负数
反码:1110 1101//符号位为1,取反
补码:1110 1110 //末位+1
E E
计算机存储整数的时候存储补码
谁能告诉我下面的1代码表示什么?
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
#include
int main()
{
int x = 0xFFFFFFFF;
prinf("%u,%d\n",x,x);
return 0;
}
%u:无符号数的输出标记
%d:有符号数的输出标记
有符号数与无符号数在存入内存的时候是相同的,比如
int a = -1;
unsigned a = -1;
//此两者在存储时是相同的,存入内存的数值都是
//FFFF FFFF
#include
int main()
{
unsigned char x = 0xFF;//1111 1111
unsigned int y = x;//0000 0000 1111 1111
int y = x;//1111 1111 1111 1111
printf("%p,%p\n",x,y);
return 0;
}
%x:十六进制输出标记
%p:类似于地址,全部位输出标记
#include
int main()
{
char x = 0xFF;
printf("%x\n",x);
int y = x;
printf("%x\n",y);
unsigned char a = 0xFF;
printf("%x\n",a);
unsigned int b = a;
printf("%x\n",b);
getchar();
return 0;
}
计算结果如下:
ffffff ff//拓展成四个字节打印
fffff ff//有符号数,使用符号位进行补位
ff//无符号数
ff//无符号数
#include
int main()
{
unsigned int a = -1;
if (a>1)
{
printf("%p",a);
}
return 0;
}
<1>拓展的时候
<2>运算的时候
只有整数才有有符号与无符号之分
浮点数另算
单引号==’ '==只是单个字符
ACSII表
A-65
a-97
putchar()
只能打印一个字符,给他任何数字都会进行查表,然后输出表的对应值
转义字符 \a = 7, \n = 10
#include
void main()
{
char buffer[6] = {'H','e','l','l','o','!'};
printf("%s",buffer);
}
结果:因为没有0结束,会出现一些别的打印结果
所谓字符串是以数组的形式来表示的
输出打印字符串需要见到0才能停止,当数组扩大,会自动补0
一般情况下不用指明长度,编译器会计算长度,自动补0。
字符串的来由
英文字符查表,中文如何操作的呢?
中文也有值,每个中文字有两个字节的占格
计算机发明之后及后面的很长一段时间,只用应用于美国及一些西方国家
我们专家把那些127之后的奇异符号们(EASCII)取消掉
规定两个大于127的数定义为汉字,字符等,全角
GB2312
Win32-unicode本质就是查表
数组是连续申请一些内存供应使用
数组的地址是第一个数组的地址
如果我们要存储多人的年龄
能否让编译器分配多一点的int
void main()
{
int age[20];//向编译器申请了40个字节的空间
}
整数是小端存储
int age[20] = {0};//初始化全部为0
int age[20];
int age[10] = {1,2,3,4,5,6,7,8,9,10}
int age[10] = {1,2,3,4,5};
越界/当你取数组中的数值时,假设数组中有10个值,age[10],值已经越界。
通过下标访问数组
char arr[10];
short arr[20];
int arr[20];
查看-调试-watch-右边输入名称
#include
void main()
{
int arr[10]={0,3,4,6,8,10,12,14,16,18};
int a;
printf("交换前:%d %d\n",arr[0],arr[9]);
a = arr[0];
arr[0] = arr[9];
arr[9] = a;
printf("交换后:%d %d\n",arr[0],arr[9]);
}
解决问题
name | math | chinese | english |
---|---|---|---|
小明 | 89 | 67 | 67 |
小黄 | 73 | 42 | 65 |
小红 | 56 | 56 | 47 |
47 | 78 |
int score[12] = {...}
//寻找
第x个同学,第y门课
score[x*3+y]
直接告诉编译器几人几科
int score[3][2] = {...};//二维数组
int score[0][0];//第一人第一科
int score[1][1];//第二人第二科
int score[2][2];//第三人第三科
二维数组与数组在存储方式上是相同的,不同工作主要是由编译器运作,二维数组就是一维数组
修改的情况下直接修改可以
int arr[3][4]={
1,2,3,4,
5,6,7,8,
9,7,6,5
}
int arr[3][4]={
{1,2,3,4},
{5,6,7,8},
{9,7,6,5}
}
int arr[3][4]={
{1,2},
{5},
{9}
}
int arr[][4]={
1,2,3,4,
5,6,7,8,
9,10,11,12
}//自动分配少数补0
第二个维度必须指定
初始化写{0}即可
多维数组
int arr[3][4][5] ={
{{1,2,3},{4,5,6},{7,8,9},{10,11,12,14}},
{{10,20,30},{40,50,60},{70,80,90},{110,120,130}},
{{11,21,31},{41,51,61},{71,81,91},{111,121,131}}
}
第几个组(x):0,1,2
第几个人(y):0,1,2,3
第几门课(z):0,1,2
寻找
2-2-2;
arr[1*3*4+1*3+1] = arr[1][1][1];
没有二维数组或者多维数组,本质都是一维数组
表达式是运算符与运算与常量的之间的关系
x+y x-y (x+y)(x-y) 表达式都是值
==%%==使用两个才能显示
//++ – 单目运算符
int x = 10;
++x;
printf("%d \n",x);//输出11
printf("%d \n",x++)//先参与运算,再自加
()具有最高优先级
char x = 1;
short y = 2;
int z = 3;
printf("%d\n",sizeof(x+y));
printf("%d\n",sizeof(x+z));//当与int运算时会升级
void main()
{
int n = 1;
unsigned int = 0xffffffff;
if((m+n)>0)
{
printf("表达式类型为unsigned: %d\n");
}
//有符号数与无符号数进行运算,结果是无符号数
}
计算机底层相关领域:
加密解密 安全 反病毒 反外挂
位运算能够精确的对某一个位进行操作
计算方式 | 计算过程 |
---|---|
按位与 & | 全部是1取1 |
按位或 | | 有1取1 |
按位异或 ^ | 不同为1,相同为0 |
按位取反 ~ | 取反 |
左移 移位运算 << | |
右移 移位运算 >> | 无符号数补0,有符号数补符号位 |
如何将二进制数中的某一个位置修改为1? //3位
x|4//修改某一个位,通过与运算
1010 1010
0000 0100
---------
1010 1110
如何将二进制数中的某一位置修改为0; //3位
x&FB
1010 1110
1111 1011
---------
1010 1010
2 | 0000 0010 |
---|---|
2*8 | 0001 0000 |
//右进位进三位
3 | 0000 0011 |
---|---|
按位或 | | 0000 0001 |
有1取1 | 0000 0011 |
//相同为奇数,不同为偶数
16 | 0001 0000 |
---|---|
16>>(n-1)&1 | 0000 0001 |
取n位值(x>>(n-1))&1
n修改第n位的值为1 | 0000 0000 |
---|---|
按位或| (2n-1) | 0001 0000 |
1<0001 0000 |
|
修改第n位的值为0 | 0001 0000 |
---|---|
按位与 &((2字节长度-1)-2n-1) | 1110 1111 |
0000 0000 |
设置相反x^(1<
2 | 0000 0010 |
---|---|
5 | 0000 0101 |
自己的见解
#include
int a = 2;
int b = 5;
void main()
{
a=(a << 1)|1;
b=b >> 1;
printf("%d %d",a,b);
}
王者见解
#include
int a = 2, b= 5;
void main()
{
a = a^b;
b = b^a;
a = a^b;
printf("%d%d",a,b);
}
#include
void main()
{
int a;
a=0;
printf("%x",~i);
}
赋值是一个动作,表达式是一个数
x = x + 8;
x += 8
标准运算
拓展赋值
关系运算符用于比较两者的关系
关系运算符也是双目运算符
void main()
{
int x = 1;
int y = 2;
printf("%d,%d", x>y);/假,为0
}
也叫条件运算符
表达式1 ? 表达式2 :表达式3
当表达式1为真时 整个表达式的结果为表达式2
当表达式2为真时 整个表达式的结果为表达式3
void main()
{
int x = 1;
int y = 2;
int z = 3;
int k = x=y?y:z;//三目运算符
printf("%d",k);
}
说明:
加在任何表达式的前面,改变表达式的值
自己迂腐之见
#include
int x;
int y;
int z;
void main()
{
scanf("%d %d %d",&x,&y,&z);
int a = x>y?x:y;
int b = x>z?x:z;
int c = y>z?y:z;
if(a==x&&b==x)
printf("最大值为x:%d",x);
else if(a==y&&c==y)
printf("最大值为y:%d",y);
else
printf("最大值为z:%d",z);
getchar();
getchar();
}
王者级别
#include
int x=3,y=4,z=7;
void main()
{
printf("%d",x>y?(x>z?x:z):(y>z?y:z));
}
#include
void main()
{
int x;
printf("%d\n",x = 60);
printf("%d\n",x ==60);
}
60//表达式为值
1//有数为真为1
#include
void main()
{
int a=1,b=2,c=0,d=0,e;
e= (d = b > a) || (c = a < b);
printf("%d %d %d\n", e,c,d);
}
1
0
1//b>a的优先级比较高
1
1
1
人生选择坚持的人,虽然不一定会成功,但是一定无限接近于成功
if
如果
分支语句的本质是选择
循环语句的本质是重复执行(重点是终止条件)
实例
打印99乘法表
#include
//核心就是i是从1-9,j每次都从1开始到与i同等大小为止
int main(void)
{
int i = 1;
int j;
while (i<10)
{
j = 1;
while(j<=i)
{
printf("%d*%d=%d ",i,j,i*j);
j++;
}
i++;
printf("\n");
}
}
实例
计算1+2+3+…+(n-2)+(n-1)+n的值
int sum = 0;
int i = 1;
do
{
sum = sum + i;
i++;
}while(i>n)
有1,2,3,4四个数字,能组成多少互不相同且无重复的三位数?都是多少?
#include
int main(void)
{
int cont = 0;
for(int i = 1; i<5; i++)
{
for(int j = 1; j<5;j++)
{
for(int k = 1; k < 5; k++)
if((i != j)&&(i != k)&&(j != k))
{
printf("%d%d%d\n",i,j,k);
cont++
}
}
}
print("共计%d",cont);
return 0;
}
void main()
{
int x = 56;
if(x>=68)
printf();
else
printf();
}
if(表达式x)//表达式可以是任何类型
语句y;//当表达式x为真(非零)时,执行语句y
一行里可以写很多语句
分支语句/无论条件如何,只有一个分支运行,只走一条线
可以精简代码
void main()
{
int x = 80;
if(x<68)
{
printf("不及格\n");
}
else if(x<70)//范围可以精简
{
printf();
}
else if(x<80)
{
printf();
}
else
{
printf();
}
}
可以嵌套
#include
int x,y,z;
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int main()
{
scanf("%d %d %d",&x,&y,&z);
int temp;//精妙三者排序
if(x>y)swap(&x,&y);
if(x>z)swap(&x,&z);
if(y>z)swap(&y,&z);
printf("%d %d %d",x,y,z);
getchar();
getchar();
return 0;
}
#include
int x;
void main()
{
scanf("%d",&x);
if(x%4==0)
printf("%d年是闰年",x);
else
printf("%d年不是闰年",x);
}
#include
int a;
void main()
{
scanf("%d",&a);
if((a/10000)%10==(a%10)&&(a/10)%10==(a/1000)%10)
printf("是回文数\n");
else
printf("不是回文数\n")
}
#include
void main()
{
char c;
c = getchar();//scang("%d",c)
if(c < 65)
printf("请重新输入");
else if(c < 91)
printf("%c",c+32);
else if(c<123)
printf("%c",c-32);
else
printf("请重新输入");
getchar();
getchar();
}
5.不运行程序,说出下面程序执行的结果
程序 1:
int x = 80;
if (x >= 80)
{
printf("Hello World! \n");
}
else if (x = 40)
{
printf("Hello Bcdaren! \n");
}
else
{
printf("GoodBye! \n");
}
Hello World!
程序 2:
int x =2 ,y = 3,z = 4;
int n;
if(x >= y)
if(z == 4)
n = x + y + z;
else
{
n = x * y * z;
}
printf("%d \n",n);、
24
if(a>b)
{
if(a>c)
printf("%d",a);
else
printf("%d",c);
}
else
if(b>c)
printf("%d",b);
else
printf("%d",c)
#include
int main()
{
int a,b,c,l;
scanf("%d%d%d",&a,&b,&c);
if (a+b<c||a+c<b||b+c<a)
{
printf("不能构成三角形");
}
else
{
l = a + b + c;
if(a==b&&a==c)
printf("正三角形\n");
else if(a==b||b==c||a==c)
printf("等腰三角形\n");
else if(a*a+b*b==c*c||a*a == b*b + c*c ||a*a + b*b == c*c)
printf("直角三角形\n");
else
printf("普通三角形\n");
printf("%d",l);
}
return 0;
}
(注: int x ; scanf("%d",&x); // 表示从键盘接受一个整数,存入变量 x 中)
switch(表达式x)
{
case 常量N;//字符也可以,字符也是常量。会转换成ACSII码
break;
case 常量N;
break;
default;
break;
}
说明:
<1> 表达式x必须是整数类型
<2> M K 必须是常量
#include
int x = 0;
switch(x+1)
{
case 1:
printf("case1执行了");
break;
case 2:
case 3:
case 4:
printf("error");
break;//条件可以合并
}
如果分支多,效率高//4
if…else语句适合判断区间,而switch不适合
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|
30 | 28/29 | 30 | 30 | 30 | 30 | 30 | 30 | 30 | 30 | 30 | 30 |
1 | -2 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 1 |
0 | 1 | -1 | 0 | 0 | 1 | 1 | 2 | 3 | 3 | 4 | 4 |
#include
int main()
{
int y,m,d;
scanf("%d%d%d",&y,&m,&d);
int today;
today = (m-1)*30+d;
switch(m)
{
case 2:
today+=1;
break;
case 3:
today-=1;
break;
case 6:
case 7:
today+=1;
break;
case 8:
today+=2;
break;
case 9:
case 10:
today+=3;
break;
case 11:
case 12:
today+=4;
break;
}
if(y%4==0&&m>2)
{
today += 1;
}
printf("今天是第%d天",today);
return 0;
}
一步一步执行调试
设置断点F9,取消断点F9
F5启动程序
shift+F5停止程序
F5单步走
while(表达式)
{
//代码;
}
#include
int main()
{
int i = 0;
while(i<100)
{
printf("hello world\n");
i++;
}
return 0;
}
#include
void main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int nlength = sizeof(arr)/sizeof(int);
int i = 0;
while(i < nlength)
{
printf("%d\n",arr[i]);
i++;
}
}
断点只能写在有语句的地方
#include
void main()
{
int arr[20] = {0};
int nlength = sizeof(arr)/sizeof(int);
int i = 0;
while(i<nlength)
{
arr[i] = i*2;
i++;
}
i = 0;
while(i < nlength)
{
printf("%d\n",arr[i]);
i++;
}
}
#include
void main()
{
int arr[20] = {0};
int nlength = sizeof(arr)/sizeof(int);
int i = 0;
while(i<nlength)
{
arr[i] = i*2;
i++;
}
i = 0;
while(i < nlength)
{
if (arr[i]>10)
printf("%d\n",arr[i]);
i++;
}
}
int arr[] = [3,1,4,2,5,8,6];
int nlength = sizeof(arr)/sizeof(int);
int i = 0,k = 0;
int temp = 0;
while (k<(nlength-1))//控制循环次数
{
while(i<(nlength-1))//元素比较,交换
{
if(arr[i]>arr[i+1])
{
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}//代码要运行六次
#include
void main()
{
int arr[] = {21,34,53,54,65,76,34};
int nlength = sizeof(arr)/sizeof(int);
int i = 0;
while(i< nlength)
{
if (arr[i]%2!=0)
{
i++;
continue;
}
printf("%d\n",arr[i]);
i++;
}
getchar();
}
#include
void main()
{
int i = 1;
int m;
scanf("%d",&m);
int sum = 0;
while(i<=m)
{
if (i%2 == 1)
sum += i;
i++;
}
printf("%d",sum);
}
#include
int i,j;
void main()
{
int i = 1;
while(i<=9)
{
int j = 1;
while(j<=i)
{
printf("%d*%d=%d ",i,j,i*j);
j++;
}
i++;
printf("\n");
}
getchar();
}
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
do
{
}while(表达式x);
说明:
#include
void main()
{
int arr[] = {1,4,6,7,9,12,44,34};
int nlength = sizeof(arr)/sizeof(int);
int i = 0;
do
{
if(arr[i] == 12)
{
break;
}
printf("%d\n",arr[i]);//不成立也会成立
}while(i < nlength);//1时不断执行
}
至少会执行一次,所以,通常用来实现
做到…直到…为止
举例:
从键盘上输入字符,并显示,直到输入TAB为止
#include
void main()
{
char cInput;
do
{
cInput = getchar();
printf("%c\n",cInput);
getchar();
}while(cInput != '\t');
}
#include
void main()
{
int cInput;
int a=0,b=1,i=1;
do
{
scanf("%d",cInput);
if (cInput%2 == 0)
b = b*cInput;
else
{
a+=cInput;
i++;
}
}while(cInput = 0);
int av = a/i;
printf("%d %d\n",av,b);
}
3.计算 PI/4 = 1 - 1/3 + 1/5 - 1/7 +…,直到最后一项小于 10 负 6 次方。
4.编程将所有“水仙花数”打印出来,并打印其总个数。 “水仙花数”是一个 各个位立方之和等于该整数的三位数
5.验证“角谷猜想”, 判断给定的一个自然数,若为偶数除以 2,若为奇数则乘 3 加 1,得到一个新的自然数后按照上面的法则继续演算,一直到结果变为 1,并且将每一步的运算过程和得到的新的自然数显示出来。
6.百鸡问题:一只公鸡值 5 元,一只母鸡值 3 元,而 1 元可买 3 只小鸡。现有 100 元钱,想买 100 只鸡。问可买公鸡、母鸡、小鸡各几只?
7.编程实现:某人想将手中一张面值 100 元的人民币换成 5 元(可单换 20 张)、1 元(可单
换 100 张)和 0.5 元(可单换 200 张)面值的票子,但要求 100 元换以上的零钱共 100 张,
且要求每种不少于 1 张,共有多少种兑换方法。
8.韩信点兵:韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、
五人一排、七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入 3
个非负整数 a,b,c,表示每种队形排尾的人数(a < 3,b < 5,c < 7),输出总人数的最小值
(或报告无解)。已知总人数不小于 10,不超过 100。
9.一辆卡车违反交通规则,撞人后逃逸。现场有三位目击证人,但都没有记住车号,只记下
车号的一些特征。甲说:牌照的前两位数字是相同的。乙说:牌照的后两位数字是相同的,
但是和前两位不同。丙说;四位的车号刚好是一个整数的平方(四位车牌号>999)。请用以上
线索求出车号。
\10. 有一对兔子,从出生后的第三个月起每个月都生一对兔子。小兔子长到三个月以后每个
月都生一对兔子。小兔子长到第三个月以后每个月又生一对兔子。假设所有的兔子都不死,
问 30 个月内每个月的兔子总数是多少。
11.如果整数 A 的全部因子(包括 1,不包括 A 本身)之和等于 B,且整数 B 的全部因子(包
括 1,不包括 B 本身)之和等于 A。则将 A 和 B 称为亲密数。求 3000 以内的全部亲密数。
#include
void main()
{
int arr[] = {1,3,6,8,9,1,2,31}
}
函数就是一系列指令的集合,可以完成某一些特定的功能
返回类型 函数名(参数列表)
{
函数体;
}
说明:
编写一个函数,能够对任意两个整数实现加法操作,并且返回结果
#include
int Plus(int x,int y)//占位符,int是返回类型,形式参数
{
int z = x + y;
return z;
}
避免编写相同的代码
1.编写一个函数,求两个数的最大公约数并返回。
2.编写一个函数,求一个 int 类型数组所有成员的平均值,并输出数组中最接近平均值的成
员。
3.实现一个函数判断 year 是不是润年,是返回 1,不是返回 0。
4.实现一个函数,判断参数是不是素数,是返回 1,不是返回 0。
5.编写一个函数,可以将字符串 2 合并到字符串 1 中。
6.编写一个函数,打印 x*x 乘法表 x 为参数。
7.编写一个函数, int fun(int a,int b, int c);如果三个数相等返回 1,其中两个数相等返回 0,其他情况返回-1
8.编写一个函数,输出 x 以内所有的素数,x 为参数
9.一函数,输入一行字符,将此字符串中最长的单词输出,单词间以空格分隔。
10.定义一个函数,使给定的二维数组(3×3)转置,即行列转换,并输出转换前和转换后的数据。
函数声明有返回类型,必须使return进行返回
#include
int Plus(int x, int y)
{
int r = x + y;
return r;
}
int Plus2(int a,int b,int c)
{
int r = Plus(a,b);
int m = Plus(r,c);
return m;
}//函数嵌套太多不好
int main(int int)
输出某一个数组的素数
#include
//判断某个数是否为素数,是1不是0
int IsPrime(int n)
{
int r = 1;
for(int i = 2; i<n; i++)
{
if (n%i == 0)
{
r=0;
break;
}
return r;
}
}
int main()
{
int arr[] = {3,6,7,9,10,11,12};
int nlength = sizeof(arr)/sizeof(int);
for(int i=0; i<n; i++)
{
if(IsPrime(arr[i]))//将函数直接作为表达式来使用
{
printf("%d \n",arr[i]);
}
}
return 0;
}
#include
void Fu1()
{
printf("Fu1.....");
}
void u2()
{
printf("Fu2.....");
}
int Fu3()
{
printf("Fu3.....");
return 1;
}
void Fu4()
{
printf("Fu4.....");
}
int main()
{
for(Fu1;Fu2:Fu3)
{
Fu4;
}
return 0;
}
函数有返回值,就是一个值
一个函数只能执行一次return
return 可以写多个,但只能执行一次
建议大家定义一个变量r
定义返回结果
然后最后return r
int Plus(int x, int y)//形式参数,占位符
{
return x+y;
}
int r = Plus(1,2)//实参
#include
void Fun(int x)
{
x = x+1;
}
int main()
{
int a = 10;
Fun(a);//只能传递值
printf("%d \n",a);
return 0;
}
#include
void Fun(int arr[])
{
arr[0]=100;
arr[1]=200;
}
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int nlength = sizeof(arr)/sizeof(int);
for(int i = 0;i<nlength;i++)
{
printf("%d ",arr[i]);
}
printf("\n-----------------------\n");
Fun(arr);
for(int j=0;j<nlength;j++)
{
printf("%d ", arr[j]);
}
return 0;
}
数组作为参数传值的时候,是把当前数组的地址,是通过地址进行传递
int类型作为参数传递的时候传递的是值
#include
int x = 100;//全局变量
void Fn1()
{
int y = 200;
}
void Fn2()
{
}
int main()
{
}
全局变量与局部变量
#include
void Fn()
{
printf("执行了\n");
Fn();
}
int main
代码 | 内存 | |
---|---|---|
栈 | 函数运行时所使用的内存称为栈 | |
当程序用完之后依然没有使用栈内存,会报错 | 函数执行完会释放内存 |
什么是栈溢出
#include
int Fn(int n)
{
if(n==1||n==2)
return n;
return n*Fn(n-1);
}
int main()
{
int r = Fn(4);
}
求给定的x给y的值(y = Fn(x))
#include
int Fn(int n)
{
if(n == 0)
return 0;
if(n < 2)
return 1;
return Fn(n-1)+Fn(n-2);
}
int main()
{
int r = Fn(4);
printf("%d",r);
}
尽量不要使用,递归非常浪费内存
当你需要一个容器能够存储1个字节,怎么做?//char
当你需要一个容器能够存储4个字节,你会怎么做?//int arr[10]
数组解决不了 成员之间类型不一样的问题
游戏角色
生命 | 魔法 | 技能 | 经验 | 血量 | 等级 | 移动速度 |
---|---|---|---|---|---|---|
int | int | int | int | int | int | float |
#include
//先定义类型 == int/float/double
struct stPoint//看成声明一种类型
{
int x;
int y;
};//此时不占用内存空间
//定义类型的变量
struct stPoint point;
int main()
{
stPoint point = {0};//初始化
}
struct 类型名
{
//可以定义多种类型
int a;
int b;
float c;
};
结构体在定义时要字节对齐
比如都是char,会自动扩充至int
//单独赋值
int main()
{
stStudent studen = {0};
//单独赋值
student.stucode = 101;
student.stuAge = 18;
student.stuSex = 'M';
strcpy(student.stuName,"编程达人")
}
int main()
{
stStudent studen = {0};
//单独赋值
student.stucode = 101;
student.stuAge = 18;
student.stuSex = 'M';
strcpy(student.stuName,"编程达人");
int x = student.stucode;
printf("%s \n",student.stuName);
strcpy(buffer,student.stuName);
}
结构体的大小未必是整体大小
当数组内的类型不一样时,定义结构体类型
可以,但是要赋值,否则会出现乱码
struct Person
{
char name[] ="itcast";
int age=20;
};
有错误
strcpy(Person.name,"itcast")
#include
#include
struct Books
{
int type;
char name[20];
char author[5];
int Book_ID;
};
int main()
{
struct Books Book = {2,"typora","tom",123123};
printf("%s ",Book.author);
strcpy(Book.author,"tony");
printf("%s ",Book.author);
return 0;
}
#include
#include
struct Scores//声明类型
{
int Math;
int Chinese;
int English;
};
struct Students
{
char Name[10];
int Age;
float Height;
struct Scores score;
};
int main()
{
struct Students student = {"Tom",14,176,0};
printf("%s\n",student.Name);
printf("%d\n",student.score.Math);
printf("%d\n",student.score.English);
student.score.Math = 67;
student.score.Chinese = 78;
student.score.English = 87;
strcpy(student.Name,"Tony");
printf("%d\n",student.score.Math);
printf("%d\n",student.score.English);
printf("%s\n",student.Name);
return 0;
}
6.定义一个结构体表示点的 x,y 坐标,依次读入三个正整形坐标值,输出三个点构成的三角形面积
用到头文件#include
7.在全局定义的结构体和在局部定义的结构体有什么区别?
<1>编写一函数,计算两个日期之间的时间差,并将其值返回。
日期以年、月、日表示。“时间差”以天数表示。注意考虑日期之间的闰年。
函数的输入参数为日期 1 和日期 2,函数的返回值为时间差,单位为天数。
<2>编写一程序,在主函数中输入两个日期,调用上述函数计算两个日期之间的时间差,并将结果输出。
#include
{
int x;
int y;
};
void MyPrint(stPoint point)//结构体也可以变量,你可以用其他任何地方当返回值
{
printf("%d %d \n",point.x,point.y)
}
结构体参数为int/char/float/double等基本类型时,传递的是值,是在复制内容
参数为数组类型时,传递的是地址
允许p=p2,结构类型相同
stPoint p = {0,0,0},p1 = {1,2,3},p2 = {3,3,3};
p1 = p2;//赋值
#include
//定义结构体类型
struct stStudent
{
int Code;
int level;
};
int main()
{
stStudent student[10]=
{
{101,"zhang san"},
{102,"li si"},
{103,"wang wu"}
};//如何定义一个结构体类型的数组
//调用
int x = student[1].Code;
printf("%s \n",student[1].Name);
//改
student[2].Code = 100;
strcpy(student[1].code,"sda");
return 0;
}
<1>定义结构体包含如下信息:学生姓名,性别,语文数学英语成绩。
<2>设某班有20个学生,请实现以下功能:
1.可以录入学生信息。
2.可以删除学生信息。
3.可以查找学生信息。
#include
struct students
{
char Name[10];
char gender;
int math;
int chinese;
int english;
};
struct students student[20];
int main()
{
for(int i=0;i<20;i++)
{
strcpy(student[i].Name,"张三");
student[i].gender = 1;
student[i].math = 87;
student[i].english = 87;
student[i].chinese = 97;
}
}
char x; | char* x; |
---|---|
short y; | short* y; |
int z; | int* z; |
float f; | float* f; |
double d; | double* d; |
student st; | student* st; |
1.带有*变量类型的标准写法:变量类型 * 变量名
2.任何类型都可以带 * 加上以后就是新的类型,统称为“指针类型”
3.*可以是任意多
#include
struct Point
{
int x;
int y;
};
int main()
{
char* x;
int* y;
Point* point;
x = (char*)1;//
y = (char*)2;//指针类型的赋值
point = (Point*)0;
printf(sizeof());
}
指针的本质是类型
指针本质类型的4个字节
++
–
运算幅度是类型砍掉一个类型之后的类型宽度
总结:
1.不带 * 类型的变量,++ 或者 – 都是加 1或者减1
2.带类型的变量,++或者–新增(减少)的数量是去掉一个后变量的宽度
指针类型的变量宽度永远是4字节
还可以跟整数做运算
任何一个变量都加 * 变为新的类型
指针类型
内存4GB | |
---|---|
BYTE | 0 |
内容-12345 | 1(当前内存的编号,代号不需要存储) |
2 | |
… | |
0xFFFFFFFF |
#inlcude
struct Point
{
int x;
int y;
}
int main()
{
char a = 9;//&a char*
short b = 1;//&b short*
int c = 2;//&c int8
Point p = {3,3};//&d point*
char* pa = (char*)0x12FF7c;
char x = *pa;//指针变量
*pa = 8;
printf("%d \n",x);
pa->x = 4;
pa->y = 5;
printf9("%d %d \n", pa->x,pa->y);
return 0;
}
指针: 间接引用运算符 *
nurse = 22;
ptr = &nurse;
val = *ptr;
变量也有两个属性:地址和值。地址就是变量在计算机内部的名称
许多程序中,地址都归计算机管,对程序员隐藏。然而在C中,可以通过&运算符访问地址,通过*运算符获得地址上的值。
简而言之,普通变量把值作为基本量,把地址作为通过&运算符获得的派生量,而指针变量把地址作为基本量,把值作为通过*运算符获得的派生量。
有时需要把数组设置为只读,这样程序只能从数组中检索值。不能把新值写入数组,要创建只读数组,应该用const声明数组
如果我在程序编译的时候,我并不知道存多少
代码区
全局变量区
常量区
栈(参数局部变量)
堆
#include
#include
struct Student
{
int x;
int y;
}
void main()
{
//int
int* p = (int*)malloc{100*sizeof(int)};
//(int*)强制类型转换
char* p = (char*)malloc{200*sizeof(char)};
//申请结构体
Student* p = (Student*)malloc(100*sizeof(Student));
free(p);//释放掉内存
}
堆内存 | 有人帮你记录 |
---|---|
1-5int | Begin-Bigin+5 |
2-8int | Begin-Bigin+8 |
3-9int | Begin-Begin+9 |
会出现碎片
导致出现一个空白的内存
整个堆空间有一部分用了,有一部分没用,整个内存没有连续,当你申请一个较大内存的时候
用于永久存储数据
1.文件名
2.文件路径
3.文件大小
4.文件属性:只读、可读可写,隐藏
文本文件
二进制文件
头文件
#include
相关函数
fopen、fclose、fread、fwrite、fseek等
文件操作流程
第一步:打开文件
第二步:处理文件
第三步:关闭文件
#include
#include
void TestWriterfile()
{
//1.打开文件,2.向文件中写数据,3.关闭文件
char szPath[] = "C:\\Test.txt";
FILE* pFile = NULL;
char szBuffer[0x10];//创建缓冲区
pFile = fopen(szPath,"wb");//wb,如果文件不存在,创建一个新的文件,如果文件存在则清零
if(pFile == NULL)
{
printf("文件打开失败 \n");
return;
}
//从文件中写数据
memset(szBuffer,0,sizeof(szBuffer));
strcpy(szBuffer,"China");
nWrite = fwrite(szBuffer,1,strlen(szBuffer),pFile);//一次多少,写多少个,写入文件
if(nWrite == 0)
{
printf("文件写入失败");
return;
}
//关闭文件
fclose(pFile);
}
void main()
{
TestWritefile()
}
什么是预处理
预处理一般是指在程序源代码被转换为二进制代码之前,由预处理器对程序源代码文本进行处理,处理后的结果再由编译器进一步编译。
预处理功能主要包括宏定义,文件包含,条件编译三部分