学习记录表

# 2021-10-27

1.

#include <stdio.h>

void main()
{
    printf("hello,word!\n");
}

2.

#include <stdio.h>
#include <math.h>

void main()
{
    double x, s;
    printf("input number:\n");
    scanf("%lf", &x);
    s = sin(x);
    printf("sin of %lf is %lf\n", x, s);
}

3.

C语言程序是由多个模块组成的,这些模块叫做函数!{函数(一个事件)}

C语言程序运行的步骤:
1. 编辑
 
 C语言文件通过VC++平台默认后缀名为.cpp

2.编译 就是将已编辑好的C语言程序翻译成二进制代码的过程。

如果程序有错,就需要重新编译;
如果程序无错,就会产生后缀名为.obj的目标文件。


3.连接 所有编译好的独立模块的目标代码与系统提供的标准模块(C语言标准函数库)进行连接,得到绝对地址的执行文件   .exe

4.执行!

语法:  #include<头文件名>
注意:
1.头文件一般以.h为后缀
2.导入头文件一般写在所有的代码上方
3.如果需要导入多个头文件,可以重复使用#include

main函数

函数是C语言中最基本的功能单元,因此C语言被称为函数语言。
函数是C语言中非常重要的组成部分,最常见的函数是main函数

main函数称为主函数,是所有C语言程序的入口,任何C语言程序都是从Main函数开始,在Main函数中结束。

每一个C语言程序,有且仅有一个Main函数。


printf函数

输出函数  程序的最基本功能

printf函数主要用于向屏幕上打印显示数据


语法:
         printf(“控制字符串”);

printf函数的格式控制符
2.换行  \n

2.制表位 \t

# 2021-10-28

1.C数据类型:
1)基本类型:基本数据类型最主要的特点是,其值不可以再分解为其他类型。也就是说,基本数据类型是自我说明的。
·整型
·字符型
·实型(浮点型){单精度型;双精度型}
·牧举类型
2)指针类型:指针是一种特殊的,同时又是具有重要的数据类型。其值用来表示某个变量在内存储器中的地址。虽然指针变量的取值类似于整型量,但这是两个类型完全不同的量,因此不能混为一谈
3)构造类型:构造数据类型是根据已定义的一个或多个数据类型用构造的方法来定义的。也就是说,一个构造类型的值可分解成若干个“成员”或“元素”。每个“成员”都是一个基本数据类型或又是一个构造类型。在C语言中,构造类型有以下几种:
·数组类型
·结构体类型
·共用体(联合)类型
4)空类型:在调用函数值时,通常应向调用者返回一个函数值。这个返回的函数值是具有一定的数据类型的,应在函数定义及函数说明中给以说明,例如在例题中给出的max函数定义中,函数头为:int max(int a,int b);其中“int”类型说明符即表示该函数的返回值为整型量。但是,也有一类函数,调用后并不需要向调用者返回函数值,这种函数可以定义为“空类型”其类型说明为void。

2.

常量与变量
在程序执行过程中,其值不发生改变的量称为常量,其值可变的量称为变量。 
    一个变量应该有个名字,在内存中占据一定的存储单元。变量定义必须放在变量使用之前。一般放在函数体的开头部分。要区分变量和变量值是两个不同的概念。 

整型数据
整型常量就是整常数(八进制,十进制,十六进制)
整型变量

内存中的二进制存储(一个字节BYTE=8位bit)
10  00000101
-10 11110110  (第一位是符号位)0是正数,1是负数

整型变量
定义:一般形式:类型说明符、变量名标识符、变量名标识符,...
注意:
·允许在一个类型说明符后,定义多个相同类型的变量。各变量名之间用“,”号间隔。类型说明符与变量名之间至少用一个空格间隔
·最后一个变量名之后必须以“;”号结尾
·变量定义必须放在变量使用之前。一般放在函数体的开头部分

例:
#include <stdio.h>
void main()
{
 int a,b;
 a=32767;
 b=a+1;
 printf("%d,%d\n",a,b);
}
32767: 0111111111111111
-32768: 1000000000000000 


实型数据
实型常量的表示方法
实型也称为浮点型。实型常量也称为实数或者浮点数。在C语言中,实数只采用十进制。它有二种形式:十进制小数形式,指数形式。

存放形式
1)实型数据一般占4个字节(32位)内存空间。按指数形式存储。实数3.14159在内存中的存放形式如下
符号:+    小数部分:.314159  指数部分:1
·小数部分占的位(bit)数愈多,数的有效数字愈多,精度愈高
·指数部分占的位数愈多,则能表示的数值范围愈大
float 32bit=1bit符号位+23bit小数位+8bit指数位

2)实型变量分为:单精度(float型)、双精度(double型)和长双精度(long double型)三类。
#include <stdio.h>
void main()
{
 printf("%d\n",sizeof(float));
}

3.

#include <stdio.h>
#define PRICE 30
void main()
{
 int num,total;
 num=10;
 total=num*PRICE;
 printf("total=%d\n",total);
}

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

 #include <stdio.h>
void main()
{
 printf("%d\n",sizeof(short));
}

 #include <stdio.h>
void main()
{
 printf("%d\n",sizeof(float));
}

 #include <stdio.h>
void main()
{
 int a,b,c,d;
 unsigned u;
 a=12;
 b=-24;
 u=10;
 c=a+u;
 d=b+u;
 printf("a+u=%d,b+u=%d\n",c,d);
}

ㅤ:
#include <stdio.h>
void main()
{
    int a,b;
    a=32767;
    b=a+1;
    printf("%d,%d\n",a,b);
}

ㅤ:
[图片]

 #include <stdio.h>
void main()
{
 short int a,b;
 a=32767;
 b=a+1;
 printf("%d,%d\n",a,b);
}

 #include <stdio.h>
void main()
{
 long x,y;
 int a,b,c,d;
 x=5;y=6;a=7;b=8;c=x+a;d=y+b;
 printf("c=x+a=%d,d=y+b=%d\n",c,d);
}

# 2021-10-29

1.

各类数值型数据之间的混合运算
变量的数据类型是可以转换的。转换的方法有两种,一种是自动转换,一种是强制转换。自动转换发生在不同数据类型的混合运算时,由编译系统自动完成。自动转换遵循以下规则:
1)若参与运算量类型不同,则先转换成同一类型,然后进行运算
2)转换按数据长度增加的方向进行,以保证精度不降低。如int和long型运算时,先把int量转换成long型后再进行运算
3)所有的浮点运算都是以双精度进行的,即使仅含float单精度量运算的表达式,也要先转换成double型,再作运算
4)char型和short型参与运算时,必须先转换成int型
5)在赋值运算中,赋值号两边量的数据类型不同时,赋值号右边量的类型将转换左边量的类型。如果右边量的数据类型长于左边长时,将丢失一部分数据,这样会降低精度,丢失的部分按四舍五入向前舍入。


#include <stdio.h>
void main()
{
    float PI=3.14159;
    int s,r=5;
    s=r*r*PI;
    printf("s=%d\n",s);
}

本例程序中,PI为实型;s,r为整型。在执行s=r*r*PI语句时,r和PI都转换成double型计算,结果也为double型。但由于s为整型,故赋值结果仍为整型,舍去了小数部分

强制类型转换是通过类型转换运算实现的。
一般形式为:
(类型说明符)(表达式)
其功能是把表达式的运算结果强制转换成类型说明符所表示的类型
例如:(float)a;(int)(x+y)把x+y的结果转换为整型
注意:无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类型

例:
#include <stdio.h>
void main()
{
 float f=5.75;
 printf("(int)f=%d,f=%f\n",(int)f,f);
}

2. 基本的算术运算符
·加法运算符“+”:加法运算符为双目运算符,即应有两个量参与加法运算。如a+b,4=8。具有右结合性
·减法运算符“-”:减法运算符为双目运算符。但“-”也可作赋值运算符,此时为单目录运算,如-x,-5等,具有左结合性
·乘法运算符“*”:双目运算,具有左结合性
·除法运算符“/”:双目运算具有左结合性。参与运算量均为整型时,结果也为整型,舍去小数。如果运算量中有一个是实型,则结果为双精度实型
·求模运算符“%”
#include <stdio.h>
void main()
{
    printf("%d\n",3/2);
}
运行结果为1
#include <stdio.h>
void main()
{
    printf("%d\n",3/4);
}
运行结果为0

例:
1)#include <stdio.h>
void main()
{
    printf("%d,%d\n",20/7,-20/7);
    printf("%f,%f\n",20.0/7,-20.0/7);
}

 2)#include <stdio.h>
void main()
{
    printf("%d\n",100%3);
}
3)#include <stdio.h>
void main()
{
    printf("7÷2=%d……%d\n",7/2,7%2);
}

算术运算符和算术表达式
·运算符的优先级:C语言中,运算符的运算优先级共分为15级。1级最高,15级最低。在表达式中,优先级较高的先于优先级较低的进行运算。而在一个运算量两侧的运算符优先级相同时,则按运算的结合性所规定的结合方向处理。
·运算符的结合性:C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。例如算术运算符的结合性是自左至右,即先左后右。如有表达式x-y+z则y应与“-”号结合,执行x-y运算,然后再执行+z的运算。这种自左至右的结合方向就称为“左结合性”。而自右至左的结合方向称为“左结合性”。最典型的右结合性运算符是赋值运算符。如x=y=z,由于“=”的右结合性,应先执行y=z再执行x=(y=z)运算。C语言运算符中有不少为右结合性,应注意区,避免理解错误。 

自增1,自减1运算符:自增1运算符记为“++”,其功能是使变量的值自增1。
自增1运算符记为“--”,其功能是使变量的值自减1。
自增1,自减1运算符均为单目录运算,都具有右结合性

++i:i自增1后再参与其他运算
--i:i自减1后再参与其他运算
i++:i参与运算后,i的值再自增1
i--:i参与运算后,i的值再自减1

例:
1)#include <stdio.h>
void main()
{
    int i=8;
    printf("%d\n",++i);
    printf("%d\n",--i);
    printf("%d\n",i++);
    printf("%d\n",i--);
    printf("%d\n",-i++);
    printf("%d\n",-i--);
}

 2)#include <stdio.h>
void main()
{
    int i=5,j=5,p,q;
    p=(i++)+(i++)+(i++);
    q=(++j)+(++j)+(++j);
    printf("%d,%d,%d,%d\n",p,q,i,j);
}

 

赋值运算符
简单赋值运算符和表达式:简单赋值运算符记为“=”。由“=”连接的式子称为赋值表达式。一般形式:变量=表达式

例:
#include <stdio.h>
void main()
{
    int a,b=322;
    float x,y=8.88;
    char cl='k',c2;
    a=y;x=b;a=cl;c2=b;
    printf("%d,%f,%d,%c\n",a,x,a,c2);
}

复合的赋值运算符
在赋值符“=”之前加上其它二目运算符可构成复合赋值符。如+=,-=,*=,/=,<<=,>>=,&=,^=,!=。如a+=5:a=a+5;x*=y+7:x=x*(y+7);r%=p:r=r%p

逗号运算符和逗号表达式
例:
#include <stdio.h>
void main()
{
    int a=2,b=4,c=6,x,y;
    y=(x=a+b),(b+c);
    printf("y=%d,x=%d\n",y,x);
}

练习:

1.#include <stdio.h>
void main()
{
    printf("I love FishC.com!\n");
}

 2.

#inc1ude <stdio.h>

int main()
{
        printf("Hello World!\n");
        return 0;
}

预编译命令错误

#include <stdio.h> 

3.

#include <stdio.h>

int main()
{
        printf(“小甲鱼说:好好学习才能天天向上!”);
        return 0;
}

 引号和逗号用的是中文的

4.代码写成下边这样,能正常编译运行吗?

可以,如下图

 

5. 写一个 printf 函数,要求在屏幕上打印下边内容:

搜狗截图20151124034358.png

#include <stdio.h>

void main()
{
    printf("[fishc@localhost sle2]$ ./test\n Fishc.com no 'fish'\n");
}

 3.

顺序程序设计
从程序流程的角度来看,程序可以分为三种基本结构,即顺序结构、分支结构、循环结构。这三种基本结构可以组成所有的各种复杂程序。C语言提供了多种语句来实现这些程序结构。

C语句可分为以下五类:
1)表达式语句:表达式语句由表达式加上分号“:”组成。执行表达式语句就是计算机表达式的值。例y=x+z 赋值语句;y+z 加法语句,但计算结果不能保留,实际无意义;i++ 自增语句,i增值1。

2)函数调用语句:由函数名、实际参数加上分号“:”组成。函数名(实际参数赛)执行函数语句就是用调用函数体并把实际参数赋予函数定义中的形式参数,然后执行被调用函数体中的语句,求取函数值。例printf(“C Drogram”);调用库函数,输出字符串

3)控制语句:控制语句用于控制程序的流程,以实现程序的各种结构方式。它们由特定的语句定义符组成。C语言有九种控制语句。可分成以下三类:条件判断语句:if语句、switch语句;循环执行语句:do while语句、while语句、for语句;转向语句:break语句、goto语句、continue语句、return语句。

4)复合语句:把多个语句用括号{}扩起来组成的一个语句称复合语句。在程序中应把复合语句看成是单条语句,而不是多条语句。
例{
    x=y+z;
    a=b+c;
    printf("%d%d",x,a);        
  }    
是一条复合语句。复合语句内的各条件都必须以分号“;”结尾,在括号“{}”外不能加分号

5)空语句:只有分号“;”组成的语句称为空语句。空语句是什么也不执行的语句。在程序中空语句可用来作空循环体。

    while(getchar()!='\n')
{
    ;
}    
本语句的功能是,只要从键盘输入字符不是回车则重新输入。这里的循环体为空语句。


putchar函数(字符输出函数)
putchar函数是字符输出函数,其功能是在显示器上输出单个字符。
putchar(字符变量),例putchar('A'):输出大写字母A

例题:
1)#include <stdio.h>
void main()
{
    char a='B',b='o',c='k';
    putchar(a);putchar(b);putchar(b);putchar(c);putchar('\t');
    putchar(a);putchar(b);
    putchar('\t');
    putchar(b);putchar(c);
}

2)#include <stdio.h>
void main()
{
    char c;
    printf("input a character\n");
    c=getchar();
    putchar(c);
}

3)#include <stdio.h>
void main()
{
    int a=88,b=89;
    printf("%d %d\n",a,b);
    printf("%d,%d\n",a,b);
    printf("%c,%c\n",a,b);
    printf("a=%d,b=%d\n",a,b);
}

格式字符串

 

例题:
#include <stdio.h>
void main()
{
    int a=15;
    float b=123.1234567;
    double c=12345678.1234567;
    char d='p';
    printf("a=%d,%5d,%o,%x\n",a,a,a,a);
    printf("b=%f,%lf,%5.4lf,%e\n",b,b,b,b);
    printf("c=%lf,%f,%8.4lf\n",c,c,c);
    printf("d=%c,%8c\n",d,d);
}

格式输入与输出
使用printf函数时还需要注意一个问题,那就是输出表列这中的求值顺序。不同的编译系统不一定相同,可以从左到右,也可以从右到左。Turbo C是按从右到左进行的。

