c#title: C语言基础


6.创建并运行第一个C程序

集成开发环境(IDE)

编译器/C语言中的指令-机器指令

VC6版本

安装虚拟机+VC6建议学习

同学帮助安装

编写C程序

1.创建项目,选择win32控制台项目(Win32 console Application)

文件-新建-Win32 console Application(项目名字为时间的顺序2020_06_16)

2.添加文件

文件-新建-C++ Source File-Main.cpp

3.生成项目(编译):*.exe

 #include <stdio.h>
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版本(发布版本) 编译器会优化掉一部分无用代码

7.内存与变量

内存的使用

内存的单位是字节(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

课后练习

1.如何理解内存

一个内存为一个字节

2.如何理解内存编号

内存编号就是内存地址,别名就是变量名

3.分别使用char、short、int、float、double申请内存,并用 printf 正确输出对应内容和地址

#include<stdio.h>
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;
}

3.为什么要使用变量

回顾

char 一个字节、

short 四个内存

int 八个字节

使用&地址符号,获得当前地址的内存

编译器替我们是申请

内存太多,使用编号代替,一个内存的编号就是地址,一个地址里面代表一个字节,一个字节就是八个0或者1

#include<stdio.h>
//变量类型 变量名字 值
int main()
{char x = 10;//可以放进程序里面可以放到程序外面,但是如果放进程序里面,仅仅是当前程序使用,其他程序无法使用printf("%d",x);getchar();return 0;
}

放到函数里面必须有一个明确的初始值

放到函数外面称为全局变量

为什么要使用变量

变量本身是一个内存

变量的本质是容器,里面可以存储任意类型的数据

实例

可以根据用户输入圆的半径,计算出圆的面积。

#include <stdio.h>
#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 <stdio.h>char a = 0x12;//一个字节
short b = 0x1234;.//两个字节
int c = 0x12345678;//四个字节
printf("%p,%p,%p \n",&x,&y,&z)

大端小端针对的是数据超过1个字节的存储

小端模式:数据低位在内存地址编号低位,数据高位在高位

大端模式:数据高位在内存地址编号低位,数据高位在低位

程序在断点才可以看memory

float使用二进制规范存储,将小数点变为二进制IEEE规则

#include <stdio.h>int main()
{char x = 0x12;short y = 0x1234;int z = 0x12345678;//12 34 56 78//0019FF28-0019FF24//78 56 34 12printf("%p,%p,%p\n,"&x,&y,&z);getchar();//断点在getchar不能看memoryreturn 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 <stdio.h>int main()
{int x = 0xFFFFFFFF;prinf("%u,%d\n",x,x);return 0;
}

%u:无符号数的输出标记

%d:有符号数的输出标记

有符号数与无符号数在存入内存的时候是相同的,比如

int a = -1;
unsigned a = -1;
//此两者在存储时是相同的,存入内存的数值都是
//FFFF FFFF
#include <stdio.h>int main()
{unsigned char x = 0xFF;//1111 1111unsigned int y = x;//0000 0000 1111 1111int y = x;//1111 1111 1111 1111printf("%p,%p\n",x,y);return 0;
}

%x:十六进制输出标记

%p:类似于地址,全部位输出标记

有符号数与无符号数区别

  • 拓展的时候有差异
#include <stdio.h>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 <stdio.h>int main()
{unsigned int a = -1;if (a>1){printf("%p",a);}return 0;
}

总结

  1. 无论有符号数与无符号数,内存存储的方式是一样的,补码
  2. 有符号数与无符号数在使用的时候,主要的区别是:

<1>拓展的时候

<2>运算的时候

只有整数才有有符号与无符号之分

浮点数另算

字符与字符串

单引号==’ '==只是单个字符

ACSII表

A-65

a-97

putchar()只能打印一个字符,给他任何数字都会进行查表,然后输出表的对应值

转义字符 \a = 7, \n = 10

#include <stdio.h>void main()
{char buffer[6] = {'H','e','l','l','o','!'};printf("%s",buffer);
}

结果:因为没有0结束,会出现一些别的打印结果

所谓字符串是以数组的形式来表示的

输出打印字符串需要见到0才能停止,当数组扩大,会自动补0

一般情况下不用指明长度,编译器会计算长度,自动补0。

字符串的来由

  • 字符串其实是一对字符组成的
  • 字符就是ASCII码对应得到的
  • ASCII码对照的是十进制数
  • 存入的是十进制数的二进制数

中文字符

英文字符查表,中文如何操作的呢?

中文也有值,每个中文字有两个字节的占格

计算机发明之后及后面的很长一段时间,只用应用于美国及一些西方国家

我们专家把那些127之后的奇异符号们(EASCII)取消掉

规定两个大于127的数定义为汉字,字符等,全角

GB2312

Win32-unicode本质就是查表

8.数组

为什么要使用数组

数组是连续申请一些内存供应使用

数组的地址是第一个数组的地址

如果我们要存储多人的年龄

能否让编译器分配多一点的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来查看你申请得到的数组内的值

查看-调试-watch-右边输入名称

训练

  1. 创建一个长度为10的整型数组,并为这个数组赋值(值是下标的2倍);
  2. 将上题中数组的第一个元素与最后一个元素的值交换。
#include <stdio.h>
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];

