1.C语言的特点
2.C语言的关键字
3.C语言的应用领域
1)系统软件的开发
2)应用软件开发
- 办公软件:WPS
- 图形图像多媒体:ACDSee Photoshop mediaplayer
- 嵌入式软件开发:智能手机、掌上电脑
- 游戏开发:2D、3D游戏
4.参考资料
谭浩强《C语言程序设计》清华
《The C programming langugae》机械工业
《C Primer Plus》60元 人民邮电
《C和指针》65 人民邮电
《C专家编程》绝版
《C陷阱与缺陷》人民邮电30
《C科学与艺术》机械工业
5.举例:一元二次方程的解
代码如下:
# include
# include
int main(void)
{
//把三个系数保存到计算机中
int a = 1; //=不表示相等,表示赋值
int b = 5;
int c = 6;
double delta; //delt存放的是 b*b - 4*a*c
double x1; //存放一元二次方程的其中一个解
double x2; //存放一元二次方程的其中一个解
delta = b*b - 4*a*c;
if (delta > 0)
{
x1 = (-b + sqrt(delta)) / (2*a);
x2 = (-b - sqrt(delta)) / (2*a);
printf("该一元二次方程有两个解, x1 = %f, x2 = %f\n", x1, x2);
}
else if (delta == 0)
{
x1 = (-b) / (2*a);
x2 = x1; //右边赋给左边
printf("该一元二次方程有一个唯一解, x1 = x2 = %f\n", x1);
}
else
{
printf("无解\n");
}
return 0;
}
6.关于vc++6.0的一些问题
如果在程序起名字的时候含有“…”,那么需要在名字后面加后缀“.cpp”。否则,在编译运行那一块将无法点击。
1.CPU 内存条 硬盘 显卡 主板 显示器 之间的关系
2.HelloWorld程序如何运行
# include
int main (void)
{
printf("欢迎来到c世界!\n");
return 0;
}
基本数据类型
整数:
1)整型 — int (4字节)
# include
int main (void)
{
int i=10;//表示 i 变量时整型变量,所谓整型变量就是指i只能存放整数不能存放实数
printf("%d\n",i);
return 0;
}
2)短整型—short int (2字节)
3)长整型—long int (8字节)
浮点数【实数】
1)单精度浮点数—float(4字节)
2)双精度浮点数—double (8字节)
字符:
char
char i='A';
printf("%c\n",i);
4.变量
5.CPU 内存条 VC++6.0 操作系统 之间的关系
int i;
i=3;//3最终是存放在内存中,程序终止以后3所占的空间被释放
6.变量为什么 必须初始化(所谓初始化就是赋值的意思)
7.如何定义变量
9.常量在C语言中是如何表示的
包括:整型、实型、字符型、字符串、枚举型
10.常量以什么样的二进制代码存储在计算机中
11.代码规范化
13.不同类型数据之间相互赋值的问题
暂不考虑
14.什么是ASCII
char ch = "AB";//error 因为“AB”是字符串,我们不能把字符串赋给单个字符
char ch = "A";//error
char ch = 'AB';//error,‘AB’是错误的
15.字符的存储[字符本质上与整数的存储方式相同]
#include
void main()
{
printf("Hello World!\n");
}
对于该结构来说:
一、宏常量
二、const常量
4. 必须在定义时赋初值
例:const double pi = 3.14159
5. const常量与宏常量相比的优点是什么
const常量有数据类型,编译器能对其进行类型检查
某些集成化调试工具可以对const常量进行调试
printf ("哈哈!\n");//\n表示换行
int i = 10;
printf("%d\n",i);//d是十进制
int x=47;
printf ("%x\n",x);//输出结果:2f
printf ("%X\n",x);//输出结果:2F
printf ("%#X\n",x);//输出结果:0X2F(这种输出结果最好,推荐使用)
printf ("%#x\n",x);//输出结果:0x2f
int i;
scanf(”%d“,&i);//&i表示i的地址 &是一个取地址符
printf (”i=%d\n“,i);
数据位宽:scanf(“%2d%2d”,&a,&s);
例:输入1234,则a=12,s=34
2. scanf(“非输入控制符 输入控制符”,输入参数);
功能:将从键盘输入的字符转化为输入控制符所规定格式的数据,然后存入以输入参数的值为地址的变量中。非输入控制符必须原样输入。
int i;
scanf("m%d",&i);//1:输入:m123;2:输入:123(错误)
printf("i=%d\n",i);1:输出:i=123;2:输出:-12324341(垃圾数字)
scanf("%d,%d",&a,&b);//输入2,3(必须与“”内的格式一致)
scanf("a=%d,b=%d",&a,&b);//输入a=3,b=4
附:
scanf()的格式字符
%d :输入十进制int型
%f,%e:输入float型(不能指定输入数据的精度)
%c:输入一个字符(包括空白字符)
*:输入项在读入后不赋给相应的变量,
例:scanf("%2d%*2d%2d",&a,&b);//输入123456
printf(“a=%d,b=%d”,a,b);//输出a=12,b=56
3. scanf(“输入控制符,输入控制符,输入控制符”,输入参数,输入参数。输入参数);
int i,j,k;
scanf("%d,%d,%d",&i,&j,&k);
printf("i=%d,j=%d,k=%d\n",i,j,k);
int i;
scanf("%d\n",&i);//非常不好的格式,不要加\n
printf("i=%d\n",i);
while ((ch=getchar())!='\n')
continue;
#include
main()
{
char ch;
printf("press a key and then press enter:");
ch =getchar();
ch=ch+32;
putchar(ch);
putchar('\n');//不能用“”
}
将输入字符先放入输入缓冲区队列中,再从缓冲队列读取字符,直到键入回车符或文件结束符EOF时,程序才认为输入结束。一行输入结束,getchar()才开始从输入缓冲队列读取字符,前面函数没读走的数据仍在缓冲队列中,将被下一个函数读取。
使用getchar()输入字符时的怪象,相当于一次性把键盘输入的一行字符都放入缓冲区,然后再从输入缓冲去逐个读取字符
在%c前加上空格用以忽略用户输入的空白字符
1.不同类型数据的运算结果的类型是什么?
取值范围较大的那种类型
2.当取值范围大的类型转化为取值范围小的类型时,通常都是不安全的,会发生数据溢出(小蛇吞大象 )
3.上溢出
一个数值运算结果>类型能表示的最大数
进位超过最高位而发生进位丢失
或进位到达最高位而改变符号位
4.下溢出
浮点数运算结果<类型能表示的最小数
1.格式:
(数据类型)(表达式);
2.功能
把表达式的值强制转换为前面所制定的类型
例子:
(int )(4.5+2.2);最终值是6
(float)(5);最终值是5.000000
float和double都不能保证可以精确的存储一个小数
举例:
1.有一个浮点型变量x,如何判断x的值是否是零
if (|x-0.000001|<=0.00001)
是零
else
不是零
2.为什么循环中更新的变量不能是定义成浮点型
循环中更新的变量不要定义成浮点型
函数名 | 功能 |
---|---|
exp(x) | ex |
pow(x,y) | xy |
sqrt(x) | x的平方根(x>=0) |
fabs(x) | ∣ \mid ∣x ∣ \mid ∣ |
log(x) | lnx(x>0) |
log10(x) | lgx(x>0) |
sin(x) | sinx.x为弧度值 |
cos(x) | cosx,x为弧度值 |
注:使用这些数学函数时,必须在代码前加#include
<, <=, >, >=, !=, ==
!(非),&&(并且),||(或)(具有短路特性)
!真--------假;
!假--------真;
真&&真----真;
假&&真----假;
真&&假----假;
假&&假----假;
真||假------真;
假||真------真;
真||真------真;
假||假------假;
C语言对真假的处理:非零是真,零是假;真是1表示,假是0表示。
int i = 10;
int k = 20;
int m;
m = (1>2) && (k=8);//不含有分号的是表达式,含有分号的就是语句。
printf ("m=%d,k=%d\n",m,k);//m=0,k=20.因为1>2是假的,所以k=8就不执行,故k不变
+=,=,/=,-= ,*=
1.自增(或者自减)
a.分类:
前自增------++i
后自增------i++
b.前自增和后自增的异同:
相同:
最终都使i的值加1
不同:
前自增整体表达式的值是i加1之后的值(先+后用)
后自增整体表达式的值是i加1之前的值(先用后+)
例:m=++n;
运行时为:n=n+1;
m=n;
例:m=n++;
运行时为:m=n;
n=n+1;
例:m=++n-2;
运行时:n=n+1;//n=6
m=n-1;//m=4
例:m=n++ -2;
运行时:m=n-2;//n=6
n=n+1;//m=3
int i;
int j;
int k;
int m;
i=j=3;
k=i++;
m=++j;
printf("i=%d,j=%d,k=%d,m=%d\n",i,j,k,m);
//结果是:i=4,j=4,k=3,m=4
c.为什么会出现自增
代码更精炼
自增的速度更快
d.学习自增要明白的几个问题:
2.三目运算符
A?B:C
等价于
if(A)
B;
else
C;
int i;
i= (1>2 ?5:1);
printf ("%d\n",i);
3.逗号表达式
格式:
(A,B,C,D)
功能:
从左到右执行
int i;
int j=2;
i= (j++,++j,j+2,j-3);//j=4,最后一个j-3赋给i,所以为1
printf ("%d\n",i);
// i=1
1.什么是流程控制
程序代码执行的顺序
2.流程控制的分类
a. if最简单的用法
if (3 >2)
printf ("AAA\n");//会输出
if (3)
printf("Aaa\n");//会输出
if (0)
printf (NNN\n");//不会输出
if (0==0)
printf("ZZZ\n");//会输出
b. if的范围问题
if(表达式)
语句A;
语句B;
解释:
if默认的只能控制一个语句A的执行或不执行
if无法控制语句B的执行或不执行
或者讲:语句B一定会执行
if (1 > 2)
printf("AAA\n");
printf("DDD\n");
//在vc++6.0中输出的结果是DDD
if(表达式)
{
语句A;
语句B;
}
此时if可以控制语句A和语句B
c. if…else…的用法
d. if…else if…else…的用法
double delta = -1;
if (delta > 0)
printf ("有两个解!\n");
printf ( "哈哈!\n");//不是if语句里面的,这里匹配出错,不能这样写
else if (delta==0)
printf ("有一个唯一解!\n");
else
printf ("无解!\n");
e. C语言对真假的等级
f. if举例–求分数的等级
# include
int main (void )
{
float score ;//分数
printd ("请输入您的考试成绩:");
scanf ("%f",&score);
if (score > 100)
printf ("这是做梦!\n");
else if (score >=90 && score <=100)//不能写成 90<=score<-100
printf ("优秀!\n");
else if (score >=80 && score <90)
printf("良好!\n");
else if (score >=60 && score<80)
printf ("及格!\n");
else if (score >=0 && score<60)
printf ("不及格,继续努力!\n");
else
printf ("输入的分数过低,不要如此自卑!\n");
return 0;
}
g. if的常见问题及解析
if (1>2); //此处的空语句类似于 if () ; (所以1>2成立是执行空语句)不能加;
printf (”AAA\n“);
printf("BBB\n");
//执行后为:
AAA
BBB
if (表达式1)
A;
else
B;
是正确的
if (表达式1);
A;
else
B;
是错误的
if (表达式1)
A;
else if (表达式2)
B;
else if(表达式3)
C;
else
D;
即便表达式1和2都成立,也只会执行语句A
if (表达式1)
A;
else if(表达式2)
B;
else if(表达式3)
C;
这样写语法不会出错,但逻辑上有漏洞
if(表达式1)
A;
else if (表达式2)
B;
else if (表达式3)
C;
else(表达式4)//第7行
D;
这样是不对的,正确的写法是:
要么去掉第七行的(表达式4)
要么在第七行的else后面加if
if (表达式1)
A;
else if(表达式2)
B;
else if (表达式3)
C;
else (表达式4);
D;
这样写语法不会出错,但逻辑上是错的
else (表达式4);
D;
等价于
else
(表达式4);
D;
h.如何看懂一个程序,分三步:
1. 流程
2. 每个语句的功能
3. 试数
如何学习一些小算法的程序
1. 尝试自己去编程解决他,大部分人都自己无法解决
2. 如果解决不了就看答案
3. 关键是把答案看懂之后,这个要花很大的精力,也是我们学习的重点
4. 看懂之后尝试自己去修改程序,并且知道自己修改之后程序的不同输出结果的含义
5. 照着答案去敲
6. 不看答案,自己独立把答案敲出来
小算法的程序:
1. 判断一个数字是否是素数
2. 判断一个数字是否是回文数
3. 编程实现求一个是进制数字的二进制形式
4. 求一个数字的每位是奇数的数字取出来组合形成的新数字
5. 求一个数字倒过来的数字
a.用法:看懂电梯程序
int val;
printf ("请输入您要进入的楼层:");
scanf ("%d",&val);
switch (val)
{
case 1:
printf("1层开!\n");
break;
case 2:
printf ("2层开!\n");
break;
case 3:
printf ("3层开!\n");
break;
default:
printf ("没有盖到这一层!\n");
break;
}
b.
c.
a. 格式:
for (1;2;3)
语句A;
# include
int main (void)
{
int i;
int sum = 0;
for(i=1;i<=9;++i)
sum = sum + i;
printf ("sum= %d\n",sum);
return 0;
}
b. 执行的流程【重点】
单个for循环的使用
多个for循环的嵌套使用
for (1;2;3)//1
for(4;5;6)//2
A;//3
B;//4
整体是两个语句,1 2 3是第一个语句
4是第二个语句
总结:
第一行的for 循环如果不执行了再执行B
for(1;2;3)
for(4;5;6)
{
A;
B;
}
整体式一个语句
3.
for (7;8;9)
for(1;2;3)
{
A;
B;
for(4;5;6)
C;
}
整体式一个语句
c.范围问题
d.举例
1 + 2 + 3 + 4 + 5… + 100;
1 +1/2 + 1/3 + 1/4 + … + 1/100;
//例2
# include
int main (void)
{
int i=1;
float sum=0;
for (i=1;i<=100;i++)
sum = sum + 1/(float)i;//把i强制转换为浮点型
//或者sum=sum+1/(float)(i);
printf ("sum=%f\n",sum); //float必须用%f输出
return 0;
}
//结果:sum=5.187378
e.练习
1.求1到100之间的奇数之和
2.求1到100之间的奇数的个数
3.求1到100之间的奇数的平均数
4.求1到100之间的奇数之和,再求1到100之间的偶数之和
a.执行顺序
格式:
while (表达式)
语句;
例子:
int i=1;
int sum=0;
while (i<101)
{
sum = sum + i;
i++;
}
printf ("sum=%d\n",sum);
b.与for的相互比较
for(1;2;3)
A;
等价于
1;
while(2)
{
A;
3;
}
总结:
while 和for可以相互转化,但for的逻辑性更强,更不容易出错,推荐多使用for。
c.举例
int val;//存放待判断的数字
int m;
int sum=0;
printf("请输入您需要判断的数字:");
scanf("%d",&val);
m=val;
while(m)
{
sum=sum*10+m%10;//理解它
m/=10;
}
if(sum==val)
printf("yes!\n");
else
printf("no!\n");
# include
int main(void)
{
int f1,f2,f3;
f1=1;
f2=2;
int n;
int i;
printf("请输入数字");
scanf("%d",&n);
if(n==1)
f3=1;
else if(n==2)
f3=2;
else
{
for(i=3;i<=n;i++)
{
f3=f1+f2;
f1=f2;
f2=f3;
}
}
printf("f3=%d",f3);
return 0;
}
d.什么时候使用while ,什么时候使用for
用多了自然而然就知道了
a.
格式:
do
{
…
}while (表达式);
例子:二元一次方程的求解
# include
# include
int main (void)
{
double a,b,c,x1,x2,l;
char ch;
do{
printf ("请输入数字a=");
scanf ("%lf",&a);
printf ("请输入数字b=");
scanf ("%lf",&b);
printf ("请输入数字c=");
scanf ("%lf",&c);
l = b * b - 4 * a * c;
x1 = (-b + sqrt(l))/(2 * a);
x2 = (-b - sqrt(l))/(2 * a);
if (l>0){
printf ("该二元一次方程有两个不同实数解:x1=%lf,x2=%lf",x1,x2);
}
else if (l==0)
{
printf ("该二元一次方程有两个相同实数解:x1=%lf,x2=%lf",x1,x2);
}
else
{
printf("该方程无解");
}
printf("您是否还要进行运算:(Y/N)");
scanf(" %c",&ch);//这里%c前面必须加一个空格
}while('y'==ch||'Y'==ch);
return 0;
}
1.break
for (i=0;i<3;++i)
{
if (3>2)
break;//break虽然是if内部的语句,但它终止的是外部的for循环
printf ("hihi1!\n");//永远不会输出
}
int i,j;
for(i=0;i<3;++i)
{
for(j=1;j<4;++j)
break;
printf ("同志们好!\n");
}
//输出结果为:
同志们好!
同志们好!
同志们好!
int x=1,y=0,a=0,b=0;
switch (x) //第一个switch
{
case 1:
switch (y) //第二个switch
{
case 0:
a++;
break; //终止的是第二个switch
case 1:
b++;
break;
}
b=100;
break; //终止的是第一个switch
case 2:
a++;
b++;
break;
}
printf ("%d %d\n",a,b); //26行
//最终输出结果是1 100
2.continue
for(1;2;3)
{
A;
B;
continue;//如果执行该语句,则执行完该语句后,会执行语句3,C和D都会被跳过,C和D不会被执行
C;
D;
}
while (表达式)
{
A;
B;
continue; //如果执行该语句,则执行完该语句后,会执行表达式,C和D都会被跳过去,C和D不会被执行
C;
D;
}
1.递推的基本方法
正向递推:一步一步推得结果
反向逆推:由结果一步一步推得初值
2.递推的本质
把一个复杂的计算过程转化为一个简单过程的多次重复计算
1.为什么需要学习数组
为了解决大量同类型数据的存储和使用问题
为了模拟现实世界
例子:
int a [5] = {1,2,3,4,5};
// a是数组的名字,5表示元素的个数,并且这5个元素分别用a[0],a[1],a[2],a[3],a[4]表示
int i;
for (i=0;i<5;++i)
printf ("%s\n",a[i]);
2.数组的分类
3.高效的数组初始化
memset(a,0,sizeof(a));
用sizeof(a)来获得数字组a所占的内存字节数
所用到的头文件 #include
4.高效的数组赋值的方法
memcpy(b,a,sizeof(a));//数组a复制给数组b,要求数组a,b长度一致
所需要的头文件 #include
怎样定义一维数组
为n个变量连续分配存储空间
所有的变量数据类型必须相同
所有变量所占的字节大小必须相等
例子:
int a [5];
一维数组名不代表数组中所有的元素,一位数组名代表数组第一个元素的地址
有关一维数组的操作
a. 初始化
1)完全初始化
int a [5] = {1,2,3,4,5};
2)不完全初始化,未被初始化的元素自动为零
int a [5] = {1,2,3};
3)不初始化,所有元素是垃圾值
int a [5];
4)清零
int a [5]={0};
5)错误写法:
int a [5];
a [5] = {1,2,3,4,5};//错误
只有在定义数组的同时才可以赋值,其他情况下整体赋值都是错误的
int a [5] = {1,2,3,4,5};
a [5] = 100;//error因为没有a [5]这个元素,最大只有a[4]
int a [5] = {1,2,3,4,5};
int b [5];
//如果要把a数组中的值全部复制给b数组
错误写法:
b=a;//error
正确的写法:
for (i=0;i<5;++i)
b [i]=a[i];
b.赋值
int a [5];
int i;
scanf ("%d",&a[0]);
printf ("%d\n",a[0]);
scanf ("%d",&a[3]);
printf ("%d\n",a[3]);
for (i=0;i<5;++i)
ptintf ("%d",a[i]);
c.排序
d.求最大/最小值
f.倒置
int a [7] = {1,2,3,4,5,6,7};
int i,j;
int t;
i=0;
j=6;
while (i < j)
{
t = a[i];
a[i] = a[j];
a[j] = t;
i++;
--j;
}
for (i=0;i<7;++i)
printf("%d\n",a[i]);
//输出为:7,6,5,4,3,2,1
g.查找
h.插入
i.删除
//其他的看书
2.初始化
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int a[3][4] = {
{1,2,3,4},
{5,6,7,8},
{9 ,10,11,12}
};
3.输出二维数组的内容
int a[3][4] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
int i,j;
//输出数组内容
for (i=0;i<3;++i)
{
for (j=0;j<4;++j)
printf ("%d ",a[i][j]);
printf ("\n");
}
4.对二维数组的排序
5.求每一行的最大值
6.判断矩阵是否对称
int a[3][4][5];
该数组是含有3个元素的一维数组
只不过每个元素都是4行5列的二维数组
#include
#include
#define N 100
void SiftPrime(int a[],int n);
void PrintfPrime(int a[],int n);
int main()
{
int a[N+1];
SiftPrime(a,N);
PrintfPrime(a,N);
return 0;
}
void SiftPrime(int a[],int n)
{
int i,j;
for(i=2;i<=N;i++)
{
a[i]=i;
}
for(i=2;i<=sqrt(N);i++)
{
for(j=i+1;j<=N;j++)
{
if(a[i]!=0&&a[j]!=0&&a[j]%a[i]==0)
{
a[j]=0
}
}
}
}
void PrintfPrime(int a[],int n)
{
int i;
for(i=2;i<=N;i++)
{
if(a[i]!=0)
{
printf("%d\t",a[i]);
}
}
printf("\n");
}
int main()
{
...
MakeDigit(a);//随机生成一个各位相异的4位数
printf("How many times do you want to guess?");
scanf("%d",&level);//最多允许猜的次数
count=0;//记录用户猜的次数
do{
printf("No.%d of %d times\n",count,level);
if(InputGuess(b)==0)
continue;
count++;//记录已经猜的次数
rightPosition=IsRightPosition(a,b);//统计数字和位置都猜对的个数
rightDigit=IsRightDigit(a,b)-rightPosition;//统计数字猜对位置不对的个数
printf("%dA%dB\n",rightPosition,rightDigit);
}while(rightPosition!=a&&count<level);
if(rightPosition==4)
printf("Congratulation,you guess the right number at No.%d\n",count);
else
printf("Sorry,you haven't guess the right number,see you next time!\n");
return 0;
}
//随机生成一个各位相异的4位数---第一种方法
void MakeDigit(int a[])
{
srand(time(NULL));
a[0]=rand()%10;//千位数字
do{
a[1]=rand()%10;//百位数字
}while(a[0]==a[1]);
do{
a[2]=rand()%10;//十位数字
}while(a[0]==a[2]||a[1]==a[2]);
do{
a[3]=rand()%10;//个位数字
}while(a[0]==a[3]||a[1]==a[3]||a[2]==a[3]);
}
//随机生成一个各位相异的4位数---第二种方法
void MakeDigit(int a[])
{
int i,j,temp;
srand(time(NULL));
for(i=0;i<10;i++)
{
a[i]=i;
}
for(i=0;i<10;i++)
{
j=rand()%10;
temp=a[j];
a[j]=a[i];
a[i]=temp;
}
}
//用户输入
int InputGuess(int b[])
{
int i,ret;
for(i=0;i<<4;i++)
{
ret=scanf("%ld",&b[i]);
if(ret!=1)
{
printf("Input Data Type Error!\n");
fflush(srdin);//清空输入缓冲区
return 0;//表示输入数据不合法
}
}
if(b[0]==b[1]||b[0]==b[2]||b[0]==b[3]||b[1]==b[2]||b[1]==b[3]||b[2]==b[3])
{
printf("The numbers must be different from each other ,input again\n");
return 0;//表示输入数据不合法
}
else
{
return 1;//表示输入数据合法
}
}
//A前面的数字
int IsRightPosition(int magic[],int guess[])
{
int rightPosition=0;
int=j;
for(j=0;j<4;j++)
{
if(guess[j]==magic[j])
{
rightPosition++;
}
}
return rightPosition;
}
//B前面的数字
int IsRightDigit(int magic[],int guess[])
{
int rightDigit=0;
int j;k;
for(j=0;j<4;j++)
{
for(k=0;k<4;k++)
{
if(guess[j]==magic[k])
{
rightDigit++;
}
}
}
return rightDigit;
}
1.为什么需要函数
# include
int main(void)
{
int a=1,b=2,c=32,d=11,e=31,f=54;
if (a>b)
printf ("%d\n",a);
else
printf ("%d\n",b);
if (c>d)
printf ("%d\n",c);
else
printf ("%d\n",d);
if (e>f)
printf ("%d\n",e);
else
printf ("%d\n",f);
return 0;
}
等价于函数:
# include
void max (int i,int j) //max是函数的名字,i和j是形参(形式参数),void表示函数没有返回值
{
if (i>j)
printf ("%d\n",i);
else
printf ("%d\n",j);
}
int main(void)
{
int a=1,b=2,c=32,d=11,e=31,f=54;
max (a,b);
max (c,d);
max (e,f);
return 0;
}
2.什么叫函数
# include
int f(void) //括号中的void表示该函数不能接受数据,int表示函数返回值是int类型
{
return 10;//向主调用函数返回10
}
void g(void)//8行 函数名前面的void表示该函数没有返回值
{
// return 10;//error 与8行行首的void相矛盾
}
int main(void)
{
int j=88;
j = f();
printf ("%d\n",j);
//j = g();//error因为g函数没有返回值
return 0;
}
3.如何定义函数
格式:
函数的返回值 函数的名字(函数的形参列表)
{
函数的执行体
}
# include
void f(void)
{
int i;
for(i=0;i<5;++i)
{
printf ("大家辛苦了!\n");
//break;//当这里为break 时,输出为:大家辛苦了!同志们好!
return ;//当这里为return 时,输出为:同志们好!
}
printf ("同志们好!\n");
}
int main(void)
{
f();
return 0;
}
void f()
{
return ;//return只用来终止函数,不向被调函数返回任何值
}
int f()
{
return 10;//第一:终止函数; 第二:向主调函数返回10
}
# include
int f()
{
return 10.5;//因为函数的返回值类型是int ,所以最终返回的是10而不是10.5
}
int main(void)
{
int i=99;
double x=6.6;
x=f();
printf ("%lf\n",x);
return 0;
}
4.函数的分类
5.举例子:
# include
void max1 (int i,int j) //max是函数的名字,i和j是形参(形式参数),void表示函数没有返回值
{
if (i>j)
printf ("%d\n",i);
else
printf ("%d\n",j);
}
int max2 (int i,int j)
{
if(i>j)
return i;
else
return j;
}
int main(void)
{
int a=1,b=2,c=32,d=11,e=31,f=54;
//当用函数max2时
printf ("%d\n",max2(a,b));
printf ("%d\n",max2(c,d));
printf ("%d\n",max2(e,f));
//当用函数max1时
max1 (a,b);
max1 (c,d);
max1 (e,f);
return 0;
//max1有两个作用:找最大值和进行处理;而 max2只是找最大值;所以将来编写代码主要看目的是什么
# include
int main (void)
{
int val;
int i;
scanf ("%d",&val);
for(i=2;i
方法二:(用函数的方法)
# include
bool IsPrime(int val)
{
int i;
for(i=2;i
# include
void f(int i)
{
}
int main (void)
{
int i;
i = f(5);//但是 f 函数中没有返回值,所以不能赋值给 i
return 0;
}
6.注意的问题
# include
void f(void);//函数声明,分号不能丢
//声明的作用:告诉软件接下来有个函数没有返回值,没有形参
int main (void)
{
f();
return 0;
}
void f(void)
{
printf ("哈哈!\n");
}
例2:
#include
void f(void);
void g(void)
{
f();//如果不加函数声明,则会报错;因为函数f的定义放在了调用f语句的后面,所有语法出错
}
void f(void)
{
printf ("哈哈!\n");
}
int main (void)
{
g();
return 0;
}
# include
void f (int i,float x)
{
printf ("%d\n",i);
}
int main (void)
{
f(9,6.6);//必须是int和float,位置不能颠倒
return 0;
}
/*判断一个数字是否是素数;
用单独的函数来实现,代码的可重用性提高*/
# include
bool IsPrime(int val)
{
int i;
for (i=2;i
例2:
/*求1到某个数字之间(包括该数字)所有的素数,并将其输出
用1个函数来判断一个数字是否是素数
优点:
代码更容易理解
代码的可重用性高
缺点:
可重用性仍然不是非常高,
比如求1000个数字,求他们每个数字从1到他本身的素数,
则
for (i=2;i<=val;++i)
{
if (IsPrime(i))
printf ("%d\n",i);
}
要写1000次
# include
bool IsPrime(int m)
{
int i;
for(i=2;i
7.常用的系统函数
8.如何合并成一个完整的程序
long Fact(int n)
{
if(n<0)
return -1;
else if(n==0||n==1)
return 1;
else
return n*Fact(n-1);
}
//Fact(3)=3*Fact(2)
// Fact(2)=2*Fact(1)
// Fact(1)=1
// 结束
例子:汉诺塔问题:将n个圆盘借助C从A移到B
void Hanoi(int n,char a,char b,char c)
{
if(n==1)
{
Move(n,a,b);
}
if(n>1)
{
Hanoi(n-1,a,c,b);//将上面的N-1个圆盘由A移到C
Move(n,a,b);//将第n号圆盘从A移到B
Hanoi(n-1,c,b,a);//将上面n-1个圆盘从C移到B
}
}
//定义函数
void ReadScore(int score[],int n)
{
int i;
printf("Input score:");
for(i=0;i<n;i++)
{
scanf("%d",&score[i]);
}
}
//调用函数
#include
#define N 40
void ReadScore(int score[],int n);
int main()
{
int score[N],aver,n;
printf("Input n;");
scanf("%d",&n);
ReadScore(score,n); //用不带下标的数组名做函数实参
printf("Average score is %d\n",aver);
return 0;
}
//函数的定义
void AverforCourse(int score[][COURSE_N],int sum[],float aver[],int n)
{
int i,j;
for(j=0;i<COURSE_N;j++)//先遍历每门课程
{
sum[j]=0;
for(i=0;i<n;i++)
{
sum[j]=sum[j]+score[i][j]
}
aver[j]=(float)sum[j]/n;
}
}
//函数的调用
//函数的定义
int FindMaxValue(int x[],int n)
{
int maxValue,i;
maxValue=x[0];
for(i=1;i<n;i++)
{
if(x[i]>maxValue)
{
maxValue=x[i];
}
}
return maxValue;
}
//函数的调用
#include
#define N 40
int ReadScore(int scpre[]);
int FindMaxValue(int x[],int n);
int main()
{
int score[N],maxValue,n;
n=ReadScore(score);
printf("Total students are %d\n",n);
maxValue=FindMaxValue(score,n);
printf("The highest score is %d\n",maxValue);
return 0;
}
例:查找某学号学生的成绩
//主函数
#define N 40
#include
int ReadScore(long num[],int score[]);
int LinSearch(long num[],long x,int n);
int main()
{
int score[N],n,pos;
long num[N],x;
n=ReadScore(num,score);
printf("Input the serching ID:");
scanf("%ld",&x);
pos=LinSearch(num,x,n);
if(pos!=-1)
{
printf("score=%d\n",score[pos]);
}
else
{
printf("Not found!\n");
}
return 0;
}
//定义函数
int LinSearch(long num[],long x,int n)
{
int i;
for(i=0;i<n;i++)
{
if(num[i]==x)
{
return i;//找到时返回下标
}
}
return -1;//找不到时返回-1
}
int ReadScore(long num[],int score[])
{
int i=-1;
do{
i++;
printf("Input num,score:");
scanf("%ld%d",&num[i],&score[i]);
}while(score[i]>=0);
return i;
}
int BinSearch(long num[],long x,int n)
{
int low =0,high=n-1,mid;
while(low<=high)
{
//mid=(high+low)/2;//当数组很大时,low和high之和大于有符号整数的极限值就会发生数值溢出,使mid成为一个负数
mid = low+(high-low)/2;//正确的方式
if(x>num[mid])
{
low=mid+1;
}
else if(x<num[mid])
{
high=mid-1;
}
else
{
reutrn mid;
}
}
return -1;
}
void BubbleSort(int score[],int n)
{
int i,j,temp;
for(i=0;i<n-1;i++)
{
for(j=1;j<n-i;j++)
{
if(score[j]<score[j-1])
{
//交换相邻元素
temp=score[j];
score[j]=score[j-1];
score[j-1]=temp;
}
}
}
}
void ChangeSort(int score[],int n)
{
int i,j,temp;
for(i=0;i<n-1;i++)
{
for(j=i+1;j<n;j++)
{
if(score[j]<score[i])
{
temp=score[j];
score[j]=score[i];
score[i]=temp;
}
}
}
}
void SelectionSort(int score[],int n)
{
int i,j,k,temp;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
{
if(score[j]<score[k])
{
k=j;//记录最小下标位置
}
}
if(k!=i)//若最小不在下标位置i
{
temp=score[k];
score[k]=score[i];
score[i]=temp;
}
}
}
1.按作用域分
int k=1000;
void g()
{
printf ("k=%d\n",k);
}
//k在g函数的外面,k在任何函数中都可以用
但如果:
void g()
{
printf ("k=%d\n",k);
}
int k=1000;
//这时会报错,程序运行是由上到下的,k在g 函数的下面,则会出错;
//一定要把`int k=1000`放在函数g的前面
void f(int i)
{
int j = 20;
}
//i和j都属于局部变量
# include
int i=99;
void f(int i)
{
printf ("i=%d\n",i);
}
int main (void)
{
f (8);
return 0;
}
//最后输出的值为:i=8
2.按变量的存储方式
#include
int main()
{
int a=0,b=1;
int *pa,*pb;
pa=&a;
pb=&b;
printf("a=%d,b=%d\n",a,b);
printf("*pa=%d,*pb=%d\n",*pa,*pb);
return 0 ;
}
#include
void Fun(int x,int y,int (*f)(int, int));
int Max(int x,int y);
int Min(int x,int y);
int Add(int x,int y);
int main()
{
int a,b;
scanf("%d,%d",&a,&b);
Fun(a,b,Max);
Fun(a,b,Min);
Fun(a,b,Add);
return 0;
}
void Fun(int x,int y,int (*f)(int,int))
{
int result;
result=(*f)(x,y);
paintf("%d\n",result);
}
int Max(int x,int y)
{
printf("max=");
return x>y?x:y;
}
int Min(int x,int y)
{
printf("min=");
return x<y?x:y;
}
int Add(int x,int y)
{
printf("sum=");
return x+y;
}
#define STR_LEN 80
char str[STR_LEN+1];
//方法一:逐个字符输入输出
for(i=0;str[i]!='\0';i==)//一般不用字符串长度控制,如i
{
putchar(srt[i]);
}
putchar('\n');
//方法二:整体输入输出字符串
scanf("%s",str);//本来就是字符数组,故不用&,直接用数组名即可
printf("%s\n",str);
//方法三:
gets(str);//从键盘输入,不等价与scanf
//scanf不能输入带空格的字符串,而gets可以
puts(str);//输出到屏幕上,等价于printf
#define STR_LEN 80
char str[STR_LEN+1];
char str[6]={'C','h','i','n','\0'};
用字符串常量直接对数组初始化
char str[6]={"China"};//末尾自动加一个结束字符'\0'
char str[6]="China";//可省略花括号
char str[]="China";//可省略数组的长度
char str[10]="China";//当数组长度超过字符的长度时,自动把后面的数组元素定义为空字符
char *pStr="Hello China";
//与char str[]="Hello China";的区别在于指针可修改,而数组不可修改
#include //头文件必须要有
char str[10]={"China"};
printf("%d",strlen(str));
//输出结果为5
#include
strcpy(str2,strcpy(str1,"Hello"));//多重复制,函数有返回值才可以
strcat(str2,strcat(str1,"Hello"));
if(strcmp(str2,str1)==0)
if(strncmp(str2,str1,n)==0)//最多比较字符串中n个字符的大小
unsigned int MyStrlen(const char *pStr)//从右往左读,指针变量,指向字符常量
{
unsigned int len=0;
//for(;*pStr!='\0';pStr++)
for(;*pStr;pStr++)//简化为判断是否为真
//还可以将其合并为一个表达式
for(;*pStr++;)
{
len++;
}
//继续优化上述代码
unsigned int MtStrlen(const char *pStr)
{
const char *start =pStr;
while(*pStr)
{
pStr++;
}
return pStr-start;
}
return len;
}
unsigned int MyStrlen(const char *pStr)//从右往左读:指针变量,指向字符常量
{
unsigned int len=0;
for(;*pStr1='\0';pStr++)
{
len++;
}
return len;
}
void MyStrcpy(chaar dstStr[],char srcStr[])
{
int i=0;
while(srcStr[i]!='\0')
{
dstStr[i]=srcStr[i];
i++;
}
dstStr[i]='\0';//前面的循环没有将结束标志复制,这里我们单独将结束标志复制到字符串中
}
void MyStrcpy(char *dstStr,char *srcStr)
{
while(*srcStr!='\0')
{
*dstStr=*srcStr;
srcStr++;
dstStr++;
}
*dstStr='\0';
//优化上述代码
while(*srcStr)
{
*dstStr++=*srcStr++;
}
*dstStr='\0';
//继续优化上述代码
void MyStrcpy(char *dstStr,const char *srcStr)
{
while(*dstStr++= *srcStr++)//循环在复制空字符后才会终止
{
;
}
}
}
编程实现strcat()功能
#include
#define N 80
char *MyStrcat(char *dstStr,char *srcStr);
int main()
{
char first[2*N+1];
char second[N+1];
char *result=NULL;
printf("Input the first string:");
gets(first);
printf("Input the second string:");
gets(first);
printf("Input the second string:");
result=MyStrcat(first,second);
printf("The result is:%s\n",result);
return 0;
}
char *MyStrcat(char *dstStr,char *srcStr)
{
char *pStr=dstStr;
while (*dstStr!='\0')
{
dstStr++;
}
while(*srcStr!='\0')
{
*dstStr=*srcStr;
srcStr++;
dstStr++;
}
*dstStr='\0';
return pStr;//返回字符串首地址
}
void InputArray(int a[],int n)
{
int i;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
}
void OutputArray(int a[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("%4d",a[i]);
}
printf("\n");
}
void InputArray(int *p,int n)
{
int i;
for(i=0;i<n;i++)
{
scanf("%d",p++);
}
}
void OutputArray(int *p,int n)
{
int i;
for(i=0;i<n;i++)
{
printf("%4d",*p++);
}
printf("\n");
}
int main(int argc,char* argv[])
- argc:命令行参数的数量(包括程序名本身)
- argv:指向命令行参数的指针数组
- argv[0]:为指向程序名的字符指针
- argv[1]~argv[argc-1]为指向余下的命令行参数的字符指针
int main(int argc,char *argv[])
{
int i;
printf("The number of command line arguments is:%d\n",argc);
printf("The program name is:%s\n",argv[0]);
if(argc>1)
{
printf("The other arguments are following:\n");
for(i=1;i<argc;i++)
{
printf("%s\n",argv[i]);
}
}
return 0;
}
struct student //定义结构体类型
{
long studentID;
char studentName[10];
char studentSex;
int yearOfBirth;
int score[4];
];
struct student stu1;//定义变量名
方法二:在定义结构体类型的同时定义变量
struct student
{
long studentID;
char studentName[10];
char studentSex;
int yearOfBirth;
int score[4];
}stu1;//分号一定不能省略
方法三:直接定义结构体变量(不指定结构体标签)
struct
{
long studentID;
char studentName[10];
char studentSex;
int yearOdBirth;
int score[4];
}stu1;
struct student stu1;和STUDENT stu1;
struct student //定义结构体类型
{
long studentID;
char studentName[10];
char studentSex;
int yearOfBirth;
int score[4];
];
typedef struct student STUDENT;//定义变量名
方法二:
typedef struct student
{
long studentID;
char studentName[10];
char studentSex;
int yearOfBirth;
int score[4];
}STUDENT;//分号一定不能省略
方法三:
typedef struct
{
long studentID;
char studentName[10];
char studentSex;
int yearOfBirth;
int score[4];
}STUDENT;//分号一定不能省略
printf("%d\n",sizeof(struct sample));或printf("%d\n",sizeof(SAMPLE));
访问数组的元素:通过下标(位置)选择数组元素
访问结构体变量的成员:通过名字访问结构体的成员
stu1.studentID=100002;
stu1.studentName="王刚";//错误
strcpy(stu1.studentName,"王刚");//正确
stu1.birthday.year=1991;
//结构体
typedef struct student
{
long studentID;
char studentName[10];
char studentSex;
DATA birthday;
int score[4];
float aver;
}STUDENT;
void AverScore(STUDENT stu[],int n,int m)
{
int i,j,sum[N];
for(i=0;i<n;i++)
{
sum[i]=0;
for(j=0;j<m;j++)
{
sum[i]=sum[i]+stu[i].score[j];
}
stu[i].aver=(float)sum[i]/m;
}
}
//结构体
typedef struct student
{
long studentID;
char studentName[10];
char studentSex;
DATA birthday;
int score[4];
float aver;
int sum;
}STUDENT;
void AverScore(STUDENT stu[],int sum[],int n,int m)
{
int i,j,sum[N];
for(i=0;i<n;i++)
{
sum[i]=0;
for(j=0;j<m;j++)
{
sum[i]=sum[i]+stu[i].score[j];
}
stu[i].aver=(float)sum[i]/m;
}
}
void AverScore(STUDENT stu[],int n,int m)
{
int i,j;
for(i=0;i<n;i++)
{
stu[i].sum=0;
for(j=0;j<m;j++)
{
stu[i].sum=stu[i].sum+stu[i].score[j];
}
stu[i].aver=(float)stu[i].sum/m;
}
}
enum weeks {SUM,MON,TUE,WED,THU,FRI,SAT};
enum weeks {SUM=7,MON=1,TUE,WED,THU,FRI,SAT};
typedef enum weeks {SUM,MON,TUE,WED,THU,FRI,SAT}WEEKS;
enum weeks today;//定义
WEEKS today;//定义
1.传统数组的缺点
a.
数组长度必须事先制定,且只能是常整数,不能是变量
例子:
int a[5]; //OK
int len = 5; int a[len]; //error
b.
传统形式定义的数组,该数组的内存程序员无法手动释放
在一个函数运行期间,系统为该函数中数组所分配的空间会一直存在,知道该函数运行完毕,数组的空间才会被系统释放
# include
void f(void)
{
int a[5] = {1,2,3,4,5};
//20个字节的存储空间,程序员无法手动编程释放它,它只能在本函数运行完毕时由系统自动释放
}
int main(void)
{
return 0;
}
c.
数组的长度一旦定义,其长度就不能再更改
数组的长度不能在函数运行的过程中动态的扩充或缩小
d.
A函数定义的数组,在A函数运行期间可以被其他函数使用,但A函数运行完毕之后,A函数中的数组将无法在被其他函数使用
传统方式定义的数组不能跨函数使用
# include
void g(int * pArr, int len )
{
pArr[2] = 88; //pArr[2] ==a[2]
}
void f(void)
{
int a[5] = {1,2,3,4,5};//20个字节的存储空间程序员无法手动编程释放它,
g(a,5); //它只能在本函数运行完毕时由系统自动释放
printf("%d\n",a[2]);
}
int main(void)
{
f();
return 0;
}
2.为什么需要动态分配内存
动态数组很好地解决了传统数组的这4个缺陷
传统数组也叫静态数组
#include
#include //不能省
int main (void)
{
int i = 5; //分配了4个字节 静态分配 11行
int * p = (int *)malloc(4); //12行,malloc后面的括号里只能写一个不能写两个
/*
1.要使用malloc函数,必须添加 malloc.h 这个头文件
2.malloc函数只有一个形参,并且形参是整数
3. 4表示请求系统为本程序分配4个字节
4. malloc函数只能返回第一个字节的地址
5. 12行分配了8个字节,p变量占4个字节,p所指向的内存也占4个字节
6. p本身所占的内存是静态分配的,p所指向的内存是动态分配的
*/
* p = 5; //*p代表的就是一个int变量,只不过*p这个整型变量的内存分配和11行的 i 变量的分配方式不同
free(p); //free(p)表示把p所指向的内存给释放掉 p本身的内存是静态的,不能由程序员手动释放,p本身的内存只能在p变量所在的函数运行终止时由系统自动释放
printf ("同志们好!\n");
return 0;
}
# include
# include
void f(int * q)
{
// *p = 200; //error
// q = 200;
// **q = 200; //error
*q = 200;
// free (q); //把q所指向的内存释放掉 本语句必须注释掉,否则会导致第20行的代码出错
}
int main (void)
{
int * p=(int *)malloc (sizeof(int )); //sizeof (int )返回值是int 所占的字节数
*p = 10;
printf ("%d\n",*p); //200 第20行
return 0;
}
# include
# include
int main (void)
{
int a[5]; //如果int 占4个字节的话,则本数组总共包含有20个字节,每四个字节被当做了一个int 变量来使用
int len;
int * pArr;
int i;
//动态的构造一维数组
printf ("请输入你要存放的元素个数:");
scanf("%d",&len);
pArr = (int *)malloc(4*len); // 类似于int pArr [len]; 本行动态的构造了一个一维数组,该数组的长度是len,该数组的数组名是pArr,该数组的每个元素是int 类型
//对一维数组进行操作,如:对动态一维数组进行赋值
for(i=0;i
4.静态内存和动态内存的比较
5.跨函数使用内存的问题
例1:(静态内存不能跨函数使用)
# include
void f(int ** q) //q是个指针变量,无论q是什么类型的指针变量,都只占4个字节
{
int i=5;
//*q等价于p q和**q都不等价于p
//*q = i; //error 因为*q = i;等价于 p = i ;这样是错误的
*q = &i; // p = &i;
}
int main(void)
{
int *p; //13行
f(&p);
printf ("%d\n",*p); //16行 本语句语法没有问题,但逻辑上有问题
return 0;
}
例2:(动态函数可以跨函数使用)
# include
# include
void f(int **q)
{
*q = (int *)malloc(sizeof(int)); //sizeof(数据类型) 返回值是该数据类型所占的字节数
//等价于 p = (int *)malloc(sizeof(int));
// q=5;
// *q=5; //p = 5;
**q=5; //*p = 5; // 把动态内存更改为5个字节
}
int main(void)
{
int * p;
f(&p);
printf ("%d\n",*p);
return 0;
}
1.什么是枚举
把一个事物所有可能的取值一一列举出来
例1:
# include
//只定义了一个数据类型,并没有定义变量,该数据类型性的名字是enum WeekDay
enum WeekDay
{
MonDay,TuesDay,WednesDay,ThursDay,FfiDay,SaturDay,SunDay
};
int main (void)
{
//int day; //day定义成int类型不合适
enum WeekDay day = SunDay;
printf("%d\n",day);
return 0;
}
2.怎样使用枚举
例子:
# include
enum weekday
{
MonDay,TuesDay,WednesDay,ThursDay,FriDay,SaturDay,SunDay
};
void f(enum weekday i)
{
switch(i)
{
case 0:
printf ("MonDay!\n");
break;
case 1:
printf ("TuesDay!\n");
break;
case 2:
printf ("WednesDay!\n");
break;
case 3:
printf ("ThursDay!\n");
break;
case 4:
printf ("FriDay!\n");
break;
case 5:
printf ("SaturDay!\n");
break;
case 6:
printf ("SunDay!\n");
break;
}
}
int main (void)
{
f(FriDay);
return 0;
}
3.枚举的优缺点
优点:
代码更安全
缺点:
书写麻烦
1.原码
原码:
也叫 符号-绝对值码
最高位 0 表示正 1表示负,其余二进制位是该数字的绝对值的二进制位
原码简单易懂
加减运算复杂
存在加减乘除四种运算 ,增加了CPU的复杂度
零的表示不唯一
2.反码
反码运算不便,也没有在计算机中应用
3.移码
移码表示数值平移n 位,n称为移码量
移码主要用于浮点数的阶码的存储
4.补码
# include
int main(void)
{
int i=-3;
printf ("%#X\n",i); //用16进制输出 -3的补码
return 0;
}
//输出为:0XFFFFFFFD
# include
int main (void)
{
int i = 0XFFFFFFEF;
printf("%d\n",i);
return 0;
}
//输出结果为:-17
注:如果是负数,最高位一定是1
1.十进制转 r 进制
方法:除 r 取余,直至商0,余数倒序排列
2.r 进制转化为十进制
例:201(8)=18º + 08¹ + 2*8² = 129
3.二进制与十六进制的转化
二进制转化为十六进制
例:(0101110)(2)→(0010,1110)(2)左补一个0 →
(2 E)(16)
十六进制转化为二进制
例:(2E)(16)→(0010 1110)(2)
4.二进制与八进制
5.十六进制与八进制
1.算法
2.我们至少可以通过两种结构来存储数据
头结点
头结点的数据类型和首节点的类型是一模一样的
头结点是首节点前面的那个节点
头结点并不存放有效数据
设置头结点的目的是为了方便对链表的操作
头指针
存放头结点地址的指针变量
首节点
存放第一个有效数据的节点
尾结点
存放最后一个有效数据的节点
确定一个链表需要一个参数:
头指针
例1:
# include
//定义可一个链表节点的数据类型
struct Node
{
int data;
struct Node * pNext;
};
int main(void)
{
struct Node * pHead; //pHead用来存放链表头结点的地址
pHead = CreateList();
TraverseList(pHead);
return 0;
}
# include
# include
# include
struct Node
{
int data; //数据域
struct Node * pNext; //指针域
};
//函数声明
struct Node * create_list(void);
void traverse_list(struct Node *);
int main(void)
{
struct Node * pHead = NULL; //等价于 struct Node * pHead = NULL;
pHead = create_list(); //create_list()功能:创建一个非循环单链表,并将该链表的头结点的地址付给pHead
traverse_list(pHead);
return 0;
}
struct Node * create_list(void)
{
int len; //用来存放有效节点的个数
int i;
int val; //用来临时存放用户输入的结点的值
//分配了一个不存放有效数据的头结点
struct Node * pHead = (struct Node *)malloc(sizeof(struct Node));
if (NULL == pHead)
{
printf("分配失败, 程序终止!\n");
exit(-1);
}
struct Node * pTail = pHead;
pTail->pNext = NULL;
printf("请输入您需要生成的链表节点的个数: len = ");
scanf("%d", &len);
for (i=0; idata = val;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return pHead;
}
void traverse_list(struct Node * pHead)
{
struct Node * p = pHead->pNext;
while (NULL != p)
{
printf("%d ", p->data);
p = p->pNext;
}
printf("\n");
return;
}
# include
int main (void)
{
int i = 5;
int j = 7;
int k;
k = i & j;
printf ("5%d\n",k);
k = i && j;//k的值只能是1或0,因为&&是逻辑运算符,逻辑运算符的结果只能是1或者0
printf ("%d\n",k);
return 0;
}
//输出为:5 1
/* 5 : 0 1 0 1
7 : 0 1 1 1
& : 0 1 0 1-----5
*/
# include
int main (void)
{
int i = 3;
int j = 5;
int k;
k = i | j;
printf ("%d\n",k);
return 0;
}
//输出为:7
/* 3 : 0 0 1 1
5 : 0 1 0 1
| : 0 1 1 1-----7
*/
# include
int main (void)
{
int i = 3;
int k;
k =~i;
printf ("%d\n",k);
return 0;
}
//输出结果为7
^------按位异或
相同为零,不同为1
1^0 = 1
0^1 = 1
1^1 = 0
0^0 = 0
<<-----按位左移
i<< 3 表示把 i 的所有二进制左移三位,右边要补零
左移n位相当于乘以2的n次方,前提是数据不能丢失
面试题:
A. i = i * 8;
B. i = i << 3;
请问上述两个语句,哪个语句执行的速度快?
答案:B 快
例子:
# include
int main (void)
{
int i = 3;
int j = 5;
int k;
k = i<<1;
printf ("%d\n",k);
return 0;
}
//输出为:6
------按位右移
i >> 3 表示把 i 的所有二进制右移三位,左边一般是补零,当然也可能补1
右移n位相当于除以2的n次方,前提是数据不能丢失
面试题:
A. i = i / 8;
B. i = i >> 3;
请问上述两个语句,哪个语句执行的速度快?
答案:B 快