例题
1)#include <stdio.h>
void main()
{
    int i=8;
    printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i++,i--,-i++,-i--);
}
2)#include <stdio.h>
void main()
{
    int i=8;
    printf("%d\n",++i);
    printf("%d\n",--i);
    printf("%d\n",i++);
    printf("%d\n",i--);
    printf("%d\n",-i++);
    printf("%d\n",-i--);
}


这两个程序的区别是用一个printf语句和多个printf语句输出。从结果可以看出是不同的

2021-10-30

1.

1.scanf函数称为格式输入函数,即按用户指定的格式从键盘上把数据输入到指定的变量之中。一般形式:scanf("格式控制字符串",地址列表); 地址是由地址运算符“&”后跟变量名组成。


变量的地址和变量值的关系如下:
在赋值表达式中给变量赋值,如:
a=567
则,a为变量名,567是变量的值,&a是变量a的地址
&是一个取地址运算符

例:
#include <stdio.h>
void main()
{
    int a,b,c;
    printf("input a,b,c\n");
    scanf("%d%d%d",&a,&b,&c);
    printf("a=%d,b=%d,c=%d\n",a,b,c);
}

格式字符串:

 例:
#include <stdio.h>
void main()
{
    char a,b;
    printf("input character a and b:\n");
    scanf("%c %c",&a,&b);
        printf("%c %c\n",a,b);
}

如果格式控制串中有非格式字符则输入时也需要输入该非格式字符
例:sacnf("%d,%d,%d",&a,&b,&c);    其中用非格式符“,”故输入时应为:5,6,7

例题:
1)#include <stdio.h>
void main()
{
    int a;
    printf("input a number\n");
    scanf("%d",&a);
    printf("%ld\n",a);

}

 2)#include <stdio.h>
void main()
{
    long a;
    printf("input a long integer\n");
    scanf("%ld",&a);
    printf("%ld\n",a);
}

题目:输入三个小写字母,输出其ASSII码和对应的大写字母
#include <stdio.h>
void main()
{
    char a,b,c;
    printf("input character a,b,c\n");
    scanf("%c %c %c",&a,&b,&c);
    printf("%d,%d,%d\n%c,%c,%c\n",a,b,c,a-32,b-32,c-32);
}

 题目:输出各种数据类型的字节长度

#include <stdio.h>
void main()
{
    int a;
    long b;
    float f;
    double d;
    char c;
    printf("int:%d\nlong:%d\nfloat:%d\ndouble:%d\nchar:%d\n",sizeof(a),sizeof(b),sizeof(f),sizeof(d),sizeof(c));
}

输入三角形的三边长,求三角形面积。已知三角形三边长a,b,c。s=(a+b+c)/2
#include <stdio.h>
#include <math.h>
void main()
{
    double a,b,c,s,area;
    scanf("%lf,%lf,%lf",&a,&b,&c);
    s=1.0/2*(a+b+c);
    area=sqrt(s*(s-a)*(s-b)*(s-c));
    printf("a=%7.2f,b=%7.2f,c=%7.2f,s=%7.2f\n",a,b,c,s);
    printf("area=%7.2f\n",area);
}

 

 题目

 #include <stdio.h>
#include <math.h>
void main()
{
    double a,b,c,disc,x1,x2,p,q;
    scanf("a=%f,b=%f,c=%f",&a,&b,&c);
    disc=b*b-4*a*c;
    p=-b/(2*a);
    q=sqrt(disc)/(2*a);
    x1=p+q;
    x2=p-q;
    printf("x1=%5.2f\nx2=%5.2f\n",x1,x2);
}

 

 2.分支程序设计

关系运算符和表达式
关系运算符:在程序中经常需要比较两个量的大小关系,以决定程序下一步的工作。比较两个量的运算符称为关系运算符

运算符的优先级

1)<小于;2)<=小于或等于;3)>大于;4)>=大于或等于;5)==等于;6)!=不等于

C语言中关系运算符都是双目运算,其结合性均为左结合。关系运算符的优先级低于算术运算符,高于赋值运算符。在六个关系运算符中,前四个<,<=,>,>=的优先级相同,高于==和!=,==和!=的优先级相同。

关系表达式一般形式:
表达式 关系运算符 表达式

关系表达式的值是“真”和“假”,用“1”和“0”表示。
如:
5>0的值为“真”,即为1    i=(5>0),i=1
(a=3)>(b=5)由于3>5不成立,故其值为假,即为0。

例题:
#include <stdio.h>
void main()
{
    char c='k';
    int i=1,j=2,k=3;
    float x=3e+5,y=0.85;
    printf("%d,%d\n",'a'+5<c,-i-2*j>k+1);
    printf("%d,%d\n",1<j<5,x-5.25<=x+y);
    printf("%d,%d\n",i+j+k==-2*j,k==j==i+5);
}

在使用if语句中还应该注意:
1)在三种形式的if语句中,在if关键字之后均为表达式。该表达式通常是逻辑表达式或关系表达式,但也可以是其他表达式,如赋值表达式等,甚至也可以是一个变量
例:if(a=5)语句;
if(b)语句;
都是允许的。只要表达式的值为非0,即为“真”
#include <stdio.h>
void main()
{
    int a;
    a=3;
    if (a==3)
    {
        printf("a equals 3!!\n");
    }
    else
    {
        printf("a is %d\n",a);
    }
}


#include <stdio.h>
void main()
{
    int a;
    a=2;
    if (a==3)
    {
        printf("a equals 3!!\n");
    }
    else
    {
        printf("a is %d\n",a);
    }
}

 

2)在if语句中,条件判断表达式必须用括号扩起来,在语句之后必须加分号。
3)在if语句的三种形式中,所有的语句应为单个语句,如果要想在满足条件事执行一组(多个)语句,则必须把这一组语句用{}括起来组成一个复合语句。但要注意的是在}之后不能加分号。
例如:if(a>b)
{
    a++;
    b++;
}
else
{
    a=0;
    b=10;
}

题目:写一个程序完成下列功能:
1.输入一个分值score
2.score<60     输出E
3.60<=score<70    输出D
4.70<=score<80    输出C
5.80<=score<90    输出B
6.<=score    输出A
#include <stdio.h>
void main()
{
    int score;
    printf("Please input a score: ");
    scanf("%d",&score);
    if(score<60)
    {
        printf("The score is E!\n");
    }
    else if( (score>60 || score==60) && score<70)
    {
        printf("The score is D!\n");
    }
    else if( (score>70 || score==70) && score<80)
    {
        printf("The score is C!\n");
    }
    else if( (score>80 || score==80) && score<90)
    {
        printf("The score is B!\n");
    }
    else
    {
        printf("The score is A!\n");
    }
}

2)补充例题2:输入三个数a,b,c,要求按由小到大的顺序输出。
提示:
if a>b 将a和b对换
if a>c 将a和c对换
if b>c 将b和c对换
#include <stdio.h>
void main()
{
    int a,b,c,temp;
    printf("Please input three num: ");
    scanf("%d %d %d",&a,&b,&c);
    if( a > b)
    {
        temp = a;
        a = b;
        b = temp;
    }
    if( a > c )
    {
        temp = a;
        a = c;
        c = temp;
    }
    if( b > c)
    {
        temp =b;
        b = c;
        c = temp;
    }
    printf("%d %d %d \n",a,b,c);
}
2)补充例题2:输入三个数a,b,c,要求按由小到大的顺序输出。
提示:
if a>b 将a和b对换
if a>c 将a和c对换
if b>c 将b和c对换
#include <stdio.h>
void main()
{
    int a,b,c,temp;
    printf("Please input three num: ");
    scanf("%d %d %d",&a,&b,&c);
    if( a > b)
    {
        temp = a;
        a = b;
        b = temp;
    }
    if( a > c )
    {
        temp = a;
        a = c;
        c = temp;
    }
    if( b > c)
    {
        temp =b;
        b = c;
        c = temp;
    }
    printf("%d %d %d \n",a,b,c);
}

#2021-11-01

if语句的嵌套
当if语句中的执行语句又是if语句时,则构成了if语句嵌套的情形。
一般形式如下:
if(表达式)
if语句;        if()
            {
                if()
                ......;
            }

if(表达式)        if()
if语句;            if()语句1;
else                else  语句2;
if语句;        else
                if()语句3;
                else  语句4;


在嵌套内的if语句可能又是if-else型的,这将会出现多个if和多个else重叠的情况,这时要特别注意if和else的配对问题。
例如:
    if(表达式1)
    if(表达式2)
       语句1;
    else
       语句2;

else与哪一个if配对??
就近配对

为了避免这种二义性,C语言规定,else总是与它前面最近的if配对。
例题:1)

#include <stdio.h>
void main()
{
	int a,b;
	printf("please input A,B: ");
	scanf("%d %d",&a,&b);
	if(a!=b)
		if(a>b) printf("A>B\n");
		else printf("A<B\n");
		else printf("A=B\n");
}

2)

#include <stdio.h>
void main()
{
	int a,b;
	printf("please input A,B: ");
	scanf("%d %d",&a,&b);
	if(a==b) printf("A=B\n");
		else if(a>b) printf("A>B\n");
		else printf("A<B\n");
}

采用嵌套结果实质上是为了进行多分支选择,实际上有三种选择即A>B、A<B或A=B。这种问题用if-else-if语句也可以完成。而且程序更加清晰。因此,在一般情况下较少使用if语句的嵌套结构。以使程序更便于阅读理解。


2.条件运算符为“?”和“:”,它是一个三目运算符,即有三个参与运算的量。
由条件运算符组成条件表达式的一般形式:
表达式1?表达式2:表达式3
其求值规则为:如果表达式1的值为真,则以表达式2的值作为条件表达式的值,否则以表达式2的值作为整个条件表达式的值

条件表达式通常用于赋值语句中。
例:
if(a>b) max=a;
    else max=b;
条件表达式
max=(a>b)?a:b;
执行该语句的语义是:如果a>b为真,则把a赋予max,否则把b赋予max。

注意
1)条件运算符的运算优先级低于关系运算符和算术运算符,但高于赋值运算符。
2)条件运算符?和:,是一对运算符,不能分开使用。
3)条件运算符的结合方向是自右向左。
 

#include <stdio.h>
void main()
{
	int a,b,max;
	printf("input two numbers: ");
	scanf("%d %d",&a,&b);
	printf("max=%d\n",a>b?a:b);
}

题目:输入一个字符,判断它是否大写字母,如果是,将它转换成小写字母;如果不是,不转换。然后输出最后得到的字符。

#include <stdio.h>
void main()
{
	char ch;
	printf("input a character: ");
	scanf("%c",&ch);
	ch=(ch>'A'&&ch<'Z')?(ch+32):ch;
	printf("%c\n",ch);
}

3.switch语句
switch是另外一种定义分支选择语句,一般形式:
switch(表达式){
case常量表达式1:语句1;
case常量表达式2:语句2;
case常量表达式3:语句3;
...
case常量表达式n:语句n;
default        :语句n+1;
}
其语义是:计算表达式的值。并逐个与其后的常量表达式值相比较,当表达式的值与某个常量表达式的值相等时,即执行其后的语句,然后不再进行判断,继续执行后面所有case后的语句。如表达式的值与所有case后的常量表达式均不相同时,则执行default后的语句。

例:

#include <stdio.h>
void main()
{
	int a;
	printf("input interger number: ");
	scanf("%d",&a);
	switch(a)
	{
	case 1:printf("Monday\n");break;
	case 2:printf("Tuesday\n");break;
	case 3:printf("Wednesday\n");break;
	case 4:printf("Thursday\n");break;
	case 5:printf("Friday\n");break;
	case 6:printf("Saturday\n");break;
	case 7:printf("Sunday\n");break;
	default:printf("error\n");
	}
}

注意:
1)在case后的各常量表达式的值不能相同,否则会出现错误
2)在case后,允许有多个语句,可以不用{}括起来
3)各case和default子句的先后顺序可以变动,而不会影响程序执行结果
4)default子句可以省略不用
 

题目:

1)输入三个整数,输出最大数和最小数。

#include <stdio.h>
void main()
{
	int a,b,c,max,min;
	printf("input three numbers: ");
	scanf("%d %d %d",&a,&b,&c);
	if(a>b)
	{
		max=a;
		min=b;
	}
	else
	{
		max=b;
		min=a;
	}
	if(max<c)
	{
		max=c;
	}
	else if(min>c)
	{
		min=c;
	}
	printf("max=%d,min=%d\n",max,min);
}

2)计数器程序。用户输入运算数和四则运算符,输出计算结果。

#include <stdio.h>
void main()
{
	double a,b;
	char c;
	printf("input experssion: a+(-,*,/)b \n");
	scanf("%lf%c%lf",&a,&c,&b);
	switch( c )
	{
	case '+':printf("%lf\n", a + b );break;
	case '-':printf("%lf\n", a - b );break;
	case '*':printf("%lf\n", a * b );break;
	case '/':printf("%lf\n", a / b );break;
	default:printf("input errof!\n");
	}
}

作业:

1)输入一个年份,判断是否为闰年?

#include <stdio.h>
void main()
{
	int year,leap;  //leap是判断闰年的标准,值为1表示闰年,为0表示非闰年。
	printf("Please enter a year: ");
	scanf("%d",&year);
	if(year%4==0)
	{
		if(year%100==0)
		{
			if(year%400==0)
			{
				leap=1;
			}
			else
			{
				leap=0;
			}
		}
		else
		{
			leap=1;
		}
	}
	else
	{
		leap=0;
	}
	if(leap)
	{
		printf("%d is",year);
	}
	else
	{
		printf("%d is not",year);
	}

	printf(" a leap year.\n");

}

2)运输公司对用户计算运费
路程(s)越远,每公里运费越低。标准如下:
 s    < 250 km        没有折扣
 250  <= s < 500    2%折扣    
 500  <= s < 1000    5%折扣
 1000 <= s < 2000    8%折扣
 2000 <= s < 3000    10%折扣
 3000 <= s        15%折扣
设每公里每吨货物的基本运费为p,货物重为w,距离为s,折扣为d,则总运费f的计算公式为:
f=p*w*s*(1-d)

#include <stdio.h>
void main()
{
	int c,s;
	float p,w,d,f;
	scanf("%f,%f,%d",&p,&w,&s);
	if(s>=3000)
	{
		c=12;
	}
	else
	{
		c=s/250;
	}
	switch(c)
	{
	case 0:
		d=0;break;
	case 1:
		d=2;break;
	case 2:
	case 3:
		d=5;break;
	case 4:
	case 5:
	case 6:
	case 7:
		d=8;break;
	case 8:
	case 9:
	case 10:
	case 11:
		d=10;break;
	case 12:
		d=15;break;
	}
	f=p*w*s*(1-d/100.0);
	printf("freight=%15.4f\n",f);
}

#2021-11-02

循环:循环结构是程序中一种很重要的结构。其特点是,在给定的条件成立时,反复执行某程序段,直到条件不成立为止。给定的条件称为循环条件,反复执行的程序段称为循环体。C语言提供了多种循环语句,可以组成各种不同形式的循环结构。
1)用goto语句和if语句构成循环;
2)用while语句;
3)用do-while语句;
4)用for语句;

goto语句以及goto语句构成循环
goto语句是一种无条件转移语句,与BASIC中的goto语句相似。goto语句使用格式为:
goto 语句标号;