总结

没有二维数组或者多维数组,本质都是一维数组

9.运算符与表达式

算术运算符

什么是运算符?什么是表达式?

表达式是运算符与运算与常量的之间的关系

x+y x-y (x+y)(x-y) 表达式都是值

==%%==使用两个才能显示

//++ – 单目运算符

int x = 10;
++x;
printf("%d \n",x);//输出11
printf("%d \n",x++)//先参与运算,再自加

运算符优先级别==()==

()具有最高优先级

算术表达式的结果类型

short
int
char
unsigned
double
float
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. 程序中所有数在计算机内存中都是二进制的形式存储的
  2. 位运算就是直接对整数在内存中的二进制位进行操作

位运算能做什么

计算机底层相关领域:

加密解密 安全 反病毒 反外挂

位运算能够精确的对某一个位进行操作

位运算有哪些

计算方式 计算过程
按位与 & 全部是1取1
按位或 | 有1取1
按位异或 ^ 不同为1,相同为0
按位取反 ~ 取反
左移 移位运算 <<
右移 移位运算 >> 无符号数补0,有符号数补符号位

位运算举例

如何将二进制数中的某一个位置修改为1? //3位

x|4//修改某一个位,通过与运算1010 10100000 0100---------1010 1110

如何将二进制数中的某一位置修改为0; //3位

x&FB1010 11101111 1011---------1010 1010

练习

1. 2*8的最高效的实现方式.

2 0000 0010
2*8 0001 0000

//右进位进三位

2. 如何通过位运算判断一个数是奇数还是偶数?

3 0000 0011
按位或 | 0000 0001
有1取1 0000 0011

//相同为奇数,不同为偶数

3. 如何读取二进制数中的某一位的值?

16 0001 0000
16>>(n-1)&1 0000 0001

取n位值(x>>(n-1))&1

4. 如何设置二进制数中的某一位的值?

n修改第n位的值为1 0000 0000
按位或| (2n-1) 0001 0000
1<<n-1 0001 0000
修改第n位的值为0 0001 0000
按位与 &((2字节长度-1)-2n-1) 1110 1111
0000 0000

设置相反x^(1<<n-1)^

5. 设 int a = 2; int b = 5; 使用位运算,交换两个变量的值,并打印。

2 0000 0010
5 0000 0101

自己的见解

#include<stdio.h>
int a = 2;
int b = 5;
void main()
{a=(a << 1)|1;b=b >> 1;printf("%d %d",a,b);
}

王者见解

#include<stdio.h>
int a = 2, b= 5;
void main()
{a = a^b;b = b^a;a = a^b;printf("%d%d",a,b);
}

6.使用位运算 获取 int 类型的最大值和最小值,并打印

#include<stdio.h>
void main()
{int a;a=0;printf("%x",~i);
}

运算符种类

赋值运算符

赋值是一个动作,表达式是一个数

x = x + 8;
x += 8

标准运算

拓展赋值

关系运算符

  1. 什么是真(非0),假为0
  2. 关系运算符返回结果为真假

关系运算符用于比较两者的关系

关系运算符也是双目运算符

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);
}

逻辑运算符

&&逻辑与运算,可以理解成"并且"

说明:

  1. 当表达式1为真时,并且表达式2为真时,整个表达式的结果为真,否则为假
  2. 短路特征,当表达式1为假时时候,后面的表达式将不再执行
逻辑或||,可以理解成“或者”
  1. 当表达式1为真或者表达式2为真时,整个表达式的结果为真,否则为假
  2. 短路特征,当表达式1为真的时候,后面的表达式将不再执行

非!

加在任何表达式的前面,改变表达式的值

练习

int x =4; int y = 7; int z = 3;用三目表达式求出三个变量中的最大值

自己迂腐之见

#include<stdio.h>
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);elseprintf("最大值为z:%d",z);getchar();getchar();
}

王者级别

#include<stdio.h>
int x=3,y=4,z=7;
void main()
{printf("%d",x>y?(x>z?x:z):(y>z?y:z));
}

不运行程序,说出打印结果,为什么?

#include<stdio.h>
void main()
{int x;printf("%d\n",x = 60);printf("%d\n",x ==60);
}

60//表达式为值

1//有数为真为1

不运行程序,说出结果,并解释.

#include<stdio.h>
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的优先级比较高

将上题中的 e= (d = b > a) || (c = a < b); 改为 e= (d = b > a) && (c = a < b); 说出结果 并解释

1

1

1

10.C 语言流程控制

人生选择坚持的人,虽然不一定会成功,但是一定无限接近于成功

流程控制

if如果

分支语句的本质是选择

循环语句的本质是重复执行(重点是终止条件)

常见循环

while:先判断,后循环,不达目的不罢休、

实例

打印99乘法表

#include<stdio.h>
//核心就是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");}
}

do while:先执行,后判断

实例

计算1+2+3+…+(n-2)+(n-1)+n的值

int sum = 0;
int i = 1;
do
{sum = sum + i;i++;
}while(i>n)

for 循环:指定生效次数

有1,2,3,4四个数字,能组成多少互不相同且无重复的三位数?都是多少?

#include<stdio.h>
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;
}

if 语句

1.如何控制程序的流程?

void main()
{int x = 56;if(x>=68)printf();elseprintf();
}

2.if语句

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();}
}

可以嵌套

练习

1.输入三个整数x,y,z,请把这三个数由小到大输出。

#include<stdio.h>
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;
}

2.判断某一年是否是闰年。

#include <stdio.h>int x;
void main()
{scanf("%d",&x);if(x%4==0)printf("%d年是闰年",x);elseprintf("%d年不是闰年",x);
}

3.一个5位数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同。(精)

#include<stdio.h>
int a;
void main()
{scanf("%d",&a);if((a/10000)%10==(a%10)&&(a/10)%10==(a/1000)%10)printf("是回文数\n");elseprintf("不是回文数\n")
}

4.从键盘接收一个字符,如果是小写字母,就输出对应的大写字母。如果是大写字母,输出对应的小写字母。

#include<stdio.h>
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);elseprintf("请重新输入");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

6.将 三目表达式转换成 if else 表达式。 (a > b)? (a > c ? a : c):(b > c ? b : c);

if(a>b)
{if(a>c)printf("%d",a);elseprintf("%d",c);
}
elseif(b>c)printf("%d",b);elseprintf("%d",c)

7.输入三角形的三条边长,求三角形的周长和面积,判断构成的三角形是何种三角形(正三角形,等腰三角形,直角三角形),若不能构成三角形,输出提示。

#include<stdio.h>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");elseprintf("普通三角形\n");printf("%d",l);}return 0;
}

(注: int x ; scanf("%d",&x); // 表示从键盘接受一个整数,存入变量 x 中)

switch语句

1.switch语句

switch(表达式x)
{case 常量N;//字符也可以,字符也是常量。会转换成ACSII码break;case 常量N;break;default;break;
}

说明:

<1> 表达式x必须是整数类型

<2> M K 必须是常量

switch语句的特点

  1. 见到break才结束,case1忘记写,则继续执行下面的操作,直到break才退出switch语句
  2. 没有匹配的表达式,会执行default分支,如果没有defaulit分支,则直接跳过switch语句,如果不需要default。
  3. default分支可以放在任何位置,不是必须放在最后
  4. 分支可以合并
#include <stdio.h>
int x = 0;
switch(x+1)
{case 1:printf("case1执行了");break;case 2:case 3:case 4:printf("error");break;//条件可以合并}

与if…else语句的区别

如果分支多,效率高//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<stdio.h>
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语句

1.while表达式

while(表达式){//代码;}

2.while语句举例

输出1000行“hello world”

#include<stdio.h>
int main()
{int i = 0;while(i<100){printf("hello world\n");i++;}return 0;
}

输出数组

#include <stdio.h>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++;}
}

断点只能写在有语句的地方

为数组的成员赋值,值得电容为下标*2:arr[i] = i * 2;

#include<stdio.h>
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++;}
}