其中标号是一个有效的标识符,这个标识符加上一个“:”一起出现在函数内某处,执行goto语句后,程序将跳转到该标号处并执行其后的语句。另外标号必须与goto语句同处于一个函数中,但可以不在一个循环层中。通常goto语句与if条件语句连用,当满足某一条件时,程序跳转到标号处运行。
但是注意:goto语句通常不用,主要因为它将使程序层次不清,且不易懂,但在多次嵌套退出时,用goto语句则比较合理。


例:用goto语句和if语句构成循环

#include <stdio.h>
void main()
{
	int i,sum=0;
	i=1;
loop:if(i<=100)
	  {
		  sum=sum+i;
		  i++;
		  goto loop;
	  }

	  printf("%d\n",sum);
}

输出结果为5050

while语句的一般形式:
while(表达式)语句
其中表达式是循环条件,语句为循环体
    while语句的语义是:计算表达式的值,当值为真(非0)时,执行循环体语句。

注意:如果表达式的值一开始就为0,则语句一次也不会被执行。
 

#include <stdio.h>
void main()
{
	int i,sum=0;
	i=1;
	while(i<=100)
	  {
		  sum=sum+i;
		  i++;
	  }

	  printf("%d \n",sum);
}

输出结果为5050

题目:统计从键盘输入一行字符的个数。

#include <stdio.h>
void main()
{
	int n=0;
		printf("input a string: \n");
		while(getchar()!='\n')
		{
			n++;
		}
		printf("%d\n",n);
}

本例程序中的循环条件为getchar()!='\n',其意义是,只要从键盘输入的字符不是回车就继续循环。循环体n++完成对输入字符个数计数。从而程序实现了对输入一行字符的字符个数计数。

#2021-11-03

使用while语句应注意以下几点:
1)while语句中的表达一般是关系表达式或逻辑表达式,只要表达式的值为真(非0)即可继续循环。

#include <stdio.h>
void main()
{
	int a=0,n;
	printf("input n: ");
	scanf("%d",&n);
	while(n--)
	{
		printf("%d\n",a++*2); //a==*2相当于a*2;a++
	}
}

2)循环体如包括有一个以上的语句,则必须用{}括起来,组合复合语句

do-while语句的一般形式为:
    do
       语句
    while(表达式);
这个循环与while循环的不同在于:它先执行循环体中的语句,然后再判断表达式是否为真,如果为真则继续循环;如果为假,则终止循环。因此,do-while循环至少要执行一次循环语句。

#include <stdio.h>
void main()
{
	int i,sum=0;
	i=1;
	do
	  {
		  sum=sum+i;
		  i++;
	  }while(i<=100);
	  printf("%d\n",sum);
}

输出结果5050

while和do-while循环比较

#include <stdio.h>
void main()
{
	int i,sum=0;
	scanf("%d",&i);
	while(i<=10)
	  {
		  sum=sum+i;
		  i++;
	  }
	  printf("%d\n",sum);
}

#include <stdio.h>
void main()
{
	int i,sum=0;
	scanf("%d",&i);
	do
	  {
		  sum=sum+i;
		  i++;
	  }while(i<=10);
	  printf("%d\n",sum);
}

for语句
在C语言中,for语句使用最为灵活,它完全可以取代while语句。一般形式为:
for(表达式1;表达式2;表达式3)语句
它的执行过程如下:
1)先求解表达式1
2)求解表达式2,若其值为真(非0),则执行for语句中指定的内嵌语句,然后执行下面第3)步;若其值为假(0),则结束循环,转到第5)步
3)求解表达式3
4)转回上面第2)步继续执行
5)循环结束,执行for语句下面的一个语句

for语句最简单的应用形式也是最容易理解的形式如下:
    for(循环变量赋初值;循环条件;循环变量增量)语句
循环变量赋初值总是一个赋值语句,它用来给循环控制变量赋初值;循环条件是一个关系表达式,它决定什么时候退出循环;循环变量增量,定义循环控制变量每循环一次后按什么方式变化。这三部分之间用;分开。
 

for(i=1;i<=100;i++)
	{
		sum=sum+i;
	}

先给i赋初值1,判断i是否小于等于100,若是则执行语句,之后值增加1.再重新判断,直到条件为假,即i>100时,结束循环。

#include <stdio.h>
void main()
{
	int i,sum=0;
	for(i=1;i<=100;i++)
	  {
		  sum=sum+i;
	  }
	  printf("%d\n",sum);
}

 输出结果为5050

注意:
1)for循环中的“表达式1(循环变量初值)”、“表达式2(循环条件)”和“表达式3(循环变量增量)”都是选择项,即可以缺省,但“;”不能缺省。
2)省略了“表达式1(循环变量赋初值)”,表示不对循环控制变量赋初值。
3)省略了“表达式2(循环条件)”,则不做其他处理时便成为死循环。

for(i=1;;i++)
{
	sum=sum+i;
}

4)省略了“表达式3(循环变量增量)”,则不对循环控制变量进行操作,这时可在语句体中加入修改循环控制变量的语句。

for(i=1;i<=100;)
{
	sum=sum+i;
	i++;
}

5)省略了“表达式1(循环变量赋初值)”和“表达式3(循环变量增量)”。

for(;i<=100;)
{
	sum=sum+i;
	i++;
}

6)3个表达式都可以省略。
例如:
for(;;)语句
相当于:
while(1)语句

7)表达式1可以是设置循环变量的初值的赋值表达式,也可以是其他表达式。

for(sum=0;i<=100;i++)
	sum=sum+i;

8)表达式1和表达式3可以是一个简单表达式也可以是逗号表达式。

for(sum=0,i=1;i<=100;i++)	sum=sum+i;
或
for(i=0,j=100;i<=100;i++,j--)	k=i+j;

9)表达式2一般是关系表达式或逻辑表达式,但也可是数值表达式,只要其值非零,就执行循环体。

例如:

for(i=0;(c=getchar())!=‘\n’;i+=c);
又如:
for(;(c=getchar())!=‘\n’;)
{
	printf("%c",c);
}

例题:

#include <stdio.h>
void main()
{
	int i,j,k;
	printf("i j k\n");
	for(i=0;i<2;i++)
		for(j=0;j<2;j++)
			for(k=0;k<2;k++)
				printf("%d %d %d\n",i,j,k);
}

 输出结果为:

i j k
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

 循环的嵌套
问题:输出以下图形
*
**
***
****
*****
******
分析vs提示:一共6行,每行的‘*’数目与行号相同

#include <stdio.h>
void main()
{
	int i,j;
	for(i=1;i<7;i++)
	{	
		for(j=1;j<=i;j++)
		{
			putchar('*');
		}
		printf("\n");
	}
}

输出结果为:

*
**
***
****
*****
******

#2021-11-04

几种循环的比较
1)四种循环都可以用来处理同一问题,一般情况下它们可以互相代替。但一般不提倡用goto循环。
2)在while循环和do-while循环中,只在while后面的括号内指定循环条件,因此为了使循环能正常结束,应在循环体中包含使循环体趋于结束的语句(如i++,或i=i+1等)。
for循环可以在表达式3中包含使循环趋于结束的操作,甚至可以将循环体中的操作全部放到表达式3中。因此for语句的功能更强凡用while能完成的,用for循环都能实现。
3)用while和do-while循环时,循环变量初始化的操作应在while和do-while语句之前完成而for语句可以在表达式1中实现循环变量的初始化。
4)while循环、do-while循环和for循环,可以用break语句跳出循环,用continue语句结束本次循环。而对用goto语句和if语句构成的循环,不能用break语句和continue语句进行控制。

例题:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4.组成所有的排列后再去掉不满足条件的排列。

#include <stdio.h>

void main()

{
	int i,j,k;
	for(i=1;i<5;i++)
	{
		for(j=1;j<5;j++)
		{
			for(k=1;k<5;k++);
			{
		 		if(i!=k&&i!=j&&j!=k) /*确保i、j、k三位互不相同*/
					printf("%d,%d,%d\n",i,j,k);
			}
		}
	}
}

输出结果:

1,2,5
1,3,5
1,4,5
2,1,5
2,3,5
2,4,5
3,1,5
3,2,5
3,4,5
4,1,5
4,2,5
4,3,5

break和continue语句
break语句可以用来从循环体内跳出循环体,即提前结束循环,接着执行循环下面的语句
一般形式:
    break;
break语句不能用于循环语句和switch语句之外的任何其他语句中
注意:
1)break语句对if-else的条件语句不起作用
2)在多层循环中,一个break语句只向外跳一层
例:

#include <stdio.h>
void main()

{
	int r;
	float pi=3.14159,area;
	for(r=1;r<=10;r++)
	{
		area=pi*r*r;
		if(area>100)
		{
			break;
		}
		printf("r=%d,area=%f\n",r,area);
	}
}

输出结果:

r=1,area=3.141590
r=2,area=12.566360
r=3,area=28.274311
r=4,area=50.265442
r=5,area=78.539749

程序的作用是计算r=1到r=10时的圆面积,直到面积area大于100为止。从上面的for循环可以看到:当area>100时,执行break语句,提前结束循环,即不再继续执行其余的几次循环。

#include <stdio.h>
#include <conio.h>
void main()

{
	int i=0;
	char c;
	while(1) /*设置循环*/
	{
		c='\0'; /*变量赋初值*/
		while(c!=13&&c!=27) /*键盘接受字符直到按回车或Esc键*/
		{
			c=getch();
			printf("%c\n",c);
		}
		if(c==27)
			break; /*判断若按Esc键则退出循环*/
		i++;
		printf("The No. is %d\n",i);
	}
	printf("The end");
}

continue语句
作为结束本次循环,即跳过循环体中下面尚未执行的语句,接着进行下一次是否执行循环的判定。一般形式:
    continue;

continue语句和break语句的区别
continue语句只结束本次循环,而不是终止整个循环的执行。
break语句则是结束整个循环过程,不在判断执行循环的条件是否成立。

例题:显示输入字符,如果按的是Esc键,则退出循环;如果按的是Enter键,则不做任何处理,继续输入下一个字符。

#include <stdio.h>
#include <conio.h>
void main()

{
	char ch;
	for( ; ; )
	{
		ch=getch(); /*字符输入函数*/
		if (ch==27) /*Esc键的ACSSII码为27*/
			break;	/*退出循环*/
		if(ch==13)
			continue; /*按的是Enter:键,跳过字符输出语句*/
		putch(ch); /*显示输入的字符*/
	}
	getch();  /*让程序停一下,拍任意键继续*/
}

把100~200之间的不能被3整除的数输出
提示:当n能被3整除时,执行continue语句,结束本次循环(即跳过printf函数语句),只有n不能被3整除时才执行printf。

#include <stdio.h>
void main()

{
	int n;
	for(n=100;n<200;n++)
	{
		if(n%3==0)
		continue;
	printf("%d",n);
	}
}

输出结果:

100     101     103     104     106     107     109     110     112     113     115     116     118     119     121
        122     124     125     127     128     130     131     133     134     136     137     139     140     142
        143     145     146     148     149     151     152     154     155     157     158     160     161     163
        164     166     167     169     170     172     173     175     176     178     179     181     182     184
        185     187     188     190     191     193     194     196     197     199
 

#2021-11-05
题目:
1)用π/4≈1-1/3+1/5-1/7+...公式求π的近似值,直到某一项的绝对值小于为止。
提示:1.要确定计算的精度……可以配合while循环语句用fabs()函数确定精度来退出  2.据观察,分子不变,分母却每次递增2,且正负切换。 3.记得结果乘以4.

#include <stdio.h>
#include <math.h>
void main()

{
	int s;float n,t,pi;
	t=1;pi=0;n=1.0;s=1;
	while(fabs(t)>1e-6)
	{
		pi=pi+t;n=n+2;s=-s;t=s/n;
	}
	pi=pi*4;
	printf("pi=%10.6f\n",pi);
}

输出结果:pi=  3.141594

2)求Fibonacci数列的前40个数。这个数列有如下特点:第1、2两个数为1,1.从第三个开始,该数是其前面两个数之和。
即 F(1)=1    F(2)=1    F(n)=F(n-1)+F(n-2)
    (n=1)    (n=2)        (n>=3)

#include <stdio.h>

void main()

{
	long int f1,f2;
	int n;
	f1=1,f2=1;
	for(n=1;n<=20;n++)
	{
		printf("%12ld%12ld",f1,f2);
		if(n%2==0)
		{
			printf("\n");
		}
		f1=f1+f2;
		f2=f2+f1;
	}
}

 输出结果:

           1           1           2           3
           5           8          13          21
          34          55          89         144
         233         377         610         987
        1597        2584        4181        6765
       10946       17711       28657       46368
       75025      121393      196418      317811
      514229      832040     1346269     2178309
     3524578     5702887     9227465    14930352
    24157817    39088169    63245986   102334155

3)写一个程序,运行输入一个数m,并判断m是否为素数??
素数又称质数。指在一个大于1的自然数中,除了1和此数自身外,没法被其他自然数整除的数。
算法思想:让m被2到k除,如果m能被2~k之中任何一个整数整除,则提前结束循环,此时i必然小于或等于k;如果m不能被2~k之间的任一整数整除,则在完成最后一次循环后,i还要加1,因此i=k+1,然后才终止循环。在循环之后判别I'd值是否大于或等于k+1,若是,则表明未曾被2~k之间任一整数整除过,因此输出“是素数”

#include <stdio.h>
#include <math.h>
void main()

{
	int m,i,k;
	scanf("%d",&m);
	k = sqrt(m);
	for(i=2;i<=k;i++)
	{
		if(m%i==0)
		{
			break;
		}
	}
	if(i>k)
	{
		printf("%d is a prime number\n",m);
	}
	else
	{
		printf("%d is not a prime number\n",m);
	}
}

 输出结果:

·7
  7 is a prime number
·26
  26 is not a prime number

 4)求100~200间的全部素数打印出来。

#include <stdio.h>
#include <math.h>
void main()

{
	int m,i,k,n=0;
	for(m=101;m<=200;m=m+2)
	{
		k=sqrt(m);
		for(i=2;i<=k;i++)
		{
		if(m%i==0)break;
		}
	if(i>=k+1)
	{
		printf("%d\t",m);
		n=n+1;
	}
	if(n%10==0)
	{
		printf("\n");
	}
	}
	printf("\n");
}

输出结果:

101     103     107     109     113     127     131     137     139     149
151     157     163     167     173     179     181     191     193     197
199

#2021-11-06
数组:
在程序设计中,为了处理方便,把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类数据元素的集合称为数组。在C语言中,数组属于构造类型数据。一个数组可以分解为多个数组元素,这些数组元素可以是基本数据类型或是构造类型。因此按数组元素的类型不同,数组又可分为数值数组、字符数组、指针数组、结构数组等各种类别。

数组:具有相同类型的数据组成的序列,是有序的集合。


数组中的每一个数据称:数组元素、下标变量
数组元素:由其所在的位置序号(称数组元素的下标)来区分。
用数组名与下标 可以用统一的方式来处理数组中的所有元素,从而方便的实现处理一批具有相同性质数据的问题。
注意:数组元素有序不是指元素大小顺序

一维数组的定义方式:
在C语言中使用数组必须先进行定义。
一维数组的定义方式为:
    类型说明符 数组名[常量表达式]

例如:int a[10];
它表示定义了一个整型数组,数组名为a,此数组有10个元素,10个元素都是整型变量