打印一个数组成员的值(只打印值大于10的)

#include<stdio.h>
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;}
}//代码要运行六次

使用continue打印数组偶数

#include<stdio.h>
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();
}

练习

1.求 1 到 m 间所有奇数的和

#include<stdio.h>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);
}

2.求两个数的最大公约数和最小公倍数

3.从键盘循环接收字符串,并统计字母,空格,数字及其他字符的个数,回车结束

4.猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾就多吃了一个。第二天早上又将剩下的桃子吃了一半,还是不过瘾又多吃了一个。以后每天都吃前一天剩下的一半再加一个。到第 10 天刚好剩一个。问猴子第一天摘了多少个桃子?

5.打印 9*9 乘法表

#include<stdio.h>
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();
}

6.请用 while 循环打印如下图案

1

2 3

4 5 6

7 8 9 10

11 12 13 14 15

7.小芳的妈妈每天给她 2.5 元,她都会存起来,但是每当这一天是存钱的第 5 天时或者 5 的倍数的话,她都会花去 6 元钱。请问,经过多少天小芳才可以存到 100 元。

8.使用 while 循环,拼接两个字符串。

do…while语句

1.do…while语句

do
{}while(表达式x);

说明:

  1. 执行do{}里面的代码
  2. 判断表达式x是否为真,为真时继续
#include<stdio.h>
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 <stdio.h>
void main()
{char cInput;do{cInput = getchar();printf("%c\n",cInput);getchar();}while(cInput != '\t');
}

练习

1.求 1~100 之间数的每位数的乘积大于每位数的和的数

==2.==输入一批非 0 数,直到输入 0 时为止,计算其中奇数的平均值和偶数的乘积。

#include<stdio.h>
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 以内的全部亲密数。

for语句

#include<stdio.h>
void main()
{int arr[] = {1,3,6,8,9,1,2,31}
}

函数

函数

1.什么是函数

函数就是一系列指令的集合,可以完成某一些特定的功能

2.函数定义的格式

返回类型 函数名(参数列表){函数体;
}

说明:

  1. 函数名:字母,数字和下划线的组合
  2. 参数列表::可以没有,可以有多个,中间用“,”隔开:int x,int y。
  3. 返回值类型:函数结果的类型,可以没有void。
  4. 函数体:也可以是函数的具体实现

3.有参数有返回值的函数

编写一个函数,能够对任意两个整数实现加法操作,并且返回结果

#include <stdio.h>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)转置,即行列转换,并输出转换前和转换后的数据。

函数的灵活使用

1.函数的嵌套调用

函数声明有返回类型,必须使return进行返回

#include <stdio.h>
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)

2.函数可以作为表达式来使用

输出某一个数组的素数

#include <stdio.h>
//判断某个数是否为素数,是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;
}

3.for循环的理解

#include<stdio.h>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;
}

函数有返回值,就是一个值

4.函数结束的标识

一个函数只能执行一次return

return 可以写多个,但只能执行一次

建议大家定义一个变量r定义返回结果

然后最后return r

函数的参数传递

1.有参函数的调用

int Plus(int x, int y)//形式参数,占位符
{return x+y;
}int r = Plus(1,2)//实参

2.值传递

#include <stdio.h>
void Fun(int x)
{x = x+1;
}int main()
{int a = 10;Fun(a);//只能传递值printf("%d \n",a);return 0;
}

3.将数组作为参数传递

#include <stdio.h>
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 <stdio.h>
int x = 100;//全局变量
void Fn1()
{int y = 200;
}
void Fn2()
{}
int main()
{}

全局变量与局部变量

总结

函数的递归调用

1.函数自己调用自己

#include<stdio.h>void Fn()
{printf("执行了\n");Fn();
}int main
代码 内存
函数运行时所使用的内存称为栈
当程序用完之后依然没有使用栈内存,会报错 函数执行完会释放内存

什么是栈溢出

2.递归的经典应用

1.求n的阶乘

#include <stdio.h>
int Fn(int n)
{if(n==1||n==2)return n;return n*Fn(n-1);}
int main()
{int r = Fn(4);
}

2.斐波那栔数列:0,1,1,2,3,5,8,13…

求给定的x给y的值(y = Fn(x))