注意:
1、类型说明符是任意一种基本数据类型或构造数据类型。对于同一个数组,其所有元素的数据类型都是相同的
2、数组名是用户定义的数组标识符。书写规则应符合标识符的书写规定。
3、方括号中的常量表达式表示数据元素的个数,也称为数组的长度。
4、允许在同一个类型说明中,说明多个数组和多个变量。
例如: int a,b,c,d,k1[10],k2[20];
5、a[10],表示a数组有10个元素,注意下标是从0开始的,这个10个元素是a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]。按上面定义,不存在数组元素a[10]。
6、C语言不允许对数组的大小作动态定义,即数组的大小不依赖于程序运行过程中变量的值。


重点补充:一维数组在内存中的存放
一维数组:int mark[100];
    低地址          86    mark[0]
                          92    mark[1]
                          77    mark[2]
                          52    mark[3]
                          ·            ·
                          ·           ·
                          ·            ·
    高地址          94    mark[99]
每个数据元素占用的字数,就是基类型的字节数,一个元素占4个字节。


一维数组元素的引用
数组元素是组成数组的基本单元。数组元素也是一种变量,其标识方法为数组名后跟一个下标。下标表示了元素在数组中的顺序号。
数组元素的一般类型为:
        数组名[下标]
    (下标可以是整型常量或整型表达式)
    例如:

a[0]=a[5]+a[7]-a[2*3]
	a[i+j]
	a[i++]

都是合法的数组元素

注意:
数组元素通常也称为下标变量。必须先定义数组,才能使用下标变量。在C语言中只能逐个地使用下标变量,而不能一次引用整个数组。
例如:输出有10个元素的数组必须使用循环语句逐个输出各下标变量:

for(i=0;i<10;i++)
	{
		printf(“%d”,a[i]);
	}

而不能用一个语句输出整个数组。
 

定义数组时用到的“数组名[常量表达式]”和引用数组元素时用到的“数组名[下标]”是有区别的。
例如:int a[10]; /*定义数组长度为10*/
    t=a[6]; /*引用a数组中序号为6的元素。此时6不代表数组长度*/

例题:

#include <stdio.h>
void main()
{
	int i,a[10];
	for(i=0;i<=9;i++)
	{
		a[i]=i;
	}
	for(i=9;i>=0;i--)
	{
		printf("%d ",a[i]);
	}
	printf("\n");
}

输出结果:9 8 7 6 5 4 3 2 1 0

一维数组的初始化
给数组赋值的方法除了用赋值语句对数组元素逐个赋值外,还可采用初始化赋值和动态赋值的方法。

数组初始化赋值是指在数组定义时给数组元素赋予初值。数组初始化是在编译阶段进行的。这样将减少运行时间,提高效率。
注意:之前用赋值语句或输入语句也可给数组数指定初值,是在运行时完成的。
初始化赋值的一般形式为:
    类型说明符 数组名[常量表达式]={值,值,......值};

动态赋值:

#include <stdio.h>
void main()
{
	int i,max,a[10];
	printf("input 10 numbers: \n");
	for(i=0;i<10;i++)
	{
		scanf("%d",&a[i]); 
	}
		max=a[0];
	for(i=1;i<10;i++)
	{
		if(a[i]>max)
		{
			max=a[i]; 
		}
	}
	printf("maxnum=%d\n",max);
}

输出结果:

input 10 numbers:
1
2
3
4
57
8
6
9
5
2
maxnum=57

题目:
利用数组来处理、求解Fibonacci数列。
回顾:Fibonacci数列公式:已知:a1=a2=1 an=an-1+an-2,即1,1,2,3,5,8,13,……
过程:先定义一个20个元素的数组,并将数组的第一、第二个元素都初始化为1,其他元素初始化为0,通过公式求出其他各个元素的值。

注意:经过第一趟(共5次比较与交换)后,最大的数9已“沉底”,然后进行对余下的前面5个数第二趟比较

……
如果有n个数,则要进行n-1趟比较。在第一趟比较中要进行n-1次两两比较,在第j趟比较中要进行n-j次两两比较。
1、先通过动态赋值的方法让用户输入十个待排序的数字,通过数字保存起来。
2、掌握两个循环,外层循环限制有多少趟比较,内层循环限制某趟比较要进行两两对比的次数。
3、如果a[i]>a[i+1],则将两数进行交换,因为要求从小到大排列
4、把最终的结果输出到屏幕
5、完成

#include <stdio.h>
void main()
{
	int a[10];
	int i,j,t;
	printf("input 10 numbers: \n");
	for(i=0;i<10;i++)
	{
		scanf("%d",&a[i]);
	}
	printf("\n"); /*实现用户输入数据搭到数组*/
	for(j=0;j<9;j++)
	{
		for(i=0;i<9-j;i++)
		{
			if(a[i]>a[i+1])
			{
				t=a[i];
				a[i]=a[i+1];
				a[i+1]=t; /*将a[i]和a[i+1]两数调换*/
			}
		}
	}
	printf("the sorted numbers: \n");
	for(i=0;i<10;i++)
	{
		printf("%d \t",a[i]);
	}
	printf("\n");
}

输出结果:

input 10 numbers:
2
65
6
3
4
8
9
10
11
1

the sorted numbers:
1       2       3       4       6       8       9       10      11      65

#2021-11-07
##二维数组的定义和引用

###二维数组的定义
二维数组的定义的一般形式为
类型说明符 数组名 [常量表达式] [常量表达式];
例如:定义a为3×4(3行4列)的数组,b为5×10(5行10列)的数组。如下:
float a[3] [4],b [5] [10];

3行4列的表示:

我们可以把二维数组看作是一个特殊的一维数组,它有3个元素:a[0]、a[1]、a[2],每个元素又是一个包含4个元素的一维数组。

二维数组在概念上是二维的,但是,实际的硬件存储却是连续编址的,也就是说存储器单元是按一维线性排列的。
如何在一维存储器中存放二维数组,可有两种方式:一种是按行排列,即放完一行之后顺次放入第二行。另一种是按列排列,即放完一列之后再顺次放入第二列。在C语言中,二维数组是按行排列的。

衍生:多维数组的定义

定义三维数组:float a [2] [3] [4];
多维数组元素在内存中的排列顺序:第一维的下标变化最慢,最右边的下标变化最快。

二维数组元素的引用和初始化
数据类型 数组名[常量表达式1][常量表达式2]={初始化数据};
4种方法对二维数组初始化:
1)直接分行给二维数组赋初值。
int a [3] [4] = {{1,2,3,4},{5,6,7,7},{9,10,11,12}};
2)将所有数据卸载一个花括号内,按数组排列的顺序对各元素赋初值。
int a [3] [4] = {1,2,3,4,5,6,7,8,9,10,11,12};
3)对部分元素赋初值。
int a [3] [4] ={{1},{5},{9}};
对各行中的某一元素赋初值
int a [3] [4] = {{1},{0,6},{0,0,11}};
    1    0    0    0
    0     6    0     0
    0    0     11    0
或对某几行元素赋初值:
int a [3] [4] = {{1},{5,6}};
    1    0    0    0
    5    6    0    0
    0    0    0    0
    0    0    0    0

4)如果对全部元素都赋初值,则定义数组时对第一组的长度可以不指定,但第二维的长度不能省。
int a [3] [4] = {1,2,3,4,5,6,7,8,9,10,11,12};
等价于:
int a [ ] [4] = {1,2,3,4,5,6,7,8,9,10,11,12};
在定义时也可以只对部分元素赋初值而省略第一维的长度,但应分行赋初值。
int a [3] [4] = {{0,0,3},{},{0,10}};
    0    0    3    0
    0    0    0    0
    0    10    0    0
 

#2021-11-08

例题:如图,一个学习小组有5个人,每个人有三门课的考试成绩。将各个数据保存到二维数组a[5][3]中,并求全组分科的平均成绩和总平均成绩。

Math8061598576
C7565638777
Foxpro9271709085

对数组a[5][3]:

1)按行分段赋值可写为:

int a[5] [3] = {{80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85}};

2)按行连续赋值可写为:

int a[5] [3] = {80,75,92,61,65,71,59,63,70,85,87,90,76,77,85};

这两种赋初值的结果是完全相同的。

#include <stdio.h>
void main()
{
	int i,j,sum=0,average,v[3];
	int a[5][3]={{80,75,92},{61,65,71},{**,**,**},{**,87,90},{76,77,85}};
	for(i=0;i<3;i++)	//科目
	{
		for(j=0;j<5;j++)	//学生
		{
			sum+=a[j][i];
		}
		v[i] = sum / 5;
		sum = 0;
	}
	average=(v[0]+v[1]+v[2])/3;

	printf("math:%d\nc languag:%d\nd Foxpro:%d\n",v[0],v[1],v[2]);
	printf("total:%d\n",average);
}

输出结果:

math:72
c languag:73
d Foxpro:81
total:75

题目

NO.1 将一个二维数组行和列元素,存到另一个二维数组中。i.e.将数组a[2][3]转换为数组b[3][2]

例如:

a = 1  2  3                b        =        1        4


a = 4  5  6               b        =        2        5


                                 b        =        3        6

思路提示:
化繁为简:无论大多少维数组,分解成一维的先进行转换
a[0][j]=>b[j][0]
a[i][0]=>b[0][i]

#include <stdio.h>
void main()
{
	int a[2][3] = {{1,2,3},{4,5,6}};
	int b[3][2],i,j;
	printf("%array a: \n");
	for(i=0;i<=1;i++)
	{
		for(j=0;j<=2;j++)
		{
			printf("%5d",a[i][j]);
			b[j][i] = a[i][j];
		}
		printf("\n");
	}
	printf("array b: \n");
	for(i=0;i<=2;i++)
	{
		for(j=0;j<=1;j++)
		{
			printf("%5d",b[i][j]);
		}
		printf("\n");
	}
}

输出结果:
array a:
    1    2    3
    4    5    6
array b:
    1    4
    2    5
    3    6

有一个3×4的矩阵,要求编程求出其中值最大的那个元素的值,以及其所在的行
号和列号。
提示:

#include <stdio.h>
void main()
{
    int i,j,row=0,colum=0,max;
    int a[3][4]={{1,2,3,4},{9,8,7,6},{-10,10,-5,2}};
    max=a[0][0];
    for(i=0;i<=2;i++)
    {
        for(j=0;j<=3;j++)
        {
            if(a[i][j]>max)
            {
                max=a[i][j];
                row=i;
                colum=j;
            }
        }
    }
    printf("max=%d,row=%d,colum=%d\n",max,row,colum);
}

输出结果:
max=10,row=2,colum=1

从键盘上输入9个整数,(对照九宫格的形式,输入三行,每行输入三个数)保存在二维数组中,按数组原来位置输出第一行和第一列的所有元素。
1            2            3    →  第0行    理论运行结果:
4            5            6    →  第1行          2
7            8            9    →  第2行    4    5    6
↓            ↓            ↓                               8

0列      1列       2列

#include <stdio.h>
void main()
{
	int i,j,a[3][3];
	for(i=0;i<3;i++)
	{
		for(j=0;j<3;j++)
		{
			printf("a[%d][%d]=",i,j);
			scanf("%d",&a[i][j]);
		}
	}
	for(i=0;i<3;i++)
	{
		for(j=0;j<3;j++)
		{
			if(1==i||1==j)
			{
				printf("%-6d",a[i][j]);
			}
			else
			{
				printf("%-6c",' ');
			}
		}
		printf("\n");
	}
}

输出结果:
a[0][0]=1
a[0][1]=3
a[0][2]=2
a[1][0]=4
a[1][1]=5
a[1][2]=6
a[2][0]=7
a[2][1]=8
a[2][2]=9
      3
4     5     6
      8

#2021-11-09
二维数组程序举例——二分法举例
利用数组进行数据查找--(二分法)折半查找法介绍
适应情况:在一批有序数据中查找某数
基本思想:选定这批数中居中间位置的一个数与所查数比较,看是否为所找之数,若不是,利用数据的有序性,可以决定所找的数是在选定数之前还是在之后,从而很快可以将查找范围缩小一半。以同样的方法在选定的区域中进行查找,每次都会将查找范围缩小一半,从而比较快地找到目的数。

例:假设在数组a中的数据是按由小到大顺序排列的:-12  0  6  16  23  56  80  100 110  115,从键盘上输入一个数,判定该数是否在数组中,若在,输出所在序号。
TIPS:
第一步:设low,mid和high三个变量,分别指示数列中的起始元素、中间元素、与最后一个元素位置,其初始值为low=0,high=9,mid=4,判断mid指示的数是否为所求,mid指示的数是23,不是要找的80,须继续进行查找。
[-12  0  6  16  23  56  80  100  110 115]
 low               mid                               high

第二步:确定新的查找区间。因为80大于23,所有查找范围可以缩小为23后面的数,新的查找区间为[56  80  100  110  115],low,mid,high分别指向新区间的开始、中间与最后一个数。实际上high不变,将low(low=mid+1)指向56,mid(mid=(mid+high)/2)指向100,还不是要找的80,仍须继续查找。
-12  0  6  16  23  [56  80  100  110  115]
                              low       mid           high

第三步:上一步中,所找数80比mid指示的100小,可知新的查找区间为[56  80],low不变,mid与high的值作相应修改。mid指示的数为56,还要继续查找
-12  0  6  16  23  [56        80]  100  110  115
                       low/mid       high    
第四步:根据上一步的结果,80大于mid指示的数56,可确定新的查找区间为[80],此时,low与high都指向80,mid亦指向80,即找到了80,到此为止,查找过程完成。
-12  0  6  16  23  56          [80]          100  110  115
                                    low/mid/high

注意:若在查找过程中出现了low>high的情况,则说明,序列中没有该数,亦结束查找过程。

#include <stdio.h>
#define M 10
void main()
{
	int a[M]={-12,0,6,16,23,56,80,100,110,115};
	int n,low,mid,high,found;
	low=0;
	high=M-1;
	found=0;
	printf("Input a number to be searched: ");
	scanf("%d",&n);
	while(low<=high)
	{
		mid=(low+high)/2;
		if(n==a[mid])
		{
			found=1;break;
		}/*找到,结束循环*/
		else if(n>a[mid])
			low=mid+1;
		else
			high=mid-1;
	}
	if(found==1)
		printf("The index of %d is %d\n",n,mid);
	else
		printf("There is not %d\n",n);
}

输出结果:

Input a number to be searched: 80
The index of 80 is 6

#2021-11-10

函数
一个较大的程序可分为若干个程序模块,每一个模块用来实现一个特定的功能。
在高级语言中用子程序实现模块的功能。子程序由函数来完成。
一个C程序可由一个主函数和若干个其他函数构成。

函数间的调用关系

由主函数调用其他函数,其他函数也可互相调用。同一个函数可以被一个或多个函数任意调用多次。

例:

#include <stdio.h>
void main()
{
	void printstar();
	void print_message();

	printstar();
	print_message();
	printstar();
}

void printstar()
{
	printf("*****************\n");
}

void print_message()
{
	printf("Hello,World!!!\n");
}

输出结果:

*****************
Hello,World!!!
*****************

说明:
1)一个C程序由一个或多个程序模块组成,每一个程序模块作为一个源程序文件。对较大的程序,一般不希望把所有内容全放在一个文件中,而是将他们分别放在若干个源文件中,再由若干源程序文件组成一个C程序。作业便于分别编写、分别编译,提高调试效率。一个源文件程序可以为多个C程序公用。
2)一个源程序文件由一个或多个函数以及其他有关内容(如命令行、数据定义等)组成。一个源程序文件是一个编译单位,在程序编译时是以源程序文件为单位进行编译的,而不是以函数为单位进行编译的。
3)C程序的执行是从main函数开始的,如是在main函数中调用其他函数,在调用后流程返回到main函数,在main函数中结束整个程序的运行。
4)所有函数都是平行的,即在定义函数时是分别进行的,是互相独立的。一个函数并不从属于另一函数,即函数不能嵌套定义。函数是可以互相调用,但不能调用main函数。main函数是系统调用的。
5)函数有两种:
·标准函数,即库函数。(系统提供)
·用户自己定义的函数。
6)函数分两类:
·无参数函数:在调用无参数函数时,主调函数不向被调用函数传递数据。无参数函数一般用来执指定的一组操作。
·有参数函数在调用函数时,主调函数在调用被调用函数时,通过参数向被调用函数传递数据,一般情况下,执行被调用函数时会得到一个函数值,供主调函数使用。

定义无参数函数的一般形式:
类型标识符 函数名()
{
    声明部分
    语句部分
}
定义有参数函数一般形式:
类型标识符 函数名(形式参数列表)
{
    声明部分
    语句部分
}

int max (int x,int y)
{
	int z;
	/*函数体中的声明部分*/
	z=x>y?x:y;
	return (z);
}

定义空函数的一般形式:
类型标识符 函数名()
{}
例:dummy()
{}

函数参数和函数的值
形式参数和实际参数
在前面提到的有参数函数中,在定义函数时函数名后面括号中的变量名称为“形式参数”
在主调函数中调用一个函数时,函数名后面括号中的参数(可以是一个表达式)称为“实际参数”

主调函数和被调用函数之间有数据传递的关系
return后面的括号中的值()作为函数带回的值(称函数返回值)
在不同函数之间传递数据,可使用的法:
参数:通过形式参数和实际参数
返回值:用return语句返回计算结果
全局变量:外部变量
例:

#include <stdio.h>
void main()
{
	int max(int x,int y);
	int a,b,c;
	scanf("%d,%d",&a,&b);
	c=max(a,b);
	printf("Max is %d\n",c);
}
int max(int x,int y)
{
	int z;
	z=x>y?x:y;
	/*if(x>y
	{
		z=x;
	}
	else
	{
		z=y;
	}
	*/
	return z;
}

输出结果:
1,23
Max is 23

#2021-11-11

形参与实参

1)在定义函数中的指定形参,在未出现函数调用时,它们并不占内存中的存储单元。只有在发生函数调用时,函数max中的形参才被分配内存单元。在调用结束后,形参所占的内存单元也被释放。
2)实参可以是常量、变量或表达式,如:max (3,a+b);但要求它们有确定的值。 在调用时将实参的值赋给形参。
3)在被定义的函数中,必须指定形参的类型
4)实参与形参的类型应相同或赋值兼容。如果实参为整型而形参为实型,则按照不同类型数值的赋值规则进行转换。
5)在C语言中,实参向对形参的数据传递是“值传递”(相当于COPY),单向传递,只由实参传递给形参,而不能由形参传回来给实参。在内存中,实参单元与形参单元是不同的单元。

 在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值。因此,在执行一个被调用函数时,形参的值如果发生改变,并不会改变主调函数的实参的值。例如,若在执行函数过程中的x和y的值变为10和15,而a和b仍为2和3。

 函数的返回值
通常,希望通过函数调用使主函数能得到一个确定的值,这就是函数的返回值。

1)函数的返回值是通过函数中的return语句获得的
return语句将被调用函数中的一个确定值带回主调函数中去

如果需要从被调用函数带回一个函数值供主调函数使用,被调用函数中必须包含return语句。如果不需要从被调用函数带回函数值可以不要return语句。

一个函数中可以有一个以上的return语句,执行到哪一个return语句,哪一个语句起作用。return后面的值可以是一个表达式。
如:int max (int x,int y)
{
    return (x > y ? x : y);
}

2)函数的返回值应当属于某一个确定的类型,在定义函数时指定函数返回值的类型。
(在C语言中,凡不加类型说明的函数,自动按整型处理)

3)在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致。

4)对于不带回值的函数,应当用“void”定义函数为“无类型”(或空类型)

例:

#include <stdio.h>
void main()
{
	int max(float x,float y);
	float a,b;
	int c;
	scanf("%f,%f",&a,&b);
	c=max(a,b);
	printf("Max is %d\n",c);
}

int max(float x,float y)
{
	float z;
	z=x>y?x:y;
	return z;
}

输出结果:

1.2,2.2
Max is 2

函数调用的一般形式
函数调用的一般形式为:函数名(实参列表)

如果是调用无参数,则“实参列表”可以没有,但括号不能省略。
如果实参列表包含多个实参,则各参数间用逗号隔开。实参与形参的个数应相等,类型应匹配。实参与形参按顺序对于,一一传递数据。
如果实参列表包括多个实参,对实参求值的顺序并不是确定的,有的系统按自左至右顺序求实参的值,有的系统则按自右至左顺序。

对于函数调用
int i=2,p;
p=f(i,i++);如果是按自左至右顺序求实参的值,则函数调用相当于f(2,3)
如果是按自右至左顺序求实参的值,则函数调用相当于f(3,3,)

1)被调用的函数必须是已经存在的函数(是库函数或用户自己定义的函数)
2)如果使用库函数,还应该在本文件开头用#include 命令将调用有关库函数时所需用到的信息“包含”到本文件中来。
3)如果使用用户自己定义的函数,而该函数的位置在调用它的函数(即主调函数)的后面(在同一个文件中),应该在主调函数中对被调用的函数作声明。

例:

#include <stdio.h>
void main()
{
	float add (float x,float y);
	float a,b,c;
	scanf("%f,%f",&a,&b);
	c=add(a,b);
	printf("sun is %f \n",c);
}

float add(float x,float y)
{
	float z;
	z=x+y;
	return z;
}

输出结果:
2.2,3.2
sun is 5.400000

#2021-11-12

1、自己实现pow函数并尝试验证......

#include <stdio.h>
double power (double x,double y);
void main()
{
	double x=3.0,y=3.0,z;
	z=power(x,y);
	printf("%.1f的%.1f次方是%.1f\n",x,y,z);
}

double power(double x,double y)
{
	double z=1;
	while(y)
	{
		z *= x;
		--y;
	}
	return z;
}

 输出结果:3.0的3.0次方是27.0

2、猜想一下sqrt()函数的原理并尝试编程......(暂时只要求整型数据)

#include <stdio.h>
int sqrt_02( int question);
void main()
{
	int question=49,answer;
	answer=sqrt_02(question);
	if(question < 0)
		printf("Error:sqrt return %d\n",answer);
	else
		printf("The square root of %d is %d\n",question,answer);
}

int sqrt_02(int question)
{
	int temp=question/2;
	while(temp--)
	{
		if(temp*temp==question)
			return temp;
	}
	return -1;
}

 The square root of 49 is 7

3、编写有关用来统计输入的各个数组、空白符(空格、制表符、换行符)以及所有其他字符出现次数的程序。
分别存储在变量num[10],blank,others里边并打印出来......


#2021-11-13

函数的嵌套调用

嵌套定义就是在定义一个函数时,其函数体内又包含另一个函数的完整定义。然后,C语言不能嵌套定义函数,但可以嵌套调用函数,也就是说,在调用一个函数的过程中,又调用另一个函数。

 例题:
计算s=2²!+3²!("!"在高等数学里面是阶乘的意思,!4==4*3*2*1)
思路:本题可编写两个函数,一个是用来计算平方值的函数square,另一个是用来计算阶乘值的函数factorial。
主函数先调用square计算出平方值,再在square中以平方值为实参,调factorial计算其阶乘值,然后返回square,再返回主函数,在循环程序中计算累加和。

#include <stdio.h>
long square(int p);
long factorial(int q);
void main()
{
	int i;
	long s=0;

	for(i=2;i<=3;i++)
	{
		s=s+square(i);
	}

	printf("%ld\n",s);
}

long square(int p)
{
	int k;
	long r;
	long factorial(int);

	k=p*p;
	r=factorial(k);
	return r;
}

long factorial(int q)
{
	long c=1;
	int i;
	for(i=1;i<=q;i++)
	{
		c *= 1;
	}
	return c;
}

 输出结果:2

递归
在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。C语言的特点之一就在于允许函数的递归调用。
例如:
int f (int x)
{
    int y,z;
    z=f(y);
    return (2*z);
}

递归中必须要有一个退出条件

例题:
用递归的方法求n!
求n!也可以用递归方法,即5!=4!×5,而4!=3!×4...1!=1.可以用下面的递归公式表示:
n=1    (n=0,1)
n*(n-1)!    (n>1)

#include <stdio.h>
long recursion(int n);
void main()
{
	int n;
	long result;
	printf("input a interger number:");
	scanf("%d",&n);
	result=recursion(n);
	printf("%d! = %ld\n",n,result);
}

long recursion(int n)
{
	long temp_result;
	if(n<0)
	{
		printf("n<0,input error!\n");
	}
	else if(n==0||n==1)
	{
		temp_result=1;
	}
	else
	{
		temp_result=recursion(n-1)*n;
	}
	return temp_result;
}

输出结果:input a interger number:5
5! = 120

程序中给出的函数recursion()是一个递归函数。主函数调用recursion()后即进入函数recursion()执行。

如果n<0,n==0或n==1时都将结束函数的执行,否则就递归调用recursion函数自身。

由于每次递归调用的实参为n-1,即把n-1的值赋予形参n,最后当n-1的值为1时再作递归调用,形参n的值为1时再作递归调用,形参n的值也为1,将使递归终止。然后可逐层退回。

习题:
Hanoi(汉诺)塔问题。这是一个古典的数学问题,是一个用递归方法解题的典型例子。问题是这样的:古代有一个梵塔,塔内有3个座A、B、C,开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上。

 

 #2021-11-14

习题解答:

数组作为函数的参数使用,进行数据传送。数组用作函数参数有两种形式。
一种是把数组元素(下标变量)作为实参使用;
另一种是把数组作为函数的形参和实参使用。

数组元素就是下标变量,它与普通变量并无区别。因此它作为函数实参使用与普通变量是完全相同的,在发生函数调用时,把作为实参的数组元素的值传送给形参,实现单向的值传送。
例题:
判别一个整数数组a[10]={1,2,3,4,-1,-2,-3,-4,2,3}中各个元素的值,若大于0 则输出该值,若小于等于0则输出0值。

#include <stdio.h>
void test(int v);
void main()
{
	int a[10]={1,2,3,4,-1,-2,-3,-4,2,3};
	int i;
	for(i=0;i<10;i++)
	{
		test(a[i]);
	}
	printf("\n");
}
void test(int v)
{
	if(v>0)
	{
		printf("%d ",v);
	}
	else
	{
		printf("%d ",0);
	}
}

输出结果:1 2 3 4 0 0 0 0 2 3

用数组名作函数参数与用数组元素作实参有几点不同:
1)用数组元素作为实参时,只要数组类型和函数的形参变量的类型一致,那么作为下标变量的数组元素的类型也和函数形参变量的类型是一致的。因此,并不要求函数的形参也是下标变量。换句话说,对数组元素的处理是按普通变量对待的。
然而,用数组名作为函数参数时,则要求形参和相对应的实参都必须是类型相同的数组,都必须有明确的数组说明。当形参和实参二者不一致时,即会发生错误。
2)在普通变量或下标变量作函数参数时,形参变量和实参变量是由编译系统分配的两个不同的内存单元。在调用时发生的值传送是把实参变量的值赋予变量。
在用数组名作函数参数,不是进行址的传送,即不是把实参数组的每一个元素的值都赋予形参数组的各个元素。

数据传送的实现:
在此之前我们曾介绍过,数组名介绍数组的首地址。因此在数组名作函数参数时所进行的传送只是地址的传送,也就是说把实参数组的首地址赋予形参数组名。

形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有一段内存空间。

程序例子:

#include <stdio.h>
void test(int b[10]);
void main()
{
	int a[10]={2,4,6,8,10,12,14,16,18,20};
	test(a);
	putchar('\n');
}
void test(int b[10])
{
	int i=0;
	for(;i<10;i++)
	{
		printf("%d ",b[i]);
	}
}

输出结果:2 4 6 8 10 12 14 16 18 20

内存中数组的存储:

 思考并讨论以下例题:
有一个一维数组score,内放10个学生的成绩,求平均成绩(写一个average函数求平均成绩)

#include <stdio.h>
double average(double array[10]);
void main()
{
	double score[10]={82,100,87.5,89,78,85,67.5,92.5,93,94},result;
	result=average(score);
	printf("average score is %5.2lf\n",result);
	
}
double average(double array[10])
{
	double result=0;
	int i=0;
	for(i=0;i<10;i++)
	{
		result += array[i];
	}
	result /= 10;
	return result;
}

输出结果:average score is 86.85

#2021-11-15

局部变量:
在一个函数内部定义的变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使用它们,在此函数以外是不能使用这些变量的。这称为“局部变量”。
 

 1)主函数中定义的变量(m,n)也只在主函数中有效,而不是因为在主函数中定义而整个文件或程序中有效。主函数也不能使用其他函数中定义的变量。

2)不同函数中可以使用相同名字的变量,它们代表不同的对象,互不干扰。例如,上面f1函数中定义了变量b和c,它们在内存中占不同的单元,互不混淆。
3)形式参数也是局部变量。例如上面f1函数中的形参a,也只是在f1函数中有效。其他函数可以调用f1函数,但不能引用f1函数的形参a。
4)在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效,这种复合语句也称为“分程序”或“程序块”。
实例:

void main()
{
	int a,b;
...
	{
		int c;
		c=a+b;
...
	}
...
}

 全局变量:
在函数定义的变量是局部变量,而在函数之外定义的变量称为外部变量,外部变量是全局变量(也称全程变量)。
全局变量可以为本文件中其他函数所共用。它的有效范围为从定义变量的位置开始到本源文件结束。

实例:

 分析源码!
题目一:输出正方体的长宽高l,w,h。求体积及三个面x*y,x*z,y*z的面积。
源码分析1:

#include <stdio.h>
int s1,s2,s3;
int vs(int a,int b,int c)
{
	int v;
	v=a*b*c;
	s1=a*b;
	s2=b*c;
	s3=a*c;
	return v;
}

void main()
{
	int v,l,w,h;
	printf("input length,width and height:");
	scanf("%d%d%d",&l,&w,&h);
	v=vs(l,w,h);
	printf("v=%d,s1=%d,s2=%d,s3=%d\n",v,s1,s2,s3);
}

输出结果:
input length,width and height:2 5 4
v=40,s1=10,s2=20,s3=8

题目二:有一个一维数组,内放10个学生的成绩,写一个函数,求出平均分、最高分和最低分。
源码分析2:

#include <stdio.h>
float Max=0,Min=0;
void main()
{
	float average(float array[],int n);
	float ave,score[10];
	int i;
	for(i=0;i<10;i++)
	{
		scanf("%f",&score[i]);
	}
	ave=average(score,10);
	printf("max=%6.2f\n min=%6.2f\n average=%6.2f\n",Max,Min,ave);
}