#include<stdio.h>
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.引出问题

当你需要一个容器能够存储1个字节,怎么做?//char

当你需要一个容器能够存储4个字节,你会怎么做?//int arr[10]

数组解决不了 成员之间类型不一样的问题

游戏角色

生命 魔法 技能 经验 血量 等级 移动速度
int int int int int int float

2.结构体类型的定义

#include <stdio.h>
//先定义类型 == 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

3.结构体赋值

//单独赋值
int main()
{stStudent studen = {0};//单独赋值student.stucode = 101;student.stuAge = 18;student.stuSex = 'M';strcpy(student.stuName,"编程达人")
}

4.如何读写变量中的值

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);
}

结构体的大小未必是整体大小

练习

1.为什么要定义结构体类型?

当数组内的类型不一样时,定义结构体类型

2.结构体类型可以在函数里定义吗?

可以,但是要赋值,否则会出现乱码

3.代码这么写,有错误么

struct Person
{char name[] ="itcast";int age=20;
};

有错误

strcpy(Person.name,"itcast")

4.申请几个结构体变量,分别用视频中的方法对它赋值。

#include <stdio.h>
#include <windows.h>
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;
}

5.定义结构体Student,包含成员姓名,年龄,身高,嵌套包含结构体Score,。定义结构体Score,包含成员 数学,语文,英语,三科成绩。申请结构体Student变量,对其成员赋值后打印输出至控制台。

#include <stdio.h>
#include <windows.h>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<math.h>用到开方函数 sqrt().

7.在全局定义的结构体和在局部定义的结构体有什么区别?

<1>编写一函数,计算两个日期之间的时间差,并将其值返回。

日期以年、月、日表示。“时间差”以天数表示。注意考虑日期之间的闰年。

函数的输入参数为日期 1 和日期 2,函数的返回值为时间差,单位为天数。

<2>编写一程序,在主函数中输入两个日期,调用上述函数计算两个日期之间的时间差,并将结果输出。

结构体的其他特征

1.结构体参数传递

#include <stdio.h>
{int x;int y;
};
void MyPrint(stPoint point)//结构体也可以变量,你可以用其他任何地方当返回值
{printf("%d %d \n",point.x,point.y)
}

结构体参数为int/char/float/double等基本类型时,传递的是值,是在复制内容

参数为数组类型时,传递的是地址

2.结构体赋值

允许p=p2,结构类型相同

stPoint p = {0,0,0},p1 = {1,2,3},p2 = {3,3,3};
p1 = p2;//赋值

3.不推荐的写法

  1. 匿名结构体
  2. 直接定义变量

结构体数组

#include <stdio.h>//定义结构体类型
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 <stdio.h>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;}
}

指针类型

指针类型

1.定义带*的类型的变量

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 <stdio.h>
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

1.取地址符&