float average(float array[],int n)
{
	int i;
	float aver,sum=array[0];
	Max=Min=array[0];
	for(i=1;i<n;i++)
	{
		if(array[i]>Max)
			Max=array[i];
		else if(array[i]<Min)
			Min=array[i];
		sum += array[i];
	}
	aver =sum/n;
	return aver;
}

输出结果:
99.8 34 43 12 21 23 43 32 33 87.9
max= 99.80
 min= 12.00
 average= 42.87

存储类别
动态存储方式与静态存储方式
静态存储方式是指程序运行开始时由系统分配的固定的存储空间的方式
动态存储方式则是在程序运行期间根据需要进行动态的分配存储空间的方式。

用户存储空间分为三部分:
程序区、静态存储区、动态存储区

在C语言中每一个变量和函数有两个属性:数据类型和数据的存储类别。
对数据型(如整型、字符型等)。存储类别指的是数据在内存中存储的方式。
存储方式分为两大类:静态存储类和动态存储类。
具体包含四种:自动的(auto),静态的(static),寄存器(register),外部的(extern)。根据变量的存储类别,可以知道变量的作用域和生存期。

auto变量

static变量

程序例题:

#include <stdio.h>
int f(int a)
{
	auto b=0;
	static c=3;
	b=b+1;
	c=c+1;
	return (a+b+c);
}

void main()
{
	int a=2,i;
	for(i=0;i<3;i++)
	{
		printf("%d\n",f(a));
	}
}

输出结果:

7
8
9

1)静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)属于动态存储类别,占动态存储区空间而不占静态存储区空间,函数调用结束后即释放。

2)对静态局部是在编译时赋初值的,即值赋初值一次,在程序运行时它已有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。而对自动变量赋初值,不是在编译时进行的,而是在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。

3)如在定义局部变量时不赋值的话,则对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符变量)。而对自动变量来说,如果不赋初值则它的值是一个不确定值。

这是由于每次函数调用结束后操场单元已释放,下次调用时又重新另分配存储单元,而所分配的单元中的值是不确定的。

4)虽然静态局部变量在函数调用结束后仍然存在,但其他函数是不能引用它的

例题:输出1到5的阶乘值。

#include <stdio.h>
int fac(int n)

{
	static int f=1;
	f=f*n;
	return (f);
}
void main()
{
	int i;
	for(i=1;i<=5;i++)
	{
		printf("%d! = %d\n",i,fac(i));
	}
}

输出结果:
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120

 寄存器变量

当程序中用到哪一个变量的值时,由控制器发出指令将内存中该变量的值送到运算器中。经过运算器进行运算,如果需要存数,再从运算器将数据送到内存存放。 

用关键词register作声明。

程序是输出1到n的阶乘的值

#include <stdio.h>
int fac(int n)

{
	register int i, f=1;
	for(i=1;i<=n;i++)
	{
		f *= i;
	}
	return (f);
}
void main()
{
	int i;
	for(i=1;i<=15;i++)
	{
		printf("%d! = %d\n",i,fac(i));
	}
}

 输出结果:
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 1932053504
14! = 1278945280
15! = 2004310016

同上个例题相比,register变量的速率明显快于static。

#include <stdio.h>
int max(int x,int y)
{
	int z;
	z=x>y?x:y;
	return (z);
}
void main()
{
	extern A,B;
	printf("%d\n",max(A,B));
}
int A=13,B=-8;

输出结果:13

#2021-11-16 

在多文件的程序中声明外部变量

实例:

file1:
#include <stdio.h>
int A;
void main()
{
	int power(int);
	int b=3,c,d,m;
	printf("enter the number A and its power m:\n");
	scanf("%d %d",&A,&m);
	c=A*b;
	printf("%d*%d=%d\n",A,b,m);
	d=power(m);
	printf("%d ^ %d\n",A,m,d);
}
file2:
extern A;  //声明A为一个已定义的外部变量
int power(int n)
{
	int i,y=1;
	for(i=1;i<=n;i++)
	{
		y *= A;
	}
	return y;
}

输出结果:
enter the number A and its power m:

3 3
3*3=9
3^3=27

有时在程序设计中希望某些外部变量只限于被本文件引用,而不能被其他文件引用。这时可以在定义外部变量时加一个static声明。

对变量而言,声明与定义的关系稍微复杂一些。在声明部分出现的变量有两种情况:一种是需要建立存储空间的(如:int a;),另一种是不需要建立存储空间的(如 extern a;)。
前者称为“定义性声明”;后者称为“引用性声明”


小结:
1)从作用域角度分,有局部变量和全局变量。采用存储类别如下

 

 2)从变量存在的时间来区分,有动态存储和静态存储两种类型。静态存储是程序整个运行时间都存在,而动态存储则是在调用函数时临时分配单元。

 3)从变量值存放的位置来区分,可分为:

 4)关于作用域和生存期的概念


5)static对局部变量和全局变量的作用不同。

函数本质上是全局的,因为一个函数要被另外的函数调用,但是,也可以指定函数不能被其他文件调用。
根据函数能否被其他源文件调用,将函数区分为内部函数和外部函数

一个函数只能被本文件中其他函数所调用,称为内部函数
在定义内部函数时,在函数名和函数类型前面加static

题:有一个字符串,内有若干个字符,要求输入一个字符,程序便将字符串中的该字符删去。用外部函数

file1:
#include <stdio.h>
void main()
{
	extern void enter_string(char str[]);
	extern void delete_string(char str[],char ch);
	extern void print_string(char str[]);

	char c;
	char str[80];
	enter_string(str);
	scanf("%c",&c);
	delete_string(str,c);
	print_string(str);
}
file2:
#include <stdio.h>

//定义外部函数enter_string()

void enter_string(char str[80])
{
	gets(str);
}
file3:
//定义外部函数 delete_string()

void delete_string(char str[],char ch)
{
	int i,j;
	for(i=j=0;str[i] != '\0';i++)
	{
		if(str[i] != ch)
		{
			str[j++]=str[i];
		}
	}
	str[j]='\0';
}
file3:
#include <stdio.h>
void print_string(char str[])
{
	printf("%s\n",str);
}

输出结果:
Hello World!! s
s
Hello World!!

#2021-11-17

指针

对变量的访问方式:直接访问和间接访问

直接访问如:a=5;
系统在编译时,已对变量分配了地址,例如,若变量a分配的地址是2000,则该语句的作用就是把常数5保存到地址为2000的单元。
间接访问如:scanf("%d",&a);
调用函数时,把常量a的地址传递给函数scanf,函数首先把该地址保存到一个单元中,然后把从键盘接收的数据通过存储的地址保存到a变量中。

在C语言中,指针是一种特殊的变量,它是存放地址的。

例如:定义一个指针变量 int *i_pointer 用来存放整数变量i的地址,可以通过语句:i_pointer = &i;

将i的地址(2000)存放到i_pointer中。这时,i_pointer的值就是(2000),即变量i所占用单元的起始地址。要存取变量i的值,可以采用间接方式:先找到存放“i的地址”的变量i_pointer,从中取出i的地址(2000),然后取出i的值3。

*:取值操作符
&:取址操作符

如:int i =2000;
int *pointer; //*定义指针变量
pointer = &i;
printf("%d\n",*pointer);//*取值操作符


知道了一个变量的地址,就可以通过这个地址访问这个变量,因此,又把变量的地址称为变量的“指针”。

C语言中可以定义一类特殊的变量,这些变量专门用来存放变量的地址,称为指针变量。

注意:指针变量的值(即指针变量中存放的值是地址(即指针)。)请区分“指针”和“指针变量”这两个概念。

一、指针变量前面的“*”,表示该变量的类型为指针变量。其一般形式为:
类型说明符 *变量名;
其中,*表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。
例如:float *pointer_1;
指针变量名是pointer_1,而不是*pointer_1。
二、在定义指针变量时必须指定集类型。
需要特别注意的是,只是整型变量的地址才能放到指向整型变量的指针变量中。

指针变量中只能存放地址(指针),不要将一个整数(或任何其他非地址类型的数据)赋给一个指针变量,否则编译器也会把该值当成一个地址来处理。
C语言中提供了地址运算符&来表示变量的地址。
其一般形式为:&变量名;
如&a表示变量a的地址,&b表示变量b的地址。变量本身必须预先声明。

通过指针变量访问整型变量
源代码:

#include <stdio.h>
void main()
{
	int a,b;
	int *pointer_1,*pointer_2;
	a=100,b=10;
	pointer_1=&a;
	pointer_2=&b;

	printf("%d,%d\n",a,b);
	printf("%d,%d\n",*pointer_1,*pointer_2);
}

输出结果:
100,10
100,10

代码分析:

“&”和“*”两个运算符的优先级别相同,但按自右而左方向结合,因此先进行*pointer_1的运算,它就是变量a,再执行&运算。
因此,& *pointer_1与& a相同,即变量a的地址。

如:pointer_2 = & *pointer_1;
它的作用是将&a(a的地址)赋给pointer_2,如果pointer_2原来指向b,经过重新赋值后它已不再指向b,而指向了a。

* &a 的含义是什么?
先进行&a运算,得a的地址,再进行*运算。即&a所指向的变量,也就是变量a。

* &a和*pointer_1的作用是一样的,它们都等价于变量a。即*&a与a等价。

(*pointer_1)++相当于a++。
注意:括号是必要的,如果没有括号,就成为了*pointer_1++,从附录可知:++和*为同一优先级别,而结合方向为自右而左,因此它相当于*(pointer_1 ++)。

由于++在pointer_1的右侧,是“后加”,因此先对pointer_1的原值进行*运算,得到a的值,然后使pointer_1的值改变,这样pointer_1不再指向a了。

题目:输入a和b两个整数,按先大后小的顺序输出a和b。
源代码:

#include <stdio.h>
void main()
{
	int *p1,*p2,*p,a,b;
	scanf("%d %d",&a,&b);
	p1=&a;
	p2=&b;

	if (a<b)
	{
		p=p1;
		p1=p2;
		p2=p;
	}
	printf("a=%d,b=%d\n",a,b);
	printf("max=%d,min=%d\n",*p1,*p2);
}

输出结果:
12 22
a=12,b=22
max=22,min=12

题目:对输入的两个整数按大小顺序输出。
源代码:

#include <stdio.h>
void swap(int *p1,int *p2);
void main()
{
	int a, b;
	int *pointer_1,*pointer_2;

	scanf("%d %d",&a,&b);
	pointer_1=&a;
	pointer_2=&b;

	if(a<b)
	{
		swap(pointer_1,pointer_2);
	}
	printf("%d > %d\n",a,b);
}

void swap(int *p1,int *p2)
{
	int temp;
	printf("I'm swapping……\n");
	printf("Please wait^_^");

	temp=*p1;
	*p1=*p2;
	*p2=temp;
}

输出结果:
12 22
I'm swapping……
Please wait^_^22 > 12

输出a、b、c三个整数,按大小输出。
源代码:

#include <stdio.h>

void main()
{
	void exchange(int *q1,int *q2,int *q3);
	int a,b,c,*p1,*p2,*p3;
	scanf("%d %d %d",&a,&b,&c);
	p1=&a;
	p2=&b;
	p3=&c;
	
	exchange(p1,p2,p3);
	printf("%d %d %d\n",a,b,c);
}

void exchange(int *q1,int *q2,int *q3)
{
	void swap(int *pt1,int *pt2);
	if(*q1<*q2)
	{
		swap(q1,q2);
	}
	if(*q1<*q3)
	{
		swap(q1,q3);
	}
	if(*q2<*q3)
	{
		swap(q2,q3);
	}
}

void swap(int *pt1,int *pt2)
{
	int temp;
	temp=*pt1;
	*pt1=*pt2;
	*pt2=temp;
}

输出结果:
11 22 33
33 22 11

#2021-11-18

数组与指针
一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。

指针变量既可以指向变量,也可以指向数组元素(把某一元素的地址放到一个指针变量中)。
数组元素的指针就是数组元素的地址。

int a[10];
(定义a为包含10个整型数据的数组)
int *p;
(定义p为指向整型变量的指针变量)
p=&a[0];
把a[0]元素的地址赋给指针变量p

引用一个数组元素:
1)下标法,如a[i]形式;
2)指针法,如*(a+i)或*(p+i)。
其中的a是数组名,p是指向数组元素的指针变量,其初值p=a == p=a[0]


例题:输出数组中的全部元素

下标法

#include <stdio.h>
void main()
{
	int a[10];
	int i;
	for(i=0;i<10;i++)
	{
		scanf("%d",&a[i]);
	}
	printf("\n");
	
	for(i=0;i<10;i++)
	{
		printf("%d ",a[i]);
	}
}

通过数组名计算数组元素地址,找出元素的值。

#include <stdio.h>
void main()
{
	int a[10];
	int i;
	for(i=0;i<10;i++)
	{
		scanf("%d",&a[i]);
	}
	printf("\n");
	
	for(i=0;i<10;i++)
	{
		printf("%d ",*(a+i));
	}
}

用指针变量指向数组元素

#include <stdio.h>
void main()
{
	int a[10];
	int i;
	int *p;
	for(i=0;i<10;i++)
	{
		scanf("%d",&a[i]);
	}
	printf("\n");
	
	for(p=a;p<(a+10);p++)
	{
		printf("%d ",*p);
	}
}

输出结果:
4 5 6 7 9 3 2 1 8 11

4 5 6 7 9 3 2 1 8 11

实参与形参的对于关系:
1)形参和实参都用数组名,如:
:void main()
{
    int a[10];
    f (a,10);

}
:void f(int x[],int n)
{
    ……
}
2)实参用数组名,形参用指针变量。如:
:void main()
{
    int a[10];
    f(a,10);
}
:f (int *a,int n)
{
    ……
}
3)实参形参都用指针变量。如:
:void main()
{
    int a[10],*p=a;
    f(p,10);
}
:void f(int *x,int n)
{
    ……
}
4)实参为指针变量,形参为数组名。如:
:void main()
{
    int a[10],*p=a;
    ……
    f(p,10);
}
:f (int x[].int n)
{
    ……
}
 

对数组中10个整数按由大到小的顺序排列
源代码:

#include <stdio.h>
void sort(int x[],int n);

void main()
{
	int *p,i,a[10]={3,7,9,11,0,6,7,5,4,2};
	printf("The original array:\n");
	for(i=0;i<10;i++)
	{
		printf("%d ",a[i]);
	}
	printf("\n");

	p=a;
	sort(p,10);
	printf("The result is:\n");
	for(p=a,i=0;i<10;i++)
	{
		printf("%d ",*p);
		p++;
	}
	printf("\n");
}

void sort(int x[],int n)
{
	int i,j,k,t;
	for(i=0;i<n-1;i++)
	{
		k=i;
		for(j=i+1;j<n;j++)
		{
			if(x[j]>x[k])
			{
				t=x[j];
				x[j]=x[k];
				x[k]=t;
			}
		}
	}
}

输出结果:

The original array:
3 7 9 11 0 6 7 5 4 2
The result is:
11 9 7 7 6 5 4 3 2 0

#2021-11-19

多维数组与指针
用指针变量可以指向一维数组中的元素,也可以指向多维数组中的元素
 

定义int  a[3][4]={{1,3,5,7},{9,1,13,15},{17,19,21,23}};

则二维数组a是由3 个一维数组所组成的。设二维数组的首行的首地址为2000,则:

表示形式含义地址
a二维数组名,指向一维数组a[0],即0行首地址2000

a[0],

*(a+0),

*a

0行0列元素2000
a+1,&a[1]1行首地址2016
a[1],*a(a+1)

1行0列元素a[0][1]的地址

2016

a[1]+2,

*(a+1)+2,

&a[1][2]

1行2列元素a[1][2]的地址

2024

*(a[1]+2),

*(*(a+1)+2),

a[1][2]

1行2列元素a[1][2]的值元素为13

把二维数组a分解为一维数组a[0],a[1],a[2]之后,设p为指向二维数组的指针变量。
int (*p)[4]
它表示p是一个指针变量,它指向包含4个元素的一维数组。若指向第一个一维数组a[0],其值等于a,a[0],或&a[0][0]等。而p+i则指向了一维数组a[i]

分析得出*(p+i)+j是二维数组i行j列的元素地址,而*(*(p+i)+j)则是i行j列元素的值。

二维数组指针变量说明的一般形式为:
类型说明符 (*指针变量名)[长度]

其值“类型说明符”为所指数组的数据类型。“*”表示其后的变量是指针类型。“长度”表示二维数组分解为多个一维数组时,一维数组的长度。也就是二维数组的列数。

用指针变量输出二维数组元素。
源代码:

#include <stdio.h>
void main()
{
	int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
	int (*p)[4];
	int i,j;
	p=a;
	for(i=0;i<3;i++)
	{
		for(j=0;j<4;j++)
		{
			printf("%2d ",*(*(p+i)+j));
		}
	}
	printf("\n");
}

输出结果: 0  1  2  3  4  5  6  7  8  9 10 11


通过输入指定行数和列数打印出二维数组对应任一行任一列元素的值。

#include <stdio.h>
void main()
{
	int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
	int (*p)[4],i,j;
	p=a;
	printf("i = ");
	scanf("%d",&i);
	while(i > 2|| i < 0)
	{
		printf("i = ");
		scanf("%d",&i);
	}
	printf("j = ");
	scanf("%d",&j);
	while(j > 3 || i < 0)
	{
		printf("j = ");
		scanf("%d",&j);	
	}
	printf("a[%d,%d] = %d\n",i,j,*(*(p+i)+j));
}

输出结果

i = 3
i = 1
j = 2
a[1,2] = 13

#2021-11-20

字符指针变量和字符数组

1.字符数组由若干元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第一个1个字符的地址),决不是将字符串放到字符指针变量中。
2.赋值方式。对于字符数组只能对各个元素赋值,不能用以下办法对字符数组赋值。
char str[20];
str="......";
而对字符指针变量,可以采用下面方式赋值:
char *a;
a="......";
但注意赋给a的不是字符,而是字符串第一个元素的地址。
3.对字符指针变量赋初值:
char *a = " …… ";
等价于
char *a;
a = " …… ";
而对于数组的初始化:
char str[20] = {"……"};
不能等价于
char str[20];
str[ ]=" …… ";
4.如果定义了一个字符数组,在编译时它分配内存单元,它有确定的地址。而定义一个字符指针变量时,给指针变量分配内存单元,在其中可以放一个字符变量的地址,也就是说,该指针变量可以指向一个字符型数据,但如果未对它赋予一个地址值,则它并未具体指向一个确定字符数据。
5.指针变量的值是可以改变的。

如:

#include <stdio.h>
void main()
{
	char *a = " Hello,Wrold!!";
	printf("%s\n",a);
	a += 7;

	printf("%s\n",a);
}

输出结果: Hello,Wrold!!
Wrold!!

另外需要说明的是,若定义了一个指针变量,并使它指向一个字符串,就可以用下标形式引用指针变量所指的字符串中的字符。
例如:

#include <stdio.h>
void main()
{
	char *a = " Hello,Wrold!!";
	int i;
	printf("The sixth character is %c\n\n",a[5]);
	
	for(i=0;a[i]!='\0';i++)
	{
		printf("%c",a[i]);
	}

	printf("\n");
}

输出结果:
The sixth character is o

 Hello,Wrold!!

用函数指针变量调用函数
可以用指针变量指向整型变量、字符串、数组,也可以指向一个函数。一个函数在编译时被分配给一个入口地址。这个函数的入口地址就称为函数的指针。

指向函数的指针.c   比较a和b的大小,求大值
源代码:

include <stdio.h>

#if(1)
void main()
{
	int max(int ,int);
	int a,b,c;
	scanf("%d %d",&a,&b);
	c=max(a,b);
	printf("a=%d,b=%d,max=%d\n",a,b,c);
}
#endif
int max(int x,int y)
{
	int z;
	if(x>y)
	{
		z=x;
	}
	else
	{
		z=y;
	}
	return z;
}
#if(0)
//将main函数改为
void main()
{
	int max(int ,int);
	int (*p)();
	int a,b,c;
	p=max;
	scanf("%d %d",&a,&b);
	c=(*p)(a,b);
	printf("a=%d,b=%d,max=%d\n",a,b,c);
}
#endif

输出结果:2 3
a=2,b=3,max=3


题目:设一个函数process,在调用它的时候,每次实现不同的功能。
输入a和b两个数,第一次调用process时找出a和b中大者,第二次找出其中小值,第三次求a与b之和。

#2021-11-21

一个函数可以带回一个整型值、字符值、实型值等,也可以带回指针型的数据,即地址。其概念与以前类似,只是带回的值的类型是指针类型而已。

一般形式为:
类型名  *函数名(参数列表);
例:
int *a(int x,int y);

例题:有若干个学生的成绩(每个学生有4门课程),要求自己用户输入学生序号以后,能输出该学生的全部成绩。用指针函数来实现。


这两个概念都是简称:
指针函数指带指针的函数,即本质是一个函数。
函数指针是指向函数的指针变量,因而函数指针本身首先应是指针变量,只不过该指针变量指向函数。


指针数组的概念:
一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都相当于一个指针变量。一维指针数组的定义形式为:
类型名  数组名[数组长度]
例如:int *name[4];

实例:

#include<stdio.h>
void main()
{
	int a[5]={1,3,5,7,9};
	int *name[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};
	int i;
	for(i=0;i<5;i++)
	{
		printf("%d   ",*name[i]);
	}
	printf("\n");
}

输出结果:1   3   5   7   9

例题:将下边字符串按字母顺序(由小到大)输出。
char *name[]={"Fishc.com","www.fishc.com","home.fishc.com"};

指针数组

#include <stdio.h>
#include <string.h>
void main()
{
	void sort(char *name[],int n);
	void print(char *name[],int n);
	char *name[]={"Fishc.com","www.fishc.com","home.fishc.com","Fishc.com/dz"};
	int n=4;
	sort(name,n);
	print(name,n);
}
void sort(char *name[],int n)
{
	char *temp;
	int i,j,k;
	for(i=0;i<n-1;i++)
	{
		k=i;
		for(j=i+1;j<n;j++)
		{
			if(strcmp(name[k],name[j])>0)
			{
				k=j;
			}
			if(k!=i)
			{
				temp=name[i];
				name[i]=name[k];
				name[k]=temp;
			}
		}
	}
}
void print(char *name[],int n)
{
	int i;
	for(i=0;i<n;i++)
	{
		printf("%s\n",name[i]);
	}
}

输出结果:
Fishc.com
Fishc.com/dz
home.fishc.com
www.fishc.com

指针数组的一个重要应用是作为main函数的形参。在以往的程序中,main函数的第一行一般写成以下形式:
void main()

括号中是空的。实际上,main函数可以有参数。
例如:void main(int argc,char *argv[])
argc和argv是main函数的形参。
main函数是由操作系统调用的。实际上实参和命令一起给出的。也就是在一个命令行中包括命令和需要穿给main函数的参数。
命令行的一般形式:命令名   参数1   参数2......参数n
实例:main.c

#include <stdio.h>
#include <stdlib.h>
void main(int argc,char *argv[])
{
	int i;
	printf("the number of string is: %d\n",argc-1);
	for(i=1;i<argc;i++)
	{
		printf("the string %d is: %s\n",i,argv[i]);
	}
}

 输出结果:the number of string is: 0

#2021-11-22

有关指针的数据类型小结: 

一、指针变量加(减)一个整数
例如:p++、p--、p+i、p-i、p += i、p -= i等。
指针变量赋值
将一个变量地址赋给一个指针变量。如:
p=&a;(将变量a的地址赋给p) 
p=array; (将数组array首元素地址赋给p)
p=&array[i]; (将数组array第i个元素的地址赋给p)
p=max;(max为已定义的函数,将max的入口地址给p)
p1=p2;(p1和p2都是指针变量,将p2的值都赋给p1)

二、指针变量可以有空值,即该指针变量不指向任何变量,可以这样表示:p=NULL;

 三、两个指针变量比较
若两个指针指向同一个数组的元素,则可以进行比较。指向前面的元素的指针变量“小于”指向后面元素的指针变量。

void真正发挥的作用于:
(1)对函数返回的限定
(2)对函数参数的限定
例如:void abc(void);

void指针和const指针
ANSI C新标准增加了一种“void”指针类型,即不指定它是指向哪一种类型的数据的指针变量。
例如:void *p;
表示指针变量p不指向一个确定的类型数据,它的作用仅仅是用来存放一个地址。
void指针它可以指向任何类型数据。也就是说,可以用任何类型的数据的指针直接给void指针赋值。但是,如果需要将void指针的值赋给其他类型的指针,则需要进行强制类型转换。
 

const例子:
 

#include <stdio.h>
void main(void)
{
	const char *str="Welcome to Fishc.com!\n";
	//这个语句的含义:声音一个名为str的指针变量,
	//它指向一个字符型常量,初始化str为指向字符型
	//"Welcome to Fishc.com!\n"
	printf("%s",str);
#if(0)
	str[0]='w';
#endif
	str="I love Fishc.com!\n";
	printf("%s",str);
}

输出结果:
Welcome to Fishc.com!
I love Fishc.com!

预处理
以“#”开头的均为预处理命令

无参宏定义
无参宏定义后不带参数。
一般形式:#define 标识符 字符串
其中的“#”表示这是一条预处理命令

define为宏定义命令。“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等。
例如:#define PI 3.1415926
作用是指定标识符PI来代替数3.1415926
对程序作编译时,将先由预处理程序进行宏代换,即用3.1415926表达式去置换所有的宏名PI,然后再进行编译。
实例:

#include <stdio.h>
#define PI 3.1415926
void main()
{
	double s;
	int r;
	printf("please enter the radivs: ");
	scanf("%d",&r);
	s=PI*r*r;
	printf("%g\n",s);
}

输出结果:
please enter the radivs: 2
12.5664

对宏定义的说明:
1)宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查。如有错误,只能在编译已被宏展开后的源程序时发现。
2)宏定义不是说明或语句,在行末不必加分号,如果加上则连分号也一起置换。
3)宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令。
4)宏名在源程序中若引用引号括起来,则预处理程序不对其作宏代换。
实例:

#include <stdio.h>
#define PI 3.1415926
void fun(void);
void main()
{
	double s;
	int r;
	printf("please enter the radivs: ");
	scanf("%d",&r);
	s=PI*r*r;
	printf("The area of the roundness=%g\n",s);
	fun();
}

void fun(void)
{
	printf("Now the PI = %g\n",PI);
	printf("PI\n");
}

输出结果:please enter the radivs: 2
The area of the roundness=12.5664
Now the PI = 3.14159
PI

5)宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名。在宏展开时由预处理程序层层代换。
6)习惯上宏名用大写字母表示,以便于与变量区别(也可以使用小写字母)。
实例:

#include <stdio.h>
#define PI 3.1415926
#define S PI*r*r
void fun(void);
void main()
{
	double s;
	int r;
	printf("please enter the radivs: ");
	scanf("%d",&r);
	s=S;
	printf("The area of the roundness=%g\n",s);
	fun();
}

输出结果:please enter the radivs: 2
12.5664

7)可用宏定义表示数据类型,书写方便。
例如:
#define INTEGER int

宏定义表示数据和用typedef定义数据说明符的区别:宏定义只是简单的字符串代换,是在预处理完成的,而typedef是在编译时预处理的,它不是作简单的代换,而是对类型说明符重新命名。被命名的标识符具有类型定义说明的功能。
实例:

#include <stdio.h>
#define PIN1 char*
typedef char* PIN2;
void main()
{
	PIN1 x,y;
	PIN2 a,b;

	printf("By #define : %d %d\n",sizeof(x),sizeof(y));
	printf("By typedef : %d %d\n",sizeof(a),sizeof(b));
}

输出结果:
By #define : 4 1
By typedef : 4 4

8)对“输出格式”作宏定义,可以减少书写麻烦。
实例:

#include <stdio.h>
#define P printf
#define D "%d\n"
#define F "%f\n"
void main()
{
	int a=5,c=8,e=11;
	float b=3.8,d=9.7,f=21.08;
	P(D F,a,b);
	P(D F,c,d);
	P(D F,e,f);
}

输出结果:
5
3.800000
8
9.700000
11
21.080000

#2021-11-23

C语言允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。
对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。
带参宏定义的一般形式为:
#define 宏名(形参表) 字符串

带参宏调用的一般形式为:
宏名(实参表);
例如:
#define    M(y)y*y+3*y  /*宏定义*/
……
k=M(5);    /*宏调用*/
……
在宏调用时,用实参5去代替形参y,经预处理宏展开后的语句为:
k=5*5+3*5
实例:

#include <stdio.h>
#define MAX(a,b) (a>b)?a:b
void main()
{
	int x,y,max;
	printf("input two numbers: ");
	scanf("%d %d",&x,&y);
	max=MAX(x,y);    //max = (x>y)?x:y;
	printf("The max is %d\n",max);
}

输出结果:input two numbers: 3 9
The max is 9

对于带参的宏定义有以下问题需要说明:
1.带参宏定义中,宏名和形参表之间不能有空格出现。
例如:
#define MAX(a,b) (a>b)?a:b
#define MAX (a,b) (a>b)?a:b   (错)

2.在带参宏定义中,形式参数不分配内存单元,因此不必作类型定义。而宏调用中的实参有具体的值。要用它们去代换形参,因此必须作类型说明符。
这是与函数中的情况不同的。在函数中,形参和实参是两个不同的量,各有自己的作用域,调用时要把实参值赋予形参,进行“值传递”。而在带参宏中,只是符号代换,不存在值传递的问题。

3.在宏定义中的形参是标识符,而宏调用中的实参可以是表达式。

4.在宏定义中,字符串内的形参通常要用括号括起来以避免出错。
实例:

#include <stdio.h>
#define SQ(y) (y)*(y)
void main()
{
	int a,sq;
	printf("input a number: ");
	scanf("%d",&a);
	sq=SQ(a+1); //sq=(a+1)*(a+1)
	printf("sq=%d\n",sq);
}

输出结果:
input a number: 1
sq=4

题目:修改上面实例:

#include <stdio.h>
#define SQ(y) ((y)*(y))
void main()
{
	int a,sq;
	printf("input a number: ");
	scanf("%d",&a);
	sq=160/SQ(a+1);   //sq=160/((a+1)*(a+1))
	printf("sq=%d\n",sq);
}