#inlcude <stdio.h>
struct Point
{int x;int y;
}int main()
{char a = 9;//&a char*short b = 1;//&b short*int c = 2;//&c int8Point 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

有时需要把数组设置为只读,这样程序只能从数组中检索值。不能把新值写入数组,要创建只读数组,应该用const声明数组

动态申请内存

1.引出问题

如果我在程序编译的时候,我并不知道存多少

2.内存管理

代码区

全局变量区

常量区

栈(参数局部变量)

#include<stdio.h>
#include <windows.h>struct Student
{int x;int y;
}
void main()
{//intint* 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. malloc申请的内存,必须使用free释放掉
  3. free之后,将指针置空,避免出现野指针…

文件

1.什么是文件?为什么要使用文件?

用于永久存储数据

2.文件的特点

1.文件名

2.文件路径

3.文件大小

4.文件属性:只读、可读可写,隐藏

文件类型

文本文件

二进制文件

文件读写

1.C语言中由于操作文件的相关函数

头文件

#include <stdio.h>

相关函数

fopen、fclose、fread、fwrite、fseek等

文件操作流程

第一步:打开文件

第二步:处理文件

第三步:关闭文件

#include <stdio.h>
#include <windows.h>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()
}

预处理之宏定义

什么是预处理

预处理一般是指在程序源代码被转换为二进制代码之前,由预处理器对程序源代码文本进行处理,处理后的结果再由编译器进一步编译。

预处理功能主要包括宏定义,文件包含,条件编译三部分

C语言基础语法(2遍)相关推荐

  1. Go语言基础语法--注释、基础结构2

    章节 GO语言基础语法--注释.基础结构(重要) 1.GO语言基础语法---注释.基础结构 //程序所属的包,且必须在源文件代码第一行 package mainimport "fmt&quo ...

  2. 一篇文章带你玩转C语言基础语法5:条件判断 if else 语句与分支 。(千字总结)

    我的个人主页:☆光之梦☆的博客_CSDN博客-C语言基础语法(超详细)领域博主 欢迎各位

  3. Go语言 基础语法学习 (未完待更......

    文章目录 一 Go语言结构 1 Go Hello world实例 2 执行Go程序 二 Go语言基础语法 1 Go标记 2 行分隔符 3 注释 4 标识符 5 一些关键字 6 Go语言的空格 7 格式 ...

  4. C语言基础语法【1】

    目录 1.在linux系统编写C语言,基本命令:变量.常量.标识符 2.数据类型.取值范围.字符串 3.短路原则.类型转换 4.switch语句.for.while循环.死循环 1.在linux系统编 ...

  5. 一篇文章带你玩转C语言基础语法。2:数据类型。千字总结

    我的个人主页:☆光之梦☆的博客_CSDN博客-C语言基础语法(超详细)领域博主 欢迎各位

  6. GO 语言基础语法一 (快速入门 Go 语言)

    Go语言基础语法 一. golang 标识符,关键字,命名规则 二. golang 变量 三. golang 常量 四. golang 数据类型 五. golang 布尔类型 六. golang 数字 ...

  7. 【Go编程语言】 Go语言基础语法

    Go语言基础语法 文章目录 Go语言基础语法 一.注释 1.单行注释 2.多行注释 二.变量 1.变量的定义 2.变量的初始化 3.理解变量(内存地址) 4.变量交换 5.匿名变量 6.变量的作用域 ...

  8. 【Day4 C语言基础语法学习-3】

    Day4 C语言基础语法学习-3 一 数组 1.1 数组的概念 1.2 一维数组 1.2.1 一维数组的定义 1.2.2 一维数组的性质 1.3 一维数组的初始化和遍历 1.4 冒泡排序法 二.二维数 ...

  9. 【Day3 C语言基础语法学习-2】

    Day3 C语言基础语法学习-2 一.输入输出函数 1.1 getchar()/putcgar() 1.1.1getchar() 1.1.2 putchar 1.2 gets()/puts() 1.2 ...

最新文章

  1. 【安全加密技术】 对称加密
  2. SpringBatch学习一个Demo项目
  3. Nginx重定向到子目录问题
  4. 性能服务器解读,【MySQL数据库】第三章解读:服务器性能剖析(上)
  5. python画图fig.show()一闪而过的解决方法
  6. 汇编写java模块_java – maven汇编插件moduleset源指令不包括任何文件,不符合附带的模块...
  7. std::map的insert和下标[]访问
  8. LeetCode 962. 最大宽度坡(单调栈)
  9. 300php是多少人民币,GV300S登陆欧洲市场 售价约为3.82万人民币
  10. 走进WPF之开发类似Visio软件
  11. 墨卡托投影和高斯-克吕格 (Gauss-Krüger) 投影
  12. ECharts(官网:http://echarts.baidu.com)
  13. 有了PDA手持终端,仓库再也不愁盘点了
  14. 几款优秀的文档管理系统
  15. 微信页面隐藏分享按钮
  16. postman-批量导入数据
  17. 如何实现微信内域名防封,微信域名防封跳转
  18. 立象(ARGOX) 条码标签打印机通用库 PLLB(BWIN-SCAPI)
  19. ui动画_ui后效动画指南
  20. 安卓小项目之EveryDay(6)----使用第三方平台获取短信验证码

热门文章

  1. LiDAR 3 MEMS激光雷达
  2. 学习Oracle这一篇就够了
  3. 文献解读:中国黑龙江省蜱虫传播病毒的病毒学分析
  4. Windows电脑网线直连iperf测试
  5. 计算机基础知识点文库,计算机基础知识点汇总.doc
  6. 攻防演练前 临战阶段:战前动员,鼓舞士气
  7. 把UTF-8编码转换为GB2312编码
  8. 【C++探索之旅】第一部分第六课:控制流程,随心所至
  9. php发光字体代码,CSS3实现字体发光效果(代码实例)
  10. 12_JLink在线调试_软件调试方法和端口复用和重映射