输出结果:
input a number: 3
sq=10

 课后题:比较程序
代码1:

#include <stdio.h>
void main()
{
	int i=1;
	int SQ(int y);
	while(i<=5)
	{
		printf("%d\n",SQ(i++));
	}
}
int SQ(int y)
{
	return( (y) * (y) );
}

输出结果:
1
4
9
16
25

代码2:

#include <stdio.h>
#define SQ(y) ( (y)*(y) )
void main()
{
	int i=1;
	while(i<=5)
	{
		printf("%d\n",SQ(i++));
	}
}

输出结果:
1
9
25

5.带参的宏和带参函数很相似,但有本质上的不同,除上面已谈到的各点外,把同一表达式用函数处理与用宏处理两者的结果有可能是不同的。
6.宏定义也可用来定义多个语句,在宏调用时,把这些语句又代换到源程序内。
实例:

#include <stdio.h>
#include <string.h>
#define STR(s1,s2,s3,sum) strcat( strcat( strcat(sum,s1),s2),s3);
void main()
{
	char str1[]= "I ",str2[]="love ",str3[]="Fishc.com!",str[40]= "";
	STR(str1,str2,str3,str);  //strcat( strcat( strcat(str,s1),s2),s3);
	printf("str1=%s\nstr2=%s\nstr3=%s\nStr=%s\n",str1,str2,str3,str);
}

输出结果:
str1=I
str2=love
str3=Fishc.com!
Str=I love Fishc.com!

文件包含命令:
1.一个include命令只能指定一个被包含文件,若有多个文件要包含,则需要多个include命令。
2.文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。
3.包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。
例:#include“stdio.h”/ #include<stdio.h>
{但是这两种形式是有区别的:使用尖括号表示在包含文件目录中去查找(包含目录是由用户在设置环境时设置的),而不在源文件目录去查找;
使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。用户编程时可根据自己文件所在的目录来选择某一种目录形式。}

预处理程序提供了条件编译的功能。可以按不同的条件去编译不同的程序部分,因而产生不同的目标代码文件。这对于程序的移植和调试是很有用的。

条件编译有三种潜规则,下面分别介绍:
第一种形式:
    #ifdef    标识符
        程序段1
    #else
        程序段2
    #endif
它的功能是,如果标识符已被#define命令定义过则对程序段1进行编译;否则对程序段2进行编译。
如果没有程序段2(它为空),本格式中的#else可以没有,即可以写为:
    #ifdef    标识符
        程序段
    #endif

第二种形式:
    #ifndef    标识符
        程序段1
    #else
        程序段2
    #endif
实例:

#include <stdio.h>
#define CORRECT "fishc.com"
void main()
{
	char str[40];
	int cmp(char *str1,char str2);
	printf("Please enter website you like the best: ");
	scanf("%s",str);
#ifndef CORRECT
#define CORRECT "fishc.com"
#endif
	if( cmp(str,CORRECT)==0 )
	{
		printf("Yeah! You are a smart man!\n");
	}
	else
	{
		printf("You fool! Man!\n");
	}
}
int cmp(char *str1,char *str2)
{
	int i=0,j=0;
	while(str1[i])
	{
		while(str2[j]==str1[i])
		{
			i++;j++;
			if( !str2[j] )
			{
				return 0;
			}
		}
			j=0;
			i++;
	}
		return -1;
}

输出结果:
Please enter website you like the best: fishc.com
Yeah! You are a smart man!

/

#include <stdio.h>

void main()
{
	char str[40];
	int cmp(char *str1,char str2);
	printf("Please enter website you like the best: ");
	scanf("%s",str);
#ifndef CORRECT
#define CORRECT "fishc.com"
#endif
	if( cmp(str,CORRECT)==0 )
	{
		printf("Yeah! You are a smart man!\n");
	}
	else
	{
		printf("You fool! Man!\n");
	}
}
int cmp(char *str1,char *str2)
{
	int i=0,j=0;
	while(str1[i])
	{
		while(str2[j]==str1[i])
		{
			i++;j++;
			if( !str2[j] )
			{
				return 0;
			}
		}
			j=0;
			i++;
	}
		return -1;
}

输出结果:
Please enter website you like the best: fishc.com
Yeah! You are a smart man!

第三种形式:
    #if   常量表达式
        程序段1
    #else
        程序段2
    #endif
实例:

#include <stdio.h>
#define ROUND 1   //当后面为1 时,计算的是圆的面积,当为0时,计算的是正方形的面积
#define PI 3.1415926
void main()
{
	int r;
	double s;
	printf("input a number: ");
	scanf("%d",&r);
#if ROUND
	s=r*r*PI;
	printf("Area of round is:%6.5f\n",s);
#else
	s=r*r;
	printf("Area of square is:%6.5f\n",s);
#endif
}

输出结果:
input a number: 3
Area of round is:28.27433

小结:
1.预处理功能是C语言特有的功能,它是在对源程序正式编译前由预处理程序完成的。程序员在程序中用预处理命令来调用这些功能。
2.宏定义是用一个标识符来表示一个字符串,这个字符串可以是常量、变量或表达式。在宏定义中将用该字符串代换宏名。
3.宏定义可以带有参数,宏调用时是以实参代换形参。而不是“值传送”。(函数调用是“值传送”)
4.为了避免宏代换时发生错误,宏定义中的字符串应加括号,字符串中出现的形式参数两边也应加括号。
5.文件包含是预处理的一个重要功能,它可用来把多个源文件连接成一个源文件进行编译,结果将生成一个目标文件。
6.条件编译允许值编译源程序中满足条件的程序段,使生成的目标程序较短,从而减少了内存的开销并提高了程序的效率。
7.使用预处理功能便于程序的修改、阅读、移植个调试,也便于实现模块化程序设计。

#2021-11-24

结构体和共用体

定义一个结构的一般形式:
struct 结构名
{
    成员列表
};

成员列表由若干成员组成,每个成员都是该结构的一个组成部分。对每个成员也必须作类型说明,其形式为:类型说明符   成员名;
例:
struct student
{
    int num;
    char name[20];
    char sex;
    int age;
    float score;
    char addr[30];
}

三种定义结构体类型变量的方法:
1)先声明结构体类型再定义变量名。例:
struct    student        student1,student2
类型名    结构体        变量名  ,变量名

定义了student1和student2为struct student类型的变量,即它们具有struct student类型的结构。

struct student
{
    int num;
    char name[20];
    char sex;
    int age;
    float score;
    char addr[30];
}student1,student2
在定义了结构体变量后,系统会为之分配内存单元。例如:
student1和student2在内存中各占?个字节。

2)在声明类型的同时定义变量。一般形式为:
struct 结构体名
{
    成员列表
}变量名列表;

3)直接定义结构体类型变量。一般形式为:
struct
{
    成员列表
}变量名列表;
(没有结构体名)


定义下图

首先定义一个结构date,由month(月)、day(日)、year(年)三个成员组成。

在定义并说明变量boy1和boy2时,其中的成员birthday被说明为date结构类型。成员名可与程序中其他变量同名,互不干扰。

struct date

{
       int month;

        int day;

        int year; 
}

struct
{
	int num;
	char name[20];
	char sex;
	struct date birthday;
	float score;
}boy1,boy2;

在定义了结构体变量以后,当然可以引用这个变量。应遵守以下规则:
1)不能将一个结构体变量作为一个整体进行输入和输出。
正确引用结构体变量中成员的方式为:结构体变量名.成员名
student1.num=100;
“.”是成员(分量)运算符,它在所有的运算符中优先级最高,因此可以把student1.num作为一个整体来看待。上面赋值语句的作用是将整数100赋给student1变量中成员num。

#include <stdio.h>
void main()
{
	struct date
	{
		int num;
		char *name;
		char sex;
		float score;
	}boy1,boy2;

	boy1.num=007;
	boy1.name="Jane";


	printf("Please input sex and score:");
	scanf("%c %f",&boy1.sex,&boy1.score);
	
	boy2=boy1;
	printf("Number=%d\nName=%s\n",boy2.num,boy2.name);
	printf("Sex=%c\nScore=%f\n",boy2.sex,boy2.score);
}

输出结果:
Please input sex and score:M 99.8
Number=7
Name=Jane
Sex=M
Score=99.800003

2)如果成员本身又属于一个结构体类型,则要用若干个成员运算符,一级一级地找到最低的一级的成员。只能对最低级的成员进行赋值或存取以及运算。
对上面的定义的结构体变量student1,可以这样访问各成员:
student1.num
student1.birthday.month

3)对结构体变量的成员可以像普通变量一样进行各种运算(根据其类型决定可以进行的运算)。例如:
student2.score=student1.score;
sum=student1.score+student2.score;
student1.age++;
++student2.age;

4)可以引用结构体变量成员的地址,也可以引用结构体变量的地址。
实例:

#include <stdio.h>
void main()
{
	struct student
	{
		int num;
		char *name;
		char sex;
		float score;
	}boy1;
	boy1.num=007;
	boy1.name="Jane";

	printf("The address of struct is %o \n",&boy1);
	printf("The address of num is %o \n",&boy1.num);

}

输出结果:
The address of struct is 6377440
The address of num is 6377440

结构体变量的初始化
实例:

#include <stdio.h>
void main()
{
	struct student
	{
		int num;
		char *name;
		char sex;
		float score;
	}boy1,boy2={102,"Jane",'M',98.5};
	boy1=boy2;
	printf("Number=%d\nName=%s\nScore=%f\n",boy1.num,boy1.name,boy1.score);
	printf("\n");
	printf("Number=%d\nName=%s\nScore=%f\n",boy2.num,boy2.name,boy2.score);
}

输出结果:
Number=102
Name=Jane
Score=98.500000

Number=102
Name=Jane
Score=98.500000

结构体数组
一个结构体变量中可以存放一组数据(如一个学生的学号、姓名、成绩等数据)。

如果有10个学生的数据需要参加运算,用数组,这就是结构体数组。

结构体数组与以前介绍过的数值型数组不同之处在于每个数组元素都是一个结构体类型的数据,它们都分别包括各个成员(分量)项。

定义结构体数组
和定义结构体变量的方法相仿,只需说明其为数组即可。例如:

struct student
{
	int num;
	char name[20];
	char sex;
	int age;
	float score;
	cahr addr[30];
};
struct student student[3];

与其他类型数值一样,对结构体数初始化。例如:

struct student
{
	int num;
	char name[20];
	char sex;
	int age;
	float score;
	cahr addr[30];
};stu[2]={
		{101,"LiLin",'M',18,87.5,"Beijing"},
		{102."Zhang",'F',19,99,"Shanghai"}
         };
或
struct student
{
	int num;
	...
};
struct student str[]{{...},{...},{...}};

即先声明结构体类型,然后定义数组为该结构体类型,在定义数组时初始化。
 

一个结构体变量的指针就是该结构体变量所占据的内存段的起始地址。
可以设一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。

指针变量也可以用来指向结构体数组中的元素。
结构体指针变量说明的一般形式为:
struct 结构名 *结构指针变量名

赋值是把结构变量的首地址赋予该指针变量,不能把结构名赋予该指针变量。
 

其访问的一般形式:
    (*结构指针变量).成员名

    结构指针变量->成员名
例如:
    (*pstu).num

    pstu->num
 

将一个结构体变量的值传递给另一个函数,有三种方法:
1)用结构体变量的成员作参数
2)用结构体变量作实参
3)用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给形参。

实例:有一个结构体变量stu,内含学生学号、姓名和3门课程的成绩。通过调用函数printf中将他们输出。
用结构体变量作函数参数:

#include <stdio.h>
#include <string.h>
struct student
{
	int num;
	char name[20];
	float score[30];
};

void print(struct student);
void main()
{
	struct student stu;
	stu.num=8;
	strcpy(stu.name,"hello");
	stu.score[0]=98.5;
	stu.score[1]=99.0;
	stu.score[2]=99.5;
	print( stu );
}
void print(struct student stu)
{
	printf("num	:%d\n",stu.num);
	printf("name	:%s\n",stu.name);
	printf("score_1	:%5.2f\n",stu.score[0]);
	printf("score_2	:%5.2f\n",stu.score[1]);
	printf("score_3	:%5.2f\n",stu.score[2]);
}

输出结果:
num     :8
name    :hello
score_1 :98.50
score_2 :99.00
score_3 :99.50

改用指针结构体变量的指针作实参:

#include <stdio.h>
#include <string.h>
struct student
{
	int num;
	char name[20];
	float score[30];
};

void print(struct student *);
void main()
{
	struct student stu;
	stu.num=8;
	strcpy(stu.name,"hello");
	stu.score[0]=98.5;
	stu.score[1]=99.0;
	stu.score[2]=99.5;
	print( &stu );
}
void print(struct student *p)
{
	printf("num	:%d\n",p->num);
	printf("name	:%s\n",p->name);
	printf("score_1	:%5.2f\n",p->score[0]);
	printf("score_2	:%5.2f\n",p->score[1]);
	printf("score_3	:%5.2f\n",p->score[2]);
}

输出结果:
num     :8
name    :hello
score_1 :98.50
score_2 :99.00
score_3 :99.50

常用的内存管理函数:
1)分配内存空间函数malloc、calloc
2)释放内存空间函数free

malloc函数
函数原型为void *malloc(unsigned int size);
其作用是在内存的动态存储区中分配一个长度为size的连续空间(size是一个无符号数)
此函数的返回值是一个指向分配域起始地址的指针(类型为void)。
如果此函数未能成功地执行(例如内存空间不足),则返回空指针(NULL)。

calloc函数
函数原型为void *calloc(unsigned n,unsigned size);
其作用是在内存的动态存储区中分配n个长度为size的连续空间。函数返回一个指向分配域起始地址的指针;如果分配不成功,返回null。
用calloc函数可以为一维数组开辟动态存储空间,n为数组元素个数,每个元素长度为size。

free函数
函数原型为void free(void *p);
其作用是释放由p指向的内存区,使这部分内存区能被其他变量使用。
p是最近一次调用calloc或malloc函数时返回的值
free函数无返回值


链表
链表是一种常见的重要的数据结构,是动态地进行存储分配的一种结构。

链表的组成:
头指针:存放一个地址,该地址指向第一个元素
结点:用户需要的实际数据和链接节点的指针

 实例:

#include <stdio.h>
struct student
{
	long num;
	float score;
	struct student *next;
};

void main()
{
	struct student a,b,c,*head;
	a.num=10101;
	a.score=89.5;
	b.num=10103;
	b.score=90;
	c.num=10107;
	c.score=85;

	head=&a;
	a.next=&b;
	b.next=&c;
	c.next=NULL;

	do
	{
		printf("%ld %5.1f\n",head->num,head->score);
		head=head->next;
	}while( head );
}

输出结果:
10101  89.5
10103  90.0
10107  85.0

建立动态链表
指在程序执行过程中从无到有地建立起一个链表,即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。

作业:根据下面的分析写一个程序建立一个含有学(学号、成绩)数据的单向动态链表。
 

#2021-11-25

实现链表输出
首先要知道链接第一个结点的地址,也就是要知道head的值。然后设一个指针变量p,先指向第一个结点,输出p所指的结点,然后使p后移一个结点,再输出,直到链表的尾结点。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哑巴爱说笑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值